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

Crash tfs by nekiro 1.5

jareczekjsp

Member
Joined
Jan 30, 2023
Messages
264
Solutions
1
Reaction score
22
GitHub
Jarek123
Hello Everyone I was have crash can sombody help me ?;

LUA:
#11 0x00005555557a944f in void std::__invoke_impl<void, void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>(std::__invoke_memfun_deref, void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&) ()
#12 0x00005555557a87b3 in std::__invoke_result<void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>::type std::__invoke<void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>(void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&) ()
--Type <RET> for more, q to quit, c to continue without paging--(gdb) backtrace
*, unsigned int))(unsigned int)>::__call<void, , 0ul, 1ul>(std::tuple<>&&, std::_Index_tuple<0ul, 1ul>) ()
#14 0x00005555557a38cd in void std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)>::operator()<, void>() ()
#15 0x000055555579f0ba in void std::__invoke_impl<void, std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)>&>(std::__invoke_other, std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)>&) ()
#16 0x0000555555799b0e in std::enable_if<is_invocable_r_v<void, std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)>&>, void>::type std::__invoke_r<void, std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)>&>(std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)>&) ()
#17 0x0000555555793bc1 in std::_Function_handler<void (), std::_Bind<void (LuaEnvironment::*(LuaEnvironment*, unsigned int))(unsigned int)> >::_M_invoke(std::_Any_data const&) ()
#18 0x000055555589599c in std::function<void ()>::operator()() const ()
#19 0x0000555555895400 in Task::operator()() ()
#20 0x0000555555895648 in Dispatcher::threadMain() ()
#21 0x00005555557f7a4b in void std::__invoke_impl<void, void (Dispatcher::*)(), Dispatcher*>(std::__invoke_memfun_deref, void (Dispatcher::*&&)(), Dispatcher*&&) ()
#22 0x00005555557f788e in std::__invoke_result<void (Dispatcher::*)(), Dispatcher*>::type std::__invoke<void (Dispatcher::*)(), Dispatcher*>(void (Dispatcher::*&&)(), Dispatcher*&&) ()
#23 0x00005555557f74c7 in void std::thread::_Invoker<std::tuple<void (Dispatcher::*)(), Dispatcher*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) ()
#24 0x00005555557f7120 in std::thread::_Invoker<std::tuple<void (Dispatcher::*)(), Dispatcher*> >::operator()() ()
#25 0x00005555557f6980 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (Dispatcher::*)(), Dispatcher*> > >::_M_run() ()
#26 0x00007ffff78d2253 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#10 0x000055555578b4cc in LuaEnvironment::executeTimerEvent(unsigned int) ()
#11 0x00005555557a944f in void std::__invoke_impl<void, void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>(std::__invoke_memfun_deref, void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&) ()
#12 0x00005555557a87b3 in std::__invoke_result<void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>::type std::__invoke<void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>(void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&) ()
--Type <RET> for more, q to quit, c to continue without paging--
#27 0x00007ffff755aac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#28 0x00007ffff75ec850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
(gdb) #0  0x000055555560bba0 in NetworkMessage::getLength() const ()
(gdb) #1  0x0000555555821262 in Protocol::getOutputBuffer(int) ()
(gdb) #2  0x00005555558252e6 in ProtocolGame::writeToOutputBuffer(NetworkMessage const&) ()
(gdb) #3  0x000055555582a123 in ProtocolGame::sendTextMessage(TextMessage const&) ()
(gdb) #4  0x00005555555f9230 in Player::sendTextMessage(TextMessage const&) const ()
(gdb) #5  0x000055555576f95d in LuaScriptInterface::luaPlayerSendTextMessage(lua_State*) ()
(gdb) #6  0x00007ffff7ac4fb7 in ?? () from /lib/x86_64-linux-gnu/libluajit-5.1.so.2
(gdb) #7  0x00007ffff7ad5f13 in lua_pcall ()
(gdb)    from /lib/x86_64-linux-gnu/libluajit-5.1.so.2
Undefined command: "from".  Try "help".
(gdb) #8  0x00005555556eddf5 in LuaScriptInterface::protectedCall(lua_State*, int, int) ()
(gdb) #9  0x00005555556eef46 in LuaScriptInterface::callFunction(int) ()
(gdb) #10 0x000055555578b4cc in LuaEnvironment::executeTimerEvent(unsigned int) ()
(gdb) #11 0x00005555557a944f in void std::__invoke_impl<void, void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>(std::__invoke_memfun_deref, void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&) ()
(gdb) #12 0x00005555557a87b3 in std::__invoke_result<void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>::type std::__invoke<void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&>(void (LuaEnvironment::*&)(unsigned int), LuaEnvironment*&, unsigned int&) ()
(gdb) --Type <RET> for more, q to quit, c to continue without paging--
Undefined command: "--Type".  Try "help".
(gdb)
 
