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

Playerongainexperience error

henkas

Well-Known Member
Joined
Jul 8, 2015
Messages
993
Solutions
5
Reaction score
55
Lua:
function Player:onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end

    -- Soul regeneration
    local vocation = self:getVocation()
    if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
        soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
        self:addCondition(soulCondition)
    end

    -- Apply experience stage multiplier
    exp = exp * getRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))

    -- Stamina modifier
    if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
        useStamina(self)

        local staminaMinutes = self:getStamina()
        if staminaMinutes > 2400 and self:isPremium() then
            exp = exp * 1.5
        elseif staminaMinutes <= 840 then
            exp = exp * 0.5
        end
    end

    return exp
end
Untitled.png
 
Solution
Hmm..I see you also have 2 functions with identical names, that's the only thing I can think of right now.
Code:
local function getRateFromTable(t, level, default)
    for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end


    return default
end
This is the one for experience, as I see it uses 3 parameters.

Code:
function getRateFromTable(t, skill, level, default)
    local rateTable = t[skill]
    if rateTable then
        for _, rate in ipairs(rateTable) do
            local max = rate.maxLevel or math.huge
            if level >= rate.minLevel and level <= max then
                return rate.multiplier
            end...
The error shows up on player.lua, can you post lines 208-221? To see how this function is called
208line
Lua:
function Player:onGainExperience(source, exp, rawExp)
221line
Lua:
    exp = exp * getRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))
 
Oh, I'm sorry, those lines were already on the first code, try this one out. Replace all the onGainExperience function and test it.

Code:
function Player:onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
    -- Soul regeneration
    local vocation = self:getVocation()
    if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
        soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
        self:addCondition(soulCondition)
    end
    -- Apply experience stage multiplier
    exp = exp * Game.getExperienceStage(self:getLevel())
    -- Stamina modifier
    if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
        useStamina(self)
        local staminaMinutes = self:getStamina()
        if staminaMinutes > 2400 and self:isPremium() then
            exp = exp * 1.5
        elseif staminaMinutes <= 840 then
            exp = exp * 0.5
        end
    end
    return exp
end
 
you using lua experience stages and I guess you missing something, can you check if you got this on your files.
Lua:
local experienceStages = {
    {
        minlevel = 1,
        maxlevel = 8,
        multiplier = 7
    }, {
        minlevel = 9,
        maxlevel = 20,
        multiplier = 6
    }, {
        minlevel = 21,
        maxlevel = 50,
        multiplier = 5
    }, {
        minlevel = 51,
        maxlevel = 100,
        multiplier = 4
    }, {
        minlevel = 101,
        multiplier = 3
    }
}

function getRateFromTable(t, level, default)
    for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end

    return default
end
 
Oh, I'm sorry, those lines were already on the first code, try this one out. Replace all the onGainExperience function and test it.

Code:
function Player:onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
    -- Soul regeneration
    local vocation = self:getVocation()
    if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
        soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
        self:addCondition(soulCondition)
    end
    -- Apply experience stage multiplier
    exp = exp * Game.getExperienceStage(self:getLevel())
    -- Stamina modifier
    if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
        useStamina(self)
        local staminaMinutes = self:getStamina()
        if staminaMinutes > 2400 and self:isPremium() then
            exp = exp * 1.5
        elseif staminaMinutes <= 840 then
            exp = exp * 0.5
        end
    end
    return exp
end
Untitled.png

you using lua experience stages and I guess you missing something, can you check if you got this on your files.
Lua:
local experienceStages = {
    {
        minlevel = 1,
        maxlevel = 8,
        multiplier = 7
    }, {
        minlevel = 9,
        maxlevel = 20,
        multiplier = 6
    }, {
        minlevel = 21,
        maxlevel = 50,
        multiplier = 5
    }, {
        minlevel = 51,
        maxlevel = 100,
        multiplier = 4
    }, {
        minlevel = 101,
        multiplier = 3
    }
}

function getRateFromTable(t, level, default)
    for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end

    return default
end
Have them all.
Lua:
local experienceStages = {
    {
        minlevel = 1,
        maxlevel = 8,
        multiplier = 7
    }, {
        minlevel = 9,
        maxlevel = 20,
        multiplier = 6
    }, {
        minlevel = 21,
        maxlevel = 50,
        multiplier = 5
    }, {
        minlevel = 51,
        maxlevel = 100,
        multiplier = 4
    }, {
        minlevel = 101,
        multiplier = 3
    }
}

