• 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+ Training weapons used directly from players store inbox

Unknown Soldier

Mapping a map
Joined
Oct 30, 2010
Messages
297
Solutions
11
Reaction score
670
Hello,

After few failed trials, I give up. I would want to change the exercise training script so that it would allow players to use the weapons BOTH from their store inbox right away, without a need of moving them into inventory first, and preserve the ability to use them from the backpack in inventory too. I thought that as soon as I would get the item id/count from the store inbox after iterating it, things would go easier afterwards, but they made me stuck.

What I got so far? Lines 47-65 - those are the lines that iterates through the players store inbox.
And problematic to me are the lines 72-79 (and probably later the lines with exercise:remove(1) and/or exercise:setAttribute...).

So if the script finds the certain weapon in store inbox, it should allow to go further into the script, thus allowing the training. Instead of

local exercise = player:getItemById(itemid,true)

I've tried things like

local exercise = storeInbox:getItemById(itemid,true)

or some others... But no success, and the line

if exercise:isItem() then

is giving me contstant errors. Could anyone take a look at this?

Thanks in advance

Lua:
local skills = {
    --shields
    [41860] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41861] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41862] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41863] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    --training weapons
    [31196] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31197] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31198] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31199] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31200] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [31201] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --exercise weapons
    [31208] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31209] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31210] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31211] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31212] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [31213] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --durable exercise weapons
    [41848] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41849] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41850] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41851] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41852] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [41853] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --lasting exercise weapons
    [41854] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41855] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41856] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41857] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41858] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [41859] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
}
 
------- CONFIG -----//
local houseDummies = {31215, 31216, 31217, 31218, 31219, 31220}
local freeDummies = {31214, 31221}
local skillRate = 2*configManager.getNumber(configKeys.RATE_SKILL)
local magicRate = 2*configManager.getNumber(configKeys.RATE_MAGIC)
isTrainingStorage = 4000
 
local function start_train(pid, start_pos, itemid, tilePosition, bonusDummy, dummyId)
local player = Player(pid)

    local hasStoreItem = 0
    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return false
    end
    
    for _, item in ipairs(storeInbox:getItems()) do
        if item:getId() == itemid then
            hasStoreItem = hasStoreItem + 1
            print(hasStoreItem)
        end
    end
    
    if hasStoreItem >= 1 then
        print("got the weapon")
        print(itemid) --return item ID of used weapon
    else
        print("no weapon")
    end
    
if player ~= nil then
-- local pos_n = player:getPosition()
    if Tile(tilePosition):getItemById(dummyId) then
        local pos_n = player:getPosition()
        if start_pos:getDistance(pos_n) == 0 then --and getTilePzInfo(pos_n) then
            if player:getItemCount(itemid) >= 1 then
                local exercise = player:getItemById(itemid,true)
                print(exercise)
                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
                                magicTry = voc:getRequiredManaSpent(player:getBaseMagicLevel() + 1)-player:getManaSpent()
                                if not bonusDummy then
                                    player:addManaSpent(math.ceil(250*magicRate))
                                    player:addSkillTries(SKILL_SHIELD, 1*skillRate)
                                else
                                    player:addManaSpent(math.ceil(250*magicRate)*1.1) -- 10%
                                    player:addSkillTries(SKILL_SHIELD, (1*skillRate)*1.1) -- 10%
                                end
                            else
                                if not bonusDummy then
                                    player:addSkillTries(skills[itemid].id, 1*skillRate)
                                    player:addSkillTries(SKILL_SHIELD, 1*skillRate)
                                else
                                    player:addSkillTries(skills[itemid].id, (1*skillRate)*1.1) -- 10%
                                    player:addSkillTries(SKILL_SHIELD, (1*skillRate)*1.1) -- 10%
                                end
                            end
                             tilePosition:sendMagicEffect(CONST_ME_HITAREA)
                            if skills[itemid].range then
                                pos_n:sendDistanceEffect(tilePosition, skills[itemid].range)
                            end
                            --player:setStamina(player:getStamina() + 60)
                            if charges_n == 1 then
                                exercise:remove(1)
                                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has ran out of charges.")
                                player:setStorageValue(isTrainingStorage, 0)
                                return true
                            end
                                    local training = addEvent(start_train, voc:getAttackSpeed(), pid,start_pos,itemid,tilePosition,bonusDummy,dummyId)
                                    player:setStorageValue(isTrainingStorage, 1)
                        else
                            exercise:remove(1)
                            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has vanished.")
                            stopEvent(training)
                            player:setStorageValue(isTrainingStorage, 0)
                        end
                    end
                end
            else
                -- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has been lost.")
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Move your training weapon outside store inbox first.")
                stopEvent(training)
                player:setStorageValue(isTrainingStorage, 0)       
            end
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has stopped, you moved.")
            stopEvent(training)
            player:setStorageValue(isTrainingStorage, 0)
        end
    else
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has stopped, dummy was moved.")
        stopEvent(training)
        player:setStorageValue(isTrainingStorage, 0)
    end       