Hello Everyone I was have crash can sombody help me ?;
There is something wrong with network code, that makes it send packets thru not existing connections OR
you have some addEvent in Lua that sendTextMessage to player that is no longer online.
If you don't have 50+ online, you should be able to run engine compiled in debug mode without lags. Then after crash you would get player name and text send in gdb report. Maybe then you will be able to find which addEvent send that message and to what player.
 
This script propobly crash server

look what you thing??

data/scripts/dumy.lua

LUA:
local skills = {
    [31208] = {id = SKILL_SWORD, voc = {4}},
    [31209] = {id = SKILL_AXE, voc = {4}},
    [31210] = {id = SKILL_CLUB, voc = {4}},
    [31211] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [31212] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [31213] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [37935] = {id = SKILL_SWORD, voc = {4}},
    [37936] = {id = SKILL_AXE, voc = {4}},
    [37937] = {id = SKILL_CLUB, voc = {4}},
    [37938] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [37939] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [37940] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [37941] = {id = SKILL_SWORD, voc = {4}},
    [37942] = {id = SKILL_AXE, voc = {4}},
    [37943] = {id = SKILL_CLUB, voc = {4}},
    [37944] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [37945] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [37946] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [31196] = {id = SKILL_SWORD, voc = {4}},
    [31197] = {id = SKILL_AXE, voc = {4}},
    [31198] = {id = SKILL_CLUB, voc = {4}},
    [31199] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [31200] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [31201] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE}
}

local freeDummies = {31214, 31221}
local houseDummies = {31215, 31216, 31217, 31218, 31219, 31220}
local exerciseStorage = 87027
local skillRate = 35
local magicRate = 35

local function start_train(pid, start_pos, itemid, fpos, bonusDummy, dummyId)
    local player = Player(pid)
    if not player then return true end

    if Tile(fpos):getItemById(dummyId) then
        local pos_n = player:getPosition()
        if start_pos:getDistance(pos_n) == 0 and getTilePzInfo(pos_n) then
            local exercise = player:getItemById(itemid, true)
            if exercise and exercise:isItem() and exercise:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                local charges = exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                if charges > 1 then
                    exercise:setAttribute(ITEM_ATTRIBUTE_CHARGES, charges - 1)
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Remaining uses: " .. (charges - 1))
                elseif charges == 1 then
                    exercise:remove()
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training weapon vanished.")
                    player:setStorageValue(exerciseStorage, 0)
                    return true
                else
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "No charges left.")
                    player:setStorageValue(exerciseStorage, 0)
                    return true
                end

                local voc = player:getVocation()
                if skills[itemid].id == SKILL_MAGLEVEL then
                    if not bonusDummy then
                        player:addManaSpent(math.ceil(500 * magicRate))
                    else
                        player:addManaSpent(math.ceil(650 * magicRate) * 2001.1)
                    end
                else
                    if not bonusDummy then
                        player:addSkillTries(skills[itemid].id, 7 * skillRate)
                    else
                        player:addSkillTries(skills[itemid].id, (7 * skillRate) * 1001.1)
                    end
                end

                fpos:sendMagicEffect(CONST_ME_GROUNDSHAKER)
                if skills[itemid].range then
                    pos_n:sendDistanceEffect(fpos, skills[itemid].range)
                end

                addEvent(start_train, voc:getAttackSpeed(), pid, start_pos, itemid, fpos, bonusDummy, dummyId)
                return true
            end
        end
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
        player:setStorageValue(exerciseStorage, 0)
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
        player:setStorageValue(exerciseStorage, 0)
    end
    return true
end

local exerciseTraining = Action()

function exerciseTraining.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local start_pos = player:getPosition()
    if player:getStorageValue(exerciseStorage) == 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already training.")
        return true -- ?? wazne: nie false, by uniknac "You can not use this object"
    end

    if target:isItem() then
        local tid = target:getId()
        if isInArray(houseDummies, tid) or isInArray(freeDummies, tid) then
            if not skills[item.itemid].range and start_pos:getDistance(target:getPosition()) > 1 then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            local isBonus = isInArray(houseDummies, tid)
            start_train(player:getId(), start_pos, item.itemid, target:getPosition(), isBonus, tid)
            player:setStorageValue(exerciseStorage, 1)
        end
    end
    return true
