• 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+ HP/MP BUFF No error - Crash.

Svira

Active Member
Joined
Jan 27, 2008
Messages
268
Solutions
11
Reaction score
36
Hello dear community, I am creating a code to increase HP and MP for 1 hour, but if the player uses the item and then remains logged out, a crash occurs after some time? how to prevent it?

CODE:

Lua:
local BOOST_DURATION = 3600 --  w sekundach
local STORAGE_VALUE = 224411
local BOOST_EVENT_NAME = "profession_boost"

function onUse(cid, item, fromPosition, itemEx, toPosition)
    local player = Player(cid)
    if not player then
        return false
    end

    if player:getStorageValue(STORAGE_VALUE) >= os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a profession-specific boost!')
        return true
    end

 
    local oldHealth = player:getHealth()
    local oldMana = player:getMana()


    local hpBoost = Condition(CONDITION_ATTRIBUTES)
    hpBoost:setParameter(CONDITION_PARAM_SUBID, 31)
    hpBoost:setParameter(CONDITION_PARAM_TICKS, BOOST_DURATION * 1000)
    hpBoost:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, 200)
    hpBoost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
    player:addCondition(hpBoost)

 
    local manaBoost = Condition(CONDITION_ATTRIBUTES)
    manaBoost:setParameter(CONDITION_PARAM_SUBID, 32)
    manaBoost:setParameter(CONDITION_PARAM_TICKS, BOOST_DURATION * 1000)
    manaBoost:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, 200)
    manaBoost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
    player:addCondition(manaBoost)

    player:setStorageValue(STORAGE_VALUE, os.time() + BOOST_DURATION)
    Item(item.uid):remove(1)

    -- Wysłanie informacji o przyznanym boost
    local newHealth = player:getMaxHealth()
    local newMana = player:getMaxMana()
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a profession-specific boost for the next hour! Your maximum hit points and mana points have been increased by 200%. Your health was ' .. oldHealth .. ' and now is ' .. newHealth .. '. Your mana was ' .. oldMana .. ' and now is ' .. newMana .. '. Enjoy your adventures!')

    
    local stopEventFunc
    stopEventFunc = function()
        if player:getStorageValue(STORAGE_VALUE) >= os.time() then
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has expired!')
            player:removeCondition(CONDITION_ATTRIBUTES, CONDITION_PARAM_SUBID, 31)
            player:removeCondition(CONDITION_ATTRIBUTES, CONDITION_PARAM_SUBID, 32)
            player:setStorageValue(STORAGE_VALUE, 0)
            stopEvent(BOOST_EVENT_NAME)
        end
    end
    addEvent(stopEventFunc, BOOST_DURATION * 1000, BOOST_EVENT_NAME)

    return true
end

function onLogout(player)
if not player then
        return true
    end
    local playerId = player:getId()
    local storageValue = player:getStorageValue(STORAGE_VALUE)
    if storageValue > 0 then
        local remainingTime = storageValue - os.time()
        player:setStorageValue(STORAGE_VALUE, remainingTime)
        stopEvent(BOOST_EVENT_NAME)
    end
    return true
end

function onLogin(player)
    local playerId = player:getId()
    local storageValue = player:getStorageValue(STORAGE_VALUE)
    if storageValue > 0 then
        local remainingTime = storageValue - os.time()
        if remainingTime > 0 then
            local hpBoost = Condition(CONDITION_ATTRIBUTES)
            hpBoost:setParameter(CONDITION_PARAM_SUBID, 31)
            hpBoost:setParameter(CONDITION_PARAM_TICKS, remainingTime * 1000)
            hpBoost:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, 200)
            hpBoost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
            player:addCondition(hpBoost)

            local manaBoost = Condition(CONDITION_ATTRIBUTES)
            manaBoost:setParameter(CONDITION_PARAM_SUBID, 32)
            manaBoost:setParameter(CONDITION_PARAM_TICKS, remainingTime * 1000)
            manaBoost:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, 200)
            manaBoost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
            player:addCondition(manaBoost)


            addEvent(function()
                if player:getStorageValue(STORAGE_VALUE) >= os.time() then
                    player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has expired!')
                    player:removeCondition(CONDITION_ATTRIBUTES, CONDITION_PARAM_SUBID, 31)
                    player:removeCondition(CONDITION_ATTRIBUTES, CONDITION_PARAM_SUBID, 32)
                    player:setStorageValue(STORAGE_VALUE, 0)
                end
            end, remainingTime * 1000)
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has been resumed for the remaining time!')
        else
            player:setStorageValue(STORAGE_VALUE, 0)
        end
    end
    return true
