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

Lua (TFS 1.2) Soul Point Regeneration Time Reduction

quickdload

New Member
Joined
Mar 24, 2024
Messages
5
Reaction score
1
Hi,


Currently when you kill a monster which gives equal or more exp than your level you will gain soul points for 4 minutes. I would like to change the 4 minutes to 30 seconds (for example).

So you kill 1 monster, you gain soul points for 30 seconds then you have to kill another monster to continue regenerating soul points.


Is this possible only with source edits or can anyone dream up some clever lua solution?


Thank you.
Post automatically merged:

My idea is to disable (change value to 0) soul point regeneration (gainsoulticks) in vocations.xml.

Then I would need some kind of lua action that recognises when I gain experience and forces my character to tick soul points for x seconds after this. It wouldn't really matter to me that the experience gained isn't equal or more than my level.

Is this viable? From what I'm aware the food/hp mana regen system uses lua so it must be... right?
 
Last edited:
Solution
Hi,


Thanks for looking at this for me. So my player.lua file is found in data/lib/core (I don't have an events folder) and it looks like this:


Lua:
function Player.feed(self, food)
    local condition = self:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)
    if condition then
        condition:setTicks(condition:getTicks() + (food * 1000))
    else
        local vocation = self:getVocation()
        if not vocation then
            return nil
        end

        foodCondition:setTicks(food * 1000)
        foodCondition:setParameter(CONDITION_PARAM_HEALTHGAIN, vocation:getHealthGainAmount())
        foodCondition:setParameter(CONDITION_PARAM_HEALTHTICKS, vocation:getHealthGainTicks() * 1000)...
in data/events/scripts/player.lua

at the top, add this
Lua:
local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
soulCondition:setTicks(30 * 1000) -- 30 seconds
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, 5 * 1000) -- gain soul every 5 seconds? no idea what default value is

in the function onGainExperience, add where it seems appropriate.
Lua:
if exp > 0 then
    self:addCondition(soulCondition)
end

and then yeah, in vocations.xml, just disable everyone's default soul gain.
 
in data/events/scripts/player.lua

at the top, add this
Lua:
local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
soulCondition:setTicks(30 * 1000) -- 30 seconds
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, 5 * 1000) -- gain soul every 5 seconds? no idea what default value is

in the function onGainExperience, add where it seems appropriate.
Lua:
if exp > 0 then
    self:addCondition(soulCondition)
end

and then yeah, in vocations.xml, just disable everyone's default soul gain.

Hi,


Thanks for looking at this for me. So my player.lua file is found in data/lib/core (I don't have an events folder) and it looks like this:


Lua:
function Player.feed(self, food)
    local condition = self:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)
    if condition then
        condition:setTicks(condition:getTicks() + (food * 1000))
    else
        local vocation = self:getVocation()
        if not vocation then
            return nil
        end

        foodCondition:setTicks(food * 1000)
        foodCondition:setParameter(CONDITION_PARAM_HEALTHGAIN, vocation:getHealthGainAmount())
        foodCondition:setParameter(CONDITION_PARAM_HEALTHTICKS, vocation:getHealthGainTicks() * 1000)
        foodCondition:setParameter(CONDITION_PARAM_MANAGAIN, vocation:getManaGainAmount())
        foodCondition:setParameter(CONDITION_PARAM_MANATICKS, vocation:getManaGainTicks() * 1000)

        self:addCondition(foodCondition)
    end
    return true
end

function Player.getClosestFreePosition(self, position, extended)
    if self:getAccountType() >= ACCOUNT_TYPE_GOD then
        return position
    end
    return Creature.getClosestFreePosition(self, position, extended)
end

function Player.getDepotItems(self, depotId)
    return self:getDepotChest(depotId, true):getItemHoldingCount()
end

function Player.isNoVocation(self)
    return self:getVocation():getId() == 0
end

function Player.isSorcerer(self)
    return self:getVocation():getId() == 1 or self:getVocation():getId() == 5
end

function Player.isDruid(self)
    return self:getVocation():getId() == 2 or self:getVocation():getId() == 6
end

function Player.isPaladin(self)
    return self:getVocation():getId() == 3 or self:getVocation():getId() == 7
end

function Player.isKnight(self)
    return self:getVocation():getId() == 4 or self:getVocation():getId() == 8
end

