• 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!

TFS 1.X+ lamps save house

bpm91

Intermediate OT User
Joined
May 23, 2019
Messages
942
Solutions
7
Reaction score
130
Location
Brazil
YouTube
caruniawikibr
Any way to save lamps and torches inside houses? generally they return to the map editor configuration. tfs 1.5
 
Solution
lib:

Lua:
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
    [2037] = 2038, [2038] = 2037, -- wall lamp
    [2039] = 2040, [2040] = 2039, -- wall lamp
    [2058] = 2059, [2059] = 2058, -- torch bearer
    [2060] = 2061, [2061] = 2060, -- torch bearer
    [2064] = 2065, [2065] = 2064, -- table lamp
    [2066] = 2067, [2067] = 2066, -- wall lamp
    [2068] = 2069, [2069] = 2068, -- wall lamp
    [3943] = 3944, [3944] = 3943, -- torch bearer
    [3945] = 3946, [3946] = 3945, -- torch bearer
    [3947] = 3948, [3948] = 3947, -- wall lamp
    [3949] = 3950, [3950] = 3949, -- wall lamp
    [2041] = 2042, [2042] = 2041, -- candelabrum
    [2057] = 2041, -- candelabrum map
    [2044] = 2045, [2045] = 2044, -- lamp
    [2047] = 2048, [2048] = 2047 --...
lib:

Lua:
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
    [2037] = 2038, [2038] = 2037, -- wall lamp
    [2039] = 2040, [2040] = 2039, -- wall lamp
    [2058] = 2059, [2059] = 2058, -- torch bearer
    [2060] = 2061, [2061] = 2060, -- torch bearer
    [2064] = 2065, [2065] = 2064, -- table lamp
    [2066] = 2067, [2067] = 2066, -- wall lamp
    [2068] = 2069, [2069] = 2068, -- wall lamp
    [3943] = 3944, [3944] = 3943, -- torch bearer
    [3945] = 3946, [3946] = 3945, -- torch bearer
    [3947] = 3948, [3948] = 3947, -- wall lamp
    [3949] = 3950, [3950] = 3949, -- wall lamp
    [2041] = 2042, [2042] = 2041, -- candelabrum
    [2057] = 2041, -- candelabrum map
    [2044] = 2045, [2045] = 2044, -- lamp
    [2047] = 2048, [2048] = 2047 -- candlestick
}, {}

for k, v in pairs(lampTransformIds) do
    reverseLampTransformIds[v] = k
end

function table.size(t)
    local size = 0
    for k, v in pairs(t) do
        size = size + 1
    end
    return size
end

