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

Player - Spell Experience - 1.2

Codex NG

Recurrent Flamer
Joined
Jul 24, 2015
Messages
2,994
Solutions
12
Reaction score
1,657
These functions were originally written by someone named @Athern.

All I did was adapt it to the Player metatable and apply it to spells, but these functions could be applied to anything even items.

Code:
function Player:getCustomSkill(storage)
    return self:getStorageValue(storage)
end
function Player:addCustomSkill(skillName, storage)
    local skillStorage = math.max(10, self:getStorageValue(storage))
    local skillTries =  math.max(0, self:getStorageValue(storage + 1))
    self:setStorageValue(storage, skillStorage + 1)
    self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You advanced to " .. string.lower(skillName) .. " level "..self:getCustomSkill(storage)..".")
    self:setStorageValue(storage + 1, 0)
end
function Player:addCustomSkillTry(skillName, storage)
    local skillStorage = math.max(10, self:getStorageValue(storage))
    local skillTries =  math.max(0, self:getStorageValue(storage + 1))
    self:setStorageValue(storage + 1, skillTries + 1)
    if skillTries > math.floor(20 * math.pow(1.1, (skillStorage - 11)) / 10) then
        self:addCustomSkill(skillName, storage)
    end
end
function Player:getCustomSkillPercent(storage)
    local skillStorage = math.max(10, self:getStorageValue(storage))
    local skillTries =  math.max(0, self:getStorageValue(storage + 1))
    local triesNeeded = math.floor(20 * math.pow(1.1, (skillStorage - 11)) / 10)
    local percent = math.floor(100 * (1 - skillTries / triesNeeded))
    if percent > 1 and percent <= 100 then
        return percent
    else
        percent = 1
        return percent
    end
end

Using haste as an example, you would need to apply your own formula's whether to increase the damage, speed, effects etc.. as I am not building your server for you.
Code:
    local name = "haste"
    local storage = 15000
  
    local combat = Combat()
    combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN)
    combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
  
    local function x(creature, var)
        local condition = Condition(CONDITION_HASTE)
        condition:setParameter(CONDITION_PARAM_TICKS, 33000)
        condition:setFormula(0.3, -24, 0.3, -24)
        combat:setCondition(condition)
        creature:addCustomSkillTry(name, storage)
        return combat:execute(creature, var)
    end
  
    function onCastSpell(creature, var)
        return x(creature, var)
    end

Code:
22:08 You advanced to haste level 11.
22:09 You advanced to haste level 12.
 
I have to figure how to make this into a spell with lvl and get more damage i tried doing this
Code:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
combat:setArea(createCombatArea(AREA_SQUARE1X1))

local function x(creature, var)
local condition = Condition(CONDITION_FIRE)
condition:setParameter(CONDITION_PARAM_TICKS, 33000)
condition:setFormula(2, 2, 4, 8)
combat:setCondition(condition)
creature:addCustomSkillTry(name, storage)
return combat:execute(creature, var)
end
but no success
 
I have to figure how to make this into a spell with lvl and get more damage i tried doing this
Code:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
combat:setArea(createCombatArea(AREA_SQUARE1X1))

local function x(creature, var)
local condition = Condition(CONDITION_FIRE)
condition:setParameter(CONDITION_PARAM_TICKS, 33000)
condition:setFormula(2, 2, 4, 8)
combat:setCondition(condition)
creature:addCustomSkillTry(name, storage)
return combat:execute(creature, var)
end
but no success
Because the code is incorrect
 
I have to figure how to make this into a spell with lvl and get more damage i tried doing this
Code:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
combat:setArea(createCombatArea(AREA_SQUARE1X1))

local function x(creature, var)
local condition = Condition(CONDITION_FIRE)
condition:setParameter(CONDITION_PARAM_TICKS, 33000)
condition:setFormula(2, 2, 4, 8)
combat:setCondition(condition)
creature:addCustomSkillTry(name, storage)
return combat:execute(creature, var)
end
but no success

well i was confused by his example too xD

the thing u need to do is just add this onto your scripts:
Player:addCustomSkillTry(skillName, storage)