function Player:onLook(thing, position, distance)
    local description = "You see " .. thing:getDescription(distance)
    if self:getGroup():getAccess() then
        if thing:isItem() then
            description = string.format("%s\nItem ID: %d", description, thing:getId())

            local actionId = thing:getActionId()
            if actionId ~= 0 then
                description = string.format("%s, Action ID: %d", description, actionId)
            end

            local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
            if uniqueId > 0 and uniqueId < 65536 then
                description = string.format("%s, Unique ID: %d", description, uniqueId)
            end

            local itemType = thing:getType()

            local transformEquipId = itemType:getTransformEquipId()
            local transformDeEquipId = itemType:getTransformDeEquipId()
            if transformEquipId ~= 0 then
                description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
            elseif transformDeEquipId ~= 0 then
                description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
            end

            local decayId = itemType:getDecayId()
            if decayId ~= -1 then
                description = string.format("%s\nDecays to: %d", description, decayId)
            end
        elseif thing:isCreature() then
            local str = "%s\nHealth: %d / %d"
            if thing:getMaxMana() > 0 then
                str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
            end
            description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
        end

        local position = thing:getPosition()
        description = string.format(
            "%s\nPosition: %d, %d, %d",
            description, position.x, position.y, position.z
        )

        if thing:isCreature() then
            if thing:isPlayer() then
                description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
            end
        end
    end
    self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end

function Player:onLookInBattleList(creature, distance)
    local description = "You see " .. creature:getDescription(distance)
    if self:getGroup():getAccess() then
        local str = "%s\nHealth: %d / %d"
        if creature:getMaxMana() > 0 then
            str = string.format("%s, Mana: %d / %d", str, creature:getMana(), creature:getMaxMana())
        end
        description = string.format(str, description, creature:getHealth(), creature:getMaxHealth()) .. "."

        local position = creature:getPosition()
        description = string.format(
            "%s\nPosition: %d, %d, %d",
            description, position.x, position.y, position.z
        )

        if creature:isPlayer() then
            description = string.format("%s\nIP: %s", description, Game.convertIpToString(creature:getIp()))
        end
    end
    self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end

function Player:onLookInTrade(partner, item, distance)
    self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. item:getDescription(distance))
end

function Player:onLookInShop(itemType, count)
    return true
end

local vocs = {
    [{1, 2}] = {13385, 12746, 13434, 13435, 12747, 12744, 12748, 12736, 13444, 13443, 15667, 15712}
}

function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if toPosition.x ~= CONTAINER_POSITION then
        return true
    end

    if bit.band(toPosition.y, 0x40) == 0 then
        for vocations, ids in pairs(vocs) do
            if table.contains(vocations, self:getVocation():getId()) then
                if table.contains(ids, item:getId()) then
                    return false
                end
            end
        end
    end

        local itemType, moveItem = ItemType(item:getId())
        if bit.band(itemType:getSlotPosition(), SLOTP_TWO_HAND) ~= 0 and toPosition.y == CONST_SLOT_LEFT then
            moveItem = self:getSlotItem(CONST_SLOT_RIGHT)
        elseif itemType:getWeaponType() == WEAPON_SHIELD and toPosition.y == CONST_SLOT_RIGHT then
            moveItem = self:getSlotItem(CONST_SLOT_LEFT)
            if moveItem and bit.band(ItemType(moveItem:getId()):getSlotPosition(), SLOTP_TWO_HAND) == 0 then
                return true
        end

        if moveItem then
            local parent = item:getParent()
            if parent and parent:isItem() and parent:isContainer() then
                if parent:getSize() == parent:getCapacity() then
                    self:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM))
                    return false
                else
                    return moveItem:moveTo(parent)
                end
            end
        end
    end

    return true
end

function Player:onMoveCreature(creature, fromPosition, toPosition)
    return true
end

function Player:onTurn(direction)
    return true
end

function Player:onTradeRequest(target, item)
    return true
end

function Player:onTradeAccept(target, item, targetItem)
    return true
end

local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
soulCondition:setTicks(4 * 60 * 1000)
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)

local function useStamina(player)
    local staminaMinutes = player:getStamina()
    if staminaMinutes == 0 then
        return
    end

    local playerId = player:getId()
    local currentTime = os.time()
    local timePassed = currentTime - nextUseStaminaTime[playerId]
    if timePassed <= 0 then
        return
    end

    if timePassed > 60 then
        if staminaMinutes > 2 then
            staminaMinutes = staminaMinutes - 2
        else
            staminaMinutes = 0
        end
        nextUseStaminaTime[playerId] = currentTime + 120
    else
        staminaMinutes = staminaMinutes - 1
        nextUseStaminaTime[playerId] = currentTime + 60
    end
    player:setStamina(staminaMinutes)
end

local function getRateFromTable(t, level, default)
    for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end

    return default
end

function Player:onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
    -- Soul regeneration
    local vocation = self:getVocation()
    if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
        soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
        self:addCondition(soulCondition)
    end
    -- Apply experience stage multiplier
    exp = exp * Game.getExperienceStage(self:getLevel())
    -- Stamina modifier
    if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
        useStamina(self)
        local staminaMinutes = self:getStamina()
        if staminaMinutes > 2400 and self:isPremium() then
            exp = exp * 1.5
        elseif staminaMinutes <= 840 then
            exp = exp * 0.5
        end
    end
    return exp
end


function Player:onLoseExperience(exp)
    return exp
end