end
 
Solution
now is good? @Mateus Robeerto
actions:

Lua:
local config = {
    boostDuration = 3600,                -- Boost duration in seconds
    storageValue = 224411,             -- Unique key to store boost expiration time
    hpSubId = 31,                      -- SubID for HP boost
    mpSubId = 32,                      -- SubID for MP boost
    hpBoostPercent = 200,              -- Percentage increase of HP
    mpBoostPercent = 200,              -- Percentage increase of MP
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(config.storageValue) > os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a specific boost from your profession!')...
You have to check if player still exists in events. Event will still happen even if player has logged out. So only execute event if player still exists.
 
You have to check if player still exists in events. Event will still happen even if player has logged out. So only execute event if player still exists.
can you give me more advice? I have in my code:
Lua:
if not player then
        return true
    end
now there are no more crashes but there is server lag and it throws all logged in players with error 10054 (Client) in the console there are no errors.
 
I took your script, made some corrections, and improved it. I tested it with several accounts, clicked the item, disconnected, and logged in with another account. Nothing happened, no server crash, everything was fine. I logged back in, clicked the item, waited for 30 seconds, and everything returned to normal. (I set it to 30 to test it). It seems to be working. So, it's important to test it there and comment here if there were any errors or if it didn't work.

Lua:
local config = {
    boostDuration = 3600, -- in seconds
    storageValue = 224411,
    hpSubId = 31,
    mpSubId = 32,
    hpBoostPercent = 200, -- HP increase percentage
    mpBoostPercent = 200  -- percentage increase in MP
}

function onUse(player, item, fromPosition, itemEx, toPosition)
    if player:getStorageValue(config.storageValue) > os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a profession-specific boost!')
        return true
    end

    applyBoost(player, config.hpSubId, config.boostDuration, config.hpBoostPercent)
    applyBoost(player, config.mpSubId, config.boostDuration, config.mpBoostPercent)

    player:setStorageValue(config.storageValue, os.time() + config.boostDuration)
    Item(item.uid):remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a profession-specific boost for the next hour!' ..
        ' Your maximum hit points and mana points have been increased by ' .. config.hpBoostPercent .. '%.')
    
    return true
end

function onLogout(player)
    updateStorageOnLogout(player, config.storageValue)
    return true
end

function onLogin(player)
    resumeBoostOnLogin(player, config)
    return true
end

function applyBoost(player, subId, durationInSeconds, percent)
    local boost = Condition(CONDITION_ATTRIBUTES)
    boost:setParameter(CONDITION_PARAM_SUBID, subId)
    boost:setParameter(CONDITION_PARAM_TICKS, durationInSeconds * 1000)
    boost:setParameter(subId == config.hpSubId and CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT or CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, percent)
    boost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
    player:addCondition(boost)
end

function updateStorageOnLogout(player, storageKey)
    local storageValue = player:getStorageValue(storageKey)
    local remainingTime = storageValue - os.time()
    if remainingTime > 0 then
        player:setStorageValue(storageKey, remainingTime)
    else
        player:setStorageValue(storageKey, 0)
    end
end

