• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

MoveEvent Infinity Rooms - TFS 1.3

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Support Team
Joined
Mar 16, 2017
Messages
894
Solutions
86
Reaction score
865
Location
London
GitHub
MillhioreBT
This was inspired by this thread.

data/scripts/infinityrooms.lua
Lua:
-- Infinity Room Config
local IRConfig = {
    startPos = Position(2887, 1756, 7), -- upper left corner
    tpInAid = 65000, -- actionid for enter teleport
    tpOutAid = 65001, -- actionid for exit teleport
    foodAid = 65002, -- actionid for infinity food (only work with EventCallback)
    maxRoomsPer = { -- 10 x 10 = 100 rooms max
        row = 10,
        col = 10
    },
    items = {
        {1050}, --horizontal wall
        {1049}, --vertical wall
        {1057}, --corner wall
        {1051}, --pole wall
        {426}, --tile train
        {407}, --tile base
        {407, 1484}, --coal basin
        {407, 1387, "teleport"}, --teleport
        {407, 1642, 7159, "foodhuge"}, --food panel
        {407, "Monk"} --training monster name
    },
    map = { -- room drawing mask
        {4,1,1,1,1},
        {2,10,7,10,2},
        {2,7,5,7,2},
        {2,8,6,9,2},
        {2,1,1,1,3}
    }
}

local IRoom, mapDistX, mapDistY = {}, #IRConfig.map[1], #IRConfig.map
IRoom.__index = IRoom
if not IRoomList then
    IRoomList = {}
end

function IRoom.new(pos, fromPos, index)
    local iroom = {}
    setmetatable(iroom, IRoom)
    iroom.pos = pos
    iroom.fromPos = fromPos
    for x = 1, mapDistX do
        for y = 1, mapDistY do
            local tilePos = Position(pos.x+x, pos.y+y, pos.z)
            local tileIndex = IRConfig.map[y][x]
            if tileIndex == 5 then iroom.center = tilePos end
            local lastItem
            for _, it in pairs(IRConfig.items[tileIndex]) do
                local thingType = type(it)
                if thingType == "number" then
                    lastItem = Game.createItem(it, 1, tilePos)
                    if not lastItem then
                        iroom:destroy()
                        debugPrint("[Warning - IRoom::new] the room could not be created correctly.")
                        return
                    end
                elseif thingType == "string" then
                    if it == "teleport" then
                        lastItem:setCustomAttribute("roomIndex", index)
                        lastItem:setAttribute(ITEM_ATTRIBUTE_ACTIONID, IRConfig.tpOutAid)
                    elseif it == "foodhuge" then
                        if EventCallback then
                            lastItem:setAttribute(ITEM_ATTRIBUTE_ACTIONID, IRConfig.foodAid)
                        end
                    else        
                        Game.createMonster(it, tilePos)
                    end
                end
            end
        end
    end
    IRoomList[index] = iroom
    return iroom
end

function IRoom:destroy()
    for x = 1, mapDistX do
        for y = 1, mapDistY do
            local pos = Position(self.pos.x+x, self.pos.y+y, self.pos.z)
            local tile = Tile(pos)
            if tile then
                local thingCount = tile:getThingCount()
                for index = thingCount, 0, -1 do
                    local thing = tile:getThing(index)
                    if thing then
                        if thing:isPlayer() then
                            thing:teleportTo(self.fromPos)
                        else
                            thing:remove()
                        end
                    end
                end
            end
        end
    end
    IRoomList[self.index] = nil
end

local function getNextPosition()
    local x, y, z = IRConfig.startPos.x, IRConfig.startPos.y, IRConfig.startPos.z
    local index, indey, pos = 1, 0, Position(x, y, z)
    for _, iroom in pairs(IRoomList) do
        if iroom.pos ~= pos then
            break
        else
            pos = Position(x + (mapDistX * index), y + (mapDistY * indey), z)
            index = index +1
            if index % IRConfig.maxRoomsPer.row == 0 then
                index, indey = 0, indey + 1
                if indey > IRConfig.maxRoomsPer.col then
                    return
                end
            end
        end
    end
    return pos, index
end

local moveOutTp = MoveEvent()
function moveOutTp.onStepIn(creature, item, position, fromPosition)
    local player = creature:getPlayer()
    if player then
        local roomIndex = item:getCustomAttribute("roomIndex")
        if roomIndex then
            local iroom = IRoomList[roomIndex]
            if iroom then
                player:teleportTo(iroom.fromPos)
                iroom.fromPos:sendMagicEffect(CONST_ME_TELEPORT)
                iroom:destroy()
                return true
            end
        end
    end
    return true
end
moveOutTp:aid(IRConfig.tpOutAid)
moveOutTp:register()

local moveInTp = MoveEvent()
function moveInTp.onStepIn(creature, item, position, fromPosition)
    local player = creature:getPlayer()
    if player then
        local pos, index = getNextPosition()
        if not pos then
            player:teleportTo(fromPosition, false)
            player:sendCancelMessage("There are no free training rooms, try later.")
            return true
        end
        local iroom = IRoom.new(pos, player:getTown():getTemplePosition(), index)
        if iroom then
            iroom.index = index
            player:teleportTo(iroom.center)
            iroom.center:sendMagicEffect(CONST_ME_TELEPORT)
        end
    end
    return true
end
moveInTp:aid(IRConfig.tpInAid)
moveInTp:register()

local foodAction = Action()
function foodAction.onUse(player, item, toPosition, target, fromPosition, isHotkey)
    local condition = player:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)
    if condition and math.floor(condition:getTicks() / 1000 + (10 * 12)) >= 1200 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "You are full.")
    else
        player:feed(120)
        player:say("Mmmm.", TALKTYPE_MONSTER_SAY)
    end
    return true
end
foodAction:aid(IRConfig.foodAid)
foodAction:register()

if EventCallback then
    local ec = EventCallback
    function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
        if item:getActionId() == IRConfig.foodAid then
            return false
        end
        return true
    end
    ec:register(1)
end

In the configuration table you can establish the position from where the rooms are generated and you can also change the id of the items used, for example for the walls, tiles and everything that makes up the room, including the monster that you will use for the training.

Although the name refers to infinity, there is a limit, and that limit can be configured, by default I have left 10 rooms per columns and 10 columns, this means that a maximum of 100 rooms can be generated.

create the portal in your preferred place and set the actionid of this portal with the value stored in the variable: tpInAid = 65000 this will be the one you use to enter to train room

 

Evil Puncker

prolonged absenteeism
TFS Developer
Joined
May 30, 2009
Messages
7,685
Solutions
182
Reaction score
3,476
I really like this script and the idea, but I don't like servers that use this kind of training room because we can't even know how many players are training or not :(
 
Top