function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] = {'):format(key)
                    doSerialize(v)
                    ret[#ret+1] = ('}%s'):format(comma)
                else
                    ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
                end
            end
        else
            ret[#ret+1] = s
        end
    end
    doSerialize(s)
    return (table.concat(ret) .. (isTable and "}" or ""))
end

function unserialize(str)
    local f = loadstring("return ".. str)
    return f and f() or nil
end

function serializePos(pos)
    return string.format('Position(%d, %d, %d)', pos.x, pos.y, pos.z)
end

function unserializePos(s)
    return Position(s:match("Position%((%d+), (%d+), (%d+)%)"))
end

function dumpLampStates()
    local file = io.open('lamp_states.lua', 'w')
    if file then
        file:write(serialize(wallLamps))
        file:close()
    end
end

function loadLampStates()
    local file = io.open('lamp_states.lua')
    if file then
        wallLamps = unserialize(file:read('*a'))
        if not wallLamps then
            wallLamps = {}
            return
        end
        for serializedPos, state in pairs(wallLamps) do
            local searchState = reverseLampTransformIds[state] or lampTransformIds[state]
            if searchState then
                local position = unserializePos(serializedPos)
                local lamp = Tile(position):getItemById(searchState)
                if lamp then
                    lamp:transform(state)
                end
            end
        end
        file:close()
    else
        io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
    end
end

function in use:
Lua:
-----------------------------------ALL LAMPS THAT MIGHT SAVE-----------------------------------------------------------
local lampWall = Action()
local lamps = {
    [2037] = 2038, [2038] = 2037, -- wall lamp
    [2039] = 2040, [2040] = 2039, -- wall lamp
    [2058] = 2059, [2059] = 2058, -- torch bearer
    [2060] = 2061, [2061] = 2060, -- torch bearer
    [2064] = 2065, [2065] = 2064, -- table lamp
    [2066] = 2067, [2067] = 2066, -- wall lamp
    [2068] = 2069, [2069] = 2068, -- wall lamp
    [3943] = 3944, [3944] = 3943, -- torch bearer
    [3945] = 3946, [3946] = 3945, -- torch bearer
    [3947] = 3948, [3948] = 3947, -- wall lamp
    [3949] = 3950, [3950] = 3949, -- wall lamp
    [2041] = 2042, [2042] = 2041, -- candelabrum
    [2057] = 2041, -- candelabrum map
    [2044] = 2045, [2045] = 2044, -- lamp
    [2047] = 2048, [2048] = 2047 -- candlestick
}
function lampWall.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local lamp = lamps[item:getId()]
    if not lamp then
        return false
    end

    local tile = Tile(toPosition)
    local transformId = lampTransformIds[item:getId()] or reverseLampTransformIds[item:getId()]
    item:transform(transformId)
    if tile and tile:getHouse() then
        wallLamps[serializePos(toPosition)] = transformId -- update lamp state
        dumpLampStates()
    end

    return true
end
for i, v in pairs(lamps) do
    lampWall:id(i)
end
lampWall:register()

globalevent:
Lua:
function onStartup()
    loadLampStates()
end
 
Solution
lib:

Lua:
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
    [2037] = 2038, [2038] = 2037, -- wall lamp
    [2039] = 2040, [2040] = 2039, -- wall lamp
    [2058] = 2059, [2059] = 2058, -- torch bearer
    [2060] = 2061, [2061] = 2060, -- torch bearer
    [2064] = 2065, [2065] = 2064, -- table lamp
    [2066] = 2067, [2067] = 2066, -- wall lamp
    [2068] = 2069, [2069] = 2068, -- wall lamp
    [3943] = 3944, [3944] = 3943, -- torch bearer
    [3945] = 3946, [3946] = 3945, -- torch bearer
    [3947] = 3948, [3948] = 3947, -- wall lamp
    [3949] = 3950, [3950] = 3949, -- wall lamp
    [2041] = 2042, [2042] = 2041, -- candelabrum
    [2057] = 2041, -- candelabrum map
    [2044] = 2045, [2045] = 2044, -- lamp
    [2047] = 2048, [2048] = 2047 -- candlestick
}, {}

for k, v in pairs(lampTransformIds) do
    reverseLampTransformIds[v] = k
end

function table.size(t)
    local size = 0
    for k, v in pairs(t) do
        size = size + 1
    end
    return size
end

function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] = {'):format(key)
                    doSerialize(v)
                    ret[#ret+1] = ('}%s'):format(comma)
                else
                    ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
                end
            end
        else
            ret[#ret+1] = s
        end
    end
    doSerialize(s)
    return (table.concat(ret) .. (isTable and "}" or ""))
end

function unserialize(str)
    local f = loadstring("return ".. str)
    return f and f() or nil
end

function serializePos(pos)
    return string.format('Position(%d, %d, %d)', pos.x, pos.y, pos.z)
end

function unserializePos(s)
    return Position(s:match("Position%((%d+), (%d+), (%d+)%)"))
end

function dumpLampStates()
    local file = io.open('lamp_states.lua', 'w')
    if file then
        file:write(serialize(wallLamps))
        file:close()
    end
end

function loadLampStates()
    local file = io.open('lamp_states.lua')
    if file then
        wallLamps = unserialize(file:read('*a'))
        if not wallLamps then
            wallLamps = {}
            return
        end
        for serializedPos, state in pairs(wallLamps) do
            local searchState = reverseLampTransformIds[state] or lampTransformIds[state]
            if searchState then
                local position = unserializePos(serializedPos)
                local lamp = Tile(position):getItemById(searchState)
                if lamp then
                    lamp:transform(state)
                end
            end
        end
        file:close()
    else
        io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
    end
end

function in use:
Lua:
-----------------------------------ALL LAMPS THAT MIGHT SAVE-----------------------------------------------------------
local lampWall = Action()
local lamps = {
    [2037] = 2038, [2038] = 2037, -- wall lamp
    [2039] = 2040, [2040] = 2039, -- wall lamp
    [2058] = 2059, [2059] = 2058, -- torch bearer
    [2060] = 2061, [2061] = 2060, -- torch bearer
    [2064] = 2065, [2065] = 2064, -- table lamp
    [2066] = 2067, [2067] = 2066, -- wall lamp
    [2068] = 2069, [2069] = 2068, -- wall lamp
    [3943] = 3944, [3944] = 3943, -- torch bearer
    [3945] = 3946, [3946] = 3945, -- torch bearer
    [3947] = 3948, [3948] = 3947, -- wall lamp
    [3949] = 3950, [3950] = 3949, -- wall lamp
    [2041] = 2042, [2042] = 2041, -- candelabrum
    [2057] = 2041, -- candelabrum map
    [2044] = 2045, [2045] = 2044, -- lamp
    [2047] = 2048, [2048] = 2047 -- candlestick
}
function lampWall.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local lamp = lamps[item:getId()]
    if not lamp then
        return false
    end

    local tile = Tile(toPosition)
    local transformId = lampTransformIds[item:getId()] or reverseLampTransformIds[item:getId()]
    item:transform(transformId)
    if tile and tile:getHouse() then
        wallLamps[serializePos(toPosition)] = transformId -- update lamp state
        dumpLampStates()
    end

    return true
end
for i, v in pairs(lamps) do
    lampWall:id(i)
end
lampWall:register()

globalevent:
Lua:
function onStartup()
    loadLampStates()
end
Thanks you a lot

@mano368 how do i save this in globalevents? like <globalevent type="record" name="Lampstate" script="lamps.lua" /> ??
 
Last edited:
in global events,
mine is this

Lua:
function onStartup()

    db.query("TRUNCATE TABLE `players_online`")
    db.asyncQuery("DELETE FROM `guild_wars` WHERE `status` = 0")
    db.asyncQuery("DELETE FROM `players` WHERE `deletion` != 0 AND `deletion` < " .. os.time())
    db.asyncQuery("DELETE FROM `ip_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())
    db.asyncQuery("DELETE FROM `market_history` WHERE `inserted` <= " .. (os.time() - configManager.getNumber(configKeys.MARKET_OFFER_DURATION)))

    -- Move expired bans to ban history
    local resultId = db.storeQuery("SELECT * FROM `account_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())
    if resultId ~= false then
        repeat
            local accountId = result.getNumber(resultId, "account_id")
            db.asyncQuery("INSERT INTO `account_ban_history` (`account_id`, `reason`, `banned_at`, `expired_at`, `banned_by`) VALUES (" .. accountId .. ", " .. db.escapeString(result.getString(resultId, "reason")) .. ", " .. result.getNumber(resultId, "banned_at") .. ", " .. result.getNumber(resultId, "expires_at") .. ", " .. result.getNumber(resultId, "banned_by") .. ")")
            db.asyncQuery("DELETE FROM `account_bans` WHERE `account_id` = " .. accountId)
        until not result.next(resultId)
        result.free(resultId)
    end

    -- Check house auctions
    local resultId = db.storeQuery("SELECT `id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `bid_end` != 0 AND `bid_end` < " .. os.time())
    if resultId ~= false then
        repeat
            local house = House(result.getNumber(resultId, "id"))
            if house then
                local highestBidder = result.getNumber(resultId, "highest_bidder")
                local balance = result.getNumber(resultId, "balance")
                local lastBid = result.getNumber(resultId, "last_bid")
                if balance >= lastBid then
                    db.query("UPDATE `players` SET `balance` = " .. (balance - lastBid) .. " WHERE `id` = " .. highestBidder)
                    house:setOwnerGuid(highestBidder)
                end
                db.asyncQuery("UPDATE `houses` SET `last_bid` = 0, `bid_end` = 0, `highest_bidder` = 0, `bid` = 0 WHERE `id` = " .. house:getId())
            end
        until not result.next(resultId)
        result.free(resultId)
    end

    -- store towns in database
    db.query("TRUNCATE TABLE `towns`")
    for i, town in ipairs(Game.getTowns()) do
        local position = town:getTemplePosition()
        db.query("INSERT INTO `towns` (`id`, `name`, `posx`, `posy`, `posz`) VALUES (" .. town:getId() .. ", " .. db.escapeString(town:getName()) .. ", " .. position.x .. ", " .. position.y .. ", " .. position.z .. ")")
    end
     loadLampStates()
end

loadLampStates()
in end
 
Back
Top