function resumeBoostOnLogin(player, cfg)
    local storageValue = player:getStorageValue(cfg.storageValue)
    if storageValue > 0 then
        local remainingTime = storageValue
        if remainingTime > 0 then
            applyBoost(player, cfg.hpSubId, remainingTime, cfg.hpBoostPercent)
            applyBoost(player, cfg.mpSubId, remainingTime, cfg.mpBoostPercent)
            player:setStorageValue(cfg.storageValue, os.time() + remainingTime)
            addEvent(expireBoost, remainingTime * 1000, player:getId(), cfg)
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has been resumed for the remaining time!')
        else
            player:setStorageValue(cfg.storageValue, 0)
        end
    end
end

function expireBoost(playerId, cfg)
    local player = Player(playerId)
    if player and player:getStorageValue(cfg.storageValue) > 0 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has expired!')
        player:removeCondition(CONDITION_ATTRIBUTES, cfg.hpSubId)
        player:removeCondition(CONDITION_ATTRIBUTES, cfg.mpSubId)
        player:setStorageValue(cfg.storageValue, 0)
    end
end
Post automatically merged:

what's your tfs? version? I recommend you use revscripts which is much better..
 
Last edited:
Post automatically merged:

what's your tfs? version? I recommend you use revscripts which is much better..


I'm using realots 7.7 but I have all the features from tfs 1.2.
Now tell me, can I keep it all in actions or split it between actions and creaturescript?
 
I'm using realots 7.7 but I have all the features from tfs 1.2.
Now tell me, can I keep it all in actions or split it between actions and creaturescript?
Here this works, tested OK.
However this is revscript, so if you have it just drag&drop into your "data/scripts", if not, remove the local action = Action(),local login etc....

Lua:
local config = {
    duration = 3600,
    storage = 22411,
}

local function stopBoost(playerID)
    local player = Player(playerID)
    if not player then
        return false
    end
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has expired!')
    player:removeCondition(CONDITION_ATTRIBUTES, CONDITION_PARAM_SUBID, 31)
    player:removeCondition(CONDITION_ATTRIBUTES, CONDITION_PARAM_SUBID, 32)
    player:setStorageValue(config.storage, 0)
end


local function startBoost(playerId, time)
    local player = Player(playerId)
    if not player then
        return false
    end

    local oldHealth = player:getHealth()
    local oldMana = player:getMana()
    local hpBoost = Condition(CONDITION_ATTRIBUTES)
    hpBoost:setParameter(CONDITION_PARAM_SUBID, 31)
    hpBoost:setParameter(CONDITION_PARAM_TICKS, time * 1000)
    hpBoost:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, 200)
    hpBoost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
    player:addCondition(hpBoost)

    local manaBoost = Condition(CONDITION_ATTRIBUTES)
    manaBoost:setParameter(CONDITION_PARAM_SUBID, 32)
    manaBoost:setParameter(CONDITION_PARAM_TICKS, time * 1000)
    manaBoost:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, 200)
    manaBoost:setParameter(CONDITION_PARAM_BUFF_SPELL, true)
    player:addCondition(manaBoost)

    player:setStorageValue(config.storage, os.time() + time)
    local newHealth = player:getMaxHealth()
    local newMana = player:getMaxMana()
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a profession-specific boost for the next hour! Your maximum hit points and mana points have been increased by 200%. Your health was ' .. oldHealth .. ' and now is ' .. newHealth .. '. Your mana was ' .. oldMana .. ' and now is ' .. newMana .. '. Enjoy your adventures!')
end

local action = Action()
function action.onUse(cid, item, fromPosition, itemEx, toPosition)
    local player = Player(cid)
    if not player then
        return false
    end
    local playerId = player:getId()
    if player:getStorageValue(config.storage) >= os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a profession-specific boost!')
        return true
    end
    Item(item.uid):remove(1)
    startBoost(playerId,config.duration)
    addEvent(stopBoost,  config.duration * 1000, playerId)
    return true
end
action:id(26961) --- REGISTER YOUR ITEM ID HERE, OR CHANGE TO action:aid(ACTION ID)
action:register()


