TalkAction [1.3] MapleStory2 Quiz - Revescript

Perun

nems.online
Premium User
Joined
May 1, 2009
Messages
294
Best answers
5
Reaction score
116
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:

37249

37250
37251
37252
37253



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
 

Salvus

Member
Joined
Feb 7, 2019
Messages
93
Best answers
1
Reaction score
61
Can you make this without that revescript just like normal for tfs 1.3?
 
OP
Perun

Perun

nems.online
Premium User
Joined
May 1, 2009
Messages
294
Best answers
5
Reaction score
116
Can you make this without that revescript just like normal for tfs 1.3?
Ya but in weekend. Revescript is just movements and talkactrions, you can just ctrl+c ctrl+v these parts of system to movements stepin/stepout + talkaction or globalevent func to start quiz. I can do it but as i said saturday +-
 

Andréew

Humble mapper.
Premium User
Joined
Apr 14, 2015
Messages
611
Best answers
1
Reaction score
892
Location
Sweden
haha wow, this actually seems pretty fun.. might add it to my local project just for fun :) great work!
 

Lucifer

Active Member
Joined
Dec 27, 2014
Messages
144
Best answers
0
Reaction score
31
Location
Sweden
@Perun can u change the script when the event will start to make a teleport to waiting room?
 
Last edited:

Fox Rother

Highly Skilled in Noobing
Premium User
Joined
Aug 10, 2010
Messages
64
Best answers
0
Reaction score
31
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:

View attachment 37249

end[/CODE]
I created and shared this basic and beautiful map, for the use of any member.
Exactly with the amount of sqm that is observed in the demonstrative video.
View attachment 37298
Ain't that unscripted collaboration sweet? 😊😊😊
 
Top