end

-- Rejestracja wszystkich broni
for id = 31196, 31198 do exerciseTraining:id(id) end
for id = 31199, 31201 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 31208, 31210 do exerciseTraining:id(id) end
for id = 31211, 31213 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 37935, 37937 do exerciseTraining:id(id) end
for id = 37938, 37940 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 37941, 37943 do exerciseTraining:id(id) end
for id = 37944, 37946 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end

exerciseTraining:register()

logout.lua

Code:
local exerciseStorage = 87027

function onLogout(player)
    local playerId = player:getId()

    -- Wiadomosc na wylogowanie
    player:say("We fly high, witches!", TALKTYPE_MONSTER_SAY)

    -- Czyszczenie zmiennej globalnej (jesli dotyczy twojego systemu)
    if nextUseStaminaTime and nextUseStaminaTime[playerId] then
        nextUseStaminaTime[playerId] = nil
    end

    -- Zerowanie storage
    player:setStorageValue(exerciseStorage, 0)

    return true
end

login.lua

Code:
    player:registerEvent("ResetExerciseTraining")
 
This script propobly crash server

look what you thing??

data/scripts/dumy.lua

LUA:
local skills = {
    [31208] = {id = SKILL_SWORD, voc = {4}},
    [31209] = {id = SKILL_AXE, voc = {4}},
    [31210] = {id = SKILL_CLUB, voc = {4}},
    [31211] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [31212] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [31213] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [37935] = {id = SKILL_SWORD, voc = {4}},
    [37936] = {id = SKILL_AXE, voc = {4}},
    [37937] = {id = SKILL_CLUB, voc = {4}},
    [37938] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [37939] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [37940] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [37941] = {id = SKILL_SWORD, voc = {4}},
    [37942] = {id = SKILL_AXE, voc = {4}},
    [37943] = {id = SKILL_CLUB, voc = {4}},
    [37944] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [37945] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [37946] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [31196] = {id = SKILL_SWORD, voc = {4}},
    [31197] = {id = SKILL_AXE, voc = {4}},
    [31198] = {id = SKILL_CLUB, voc = {4}},
    [31199] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [31200] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [31201] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE}
}

local freeDummies = {31214, 31221}
local houseDummies = {31215, 31216, 31217, 31218, 31219, 31220}
local exerciseStorage = 87027
local skillRate = 35
local magicRate = 35

local function start_train(pid, start_pos, itemid, fpos, bonusDummy, dummyId)
    local player = Player(pid)
    if not player then return true end

    if Tile(fpos):getItemById(dummyId) then
        local pos_n = player:getPosition()
        if start_pos:getDistance(pos_n) == 0 and getTilePzInfo(pos_n) then
            local exercise = player:getItemById(itemid, true)
            if exercise and exercise:isItem() and exercise:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                local charges = exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                if charges > 1 then
                    exercise:setAttribute(ITEM_ATTRIBUTE_CHARGES, charges - 1)
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Remaining uses: " .. (charges - 1))
                elseif charges == 1 then
                    exercise:remove()
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training weapon vanished.")
                    player:setStorageValue(exerciseStorage, 0)
                    return true
                else
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "No charges left.")
                    player:setStorageValue(exerciseStorage, 0)
                    return true
                end

                local voc = player:getVocation()
                if skills[itemid].id == SKILL_MAGLEVEL then
                    if not bonusDummy then
                        player:addManaSpent(math.ceil(500 * magicRate))
                    else
                        player:addManaSpent(math.ceil(650 * magicRate) * 2001.1)
                    end
                else
                    if not bonusDummy then
                        player:addSkillTries(skills[itemid].id, 7 * skillRate)
                    else
                        player:addSkillTries(skills[itemid].id, (7 * skillRate) * 1001.1)
                    end
                end

                fpos:sendMagicEffect(CONST_ME_GROUNDSHAKER)
                if skills[itemid].range then
                    pos_n:sendDistanceEffect(fpos, skills[itemid].range)
                end

                addEvent(start_train, voc:getAttackSpeed(), pid, start_pos, itemid, fpos, bonusDummy, dummyId)
                return true
            end
        end
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
        player:setStorageValue(exerciseStorage, 0)
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
        player:setStorageValue(exerciseStorage, 0)
    end
    return true
end

local exerciseTraining = Action()