local logout = CreatureEvent("hpmpBoost_logout")
logout:type("logout")
function logout.onLogout(player)
    if not player then
        return true
    end
    local remainingTime = player:getStorageValue(config.storage)
    local currentTime = os.time()
    if remainingTime > currentTime then
        local remainingTicks = remainingTime - currentTime
        player:setStorageValue(config.storage, remainingTicks)
    end
    return true
end
logout:register()


local login = CreatureEvent("hpmpBoost_login")
login:type("login")
function login.onLogin(player)
    local playerId = player:getId()
    local remainingTime = player:getStorageValue(config.storage)
    if remainingTime > 0 then
            startBoost(playerId,remainingTime)
            addEvent(stopBoost, remainingTime * 1000, playerId)
            addEvent(function()
                player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your profession-specific boost has been resumed for the remaining time of '..remainingTime..' seconds!')
            end, 500)

    end
    return true
end
login:register()
 
I'm using realots 7.7 but I have all the features from tfs 1.2.
Now tell me, can I keep it all in actions or split it between actions and creaturescript?
It's definitely possible. I just tested everything perfectly, keeping everything separate. Give it a try.

actions
teste.lua
Lua:
local config = {
    boostDuration = 3600,                -- Boost duration in seconds
    storageValue = 224411,             -- Unique key to store boost expiration time
    hpSubId = 31,                      -- SubID for HP boost
    mpSubId = 32,                      -- SubID for MP boost
    hpBoostPercent = 200,              -- Percentage increase of HP
    mpBoostPercent = 200,              -- Percentage increase of MP
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(config.storageValue) > os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a specific boost from your profession!')
        return true
    end

    applyBoost(player, config.hpSubId, config.boostDuration, config.hpBoostPercent)
    applyBoost(player, config.mpSubId, config.boostDuration, config.mpBoostPercent)

    player:setStorageValue(config.storageValue, os.time() + config.boostDuration)
    item:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a specific profession boost for the next ' .. config.boostDuration .. ' seconds! Your maximum health points and mana points have been increased by ' .. config.hpBoostPercent .. '%.')

    addEvent(expireBoost, config.boostDuration * 1000, player:getId(), config.hpSubId, config.mpSubId, config.storageValue)

    return true
end

function applyBoost(player, subId, durationInSeconds, percent)
    local boostCondition = player:getCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, subId)
    if boostCondition then
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, subId)
    end

    boostCondition = Condition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT)
    boostCondition:setParameter(CONDITION_PARAM_SUBID, subId)
    boostCondition:setParameter(CONDITION_PARAM_TICKS, durationInSeconds * 1000)
    if subId == config.hpSubId then
        boostCondition:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, percent)
    else
        boostCondition:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, percent)
    end
    boostCondition:setParameter(CONDITION_PARAM_BUFF_SPELL, true)

    player:addCondition(boostCondition)
end

function expireBoost(playerId, hpSubId, mpSubId, storageValue)
    local player = Player(playerId)
    if player then
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, hpSubId)
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, mpSubId)
        player:setStorageValue(storageValue, 0)
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your specific profession boost has expired!')

        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost effect has ended.')
    end
end

creaturescript
teste.lua
Lua:
local config = {
    storageValue = 224411,
    boostDuration = 3600,
}

function formatTime(seconds)
    local minutes = math.floor(seconds / 60)
    seconds = seconds % 60
    return string.format("%d minute(s) and %d second(s)", minutes, seconds)
end

function onLogout(player)
    return true
end

function onLogin(player)
    local storedTime = player:getStorageValue(config.storageValue)
    local currentTime = os.time()

    if storedTime > currentTime then
        local remainingTime = storedTime - currentTime
        local timeString = formatTime(remainingTime)

        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost is active. Remaining time: ' .. timeString)

        return true
    else
        local lastLogout = player:getLastLogout()
        if lastLogout == 0 then
            lastLogout = currentTime
        end

        local boostDuration = os.difftime(currentTime, lastLogout)

        if boostDuration >= config.boostDuration then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost has expired.')
        end

        return true
    end
end

A single file that can be pulled directly from the normal file... everything is working, tested it all. And according to the message sent about the expired time, it's all set!