function Player.isPremium(self)
    return self:getPremiumDays() > 0 or configManager.getBoolean(configKeys.FREE_PREMIUM)
end

function Player.sendCancelMessage(self, message)
    if type(message) == "number" then
        message = Game.getReturnMessage(message)
    end
    return self:sendTextMessage(MESSAGE_STATUS_SMALL, message)
end

function Player.isUsingOtClient(self)
    return self:getClient().os >= CLIENTOS_OTCLIENT_LINUX
end

function Player.sendExtendedOpcode(self, opcode, buffer)
    if not self:isUsingOtClient() then
        return false
    end

    local networkMessage = NetworkMessage()
    networkMessage:addByte(0x32)
    networkMessage:addByte(opcode)
    networkMessage:addString(buffer)
    networkMessage:sendToPlayer(self)
    networkMessage:delete()
    return true
end


I probably should've mentioned in the OP that I'm working on Nostalrius TFS 1.2. Here is their github if you need to look at the pathing of the files in full: GitHub - Ezzz-dev/Nostalrius: Nostalrius is a 7.7 Tibia Clone Project based on The Forgotten Server 1.2 and CipSoft files. (https://github.com/Ezzz-dev/Nostalrius/)

I couldn't actually find "onGainExperience" in any of the files held in the data folder.

I tried adding what you suggested at the top of my player.lua file then adding onGainExperience with your second part but it just created errors on server launch.


I'll keep trying things while I wait to hear back if you're wanting to take another look at it, thanks anyway.
Post automatically merged:

Well I'm at the point where I can add your instructions to data>lib>core>player.lua and launch the server without any errors but it doesn't seem to have changed anything for me. If I set the vocations.xml to not gain soul then no soul is gained and if I leave vocations.xml as it should be then I gain soul for the full 4 minutes as usual.

I wonder if the fact that "onGainExperience" doesn't seem to exist anywhere in the Nostalrius data files suggests that these changes made in this function are source only? I've no idea myself, very little experience on my end.
 
Last edited:
Hi,


Thanks for looking at this for me. So my player.lua file is found in data/lib/core (I don't have an events folder) and it looks like this:


Lua:
function Player.feed(self, food)
    local condition = self:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT)
    if condition then
        condition:setTicks(condition:getTicks() + (food * 1000))
    else
        local vocation = self:getVocation()
        if not vocation then
            return nil
        end

        foodCondition:setTicks(food * 1000)
        foodCondition:setParameter(CONDITION_PARAM_HEALTHGAIN, vocation:getHealthGainAmount())
        foodCondition:setParameter(CONDITION_PARAM_HEALTHTICKS, vocation:getHealthGainTicks() * 1000)
        foodCondition:setParameter(CONDITION_PARAM_MANAGAIN, vocation:getManaGainAmount())
        foodCondition:setParameter(CONDITION_PARAM_MANATICKS, vocation:getManaGainTicks() * 1000)

        self:addCondition(foodCondition)
    end
    return true
end

function Player.getClosestFreePosition(self, position, extended)
    if self:getAccountType() >= ACCOUNT_TYPE_GOD then
        return position
    end
    return Creature.getClosestFreePosition(self, position, extended)
end

function Player.getDepotItems(self, depotId)
    return self:getDepotChest(depotId, true):getItemHoldingCount()
end

function Player.isNoVocation(self)
    return self:getVocation():getId() == 0
end

function Player.isSorcerer(self)
    return self:getVocation():getId() == 1 or self:getVocation():getId() == 5
end

function Player.isDruid(self)
    return self:getVocation():getId() == 2 or self:getVocation():getId() == 6
end

function Player.isPaladin(self)
    return self:getVocation():getId() == 3 or self:getVocation():getId() == 7
end

function Player.isKnight(self)
    return self:getVocation():getId() == 4 or self:getVocation():getId() == 8
end

function Player.isPremium(self)
    return self:getPremiumDays() > 0 or configManager.getBoolean(configKeys.FREE_PREMIUM)
end

function Player.sendCancelMessage(self, message)
    if type(message) == "number" then
        message = Game.getReturnMessage(message)
    end
    return self:sendTextMessage(MESSAGE_STATUS_SMALL, message)
end

function Player.isUsingOtClient(self)
    return self:getClient().os >= CLIENTOS_OTCLIENT_LINUX
end

function Player.sendExtendedOpcode(self, opcode, buffer)
    if not self:isUsingOtClient() then
        return false
    end

    local networkMessage = NetworkMessage()
    networkMessage:addByte(0x32)
    networkMessage:addByte(opcode)
    networkMessage:addString(buffer)
    networkMessage:sendToPlayer(self)
    networkMessage:delete()
    return true
end


I probably should've mentioned in the OP that I'm working on Nostalrius TFS 1.2. Here is their github if you need to look at the pathing of the files in full: GitHub - Ezzz-dev/Nostalrius: Nostalrius is a 7.7 Tibia Clone Project based on The Forgotten Server 1.2 and CipSoft files. (https://github.com/Ezzz-dev/Nostalrius/)

I couldn't actually find "onGainExperience" in any of the files held in the data folder.

I tried adding what you suggested at the top of my player.lua file then adding onGainExperience with your second part but it just created errors on server launch.


I'll keep trying things while I wait to hear back if you're wanting to take another look at it, thanks anyway.
Post automatically merged:

Well I'm at the point where I can add your instructions to data>lib>core>player.lua and launch the server without any errors but it doesn't seem to have changed anything for me. If I set the vocations.xml to not gain soul then no soul is gained and if I leave vocations.xml as it should be then I gain soul for the full 4 minutes as usual.

I wonder if the fact that "onGainExperience" doesn't seem to exist anywhere in the Nostalrius data files suggests that these changes made in this function are source only? I've no idea myself, very little experience on my end.
Alright. xD

I've found it in the source for that server, here.

Code:
    if (getSoul() < getVocation()->getSoulMax() && exp >= level) {
        Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SOUL, 4 * 60 * 1000, 0);
        condition->setParam(CONDITION_PARAM_SOULGAIN, 1);
        condition->setParam(CONDITION_PARAM_SOULTICKS, vocation->getSoulGainTicks() * 1000);
        addCondition(condition);
    }

so you could change it like this, to match what I did above

Code:
    if (exp > 0) {
        Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SOUL, 30 * 1000, 0);
        condition->setParam(CONDITION_PARAM_SOULGAIN, 1);
        condition->setParam(CONDITION_PARAM_SOULTICKS, 5000);
        addCondition(condition);
    }
 