function exerciseTraining.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local start_pos = player:getPosition()
    if player:getStorageValue(exerciseStorage) == 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already training.")
        return true -- ?? wazne: nie false, by uniknac "You can not use this object"
    end

    if target:isItem() then
        local tid = target:getId()
        if isInArray(houseDummies, tid) or isInArray(freeDummies, tid) then
            if not skills[item.itemid].range and start_pos:getDistance(target:getPosition()) > 1 then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            local isBonus = isInArray(houseDummies, tid)
            start_train(player:getId(), start_pos, item.itemid, target:getPosition(), isBonus, tid)
            player:setStorageValue(exerciseStorage, 1)
        end
    end
    return true
end

-- Rejestracja wszystkich broni
for id = 31196, 31198 do exerciseTraining:id(id) end
for id = 31199, 31201 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 31208, 31210 do exerciseTraining:id(id) end
for id = 31211, 31213 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 37935, 37937 do exerciseTraining:id(id) end
for id = 37938, 37940 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 37941, 37943 do exerciseTraining:id(id) end
for id = 37944, 37946 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end

exerciseTraining:register()

logout.lua

Code:
local exerciseStorage = 87027

function onLogout(player)
    local playerId = player:getId()

    -- Wiadomosc na wylogowanie
    player:say("We fly high, witches!", TALKTYPE_MONSTER_SAY)

    -- Czyszczenie zmiennej globalnej (jesli dotyczy twojego systemu)
    if nextUseStaminaTime and nextUseStaminaTime[playerId] then
        nextUseStaminaTime[playerId] = nil
    end

    -- Zerowanie storage
    player:setStorageValue(exerciseStorage, 0)

    return true
end

login.lua

Code:
    player:registerEvent("ResetExerciseTraining")
event could be still active after logout
 
I make with cloude script Like that ,

LUA:
local exerciseStorage = 87027
local exerciseEvents = {} -- Tablica do przechowywania ID eventów dla graczy

function onLogout(player)
    local playerId = player:getId()
   
    -- Anulowanie aktywnego eventu treningowego
    if _G.exerciseEvents and _G.exerciseEvents[playerId] then
        stopEvent(_G.exerciseEvents[playerId])
        _G.exerciseEvents[playerId] = nil
    end
   
    -- Zerowanie storage
    player:setStorageValue(exerciseStorage, 0)
   
    -- Wiadomość na wylogowanie
    player:say("We fly high, witches!", TALKTYPE_MONSTER_SAY)
   
    -- Czyszczenie zmiennej globalnej
    if nextUseStaminaTime and nextUseStaminaTime[playerId] then
        nextUseStaminaTime[playerId] = nil
    end
   
    return true
end


Code:
local skills = {
    [31208] = {id = SKILL_SWORD, voc = {4}},
    [31209] = {id = SKILL_AXE, voc = {4}},
    [31210] = {id = SKILL_CLUB, voc = {4}},
    [31211] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [31212] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [31213] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [37935] = {id = SKILL_SWORD, voc = {4}},
    [37936] = {id = SKILL_AXE, voc = {4}},
    [37937] = {id = SKILL_CLUB, voc = {4}},
    [37938] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [37939] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [37940] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [37941] = {id = SKILL_SWORD, voc = {4}},
    [37942] = {id = SKILL_AXE, voc = {4}},
    [37943] = {id = SKILL_CLUB, voc = {4}},
    [37944] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [37945] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [37946] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE},
    [31196] = {id = SKILL_SWORD, voc = {4}},
    [31197] = {id = SKILL_AXE, voc = {4}},
    [31198] = {id = SKILL_CLUB, voc = {4}},
    [31199] = {id = SKILL_DISTANCE, voc = {3}, range = CONST_ANI_SIMPLEARROW},
    [31200] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_SMALLICE},
    [31201] = {id = SKILL_MAGLEVEL, voc = {1, 2, 3, 4}, range = CONST_ANI_FIRE}
}

local freeDummies = {31214, 31221}
local houseDummies = {31215, 31216, 31217, 31218, 31219, 31220}
local exerciseStorage = 87027
local skillRate = 45
local magicRate = 45

-- Inicjalizacja globalnej tablicy eventów
if not _G.exerciseEvents then
    _G.exerciseEvents = {}
end