XML:
<event type="logout" name="Logout1" script="teste.lua" />
<event type="login" name="Login2" script="teste.lua" />
 
It's definitely possible. I just tested everything perfectly, keeping everything separate. Give it a try.

actions
teste.lua
Lua:
local config = {
    boostDuration = 3600,                -- Boost duration in seconds
    storageValue = 224411,             -- Unique key to store boost expiration time
    hpSubId = 31,                      -- SubID for HP boost
    mpSubId = 32,                      -- SubID for MP boost
    hpBoostPercent = 200,              -- Percentage increase of HP
    mpBoostPercent = 200,              -- Percentage increase of MP
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(config.storageValue) > os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a specific boost from your profession!')
        return true
    end

    applyBoost(player, config.hpSubId, config.boostDuration, config.hpBoostPercent)
    applyBoost(player, config.mpSubId, config.boostDuration, config.mpBoostPercent)

    player:setStorageValue(config.storageValue, os.time() + config.boostDuration)
    item:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a specific profession boost for the next ' .. config.boostDuration .. ' seconds! Your maximum health points and mana points have been increased by ' .. config.hpBoostPercent .. '%.')

    addEvent(expireBoost, config.boostDuration * 1000, player:getId(), config.hpSubId, config.mpSubId, config.storageValue)

    return true
end

function applyBoost(player, subId, durationInSeconds, percent)
    local boostCondition = player:getCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, subId)
    if boostCondition then
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, subId)
    end

    boostCondition = Condition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT)
    boostCondition:setParameter(CONDITION_PARAM_SUBID, subId)
    boostCondition:setParameter(CONDITION_PARAM_TICKS, durationInSeconds * 1000)
    if subId == config.hpSubId then
        boostCondition:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, percent)
    else
        boostCondition:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, percent)
    end
    boostCondition:setParameter(CONDITION_PARAM_BUFF_SPELL, true)

    player:addCondition(boostCondition)
end

function expireBoost(playerId, hpSubId, mpSubId, storageValue)
    local player = Player(playerId)
    if player then
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, hpSubId)
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, mpSubId)
        player:setStorageValue(storageValue, 0)
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your specific profession boost has expired!')

        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost effect has ended.')
    end
end

creaturescript
teste.lua
Lua:
local config = {
    storageValue = 224411,
    boostDuration = 3600,
}

function formatTime(seconds)
    local minutes = math.floor(seconds / 60)
    seconds = seconds % 60
    return string.format("%d minute(s) and %d second(s)", minutes, seconds)
end

function onLogout(player)
    return true
end

function onLogin(player)
    local storedTime = player:getStorageValue(config.storageValue)
    local currentTime = os.time()

    if storedTime > currentTime then
        local remainingTime = storedTime - currentTime
        local timeString = formatTime(remainingTime)

        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost is active. Remaining time: ' .. timeString)

        return true
    else
        local lastLogout = player:getLastLogout()
        if lastLogout == 0 then
            lastLogout = currentTime
        end

        local boostDuration = os.difftime(currentTime, lastLogout)

        if boostDuration >= config.boostDuration then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost has expired.')
        end

        return true
    end
end

A single file that can be pulled directly from the normal file... everything is working, tested it all. And according to the message sent about the expired time, it's all set!

XML:
<event type="logout" name="Logout1" script="teste.lua" />
<event type="login" name="Login2" script="teste.lua" />


Testing...
 
@Svira never pass a userobject/userdata to an "addEvent" function. This is what caused your server to crash. You are basically expecting the "event" to remove something from a non-existent player, which is why it crashes.
 
@Mateus Robeerto
There is no crash anymore but:
1. storage "breaks down"
2. Hp/MP does not return to previous values.

from client:
afterlogin:
17:15 Your specific profession boost has expired.
onlook:
17:15 You see yourself. You are an elite knight.
Awaken: Awakened
Vitality BUFF: Activated - -1:01 - 200% hp / mp

as you can see, storage has a negative value, the time shows minus 1 minute and 1 second