and change skillname into what name u want it to have and what storage. and obviously u need to change Player into the correct thingy, for example in a normal spell script u could add this:
creature:addCustomSkillTry("spells", 3433)

after the function onCastSpell

but even if u get that to work, if u couldn't understand how to add it i dont think u can really utilize the system
 
Last edited:
well i was confused by his example too xD

the thing u need to do is just add this onto your scripts:
Player:addCustomSkillTry(skillName, storage)

and change skillname into what name u want it to have and what storage. and obviously u need to change Player into the correct thingy, for example in a normal spell script u could add this:
creature:addCustomSkillTry("spells", 3433)

after the function onCastSpell

but even if u get that to work, if u couldn't understand how to add it i dont think u can really utilize the system
These releases are really for programmers, sure I could have just made a few examples of how they could be applied, but why should I think for you.
The functions which currently exist provide the basic foundation to make it possible for spells to increase in damage, effects etc..
But I won't provide any support for them, I want to encourage people to learn the core language this way they too can have that ahh hah moment :)
 
These releases are really for programmers, sure I could have just made a few examples of how they could be applied, but why should I think for you.
The functions which currently exist provide the basic foundation to make it possible for spells to increase in damage, effects etc..
But I won't provide any support for them, I want to encourage people to learn the core language this way they too can have that ahh hah moment :)

If i get this working with a spell the way i want it I will post to let someone know I succed on a script edit & it will be contributed to this post.
 
I've surely made a lot of mistakes in this! I needed to try! Would this, in theory, be a way of implementing a new skill? Don't kill me, I'm a newbie, tried my best!


Code:
local name = "Herblore"
local storage = 15000

local redItem = 8303

local redPowders = {
    2743, 2798, 4135, 4141
}

function onUse(cid, item, fromPosition, target, toPosition, isHotkey)
    local herbSkill = Player:getCustomSkill(storage)
    if target.itemid == redPowders[1] then
        local chance = math.floor((math.random(1,100)) - (herbSkill / 2))
            if    chance <= 30 then
                local round = math.floor((math.random(1,2)) + (herbSkill / 4))
                player:addItem(redItem, round)
                Player:addCustomSkillTry(name, storage)
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You gathered " .. round .. " red powders.")
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You failed.")
    end
        return true
    end
    if target.itemid == redPowders[2] and herbSkill => 15 then
        local chance = math.floor((math.random(1,100)) - (herbSkill / 5))
            if chance <= 30 then
                local round = math.floor((math.random(1,2)) + (herbSkill / 3))
                player:addItem(redItem, round)
                Player:addCustomSkillTry(name, storage)
                Player:addCustomSkillTry(name, storage)
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You gathered " .. round .. " red powders.")
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You failed.")
            end
        return true
    else
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "You need level 15 of Herblore to harvest.")
    return true
    end
    if target.itemid == redPowders[3] and herbSkill => 30 then
        local chance = math.floor((math.random(1,100)) - (herbSkill / 6))
            if chance <= 30 then
                local round = math.floor((math.random(4,5)) + (herbSkill / 3))
                player:addItem(redItem, round)
                player:addCustomSkillTry(name, storage)
                Player:addCustomSkillTry(name, storage)
                Player:addCustomSkillTry(name, storage)
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You gathered " .. round .. " red powders.")
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You failed.")
            end
    else
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "You need level 30 of Herblore to harvest.")
    end
    return true
end
 
@Ramirow
Code:
local name = "Herblore"
local storage = 15000
-- adjust the powder table to tweak the script
local powders = {
    [2743] = {
        itemid = 2743,
        herbtype = 'red',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 1, max = 2},
        chance = 2,
        round = 4
    },
    [2798] = {
        itemid = 2798,
        herbtype = 'green',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 1, max = 2},
        chance = 5,
        round = 3
    },
    [4135] = {
        itemid = 4135,
        herbtype = 'blue',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 4, max = 5},
        chance = 6, round = 3
    },
    [4141] = {
        itemid = 4141,
        herbtype = 'yellow',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 4, max = 5},
        chance = 8,
        round = 4
    } -- guesstamit
}

