• 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+ Wall torches don't save their stat

jackl90

Member
Joined
Jul 25, 2017
Messages
249
Reaction score
12
Is there any way to save lamps or torches inside houses? I tried to add tile house to the walls, but it didn't work.
 
Solution
Alright, I got tired of having to back and forth slowly on here so I decided to just put it on my server to fix it. This seems to work for me just fine and i tested 2 types of lamps and different combinations to make sure it works.
Replace your lib file with this and it should be fine (remember to replace lampTransformIds with your own ids at the top of the script).
Lua:
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
    [3947] = 3948,
    [2039] = 2040
}, {}

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...
Yeah, you must've accidentally replaced the last line.
Add loadLampStates() at the very end of the file, so it calls that function when the file is loaded.
If you'd like to limit it only to startup (since that will also execute if you do /reload global), use an onStartup script in globalevents like so:
Lua:
function onStartup()
    loadLampStates()
end
Make sure you register it to globalevents.xml as well, just copy the format of the other startup entry and rename it.
 
I add now
Lua:
function loadLampStates()
    local file = io.open('lamp_states.lua')
    print('Loading lamp states')
    if file then
        wallLamps = unserialize(file:read('*a'))
        print('Previous data stored, size: '.. #wallLamps)
        for serializedPos, state in pairs(wallLamps) do
            local flippedState = lampTransformIds[state] or reverseLampTransformIds[state]
            local position = unserializePos(serializedPos)
            print(string.format('Restoring previous state of lamp at %s to id %d', position, flippedState))
            Tile(position):getItemById(state):transform(flippedState)
        end
    else
        print('Previous data not found, creating an empty file (no data will be loaded).')
        io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
    end
end
loadLampStates()

and i created a file inside globalevents folder called lamp_states
Lua:
function onStartup()
    loadLampStates()
end

also in globalevents.xml i add this
<globalevent type="startup" name="lamp_states" script="lamp_states.lua"/>

i got this on console

Code:
>> Loading script systems
Loading lamp states
Previous data stored, size: 0
Restoring previous state of lamp at table: 0x3843fb58 to id 5907

Lua Script Error: [Main Interface]
data/global.lua
data/lib/lamp_states.lua:76: attempt to index a nil value
stack traceback:
        [C]: in function '__index'
        data/lib/lamp_states.lua:76: in function 'loadLampStates'
        data/lib/lamp_states.lua:83: in main chunk
        [C]: in function 'dofile'
        data/lib/lib.lua:3: in main chunk
        [C]: in function 'dofile'
        data/global.lua:1: in main chunk
[Warning - ScriptingManager::loadScriptSystems] Can not load data/global.lua
 
Try this out and send me the output as well:
Lua:
function loadLampStates()
    local file = io.open('lamp_states.lua')
    print('Loading lamp states')
    if file then
        wallLamps = unserialize(file:read('*a'))
        print('Previous data stored, size: '.. table.size(wallLamps))
        for serializedPos, state in pairs(wallLamps) do
            local defaultState = reverseLampTransformIds[state]
            if defaultState then
                local position = unserializePos(serializedPos)
                print(string.format('Restoring previous state of lamp at %s to id %d', serializedPos, defaultState))
                local lamp = Tile(position):getItemById(defaultState)
                if lamp then
                    lamp:transform(state)
                else
                    print('Lamp could not be found (Search ID: '.. defaultState)
                end
            else
                print('Lamp is already in default state, skipping.')
            end
        end
    else
        print('Previous data not found, creating an empty file (no data will be loaded).')
        io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
    end
end
 
now this, working...
Code:
Loading lamp states
Previous data stored, size: 0
Lamp is already in default state, skipping.
Restoring previous state of lamp at Position(32410, 32223, 7) to id 5907


This appear on console when i use more than 1 lamp for example.
Code:
Loading lamp states

Lua Script Error: [GlobalEvent Interface]
data/globalevents/scripts/lamp_states.lua:onStartup
data/lib/lamp_states.lua:71: attempt to get length of global 'wallLamps' (a nil value)
stack traceback:
        [C]: in function '__len'
        data/lib/lamp_states.lua:71: in function 'loadLampStates'
        data/globalevents/scripts/lamp_states.lua:2: in function <data/globalevents/scripts/lamp_states.lua:1>
 
It doesn't use the # operator anymore to check for table size, I thought I edited my post fast enough, but I guess not.
Anyways the problem is loading the table for some reason, post lamp_states.lua from the main folder (not the lib or action file)
 
Code:
{["Position(32410, 32219, 7)"] = 5908, ["Position(32410, 32223, 7)"] = 5908, ["Position(32410, 32227, 7)"] = 5908, ["Position(32402, 32222, 7)"] = 5907} ["Position(32410, 32223, 7)"] = 5908}
 
Alright, I got tired of having to back and forth slowly on here so I decided to just put it on my server to fix it. This seems to work for me just fine and i tested 2 types of lamps and different combinations to make sure it works.
Replace your lib file with this and it should be fine (remember to replace lampTransformIds with your own ids at the top of the script).
Lua:
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
    [3947] = 3948,
    [2039] = 2040
}, {}

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
 
Solution
Alright, I got tired of having to back and forth slowly on here so I decided to just put it on my server to fix it. This seems to work for me just fine and i tested 2 types of lamps and different combinations to make sure it works.
Replace your lib file with this and it should be fine (remember to replace lampTransformIds with your own ids at the top of the script).
Lua:
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
    [3947] = 3948,
    [2039] = 2040
}, {}

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

now is working good, thanks so much !

just a question, I was thinking here... the action script maybe, is possible check if is house tile to work this system? summarizing only used lamps inside the houses.
 
now is working good, thanks so much !

just a question, I was thinking here... the action script maybe, is possible check if is house tile to work this system? summarizing only used lamps inside the houses.
Easy, use this:
Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tile = Tile(toPosition)
    if tile and tile:isHouse() then
        local transformId = lampTransformIds[item:getId()] or reverseLampTransformIds[item:getId()]
        item:transform(transformId)
        wallLamps[serializePos(toPosition)] = transformId -- update lamp state
        dumpLampStates()
    end
    return true
end
 
i got this console msg when i use the lamp
Code:
Lua Script Error: [Action Interface]
data/actions/scripts/others/lamp_states.lua:onUse
data/actions/scripts/others/lamp_states.lua:3: attempt to call method 'isHouse' (a nil value)
stack traceback:
        [C]: in function 'isHouse'
        data/actions/scripts/others/lamp_states.lua:3: in function <data/actions/scripts/others/lamp_states.lua:1>
 
work, but now, i cant turn on or turn off normally lamp outside the houses
:mad: I feel dumb today.
Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    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
 
Back
Top