onlook script:

Lua:
if awakenStorageValue == 1 then
            awakenState = "Awakened"
        end

        -- Vitaly BUFF
        local VITALY_BUFF_STORAGE = 224411
        local buffState = "Not Activated"
        local buffStorageValue = thing:getStorageValue(VITALY_BUFF_STORAGE)
        local buffInfo = ""
        if buffStorageValue == -1 or buffStorageValue == 0 then
            buffState = "Not Activated"
        elseif buffStorageValue > 0 then
            buffState = "Activated"
            local remainingTime = buffStorageValue - os.time()
            local hours = math.floor(remainingTime / 3600)
            local minutes = math.floor((remainingTime % 3600) / 60)
            buffInfo = string.format(" - %02d:%02d - 200%% hp / mp", hours, minutes)
        end
 
Sorry, I forgot to mention about the time expiration and storage reset. So please look for that line and add it below, then restart the server and test it. Enjoy!
look for this line
Lua:
if boostDuration >= config.boostDuration then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost has expired.')
          
        end

change to.
Lua:
if boostDuration >= config.boostDuration then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost has expired.')
            player:setStorageValue(config.storageValue, 0)
        end
 
now is good? @Mateus Robeerto
actions:

Lua:
local config = {
    boostDuration = 3600,                -- Boost duration in seconds
    storageValue = 224411,             -- Unique key to store boost expiration time
    hpSubId = 31,                      -- SubID for HP boost
    mpSubId = 32,                      -- SubID for MP boost
    hpBoostPercent = 200,              -- Percentage increase of HP
    mpBoostPercent = 200,              -- Percentage increase of MP
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(config.storageValue) > os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a specific boost from your profession!')
        return true
    end

    applyBoost(player, config.hpSubId, config.boostDuration, config.hpBoostPercent)
    applyBoost(player, config.mpSubId, config.boostDuration, config.mpBoostPercent)

    player:setStorageValue(config.storageValue, os.time() + config.boostDuration)
    item:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a specific profession boost for the next 1h! Your maximum health points and mana points have been increased by ' .. config.hpBoostPercent .. '%.')

    addEvent(expireBoost, config.boostDuration * 1000, player:getId(), config.hpSubId, config.mpSubId, config.storageValue)

    return true
end

function applyBoost(player, subId, durationInSeconds, percent)
    local boostCondition = player:getCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, subId)
    if boostCondition then
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, subId)
    end

    boostCondition = Condition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT)
    boostCondition:setParameter(CONDITION_PARAM_SUBID, subId)
    boostCondition:setParameter(CONDITION_PARAM_TICKS, durationInSeconds * 1000)
    if subId == config.hpSubId then
        boostCondition:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, percent)
    else
        boostCondition:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, percent)
    end
    boostCondition:setParameter(CONDITION_PARAM_BUFF_SPELL, true)

    player:addCondition(boostCondition)
end

function expireBoost(playerId, hpSubId, mpSubId, storageValue)
    local player = Player(playerId)
    if player then
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, hpSubId)
        player:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, mpSubId)
        -- player:setStorageValue(storageValue, 0)
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your specific profession boost has expired!')
        player:setStorageValue(config.storageValue, 0)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost effect has ended.')
    end
end
creature:

Code:
local config = {
    storageValue = 224411,
    boostDuration = 3600,
}

function formatTime(seconds)
    local minutes = math.floor(seconds / 60)
    seconds = seconds % 60
    return string.format("%d minute(s) and %d second(s)", minutes, seconds)
end

function onLogout(player)
    return true
end

function onLogin(player)
    local storedTime = player:getStorageValue(config.storageValue)
    local currentTime = os.time()

    if storedTime > currentTime then
        local remainingTime = storedTime - currentTime
        local timeString = formatTime(remainingTime)

        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost is active. Remaining time: ' .. timeString)

        return true
    else
        local lastLogout = player:getLastLogout()
        if lastLogout == 0 then
            lastLogout = currentTime
        end

        local boostDuration = os.difftime(currentTime, lastLogout)

        if boostDuration >= config.boostDuration then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost has expired.')
            player:setStorageValue(config.storageValue, 0)
        end

        return true
    end