else
    stopEvent(training) 
    if player then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has stopped.")
        player:setStorageValue(isTrainingStorage, 0)
    else
        return true
    end
end
    return true
end
 
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local start_pos = player:getPosition()
    local target_pos = target:getPosition()
    
    if target:isItem() then

        if player:getStorageValue(isTrainingStorage) == 1 then
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are already training.")
            return true
        end
        
        if isInArray(houseDummies,target:getId()) then
            if not skills[item.itemid].range and (start_pos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has started (with 10% bonus).")
            start_train(player:getId(),start_pos,item.itemid,target:getPosition(), true, target:getId())   
        elseif isInArray(freeDummies,target:getId()) then
            if not skills[item.itemid].range and (start_pos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end

            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has started.")
            start_train(player:getId(),start_pos,item.itemid,target:getPosition(), false, target:getId())           
        end
        
    end
 
    return true
end
 
I managed to solve the problem, but it took 2 hours. Please watch the video to see how everything works correctly. However, I'm having trouble adding items when the charges run out and removing the item from the Store Inbox... but everything else is working fine, okay.


Revscripts.
Lua:
local configKeys = {
    RATE_SKILL = "RATE_SKILL",
    RATE_MAGIC = "RATE_MAGIC"
}

local configManager = {
    getNumber = function(key)
        return 1
    end
}

local config = {
    gain_stamina = 60,
    skillRate = 2 * configManager.getNumber(configKeys.RATE_SKILL),
    magicRate = 2 * configManager.getNumber(configKeys.RATE_MAGIC),
    storage = 4000,
    houseDummies = {31215, 31216, 31217, 31218, 31219, 31220},
    freeDummies = {31214, 31221}
}

local skills = {
    --shields
    [41860] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41861] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41862] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41863] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    --training weapons
    [31196] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31197] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31198] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31199] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31200] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [31201] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --exercise weapons
    [31208] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31209] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31210] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31211] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31212] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [31213] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --durable exercise weapons
    [41848] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41849] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41850] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41851] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41852] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [41853] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --lasting exercise weapons
    [41854] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41855] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41856] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41857] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41858] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [41859] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
}

local trainingMessages = {
    alreadyTraining = "You are already training.",
    getCloseToDummy = "Get closer to the dummy.",
    trainingStarted = "Your training has started.",
    trainingStartedBonus = "Your training has started (with 10% bonus).",
    noChargesRemaining = "Your training weapon has run out of charges.",
    moveTrainingItem = "Move your training weapon outside store inbox first.",
    trainingItemNotFound = "You don't have the training item in your store inbox.",
    storeInboxNotFound = "Store inbox not found."
}