function onUse(cid, item, fromPosition, target, toPosition, isHotkey)
    local player = type(cid) == 'number' and Player(cid) or cid

    local herbSkill = player:getCustomSkill(storage)
    if powders[target.itemid] then
   
        local herbLevel = powders[target.itemid].level
        if herbSkill >= herbLevel.min then
       
            local chance = math.floor((math.random(1, 100)) - (herbSkill / powders[target.itemid].chance))
            if chance <= herbLevel.max then
           
                local roundChance = powders[target.itemid].roundChance
                local amount = math.floor((math.random(roundChance.min, roundChance.max)) + (herbSkill / powders[target.itemid].round))
                player:addItem(powders[target.itemid].item, amount)
                player:addCustomSkillTry(name, storage)
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You gathered " .. amount .. " " .. powders[target.itemid].herbtype .. " powders.")
           
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You failed.")
            end
        else
            player:sendTextMessage(MESSAGE_STATUS_SMALL, "You need level " .. herbLevel.min .. " of " .. name .. " to harvest.")
        end
    end
    return true
end
 
Last edited:
@Ramirow
Code:
local name = "Herblore"
local storage = 15000
-- adjust the powder table to tweak the script
local powders = {
    [2743] = {
        itemid = 2743,
        herbtype = 'red',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 1, max = 2},
        chance = 2,
        round = 4
    },
    [2798] = {
        itemid = 2798,
        herbtype = 'green',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 1, max = 2},
        chance = 5,
        round = 3
    },
    [4135] = {
        itemid = 4135,
        herbtype = 'blue',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 4, max = 5},
        chance = 6, round = 3
    },
    [4141] = {
        itemid = 4141,
        herbtype = 'yellow',
        item = 8303,
        level = {min = 1, max = 15},
        roundChance = {min = 4, max = 5},
        chance = 8,
        round = 4
    } -- guesstamit
}

function onUse(cid, item, fromPosition, target, toPosition, isHotkey)
    local player = type(cid) == 'number' and Player(cid) or cid

    local herbSkill = player:getCustomSkill(storage)
    if powders[target.itemid] then
  
        local herbLevel = powders[target.itemid].level
        if herbSkill >= herbLevel.min then
      
            local chance = math.floor((math.random(1, 100)) - (herbSkill / powders[target.itemid].chance))
            if chance <= herbLevel.max then
          
                local roundChance = powders[target.itemid].roundChance
                local amount = math.floor((math.random(roundChance.min, roundChance.max)) + (herbSkill / powders[target.itemid].round))
                player:addItem(powders[target.itemid].item, amount)
                player:addCustomSkillTry(name, storage)
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You gathered " .. amount .. " " .. powders[target.itemid].herbtype .. " powders.")
          
            else
                player:sendTextMessage(MESSAGE_STATUS_SMALL, "You failed.")
            end
        else
            player:sendTextMessage(MESSAGE_STATUS_SMALL, "You need level " .. herbLevel.min .. " of " .. name .. " to harvest.")
        end
    end
    return true
end

I've managed to follow the code step by step, played around with it, added some options, loops, etc. I guess it's a good way to learn, I'm really thankful! I'm trying to search some functions to play even more with it!
You rock! :D
 
Great, I'll use it.
I guess we should create global variable with pairs: "Skill name" => "Skill Storage" and get rid of storage in method declaration.
 
i've added the script to events/scripts/Player.lua and aswell wrote in events.xml ( <event class="Player" method="addCustomSkill" enabled="1"/> )

i've added the mining script from Ramirow into actions/scripts/mining.lua
and in actions.xml ( <action itemid="????" script="Mining.lua"/> )

when i use pickaxe on the stone, i get a massage " You need a mining level of 1 to mine this stone " but nothing more happens?

and i know codex you dont want to think for us and all that shit if you dont know then dont use it..
but i actually want to learn and i like the idea of the script and well its on forum for sharing so why not help me out a bit and point me in the right direction?

obviously the player dont get the storagevalue from mining script right since it has no mining skill?
and in console i get error " Unkown player method : addCustomSkill " so its not correctly added in event xml aswell?
 