end
 
Solution
Yes, and it's just a matter of testing. I'll test it here too..
Post automatically merged:

The HP and mana return to normal after the specified time has expired.
Another 2 errors:
When a player dies, he loses the bonus and the storage is retained. (need edit on_death i know)
When a player is offline and storage expires, HP and MP remain with the bonus after logging in until death. (there idk ;o)
 
The problem has been resolved. Just log out and log back in, wait a few seconds, and your HP and MP will return, okay? Also, after death, you won't lose the bonus; it will remain active. If the time expires, your HP and MP will return to normal, all okay.

If it's 2x, it's 100% HP and MP; if it's 3x, it's 200% and so on.
Actions.

Lua:
local config = {
    boostDuration = 3600,           -- Boost duration in seconds
    storageValue = 224411,           -- Unique key to store boost expiration time
    healthMultiplier = 3,            -- Health multiplier for 200% bonus
    manaMultiplier = 3,              -- Mana multiplier for 200% bonus
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(config.storageValue) > os.time() then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You already have a specific boost from your profession!')
        return true
    end

    local maxHealth = player:getMaxHealth()
    local maxMana = player:getMaxMana()

    player:setMaxHealth(maxHealth * config.healthMultiplier)
    player:setMaxMana(maxMana * config.manaMultiplier)

    player:setStorageValue(config.storageValue .. "_MAX_HEALTH", maxHealth)
    player:setStorageValue(config.storageValue .. "_MAX_MANA", maxMana)

    player:setStorageValue(config.storageValue, os.time() + config.boostDuration)
    item:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received a specific profession boost for the next ' .. config.boostDuration .. ' seconds! Your maximum health points and mana points have been increased by 200%.')  -- Corrected message

    local playerId = player:getGuid()
    addEvent(expireBoost, config.boostDuration * 1000, playerId, config.storageValue)

    return true
end

function expireBoost(playerId, storageValue)
    local player = Player(playerId)
    if player then
        local maxHealthRestore = player:getStorageValue(storageValue .. "_MAX_HEALTH")
        local maxManaRestore = player:getStorageValue(storageValue .. "_MAX_MANA")

        player:setMaxHealth(maxHealthRestore)
        player:setMaxMana(maxManaRestore)

        player:setStorageValue(storageValue .. "_MAX_HEALTH", -1)
        player:setStorageValue(storageValue .. "_MAX_MANA", -1)
        player:setStorageValue(storageValue, 0)

        player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your specific profession boost has expired!')
    end
end

creaturescript.
Lua:
local config = {
    storageValue = 224411,
    boostDuration = 3600,
}

function formatTime(seconds)
    local minutes = math.floor(seconds / 60)
    seconds = seconds % 60
    return string.format("%d minute(s) and %d second(s)", minutes, seconds)
end

function onLogout(player)
    player:setStorageValue(config.storageValue, os.time() + config.boostDuration)
    return true
end

function onLogin(player)
    local storedTime = player:getStorageValue(config.storageValue)
    local currentTime = os.time()

    if storedTime > currentTime then
        local remainingTime = storedTime - currentTime
        local timeString = formatTime(remainingTime)

        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost is active. Remaining time: ' .. timeString)
    else
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your specific profession boost has expired.')
        player:setStorageValue(config.storageValue, 0)
    end

    return true
end

need edit on_death i know
There's no need to edit onDeath. You can die whenever you want and not lose any bonuses. Everything is normal. What was the reason for removing all the conditions? If you die and lose HP/MP... I tried another way, but I couldn't manage it. So, I decided to use the standard functions that are compatible, and it worked perfectly.
Check out the gif showing it working: logging out and death don't make you lose any bonuses, and your HP/MP returns without crashing the server. It's all been tested! :)
 
Last edited:
Back
Top