local function start_train(pid, start_pos, itemid, fpos, bonusDummy, dummyId)
    local player = Player(pid)
    if not player then
        return
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, trainingMessages.storeInboxNotFound)
        return false
    end

    local trainingItem = nil
    for _, item in ipairs(storeInbox:getItems()) do
        if item:getId() == itemid then
            trainingItem = item
            break
        end
    end

    if not trainingItem then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, trainingMessages.trainingItemNotFound)
        return false
    end

    local voc = player:getVocation()
    local bonusApplied = false

    local function train()
        local charges_n = trainingItem:getAttribute(ITEM_ATTRIBUTE_CHARGES)
        if charges_n > 0 then
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has " .. charges_n .. " charges remaining.")
            trainingItem:setAttribute(ITEM_ATTRIBUTE_CHARGES, charges_n - 1)

            if skills[itemid].id == SKILL_MAGLEVEL then
                local magicTry = voc:getRequiredManaSpent(player:getBaseMagicLevel() + 1) - player:getManaSpent()
                if not bonusDummy then
                    player:addManaSpent(math.ceil(250 * config.magicRate))
                    player:addSkillTries(SKILL_SHIELD, 1 * config.skillRate)
                else
                    player:addManaSpent(math.ceil(250 * config.magicRate) * 1.1) -- 10%
                    player:addSkillTries(SKILL_SHIELD, (1 * config.skillRate) * 1.1) -- 10%
                    bonusApplied = true
                end
            else
                if not bonusDummy then
                    player:addSkillTries(skills[itemid].id, 1 * config.skillRate)
                    player:addSkillTries(SKILL_SHIELD, 1 * config.skillRate)
                else
                    player:addSkillTries(skills[itemid].id, (1 * config.skillRate) * 1.1) -- 10%
                    player:addSkillTries(SKILL_SHIELD, (1 * config.skillRate) * 1.1) -- 10%
                    bonusApplied = true
                end
            end

            player:getPosition():sendMagicEffect(CONST_ME_HITAREA)
            if skills[itemid].range then
                player:getPosition():sendDistanceEffect(fpos, skills[itemid].range)
            end

            if charges_n == 1 then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.noChargesRemaining)
                player:setStorageValue(config.storage, 0)
                return
            end

            addEvent(train, voc:getAttackSpeed())
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.noChargesRemaining)
            player:setStorageValue(config.storage, 0)
        end
    end

    train()

    if bonusApplied then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.trainingStartedBonus)
    else
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.trainingStarted)
    end
end


for itemId, skillData in pairs(skills) do
    local action = Action(itemId)

    action.onUse = function(player, item, fromPosition, target, toPosition, isHotkey)
        local start_pos = player:getPosition()
        local target_pos = target:getPosition()

        if target:isItem() then
            local isTrainingStorage = config.storage

            if player:getStorageValue(isTrainingStorage) == 1 then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.alreadyTraining)
                return true
            end

            if isInArray(config.houseDummies, target:getId()) then
                if not skills[item:getId()].range and (start_pos:getDistance(target_pos) > 1) then
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.getCloseToDummy)
                    return true
                end
                start_train(player:getGuid(), start_pos, item:getId(), target_pos, true, target:getId())

            elseif isInArray(config.freeDummies, target:getId()) then
                if not skills[item:getId()].range and (start_pos:getDistance(target_pos) > 1) then
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.getCloseToDummy)
                    return true
                end

                start_train(player:getGuid(), start_pos, item:getId(), target_pos, false, target:getId())
            end
        end

        return true
    end

    action:id(itemId)
    action:register()
end
 
Last edited:
I managed to solve the problem, but it took 2 hours. Please watch the video to see how everything works correctly. However, I'm having trouble adding items when the charges run out and removing the item from the Store Inbox... but everything else is working fine, okay.


Revscripts.
Lua:
local configKeys = {
    RATE_SKILL = "RATE_SKILL",
    RATE_MAGIC = "RATE_MAGIC"
}

local configManager = {
    getNumber = function(key)
        return 1
    end
}

local config = {
    gain_stamina = 60,
    skillRate = 2 * configManager.getNumber(configKeys.RATE_SKILL),
    magicRate = 2 * configManager.getNumber(configKeys.RATE_MAGIC),
    storage = 4000,
    houseDummies = {31215, 31216, 31217, 31218, 31219, 31220},
    freeDummies = {31214, 31221}
}