i've added the script to events/scripts/Player.lua and aswell wrote in events.xml ( <event class="Player" method="addCustomSkill" enabled="1"/> )

i've added the mining script from Ramirow into actions/scripts/mining.lua
and in actions.xml ( <action itemid="????" script="Mining.lua"/> )

when i use pickaxe on the stone, i get a massage " You need a mining level of 1 to mine this stone " but nothing more happens?

and i know codex you dont want to think for us and all that shit if you dont know then dont use it..
but i actually want to learn and i like the idea of the script and well its on forum for sharing so why not help me out a bit and point me in the right direction?

obviously the player dont get the storagevalue from mining script right since it has no mining skill?
and in console i get error " Unkown player method : addCustomSkill " so its not correctly added in event xml aswell?
An easy way to enable the Mining Skill I made from the start is add these lines:
Code:
player:setStorageValue(15002, 1)  -- Mining Skill
player:setStorageValue(15003, 0)  -- Mining Skill Tries
in Firstitems (/creaturescripts/scripts/firstitems.lua).
This way any new created character would receive at login the mining skill at level 1.
If you already have players created you could find a way to insert these storages with a SQL query, I'm not too good with it so I can't tell you which query to execute!

And btw, I never registered the addCustomSkill method in events.xml and it's working fine!
 
i've added the script to events/scripts/Player.lua and aswell wrote in events.xml ( <event class="Player" method="addCustomSkill" enabled="1"/> )

i've added the mining script from Ramirow into actions/scripts/mining.lua
and in actions.xml ( <action itemid="????" script="Mining.lua"/> )

when i use pickaxe on the stone, i get a massage " You need a mining level of 1 to mine this stone " but nothing more happens?

and i know codex you dont want to think for us and all that shit if you dont know then dont use it..
but i actually want to learn and i like the idea of the script and well its on forum for sharing so why not help me out a bit and point me in the right direction?

obviously the player dont get the storagevalue from mining script right since it has no mining skill?
and in console i get error " Unkown player method : addCustomSkill " so its not correctly added in event xml aswell?
If I recall correctly I never enabled it in events.xml

I believe events.xml is for TFS compiled code rather than player made code.

Events are event listeners, if you think in terms of hovering your mouse over a button, if coded to do so the button might change color or swap out text or something else, this functionality which exists is internal to the browser.

The additional metamethods we created which are assigned to player are not event listeners, they act outside the scope of the event listeners... its hard for me to explain, not because I don't understand it, but because I can't find the proper wording to do so.. i blame old age and a bit of insanity :p

You might not see the point of adding new metamethods/properties to an existing object, doing so allows you to directly effect the object with simplicity.

Why not use a function instead of metamethod?
Well its extra steps/checks and bigger possibility of failure.

Objects allow you to consolidate code, while at the same time set a level of transparency, who gets or sets what and where.

To summarize:
You can add any new metamethods/properties to player, use them and never add them to events.xml
 
Last edited:
uhm okey, now i deleted it from events.xml as you both told me :)
also added the player:SetStorageValue to firstitems.lua

dont know if i add it correct in actions.xml what itemid should i use? or should it even be an itemid? what is it based upon?

@Codex NG uhm yeah i kind of understand what you talking about, (reading explination on google :p) still a bit confused about it tho ;)
" its hard for me to explain, not because I don't understand it, but because I can't find the proper wording to do so " haha words can be meager things. Sometimes they fall short.
 
I'm trying to use the function

Code:
function onExtendedOpcode(player, opcode, buffer)
    local skillsp = getCustomSkillPercent(player, 15000)
    player:sendExtendedOpcode(55, skillsp)
    return true
end


but displays the error on the console
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/extendedopcode.lua:eek:nExtendedOpcode
data/creaturescripts/scripts/extendedopcode.lua:23: attempt to call global 'getCustomSkillPercent' (a nil value)
stack traceback:
[C]: in function 'getCustomSkillPercent'
data/creaturescripts/scripts/extendedopcode.lua:23: in function <data/creaturescripts/scripts/extendedopcode.lua:22>
this only happens when I enter with a character who has the skill

even using
Player:getCustomSkillPercent(1500)
Can someone help me
 
Back
Top