Perun
nems.online
- Joined
- May 1, 2009
- Messages
- 378
- Solutions
- 7
- Reaction score
- 176
Hello, this is my version of Maple Story 2 Quiz event.
It's just for learning purpouse, but maybe someone will use it
1. Admin msg /quiz start and Waiting Room is open now.
2. Players now can move (yes moveevent) to waiting room, and when they step in they are subscribed to event. Before event start everyone can leave waiting room (automatic unsub).
3. After countdown waiting room is closed and subscribed players teleported to game map.
4. Now everything works like on this video:
data/scripts/quiz.lua
It's just for learning purpouse, but maybe someone will use it
1. Admin msg /quiz start and Waiting Room is open now.
2. Players now can move (yes moveevent) to waiting room, and when they step in they are subscribed to event. Before event start everyone can leave waiting room (automatic unsub).
3. After countdown waiting room is closed and subscribed players teleported to game map.
4. Now everything works like on this video:
data/scripts/quiz.lua
Lua:
if not Quiz then
Quiz = {
subscribeTime = 60 * 1000,
messageDelayTime = 10 * 1000, -- delay between broadcast messages
minPlayersToStart = 1,
questionsPerGame = 3, --how many questions you want to roll (unique questions)
reward = {2160, 100} --count,id
}
--maybe sometimes im using double check for somethings but im not always sure how things works in tfs 1.3.
Quiz.mapConfig = {
waitingRoom = {
['top_left_corner'] = {x = 1033, y = 1023, z = 7},
['bot_right_corner'] = {x = 1042, y = 1033, z = 7}, -- i will ignore z_pos, maybe in future there will be multifloor
['tile_action_id'] = 30000, --auto system will set waiting room tiles to this uid
},
gameRoom = {
['center'] = {x = 1059, y = 1028, z = 7},
leftAnswer = { --sqms for left side answers
['top_left_corner'] = {x = 1048, y = 1024, z = 7},
['bot_right_corner'] = {x = 1057, y = 1032, z = 7},
['tile_action_id'] = 30001,
},
rightAnswer = { --sqms for right side answers
['top_left_corner'] = {x = 1061, y = 1024, z = 7},
['bot_right_corner'] = {x = 1070, y = 1032, z = 7},
['tile_action_id'] = 30002,
},
teleportAble = { --place to check if players can be teleported to game pos (need if a lot of players will join event.)
['top_left_corner'] = {x = 1046, y = 1022, z = 7},
['bot_right_corner'] = {x = 1072, y = 1034, z = 7}
}
},
}
Quiz.LeftAnswer = Quiz.mapConfig.gameRoom.leftAnswer['tile_action_id']
Quiz.RightAnswer = Quiz.mapConfig.gameRoom.rightAnswer['tile_action_id']
Quiz.Questions = { --questions
{
text="Question 1", answers = {
bad = "bad answer", --bad/good cuz side for every answer is random
good = "good answer",
}},
{
text="Question 2", answers = {
bad = "bad answer",
good = "good answer",
}},
{
text="Question 3", answers = {
bad = "bad answer",
good = "good answer",
}},
}
Quiz.Storage = {
players = {}, --players in event
eventEnabled = false,
WaitingRoomEvent = nil,
waitingRoomEnabled = false,
subscribeTime = 0,
messageDelayTime = 0,
Questions = {}, --text/goodUid =
QuestionEvent = nil,
currentQuestion = 0
}
function Quiz.Disable()
Quiz.Storage.players = {} --know new pointer but idk if matter to clean current
Quiz.Storage.Questions = {}
Quiz.Storage.eventEnabled = false
Quiz.Storage.QuestionEvent = nil
end
function Quiz.shuffleTable(tbl)
local len, random = #tbl, math.random ;
for i = len, 2, -1 do
local j = random( 1, i );
tbl[i], tbl[j] = tbl[j], tbl[i];
end
return tbl;
end
function Quiz.QuestionEvent(times)
local currentIndex = Quiz.Storage.currentQuestion
if(not Quiz.Storage.Questions[currentIndex]) then
--can add teleport out players but it can't happen
Quiz.Disable()
return true
else
for i = 1, #Quiz.Storage.players do
local player = Player(Quiz.Storage.players[i])
if(player) then
local text = "[Question]: "..Quiz.Storage.Questions[currentIndex].text.." Left Side: "..Quiz.Storage.Questions[currentIndex].left..", Right Side: "..Quiz.Storage.Questions[currentIndex].right
text = text.." - "..times.." seconds left."
player:sendTextMessage(MESSAGE_INFO_DESCR, text)
end
end
end
times = times - 1
if(times > -1) then --check
Quiz.Storage.QuestionEvent = addEvent(Quiz.QuestionEvent, 1000, times)
else
if(Quiz.Storage.Questions[currentIndex].goodAnswerTileId == Quiz.LeftAnswer) then
Quiz.sideEffect('right')
else
Quiz.sideEffect('left')
end
for i = 1, #Quiz.Storage.players do
local player = Player(Quiz.Storage.players[i])
if(player) then
local t = Tile(player:getPosition())
if t ~= nil then
local tileItem = t:getThing();
local tileaid = tileItem:getActionId()
if(tileaid ~= Quiz.Storage.Questions[currentIndex].goodAnswerTileId) then
Quiz.kickPlayer(player)
end
end
end
end
if(#Quiz.Storage.players > 0) then
local questionsLeft = #Quiz.Storage.Questions - currentIndex
for i = 1, #Quiz.Storage.players do
local player = Player(Quiz.Storage.players[i])
if(player) then
if(questionsLeft > 0) then
player:sendTextMessage(MESSAGE_INFO_DESCR, "Quiz: "..#Quiz.Storage.players.." players left. Questions left: "..questionsLeft..".")
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You won!")
player:addItem(Quiz.reward[1], Quiz.reward[2])
player:teleportTo(player:getTown():getTemplePosition())
end
end
end
if(questionsLeft > 0) then
Quiz.Storage.currentQuestion = Quiz.Storage.currentQuestion + 1
addEvent(Quiz.QuestionEvent, 5000, 10)
else
Quiz.Disable()
end
else
Quiz.Disable()
end
end
end
function Quiz.kickPlayer(player)
local playerId = player:getId()
if(table.contains(Quiz.Storage.players, playerId)) then
for i = 1, #Quiz.Storage.players do
if(Quiz.Storage.players[i] == playerId) then
table.remove(Quiz.Storage.players, i)
player:sendTextMessage(MESSAGE_INFO_DESCR, "You lost. Try again next time.")
player:teleportTo(player:getTown():getTemplePosition())
break
end
end
end
end
function Quiz.FillRandomQuestions()
if(Quiz.questionsPerGame > #Quiz.Questions) then
Quiz.questionsPerGame = #Quiz.Questions
end
local tmpTbl = {}
for i = 1, #Quiz.Questions do
table.insert(tmpTbl, i)
end
tmpTbl = Quiz.shuffleTable(tmpTbl)
for i = 1, Quiz.questionsPerGame do
local questionInfo = {text = Quiz.Questions[tmpTbl[i]].text}
if(math.random(100) < 50) then --randomize answer options
questionInfo.left = Quiz.Questions[tmpTbl[i]].answers.good
questionInfo.goodAnswerTileId = Quiz.LeftAnswer
questionInfo.right = Quiz.Questions[tmpTbl[i]].answers.bad
else
questionInfo.right = Quiz.Questions[tmpTbl[i]].answers.good
questionInfo.goodAnswerTileId = Quiz.RightAnswer
questionInfo.left = Quiz.Questions[tmpTbl[i]].answers.bad
end
table.insert(Quiz.Storage.Questions, questionInfo)
end
return true
end
function Quiz.InitAnswerTiles()
if(Quiz.InitLeftAnswer() and Quiz.InitRightAnswer()) then
if(Quiz.FillRandomQuestions()) then
Quiz.Storage.currentQuestion = 1
addEvent(Quiz.QuestionEvent, 5000, 10)
end
end
end
function Quiz.sideEffect(side)
if(side == 'left') then
local leftAnswerTiles = Quiz.mapConfig.gameRoom.leftAnswer
for x = leftAnswerTiles['top_left_corner'].x, leftAnswerTiles['bot_right_corner'].x do
for y = leftAnswerTiles['top_left_corner'].y, leftAnswerTiles['bot_right_corner'].y do
local position = {x=x,y=y,z=leftAnswerTiles['top_left_corner'].z}
Position(position):sendMagicEffect(7)
end
end
elseif(side == 'right') then
local rightAnswerTiles = Quiz.mapConfig.gameRoom.rightAnswer
for x = rightAnswerTiles['top_left_corner'].x, rightAnswerTiles['bot_right_corner'].x do
for y = rightAnswerTiles['top_left_corner'].y, rightAnswerTiles['bot_right_corner'].y do
local position = {x=x,y=y,z=rightAnswerTiles['top_left_corner'].z}
Position(position):sendMagicEffect(7)
end
end
end
end
function Quiz.InitLeftAnswer()
local leftAnswerTiles = Quiz.mapConfig.gameRoom.leftAnswer
for x = leftAnswerTiles['top_left_corner'].x, leftAnswerTiles['bot_right_corner'].x do
for y = leftAnswerTiles['top_left_corner'].y, leftAnswerTiles['bot_right_corner'].y do
local position = {x=x,y=y,z=leftAnswerTiles['top_left_corner'].z}
local t = Tile(position)
if t ~= nil then
local tileItem = t:getThing();
tileItem:setActionId(leftAnswerTiles['tile_action_id'])
end
end
end
return true
end
function Quiz.InitRightAnswer()
local rightAnswerTiles = Quiz.mapConfig.gameRoom.rightAnswer
for x = rightAnswerTiles['top_left_corner'].x, rightAnswerTiles['bot_right_corner'].x do
for y = rightAnswerTiles['top_left_corner'].y, rightAnswerTiles['bot_right_corner'].y do
local position = {x=x,y=y,z=rightAnswerTiles['top_left_corner'].z}
local t = Tile(position)
if t ~= nil then
local tileItem = t:getThing();
tileItem:setActionId(rightAnswerTiles['tile_action_id'])
end
end
end
return true
end
function Quiz.teleportPlayerToGame(player)
local tryPos = player:getClosestFreePosition(Quiz.mapConfig.gameRoom['center'], true)
if(tryPos) then
if(tryPos.x >= Quiz.mapConfig.gameRoom.teleportAble['top_left_corner'].x and tryPos.x <= Quiz.mapConfig.gameRoom.teleportAble['bot_right_corner'].x) then
if(tryPos.y >= Quiz.mapConfig.gameRoom.teleportAble['top_left_corner'].y and tryPos.y <= Quiz.mapConfig.gameRoom.teleportAble['bot_right_corner'].y) then
player:teleportTo(tryPos)
return true
end
end
end
player:sendTextMessage(MESSAGE_INFO_DESCR, "Sorry, not enough place for you. Try next time.")
Quiz.kickPlayer(player)
return false
end
function Quiz.WaitingRoomEvent()
if(Quiz.Storage.waitingRoomEnabled) then
if(Quiz.Storage.subscribeTime <= 0) then
Quiz.disableWaitingRoom()
local canStart = false
if(#Quiz.Storage.players >= Quiz.minPlayersToStart) then
canStart = true
end
for i = 1, #Quiz.Storage.players do
local player = Player(Quiz.Storage.players[i])
if(player) then
if(canStart) then
Quiz.teleportPlayerToGame(player)
player:sendTextMessage(MESSAGE_INFO_DESCR, "Welcome on Quiz Event! Wait for first question.")
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "Not enough players to start event. Event Canceled.")
end
end
end
Quiz.InitAnswerTiles()
else
if(Quiz.Storage.messageDelayTime <= 0) then
broadcastMessage("Quiz waiting room is open! Subscribe to event! Players subscribed: "..#Quiz.Storage.players, MESSAGE_STATUS_WARNING)
Quiz.Storage.messageDelayTime = Quiz.messageDelayTime --reset timer
else
Quiz.Storage.messageDelayTime = Quiz.Storage.messageDelayTime - 1000
end
end
Quiz.Storage.subscribeTime = Quiz.Storage.subscribeTime - 1000
Quiz.Storage.WaitingRoomEvent = addEvent(Quiz.WaitingRoomEvent, 1000)
end
end
--main func
function Quiz.open()
Quiz.resetTimers()
Quiz.enableWaitingRoom()
Quiz.WaitingRoomEvent()
Quiz.Storage.eventEnabled = true
end
function Quiz.resetTimers()
Quiz.Storage.subscribeTime = Quiz.subscribeTime
Quiz.Storage.messageDelayTime = Quiz.messageDelayTime
end
local quizTalkaction = TalkAction("/quiz")
function quizTalkaction.onSay(player, words, param)
if(player:getGroup():getAccess()) then
if(param == "start") then
if(not Quiz.Storage.eventEnabled) then
Quiz.open()
player:sendTextMessage(MESSAGE_INFO_DESCR, "You started quiz event")
return true
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "Quiz event started already")
return true
end
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "Wrong param.")
return true
end
end
end
quizTalkaction:separator(" ")
quizTalkaction:register()
function Quiz.disableWaitingRoom()
local wRoom = Quiz.mapConfig.waitingRoom
for x = wRoom['top_left_corner'].x, wRoom['bot_right_corner'].x do
for y = wRoom['top_left_corner'].y, wRoom['bot_right_corner'].y do
local position = {x=x,y=y,z=wRoom['top_left_corner'].z}
local t = Tile(position)
if t ~= nil then
local tileItem = t:getThing();
if(tileItem:getActionId() == Quiz.mapConfig.waitingRoom['tile_action_id']) then
tileItem:removeAttribute('aid')
end
end
end
end
Quiz.Storage.waitingRoomEnabled = false
broadcastMessage("Quiz waiting room is now closed!", MESSAGE_STATUS_WARNING)
end
function Quiz.enableWaitingRoom()
local wRoom = Quiz.mapConfig.waitingRoom
for x = wRoom['top_left_corner'].x, wRoom['bot_right_corner'].x do
for y = wRoom['top_left_corner'].y, wRoom['bot_right_corner'].y do
local position = {x=x,y=y,z=wRoom['top_left_corner'].z}
local t = Tile(position)
if t ~= nil then
local tileItem = t:getThing();
tileItem:setActionId(wRoom['tile_action_id'])
end
end
end
broadcastMessage("Quiz waiting room is now open!", MESSAGE_STATUS_WARNING)
Quiz.Storage.waitingRoomEnabled = true
end
local waitingRoomStepIn = MoveEvent()
function waitingRoomStepIn.onStepIn(creature, item, position, fromPosition)
if(not creature:isPlayer()) then
return false
end
local fromPosItem = Tile(fromPosition)
if(fromPosItem ~= nil) then
fromPosItem = fromPosItem:getThing()
if(fromPosItem:getActionId() == Quiz.mapConfig.waitingRoom['tile_action_id']) then
return true
end
end
local playerId = creature:getId()
if(not table.contains(Quiz.Storage.players, playerId)) then
table.insert(Quiz.Storage.players, playerId)
creature:sendTextMessage(MESSAGE_INFO_DESCR, "You subscribed to Quiz event. Players on event: "..#Quiz.Storage.players..".")
end
return true
end
waitingRoomStepIn:aid(Quiz.mapConfig.waitingRoom['tile_action_id'])
waitingRoomStepIn:register()
local waitingRoomStepOut = MoveEvent()
function waitingRoomStepIn.onStepOut(creature, item, position, fromPosition)
if(not creature:isPlayer()) then
return false
end
local currentPosTile = Tile(creature:getPosition())
if(currentPosTile ~= nil) then
currentPosTile = currentPosTile:getThing()
if(currentPosTile:getActionId() ~= Quiz.mapConfig.waitingRoom['tile_action_id']) then
local playerId = creature:getId()
if(table.contains(Quiz.Storage.players, playerId)) then
for i = 1, #Quiz.Storage.players do
if(Quiz.Storage.players[i] == playerId) then
table.remove(Quiz.Storage.players, i)
creature:sendTextMessage(MESSAGE_INFO_DESCR, "You unsubscribed from Quiz event. Players on event: "..#Quiz.Storage.players..".")
break
end
end
end
return true
end
end
end
waitingRoomStepOut:aid(Quiz.mapConfig.waitingRoom['tile_action_id'])
waitingRoomStepOut:register()
end