local skills = {
    --shields
    [41860] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41861] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41862] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41863] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    --training weapons
    [31196] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31197] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31198] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31199] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31200] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [31201] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --exercise weapons
    [31208] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31209] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31210] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31211] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31212] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [31213] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --durable exercise weapons
    [41848] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41849] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41850] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41851] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41852] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [41853] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --lasting exercise weapons
    [41854] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41855] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41856] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41857] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41858] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_ENERGY}, -- DRUID
    [41859] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
}

local trainingMessages = {
    alreadyTraining = "You are already training.",
    getCloseToDummy = "Get closer to the dummy.",
    trainingStarted = "Your training has started.",
    trainingStartedBonus = "Your training has started (with 10% bonus).",
    noChargesRemaining = "Your training weapon has run out of charges.",
    moveTrainingItem = "Move your training weapon outside store inbox first.",
    trainingItemNotFound = "You don't have the training item in your store inbox.",
    storeInboxNotFound = "Store inbox not found."
}

local function start_train(pid, start_pos, itemid, fpos, bonusDummy, dummyId)
    local player = Player(pid)
    if not player then
        return
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, trainingMessages.storeInboxNotFound)
        return false
    end

    local trainingItem = nil
    for _, item in ipairs(storeInbox:getItems()) do
        if item:getId() == itemid then
            trainingItem = item
            break
        end
    end

    if not trainingItem then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, trainingMessages.trainingItemNotFound)
        return false
    end

    local voc = player:getVocation()
    local bonusApplied = false

    local function train()
        local charges_n = trainingItem:getAttribute(ITEM_ATTRIBUTE_CHARGES)
        if charges_n > 0 then
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has " .. charges_n .. " charges remaining.")
            trainingItem:setAttribute(ITEM_ATTRIBUTE_CHARGES, charges_n - 1)

            if skills[itemid].id == SKILL_MAGLEVEL then
                local magicTry = voc:getRequiredManaSpent(player:getBaseMagicLevel() + 1) - player:getManaSpent()
                if not bonusDummy then
                    player:addManaSpent(math.ceil(250 * config.magicRate))
                    player:addSkillTries(SKILL_SHIELD, 1 * config.skillRate)
                else
                    player:addManaSpent(math.ceil(250 * config.magicRate) * 1.1) -- 10%
                    player:addSkillTries(SKILL_SHIELD, (1 * config.skillRate) * 1.1) -- 10%
                    bonusApplied = true
                end
            else
                if not bonusDummy then
                    player:addSkillTries(skills[itemid].id, 1 * config.skillRate)
                    player:addSkillTries(SKILL_SHIELD, 1 * config.skillRate)
                else
                    player:addSkillTries(skills[itemid].id, (1 * config.skillRate) * 1.1) -- 10%
                    player:addSkillTries(SKILL_SHIELD, (1 * config.skillRate) * 1.1) -- 10%
                    bonusApplied = true
                end
            end

            player:getPosition():sendMagicEffect(CONST_ME_HITAREA)
            if skills[itemid].range then
                player:getPosition():sendDistanceEffect(fpos, skills[itemid].range)
            end

            if charges_n == 1 then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.noChargesRemaining)
                player:setStorageValue(config.storage, 0)
                return
            end

            addEvent(train, voc:getAttackSpeed())
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.noChargesRemaining)
            player:setStorageValue(config.storage, 0)
        end
    end

    train()

    if bonusApplied then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.trainingStartedBonus)
    else
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.trainingStarted)
    end
end


for itemId, skillData in pairs(skills) do
    local action = Action(itemId)

    action.onUse = function(player, item, fromPosition, target, toPosition, isHotkey)
        local start_pos = player:getPosition()
        local target_pos = target:getPosition()

        if target:isItem() then
            local isTrainingStorage = config.storage

            if player:getStorageValue(isTrainingStorage) == 1 then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.alreadyTraining)
                return true
            end

            if isInArray(config.houseDummies, target:getId()) then
                if not skills[item:getId()].range and (start_pos:getDistance(target_pos) > 1) then
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.getCloseToDummy)
                    return true
                end
                start_train(player:getGuid(), start_pos, item:getId(), target_pos, true, target:getId())

            elseif isInArray(config.freeDummies, target:getId()) then
                if not skills[item:getId()].range and (start_pos:getDistance(target_pos) > 1) then
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, trainingMessages.getCloseToDummy)
                    return true
                end

                start_train(player:getGuid(), start_pos, item:getId(), target_pos, false, target:getId())
            end
        end

        return true
    end

    action:id(itemId)
    action:register()