local skillStages = {
    [SKILL_CLUB] = {
        {minLevel = 1, maxLevel = 30, multiplier = 15}
    },
    [SKILL_SWORD] = {
        {minLevel = 1, maxLevel = 30, multiplier = 15}
    },
    [SKILL_AXE] = {
        {minLevel = 1, maxLevel = 30, multiplier = 15}
    },
    [SKILL_DISTANCE] = {
        {minLevel = 1, maxLevel = 30, multiplier = 8}
    },
    [SKILL_SHIELD] = {
        {minLevel = 1, maxLevel = 30, multiplier = 8}
    },
    [SKILL_FISHING] = {
        {minLevel = 1, maxLevel = 30, multiplier = 8}
    },
    [SKILL_MAGLEVEL] = {
        {minLevel = 1, maxLevel = 30, multiplier = 8}
    }
}

function getRateFromTable(t, skill, level, default)
    local rateTable = t[skill]
    if rateTable then
        for _, rate in ipairs(rateTable) do
            local max = rate.maxLevel or math.huge
            if level >= rate.minLevel and level <= max then
                return rate.multiplier
            end
        end
    end
    return default
end

function Player:onGainSkillTries(skill, tries)
    if APPLY_SKILL_MULTIPLIER == false then
        return tries
    end

    local level = self:getSkillLevel(skill)
    local multiplier = getRateFromTable(skillStages, skill, level, 1)

    local key = (skill == SKILL_MAGLEVEL) and configKeys.RATE_MAGIC or configKeys.RATE_SKILL

    tries = tries * configManager.getNumber(key) * multiplier
    return tries
end
 
I think he means using print, for example:
Code:
function Player:onGainExperience(source, exp, rawExp)
   if not source or source:isPlayer() then
        return exp
    end
You could try adding after that part:
Code:
print(source)
print(exp)
print(rawExp)
And check if they have values, the error seems to be pointing that you are trying to multiply a Nil value, which means there's something going on with the data the function is receiving.

Also here:
Code:
-- Apply experience stage multiplier
 print(configManager.getNumber(configKeys.RATE_EXP))
 exp = exp * getRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))

Try one at a time, and check your console, it should print a value, if one of them prints Nil, there you have the issue
 
I think he means using print, for example:
Code:
function Player:onGainExperience(source, exp, rawExp)
   if not source or source:isPlayer() then
        return exp
    end
You could try adding after that part:
Code:
print(source)
print(exp)
print(rawExp)
And check if they have values, the error seems to be pointing that you are trying to multiply a Nil value, which means there's something going on with the data the function is receiving.

Also here:
Code:
-- Apply experience stage multiplier
 print(configManager.getNumber(configKeys.RATE_EXP))
 exp = exp * getRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))

Try one at a time, and check your console, it should print a value, if one of them prints Nil, there you have the issue
Aaa print its not debugging tho.
This is the value i got from all variables
source - userdata: 0x022dfe60
exp - 50
rawExp - 50
RATE_EXP - 3306
 
Hmm..I see you also have 2 functions with identical names, that's the only thing I can think of right now.
Code:
local function getRateFromTable(t, level, default)
    for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end


    return default
end
This is the one for experience, as I see it uses 3 parameters.

Code:
function getRateFromTable(t, skill, level, default)
    local rateTable = t[skill]
    if rateTable then
        for _, rate in ipairs(rateTable) do
            local max = rate.maxLevel or math.huge
            if level >= rate.minLevel and level <= max then
                return rate.multiplier
            end
        end
    end
    return default
end
You also have that one that's declared as a global var, which could interfere I think?

You could try changing the first one to:
Code:
local function getExpRateFromTable(t, level, default)
   for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end

    return default
end

And then changing this part
Code:
exp = exp * getRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))
To:
Code:
exp = exp * getExpRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))
 
Solution
Hmm..I see you also have 2 functions with identical names, that's the only thing I can think of right now.
Code:
local function getRateFromTable(t, level, default)
    for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end


    return default
end
This is the one for experience, as I see it uses 3 parameters.

Code:
function getRateFromTable(t, skill, level, default)
    local rateTable = t[skill]
    if rateTable then
        for _, rate in ipairs(rateTable) do
            local max = rate.maxLevel or math.huge
            if level >= rate.minLevel and level <= max then
                return rate.multiplier
            end
        end
    end
    return default
end
You also have that one that's declared as a global var, which could interfere I think?

You could try changing the first one to:
Code:
local function getExpRateFromTable(t, level, default)
   for _, rate in ipairs(t) do
        if level >= rate.minlevel and (not rate.maxlevel or level <= rate.maxlevel) then
            return rate.multiplier
        end
    end

    return default
end

And then changing this part
Code:
exp = exp * getRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))
To:
Code:
exp = exp * getExpRateFromTable(experienceStages, self:getLevel(), configManager.getNumber(configKeys.RATE_EXP))
Yea i forgot that i use identical callbacks one for exp and one for skill stages. Thanks.
 
Back
Top