local function start_train(pid, start_pos, itemid, fpos, bonusDummy, dummyId)
    local player = Player(pid)
    if not player then
        if _G.exerciseEvents[pid] then
            _G.exerciseEvents[pid] = nil
        end
        return true
    end

    if Tile(fpos):getItemById(dummyId) then
        local pos_n = player:getPosition()
        if start_pos:getDistance(pos_n) == 0 and getTilePzInfo(pos_n) then
            local exercise = player:getItemById(itemid, true)
            if exercise and exercise:isItem() and exercise:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                local charges = exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                if charges > 1 then
                    exercise:setAttribute(ITEM_ATTRIBUTE_CHARGES, charges - 1)
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Remaining uses: " .. (charges - 1))
                elseif charges == 1 then
                    exercise:remove()
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training weapon vanished.")
                    player:setStorageValue(exerciseStorage, 0)
                    if _G.exerciseEvents[pid] then
                        _G.exerciseEvents[pid] = nil
                    end
                    return true
                else
                    player:sendTextMessage(MESSAGE_INFO_DESCR, "No charges left.")
                    player:setStorageValue(exerciseStorage, 0)
                    if _G.exerciseEvents[pid] then
                        _G.exerciseEvents[pid] = nil
                    end
                    return true
                end

                local voc = player:getVocation()
                if skills[itemid].id == SKILL_MAGLEVEL then
                    if not bonusDummy then
                        player:addManaSpent(math.ceil(500 * magicRate))
                    else
                        player:addManaSpent(math.ceil(650 * magicRate) * 1.6)
                    end
                else
                    if not bonusDummy then
                        player:addSkillTries(skills[itemid].id, 7 * skillRate)
                    else
                        player:addSkillTries(skills[itemid].id, (7 * skillRate) * 1.1)
                    end
                end

                fpos:sendMagicEffect(CONST_ME_GROUNDSHAKER)
                if skills[itemid].range then
                    pos_n:sendDistanceEffect(fpos, skills[itemid].range)
                end

                local eventId = addEvent(start_train, voc:getAttackSpeed(), pid, start_pos, itemid, fpos, bonusDummy, dummyId)
                _G.exerciseEvents[pid] = eventId
                return true
            end
        end
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
        player:setStorageValue(exerciseStorage, 0)
        if _G.exerciseEvents[pid] then
            _G.exerciseEvents[pid] = nil
        end
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
        player:setStorageValue(exerciseStorage, 0)
        if _G.exerciseEvents[pid] then
            _G.exerciseEvents[pid] = nil
        end
    end
    return true
end

local exerciseTraining = Action()

function exerciseTraining.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local start_pos = player:getPosition()
    if player:getStorageValue(exerciseStorage) == 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already training.")
        return true -- ?? wazne: nie false, by uniknac "You can not use this object"
    end

    if target:isItem() then
        local tid = target:getId()
        if isInArray(houseDummies, tid) or isInArray(freeDummies, tid) then
            if not skills[item.itemid].range and start_pos:getDistance(target:getPosition()) > 1 then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            local isBonus = isInArray(houseDummies, tid)
            start_train(player:getId(), start_pos, item.itemid, target:getPosition(), isBonus, tid)
            player:setStorageValue(exerciseStorage, 1)
        end
    end
    return true
end

-- Rejestracja wszystkich broni
for id = 31196, 31198 do exerciseTraining:id(id) end
for id = 31199, 31201 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 31208, 31210 do exerciseTraining:id(id) end
for id = 31211, 31213 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 37935, 37937 do exerciseTraining:id(id) end
for id = 37938, 37940 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end
for id = 37941, 37943 do exerciseTraining:id(id) end
for id = 37944, 37946 do exerciseTraining:id(id) exerciseTraining:allowFarUse(true) end

exerciseTraining:register()
What you thing? i safety?
 
I make with cloude script Like that ,

LUA:
local exerciseStorage = 87027
local exerciseEvents = {} -- Tablica do przechowywania ID eventów dla graczy

function onLogout(player)
    local playerId = player:getId()
  
    -- Anulowanie aktywnego eventu treningowego
    if _G.exerciseEvents and _G.exerciseEvents[playerId] then
        stopEvent(_G.exerciseEvents[playerId])
        _G.exerciseEvents[playerId] = nil
    end
  
    -- Zerowanie storage
    player:setStorageValue(exerciseStorage, 0)
  
    -- Wiadomość na wylogowanie
    player:say("We fly high, witches!", TALKTYPE_MONSTER_SAY)
  
    -- Czyszczenie zmiennej globalnej
    if nextUseStaminaTime and nextUseStaminaTime[playerId] then
        nextUseStaminaTime[playerId] = nil
    end
  
    return true
end



What you thing? i safety?
You need to test it, no one will give you 100% answer what went wrong
 
This script propobly crash server

look what you thing??
This addEvent looks safe. You can't find crash reason by picking random Lua files and analysing them. There are too many of them.
Compile engine in debug mode, wait for next crash and read player name and text send from gdb report. Then search for script that player used.
 
Back
Top