end

You rebuilded it completely, respect. Using from store inbox is working, but in my case the training now looks like this:

training.gif

Kinda funny ^^

It is rather a walkaround than a solution, you might try something like this to remove the wepons from store inbox:
use with -> dustbin

Lua:
    if target:isItem() then
        if target:getId() == 1777 then --dustbin
            local charges = item:getAttribute(ITEM_ATTRIBUTE_CHARGES)
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have thrown " .. item:getArticle() .. " ".. item:getName() .. " with remaining " .. charges .. " charges in the dustbin.")   
            item:remove(1)
            return true
        end
     end


Well, I will take a look at this in few days and analyse, I am tired of scripting after few days and good amount of hours by the PC.

Thanks for your time!
 
Aside from the actual issue.. why are you searching the player inventory for the itemid?
Shouldn't you just check for the item that was used originally?

Cuz right now if someone had 2 of the same item, and used the '2nd' item in their inventory, the '1st' item in their inventory would lose it's charges, instead of the item that was actually used.
 
hank you for saying what I needed to hear. I'm also quite tired of the script... Soon, I'll analyze the script more to improve it 100% for my server. :)

Thanks to you I was able to improve the script and basically solve ths issue that I had starting this thread :)
Lua:
local skills = {
    --shields
    [41860] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41861] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41862] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    [41863] = {id=SKILL_SHIELD,voc=4}, -- KNIGHT
    --training weapons
    [31196] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31197] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31198] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31199] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31200] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [31201] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --exercise weapons
    [31208] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [31209] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [31210] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [31211] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [31212] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [31213] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --durable exercise weapons
    [41848] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41849] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41850] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41851] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41852] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [41853] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
    --lasting exercise weapons
    [41854] = {id=SKILL_SWORD,voc=4}, -- KNIGHT
    [41855] = {id=SKILL_AXE,voc=4}, -- KNIGHT
    [41856] = {id=SKILL_CLUB,voc=4}, -- KNIGHT
    [41857] = {id=SKILL_DISTANCE,voc=3,range=CONST_ANI_SIMPLEARROW}, -- PALADIN
    [41858] = {id=SKILL_MAGLEVEL,voc=2,range=CONST_ANI_SMALLICE}, -- DRUID
    [41859] = {id=SKILL_MAGLEVEL,voc=1,range=CONST_ANI_FIRE}, -- SORCERER
}
 
------- CONFIG -----//
local houseDummies = {31215, 31216, 31217, 31218, 31219, 31220}
local freeDummies = {31214, 31221}
local skillRate = 2*configManager.getNumber(configKeys.RATE_SKILL)
local magicRate = 2*configManager.getNumber(configKeys.RATE_MAGIC)
isTrainingStorage = 4000
 
local function start_train(pid, start_pos, itemid, tilePosition, bonusDummy, dummyId)
local player = Player(pid)

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return false
    end

    local trainingItem = nil
    for _, item in ipairs(storeInbox:getItems()) do
        if item:getId() == itemid then
            trainingItem = item
        end
    end

    if not trainingItem then
        return false
    end

