• 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.3] Exercise Weapons

pdrhtdn

New Member
Joined
Feb 8, 2022
Messages
5
Reaction score
0
Greetings everyone, I'm having a difficult time with this problem and I can't find what is wrong, so here I am XD.

My exercise weapons don't train the specific skill that they supposed to train, all of the exercises only train fist fighting, and I can't find whats doing this, here is the code:
Lua:
local skills = {
    [32384] = {itemid=SKILL_SWORD,voc=4}, -- KNIGHT
    [32385] = {itemid=SKILL_AXE,voc=4}, -- KNIGHT
    [32386] = {itemid=SKILL_CLUB,voc=4}, -- KNIGHT
    [32387] = {itemid=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [32388] = {itemid=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [32389] = {itemid=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    [32124] = {itemid=SKILL_SWORD,voc=4}, -- KNIGHT
    [32125] = {itemid=SKILL_AXE,voc=4}, -- KNIGHT
    [32126] = {itemid=SKILL_CLUB,voc=4}, -- KNIGHT
    [32127] = {itemid=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [32128] = {itemid=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [32129] = {itemid=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE} -- SORCERER
}

local houseDummies = {32143, 32144, 32145, 32146, 32147, 32148}
local freeDummies = {32142, 32149}
local skillRateDefault = (configManager.getNumber(configKeys.RATE_SKILL)* 5)
local magicRateDefault = (configManager.getNumber(configKeys.RATE_MAGIC)* 5)

local function removeExerciseWeapon(player, exercise)
    exercise:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training weapon vanished.")
    stopEvent(training)
    player:setStorageValue(Storage.isTraining,0)
end

local function startTraining(playerId, startPosition, itemid, tilePosition, bonusDummy, dummyId)
    local player = Player(playerId)
    if player ~= nil then
        if Tile(tilePosition):getItemById(dummyId) then
            local playerPosition = player:getPosition()
            if startPosition:getDistance(playerPosition) == 0 and getTilePzInfo(playerPosition) then
                if player:getItemCount(itemid) >= 1 then
                    local exercise = player:getItemById(itemid,true)
                    if exercise:isItem() then
                        if exercise:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                            local charges_n = exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                            if charges_n >= 1 then
                                exercise:setAttribute(ITEM_ATTRIBUTE_CHARGES,(charges_n-1))

                                local voc = player:getVocation()

                                if skills[itemid].id == SKILL_MAGLEVEL then
                                    local magicRate = getRateFromTable(magicLevelStages, player:getMagicLevel(), magicRateDefault)
                                    if not bonusDummy then
                                        player:addManaSpent(math.ceil(500*magicRate))
                                    else
                                        player:addManaSpent(math.ceil(500*magicRate)*1.1) -- 10%
                                    end
                                else
                                    local skillRate = getRateFromTable(skillsStages, player:getEffectiveSkillLevel(skills[itemid].id), skillRateDefault)
                                    if not bonusDummy then
                                        player:addSkillTries(skills[itemid].id, 7*skillRate)
                                    else
                                        player:addSkillTries(skills[itemid].id, (7*skillRate)*1.1) -- 10%
                                    end
                                end
                                    tilePosition:sendMagicEffect(CONST_ME_HITAREA)
                                if skills[itemid].range then
                                    playerPosition:sendDistanceEffect(tilePosition, skills[itemid].range)
                                end
                                if exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES) == 0 then
                                    removeExerciseWeapon(player, exercise)
                                else
                                    local training = addEvent(startTraining, voc:getAttackSpeed(), playerId,startPosition,itemid,tilePosition,bonusDummy,dummyId)
                                    player:setStorageValue(Storage.isTraining,1)
                                end
                            else
                                removeExerciseWeapon(player, exercise)
                            end
                        end
                    end
                end
            else
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
                stopEvent(training)
                player:setStorageValue(Storage.isTraining,0)
            end
        else
            stopEvent(training)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
            player:setStorageValue(Storage.isTraining, 0)
        end
    else
        stopEvent(training)
        if player then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
            player:setStorageValue(Storage.isTraining,0)
        end
    end
    return true
end

local exerciseTraining = Action()

function exerciseTraining.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local startPos = player:getPosition()
    if player:getStorageValue(Storage.isTraining) == 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already training.")
        return false
    end
    if target:isItem() then
        if isInArray(houseDummies,target:getId()) then
            if not skills[item.itemid].range and (startPos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            startTraining(player:getId(),startPos,item.itemid,target:getPosition(), true, target:getId())
        elseif isInArray(freeDummies, target:getId()) then
            if not skills[item.itemid].range and (startPos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            startTraining(player:getId(),startPos,item.itemid,target:getPosition(), false, target:getId())
        end
    end
    return true
end

for id = 32124, 32126 do
    exerciseTraining:id(id)
end

for id = 32127, 32129 do
    exerciseTraining:id(id)
    exerciseTraining:allowFarUse(true)
end

for id = 32384, 32386 do
    exerciseTraining:id(id)
end

for id = 32387, 32389 do
    exerciseTraining:id(id)
    exerciseTraining:allowFarUse(true)
end

exerciseTraining:register()

Also, I'm using stages on skills, idk if its needeed to solve but...
Lua:
-- Minlevel and multiplier are MANDATORY
-- Maxlevel is OPTIONAL, but is considered infinite by default
-- Create a stage with minlevel 1 and no maxlevel to disable stages
experienceStages = {
    {
        minlevel = 1,
        maxlevel = 8,
        multiplier = 50
    }, {
        minlevel = 9,
        maxlevel = 50,
        multiplier = 200
    }, {
        minlevel = 51,
        maxlevel = 100,
        multiplier = 150
    }, {
        minlevel = 101,
        maxlevel = 150,
        multiplier = 140
    }, {
        minlevel = 151,
        maxlevel = 200,
        multiplier = 130
    }, {
        minlevel = 201,
        maxlevel = 250,
        multiplier = 120
    }, {
        minlevel = 251,
        maxlevel = 300,
        multiplier = 100
    }, {
        minlevel = 301,
        maxlevel = 350,
        multiplier = 80
    }, {
        minlevel = 351,
        maxlevel = 400,
        multiplier = 50
    }, {
        minlevel = 401,
        maxlevel = 450,
        multiplier = 35
    }, {
        minlevel = 451,
        maxlevel = 500,
        multiplier = 10
    }, {
        minlevel = 501,
        maxlevel = 550,
        multiplier = 7
    }, {
        minlevel = 551,
        maxlevel = 2000,
        multiplier = 5
    }
}

skillsStages = {
    {
        minlevel = 10,
        maxlevel = 60,
        multiplier = 50
    }, {
        minlevel = 61,
        maxlevel = 80,
        multiplier = 35
    }, {
        minlevel = 81,
        maxlevel = 110,
        multiplier = 20
    }, {
        minlevel = 111,
        maxlevel = 125,
        multiplier = 15
    }, {
        minlevel = 126,
        multiplier = 10
    }
}

magicLevelStages = {
    {
        minlevel = 0,
        maxlevel = 60,
        multiplier = 25
    }, {
        minlevel = 61,
        maxlevel = 80,
        multiplier = 20
    }, {
        minlevel = 81,
        maxlevel = 100,
        multiplier = 15
    }, {
        minlevel = 101,
        maxlevel = 110,
        multiplier = 10
    }, {
        minlevel = 111,
        maxlevel = 125,
        multiplier = 5
    }, {
        minlevel = 126,
        multiplier = 2
    }
}

Thank you for your attention, waiting for replies! :)
 
Solution
You are trying to access skills[itemid].id which doesnt scist in your configuration. Try changing in the comfig the itemid inside brsckets to id or change the code to skills[itemid].itemid
You are trying to access skills[itemid].id which doesnt scist in your configuration. Try changing in the comfig the itemid inside brsckets to id or change the code to skills[itemid].itemid
 
Solution
Hey @samco, thanks for the help. I changed the skills[itemid].id to skills[itemid].itemid. It stopped training fist fighting but now doesnt train any skill. LOL

Here's the code:
Lua:
local skills = {
    [32384] = {itemid=SKILL_SWORD,voc=4}, -- KNIGHT
    [32385] = {itemid=SKILL_AXE,voc=4}, -- KNIGHT
    [32386] = {itemid=SKILL_CLUB,voc=4}, -- KNIGHT
    [32387] = {itemid=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [32388] = {itemid=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [32389] = {itemid=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    [32124] = {itemid=SKILL_SWORD,voc=4}, -- KNIGHT
    [32125] = {itemid=SKILL_AXE,voc=4}, -- KNIGHT
    [32126] = {itemid=SKILL_CLUB,voc=4}, -- KNIGHT
    [32127] = {itemid=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [32128] = {itemid=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [32129] = {itemid=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE} -- SORCERER
}

local houseDummies = {32143, 32144, 32145, 32146, 32147, 32148}
local freeDummies = {32142, 32149}
local skillRateDefault = (configManager.getNumber(configKeys.RATE_SKILL)* 5)
local magicRateDefault = (configManager.getNumber(configKeys.RATE_MAGIC)* 5)

local function removeExerciseWeapon(player, exercise)
    exercise:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training weapon vanished.")
    stopEvent(training)
    player:setStorageValue(Storage.isTraining,0)
end

local function startTraining(playerId, startPosition, itemid, tilePosition, bonusDummy, dummyId)
    local player = Player(playerId)
    if player ~= nil then
        if Tile(tilePosition):getItemById(dummyId) then
            local playerPosition = player:getPosition()
            if startPosition:getDistance(playerPosition) == 0 and getTilePzInfo(playerPosition) then
                if player:getItemCount(itemid) >= 1 then
                    local exercise = player:getItemById(itemid,true)
                    if exercise:isItem() then
                        if exercise:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                            local charges_n = exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                            if charges_n >= 1 then
                                exercise:setAttribute(ITEM_ATTRIBUTE_CHARGES,(charges_n-1))

                                local voc = player:getVocation()

                                if skills[itemid].itemid == SKILL_MAGLEVEL then
                                    local magicRate = getRateFromTable(magicLevelStages, player:getMagicLevel(), magicRateDefault)
                                    if not bonusDummy then
                                        player:addManaSpent(math.ceil(500*magicRate))
                                    else
                                        player:addManaSpent(math.ceil(500*magicRate)*1.1) -- 10%
                                    end
                                else
                                    local skillRate = getRateFromTable(skillsStages, player:getEffectiveSkillLevel(skills[itemid].itemid), skillRateDefault)
                                    if not bonusDummy then
                                        player:addSkillTries(skills[itemid].itemid, 7*skillRate)
                                    else
                                        player:addSkillTries(skills[itemid].itemid, (7*skillRate)*1.1) -- 10%
                                    end
                                end
                                    tilePosition:sendMagicEffect(CONST_ME_HITAREA)
                                if skills[itemid].range then
                                    playerPosition:sendDistanceEffect(tilePosition, skills[itemid].range)
                                end
                                if exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES) == 0 then
                                    removeExerciseWeapon(player, exercise)
                                else
                                    local training = addEvent(startTraining, voc:getAttackSpeed(), playerId,startPosition,itemid,tilePosition,bonusDummy,dummyId)
                                    player:setStorageValue(Storage.isTraining,1)
                                end
                            else
                                removeExerciseWeapon(player, exercise)
                            end
                        end
                    end
                end
            else
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
                stopEvent(training)
                player:setStorageValue(Storage.isTraining,0)
            end
        else
            stopEvent(training)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
            player:setStorageValue(Storage.isTraining, 0)
        end
    else
        stopEvent(training)
        if player then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
            player:setStorageValue(Storage.isTraining,0)
        end
    end
    return true
end

local exerciseTraining = Action()

function exerciseTraining.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local startPos = player:getPosition()
    if player:getStorageValue(Storage.isTraining) == 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already training.")
        return false
    end
    if target:isItem() then
        if isInArray(houseDummies,target:getId()) then
            if not skills[item.itemid].range and (startPos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            startTraining(player:getId(),startPos,item.itemid,target:getPosition(), true, target:getId())
        elseif isInArray(freeDummies, target:getId()) then
            if not skills[item.itemid].range and (startPos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            startTraining(player:getId(),startPos,item.itemid,target:getPosition(), false, target:getId())
        end
    end
    return true
end

for id = 32124, 32126 do
    exerciseTraining:id(id)
end

for id = 32127, 32129 do
    exerciseTraining:id(id)
    exerciseTraining:allowFarUse(true)
end

for id = 32384, 32386 do
    exerciseTraining:id(id)
end

for id = 32387, 32389 do
    exerciseTraining:id(id)
    exerciseTraining:allowFarUse(true)
end

exerciseTraining:register()
 
Firstly you use the same variable name for skills names and of a holding weapons:
here
{itemid=SKILL_DISTANCE
and here
player:getItemCount(itemid)
so there can be problems.

Try
Lua:
local skills = {
    [32384] = {skillid=SKILL_SWORD,voc=4}, -- KNIGHT
    [32385] = {skillid=SKILL_AXE,voc=4}, -- KNIGHT
    [32386] = {skillid=SKILL_CLUB,voc=4}, -- KNIGHT
    [32387] = {skillid=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [32388] = {skillid=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [32389] = {skillid=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    [32124] = {skillid=SKILL_SWORD,voc=4}, -- KNIGHT
    [32125] = {skillid=SKILL_AXE,voc=4}, -- KNIGHT
    [32126] = {skillid=SKILL_CLUB,voc=4}, -- KNIGHT
    [32127] = {skillid=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [32128] = {skillid=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [32129] = {skillid=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE} -- SORCERER
}

local houseDummies = {32143, 32144, 32145, 32146, 32147, 32148}
local freeDummies = {32142, 32149}
local skillRateDefault = (configManager.getNumber(configKeys.RATE_SKILL)* 5)
local magicRateDefault = (configManager.getNumber(configKeys.RATE_MAGIC)* 5)

local function removeExerciseWeapon(player, exercise)
    exercise:remove(1)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training weapon vanished.")
    stopEvent(training)
    player:setStorageValue(Storage.isTraining,0)
end

local function startTraining(playerId, startPosition, itemid, tilePosition, bonusDummy, dummyId)
    local player = Player(playerId)
    if player ~= nil then
        if Tile(tilePosition):getItemById(dummyId) then
            local playerPosition = player:getPosition()
            if startPosition:getDistance(playerPosition) == 0 and getTilePzInfo(playerPosition) then
                if player:getItemCount(itemid) >= 1 then
                    local exercise = player:getItemById(itemid,true)
                    if exercise:isItem() then
                        if exercise:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                            local charges_n = exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                            if charges_n >= 1 then
                                exercise:setAttribute(ITEM_ATTRIBUTE_CHARGES,(charges_n-1))

                                local voc = player:getVocation()

                                if skills[itemid].skillid == SKILL_MAGLEVEL then
                                    local magicRate = getRateFromTable(magicLevelStages, player:getMagicLevel(), magicRateDefault)
                                    if not bonusDummy then
                                        player:addManaSpent(math.ceil(500*magicRate))
                                    else
                                        player:addManaSpent(math.ceil(500*magicRate)*1.1) -- 10%
                                    end
                                else
                                    local skillRate = getRateFromTable(skillsStages, player:getEffectiveSkillLevel(skills[itemid].skillid), skillRateDefault)
                                    if not bonusDummy then
                                        player:addSkillTries(skills[itemid].skillid, 7*skillRate)
                                    else
                                        player:addSkillTries(skills[itemid].skillid, (7*skillRate)*1.1) -- 10%
                                    end
                                end
                                    tilePosition:sendMagicEffect(CONST_ME_HITAREA)
                                if skills[itemid].range then
                                    playerPosition:sendDistanceEffect(tilePosition, skills[itemid].range)
                                end
                                if exercise:getAttribute(ITEM_ATTRIBUTE_CHARGES) == 0 then
                                    removeExerciseWeapon(player, exercise)
                                else
                                    local training = addEvent(startTraining, voc:getAttackSpeed(), playerId,startPosition,itemid,tilePosition,bonusDummy,dummyId)
                                    player:setStorageValue(Storage.isTraining,1)
                                end
                            else
                                removeExerciseWeapon(player, exercise)
                            end
                        end
                    end
                end
            else
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
                stopEvent(training)
                player:setStorageValue(Storage.isTraining,0)
            end
        else
            stopEvent(training)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
            player:setStorageValue(Storage.isTraining, 0)
        end
    else
        stopEvent(training)
        if player then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Your training has stopped.")
            player:setStorageValue(Storage.isTraining,0)
        end
    end
    return true
end

local exerciseTraining = Action()

function exerciseTraining.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local startPos = player:getPosition()
    if player:getStorageValue(Storage.isTraining) == 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already training.")
        return false
    end
    if target:isItem() then
        if isInArray(houseDummies,target:getId()) then
            if not skills[item.itemid].range and (startPos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            startTraining(player:getId(),startPos,item.itemid,target:getPosition(), true, target:getId())
        elseif isInArray(freeDummies, target:getId()) then
            if not skills[item.itemid].range and (startPos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_INFO_DESCR, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You started training.")
            startTraining(player:getId(),startPos,item.itemid,target:getPosition(), false, target:getId())
        end
    end
    return true
end

for id = 32124, 32126 do
    exerciseTraining:id(id)
end

for id = 32127, 32129 do
    exerciseTraining:id(id)
    exerciseTraining:allowFarUse(true)
end

for id = 32384, 32386 do
    exerciseTraining:id(id)
end

for id = 32387, 32389 do
    exerciseTraining:id(id)
    exerciseTraining:allowFarUse(true)
end

exerciseTraining:register()
 
Yes, @jestem pro, thanks for the help, I was messing around with the code a bit, and appears that everything its working, I just need to change the rate that the skills level up, its too low. I just saw your reply, I'm gonna run some tests with this code you reply, but I think its working fine now. Thanks again.
 
Sorry about my writing, i just relalized how bad I did lol. I am in mobile and cannot do it properly. As you and jestem said, it was a matter of the variable names.
 
Lua:
Lua Script Error: [Scripts Interface]
D:\EVOLIGHT OT\Engine [DEV]\data\scripts\exercise weapons.lua:callback
...OLIGHT OT\Engine [DEV]\data\scripts\exercise weapons.lua:99: attempt to index global 'Storage' (a nil value)
stack traceback:
        [C]: in function '__index'
        ...OLIGHT OT\Engine [DEV]\data\scripts\exercise weapons.lua:99: in function <...OLIGHT OT\Engine [DEV]\data\scripts\exercise weapons.lua:97>
 
Back
Top