Solution
Alright. xD

I've found it in the source for that server, here.

Code:
    if (getSoul() < getVocation()->getSoulMax() && exp >= level) {
        Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SOUL, 4 * 60 * 1000, 0);
        condition->setParam(CONDITION_PARAM_SOULGAIN, 1);
        condition->setParam(CONDITION_PARAM_SOULTICKS, vocation->getSoulGainTicks() * 1000);
        addCondition(condition);
    }

so you could change it like this, to match what I did above

Code:
    if (exp > 0) {
        Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SOUL, 30 * 1000, 0);
        condition->setParam(CONDITION_PARAM_SOULGAIN, 1);
        condition->setParam(CONDITION_PARAM_SOULTICKS, 5000);
        addCondition(condition);
    }

Thanks again,

So just for my own future learning. As Nostalrius doesn't have that information inside the data folders you can't just enter it in there to override what was in the sources when it was compiled?
 
Thanks again,

So just for my own future learning. As Nostalrius doesn't have that information inside the data folders you can't just enter it in there to override what was in the sources when it was compiled?
With the change we made, that's correct.
You'd have to update the source if you wanted to change it again.

Without having the events folder, a lot of 'basic' triggers are missing for you, from the Lua side of things.
I was pretty sure they were added in 1.2, but I guess they are an early 1.3 feature?

Anyway. xD
 
Thanks for all the help Xikini, I know what you've suggested is the solution.


I've been having problems recompiling the server since I received this solution and as this one of the last steps on what I'm trying to do ideally I don't want to sink a load of time into properly teaching myself how to compile (so far everything I've done on my project has just been using .lua scripts).

Has anyone got any ideas on how I could possibly do this using a lua script? To change the 4 minutes of soul regeneration after killing a monster to 30 seconds (or 1 minute etc).

As far as I can see regular TFS 1.2 servers do have an events folder with onGainExperience and soul point regen information and Nostalrius runs off TFS 1.2, so perhaps it is possible as the functions do seem to exist.


Cheers.
 
Back
Top