if player ~= nil then
    if Tile(tilePosition):getItemById(dummyId) then
        local pos_n = player:getPosition()
        if start_pos:getDistance(pos_n) == 0 then
            if trainingItem:isItem() then
                if trainingItem:hasAttribute(ITEM_ATTRIBUTE_CHARGES) then
                    local charges_n = trainingItem:getAttribute(ITEM_ATTRIBUTE_CHARGES)
                    if charges_n >= 1 then
                        trainingItem:setAttribute(ITEM_ATTRIBUTE_CHARGES, (charges_n-1))

                        local voc = player:getVocation()
                        
                        if skills[itemid].id == SKILL_MAGLEVEL then
                            magicTry = voc:getRequiredManaSpent(player:getBaseMagicLevel() + 1)-player:getManaSpent()
                            if not bonusDummy then
                                player:addManaSpent(math.ceil(250*magicRate))
                                player:addSkillTries(SKILL_SHIELD, 1*skillRate)
                            else
                                player:addManaSpent(math.ceil(250*magicRate)*1.1) -- 10%
                                player:addSkillTries(SKILL_SHIELD, (1*skillRate)*1.1) -- 10%
                            end
                        else
                            if not bonusDummy then
                                player:addSkillTries(skills[itemid].id, 1*skillRate)
                                player:addSkillTries(SKILL_SHIELD, 1*skillRate)
                            else
                                player:addSkillTries(skills[itemid].id, (1*skillRate)*1.1) -- 10%
                                player:addSkillTries(SKILL_SHIELD, (1*skillRate)*1.1) -- 10%
                            end
                        end
                         tilePosition:sendMagicEffect(CONST_ME_HITAREA)
                        if skills[itemid].range then
                            pos_n:sendDistanceEffect(tilePosition, skills[itemid].range)
                        end
                        if charges_n == 1 then
                            trainingItem:remove(1)
                            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has ran out of charges.")
                            player:setStorageValue(isTrainingStorage, 0)
                            return true
                        end
                                local training = addEvent(start_train, voc:getAttackSpeed(), pid,start_pos,itemid,tilePosition,bonusDummy,dummyId)
                                player:setStorageValue(isTrainingStorage, 1)
                    else
                        trainingItem:remove(1)
                        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training weapon has vanished.")
                        stopEvent(training)
                        player:setStorageValue(isTrainingStorage, 0)
                    end
                end
            end
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has stopped, you moved.")
            stopEvent(training)
            player:setStorageValue(isTrainingStorage, 0)
        end
    else
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has stopped, dummy was moved.")
        stopEvent(training)
        player:setStorageValue(isTrainingStorage, 0)
    end       
else
    stopEvent(training)
    if player then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has stopped.")
        player:setStorageValue(isTrainingStorage, 0)
    else
        return true
    end
end
    return true
end
 
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local start_pos = player:getPosition()
    local target_pos = target:getPosition()
    
    if target:isItem() then
        if target:getId() == 1777 then
            local charges = item:getAttribute(ITEM_ATTRIBUTE_CHARGES)
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have thrown " .. item:getArticle() .. " ".. item:getName() .. " with remaining " .. charges .. " charges in the dustbin.")   
            item:remove(1)
            return true
        end
        
        if player:getStorageValue(isTrainingStorage) == 1 then
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are already training.")
            return true
        end
        
        if isInArray(houseDummies,target:getId()) then
            if not skills[item.itemid].range and (start_pos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has started (with 10% bonus).")
            start_train(player:getId(),start_pos,item.itemid,target:getPosition(), true, target:getId())   
        elseif isInArray(freeDummies,target:getId()) then
            if not skills[item.itemid].range and (start_pos:getDistance(target:getPosition()) > 1) then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Get closer to the dummy.")
                stopEvent(training)
                return true
            end

            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your training has started.")
            start_train(player:getId(),start_pos,item.itemid,target:getPosition(), false, target:getId())           
        end
    end
 
    return true
end

Aside from the actual issue.. why are you searching the player inventory for the itemid?
Shouldn't you just check for the item that was used originally?

Cuz right now if someone had 2 of the same item, and used the '2nd' item in their inventory, the '1st' item in their inventory would lose it's charges, instead of the item that was actually used.
The issue you mentioned was exactly what was happening, so I've removed that part... But now I am iterating through players store inbox, so it will do exactly the same, in mentioned case it will burn charges from another weapon. I think it doesn't bother me that much, but maybe one day I will just find it relaxing to find the solution. Thank you for pointing that out!
 
Back
Top