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

Action Exercise Dummy for TFS 0.4 :o

Thanks for reporting these errors, i have already fixed them and i also added that the weapon can only be used in a certain slot.
on this case CONST_SLOT_AMMO
Code:
---@ Create by Sarah Wesker | Tested Version: TFS 0.4
---@ list of training dummies.
local dummies = {
    [1443] = { skillRate = 1, skillSpeed = 1 },
    [26404] = { skillRate = 1, skillSpeed = 1 }
}

---@ Global training parameters of the system.
local staminaTries = 1 --# on minutes
local skillTries = 7 --# tries by blow
local skillSpent = function() return math.random(425, 575) end --# mana consumed by blow
local slotForUse = CONST_SLOT_AMMO

---@ list of weapons to train.
local weapons = {
    [26401] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_CAKE, skillType = SKILL_MAGLEVEL }, -- magicLevel Dru
    [26402] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_ENERGY, skillType = SKILL_MAGLEVEL }, -- magicLevel Sor
    [26400] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_SIMPLEARROW, skillType = SKILL_DISTANCE }, -- distance
    [2376] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_SWORD }, -- sword
    [26398] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_AXE }, -- axe
    [26399] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_CLUB } -- club
}

---@ EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

---@ functions to assign or obtain the training status of a player.
function getPlayerExerciseTrain(cid) return EDTE[cid] or false end
function setPlayerExerciseTrain(cid, status) EDTE[cid] = status return status end

---@ local training function.
local function exerciseDummyTrainEvent(params, weapon)
    if isPlayer(params.cid) then
        local item = getPlayerSlotItem(params.cid, slotForUse)
        local playerPosition = getCreaturePosition(params.cid)
        if getDistanceBetween(playerPosition, params.currentPos) == 0 and item.itemid == params.itemid then
            local weaponCharges = getItemAttribute(item.uid, "charges") or getItemInfo(params.itemid).charges
            local reloadMs = getVocationInfo(getPlayerVocation(params.cid)).attackSpeed * params.dummy.skillSpeed
            if weaponCharges >= 1 then
                doItemSetAttribute(item.uid, "charges", weaponCharges -1)
                if weapon.shootDistEffect then doSendDistanceShoot(playerPosition, params.dummyPos, weapon.shootDistEffect) end
                if weapon.shootEffect then doSendMagicEffect(params.dummyPos, weapon.shootEffect) end
                if weapon.skillType == SKILL_MAGLEVEL then
                    doPlayerAddManaSpent(params.cid, (skillSpent() * params.dummy.skillRate) * getConfigValue("rateMagic"))
                else
                    doPlayerAddSkillTry(params.cid, weapon.skillType, (skillTries * params.dummy.skillRate) * getConfigValue("rateSkill"))
                end
                local currentStamina = getPlayerStamina(params.cid)
                doPlayerSetStamina(params.cid, currentStamina + staminaTries)
                if weaponCharges <= 1 then
                    exerciseDummyTrainEvent(params, weapon)
                else
                    setPlayerExerciseTrain(params.cid, addEvent(exerciseDummyTrainEvent, reloadMs, params, weapon))
                end
                return true
            else
                doRemoveItem(item.uid)
                doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "Your exercise weapon has expired, therefore your training too.")
            end
        else
            doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "You have finished your training.")
        end
    end
    return setPlayerExerciseTrain(params.cid, nil)
end

function onUse(cid, item, fromPos, target, toPos, isHotkey)
    local ammo = getPlayerSlotItem(cid, slotForUse)
    if ammo.uid ~= item.uid then
        return doPlayerSendCancel(cid, "The weapon must be located in your slot ammunition.")
    end
    if not target then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    end
    local playerPosition = getCreaturePosition(cid)
    if not getTileInfo(playerPosition).protection then
        return doPlayerSendCancel(cid, "You can only train in protection zone.")
    end
    local dummy = dummies[target.itemid]
    local weapon = weapons[item.itemid]
    if not weapon or not dummy then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_CANNOTUSETHISOBJECT)
    end
    local dummyPosition = getThingPosition(target.uid)
    if getDistanceBetween(playerPosition, dummyPosition) > 1 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
    if not getPlayerExerciseTrain(cid) then
        local params = {}
        params.cid = cid
        params.currentPos = playerPosition
        params.dummyPos = dummyPosition
        params.itemid = item.itemid
        params.dummy = dummy
        exerciseDummyTrainEvent(params, weapon)
        doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have started training with dummy.")
    else
        doPlayerSendCancel(cid, "You can not train")
    end
    return true
end

If I forget something, please let me know.
i tested your script and for some reason it would not work for me it would ask for it to be slot arrow but then it just wouldnt work it could be because u made slotforuse and wrong getplayerSlot check my script it works but i now moved it to getplayer pos instead of and isplayer
 
If it is possible that you have details for your version, the code is fully functional for the version that was published.
If you achieve a favorable change and it works for another version, publish it without any commitment, maybe you help other people who use your version, thanks! ;)
 
If it is possible that you have details for your version, the code is fully functional for the version that was published.
If you achieve a favorable change and it works for another version, publish it without any commitment, maybe you help other people who use your version, thanks! ;)
my differnece:
getPlayerSlotItem(params.cid, CONST_SLOT_RIGHT).itemid == params.itemid then
 
ps for everyone in the thread this is what happened between me and sarah wesker
az9WQpj_460swp.webp
 
I'm little confused wich is the final scripts? unbugged...
This new function that not allow the thread creator edit the topic is sucks
 
@Sarah Wesker hi again sarah, ive just found another bug (i couldnt test before). If u start using training weapon and you drop it to the ground, it will stop cosuming charges, any chance to fix this? thanks in advance, regards!

@fyalhed try this
Lua:
---@ Create by Sarah Wesker | Tested Version: TFS 0.4
---@ list of training dummies.
local dummies = {
    [1443] = { skillRate = 1, skillSpeed = 0.5 },
    [5777] = { skillRate = 1, skillSpeed = 0.5 }
}

---@ Global training parameters of the system.
local staminaTries = 1 --# on minutes
local skillTries = 7 --# tries by blow
local skillSpent = function() return math.random(425, 575) end --# mana consumed by blow

---@ list of weapons to train.
local weapons = {
    [26401] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_CAKE, skillType = SKILL_MAGLEVEL }, -- magicLevel Dru
    [2433] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_ENERGY, skillType = SKILL_MAGLEVEL }, -- magicLevel Sor
    [2352] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_SIMPLEARROW, skillType = SKILL_DISTANCE }, -- distance
    [2376] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_SWORD }, -- sword
    [2388] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_AXE }, -- axe
    [2401] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_CLUB } -- club
}

---@ EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

---@ functions to assign or obtain the training status of a player.
function getPlayerExerciseTrain(cid) return EDTE[cid] or false end
function setPlayerExerciseTrain(cid, status) EDTE[cid] = status return status end

---@ local training function.
local function exerciseDummyTrainEvent(params, weapon)
    if isPlayer(params.cid) then
        local item = getPlayerItemById(params.cid, true, params.itemid)
        local playerPosition = getCreaturePosition(params.cid)
        if getDistanceBetween(playerPosition, params.currentPos) == 0 then
            local weaponCharges = getItemAttribute(item.uid, "charges") or getItemInfo(params.itemid).charges
            local reloadMs = getVocationInfo(getPlayerVocation(params.cid)).attackSpeed * params.dummy.skillSpeed
            if weaponCharges >= 1 then
                doItemSetAttribute(item.uid, "charges", weaponCharges -1)
                if weapon.shootDistEffect then doSendDistanceShoot(playerPosition, params.dummyPos, weapon.shootDistEffect) end
                if weapon.shootEffect then doSendMagicEffect(params.dummyPos, weapon.shootEffect) end
                if weapon.skillType == SKILL_MAGLEVEL then
                    doPlayerAddSpentMana(params.cid, (skillSpent() * params.dummy.skillRate) * getConfigValue("rateMagic"))
                else
                    doPlayerAddSkillTry(params.cid, weapon.skillType, (skillTries * params.dummy.skillRate) * getConfigValue("rateSkill"))
                end
                local currentStamina = getPlayerStamina(params.cid)
                doPlayerSetStamina(params.cid, currentStamina + staminaTries)
                if weaponCharges <= 1 then
                    exerciseDummyTrainEvent(params, weapon)
                else
                    setPlayerExerciseTrain(params.cid, addEvent(exerciseDummyTrainEvent, reloadMs, params, weapon))
                end
                return true
            else
                doRemoveItem(item.uid)
                doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "Your exercise weapon has expired, therefore your training too.")
            end
        else
            doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "You have finished your training.")
        end
    end
    return setPlayerExerciseTrain(params.cid, nil)
end

function onUse(cid, item, fromPos, target, toPos, isHotkey)
    if not target then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    end
    local playerPosition = getCreaturePosition(cid)
    if not getTileInfo(playerPosition).protection then
        return doPlayerSendCancel(cid, "You can only train in protection zone.")
    end
    local dummy = dummies[target.itemid]
    local weapon = weapons[item.itemid]
    if not weapon or not dummy then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_CANNOTUSETHISOBJECT)
    end
    local dummyPosition = getThingPosition(target.uid)
    if getDistanceBetween(playerPosition, dummyPosition) > 1 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
    if not getPlayerExerciseTrain(cid) then
        local params = {}
        params.cid = cid
        params.currentPos = playerPosition
        params.dummyPos = dummyPosition
        params.item = item.uid
        params.itemid = item.itemid
        params.dummy = dummy
        exerciseDummyTrainEvent(params, weapon)
        doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have started training with dummy.")
    else
        doPlayerSendCancel(cid, "You can not train")
    end
    return true
end

then add something like this in the items mentioned in the script, example:
Lua:
    <item id="2376" article="a" name="training sword">
            <attribute key="description" value="Use this in a target to train sword with knights." />
        <attribute key="weight" value="3500" />
        <attribute key="defense" value="1" />
        <attribute key="attack" value="1" />
        <attribute key="charges" value="200" />
        <attribute key="showcharges" value="1" />
        <attribute key="weaponType" value="sword" />
        <attribute key="extradef" value="1" />
    </item>
 
sorry for double posting ive just saw the issue was solved here
 
Last edited:
@rikardok10 here, with npc and tested on tfs 0.4. You need to equip the training weapon on your left hand, then use it on the target. To set the action id to the item just use the NPC I leave at the bottom of this post

data/actions

XML:
<action actionid="1443" event="script" value="dummy.lua"/>

Lua:
---@ Create by Sarah Wesker | Tested Version: TFS 0.4
---@ list of training dummies.
local dummies = {
    [1443] = { skillRate = 1, skillSpeed = 0.5 },
    [5777] = { skillRate = 1, skillSpeed = 0.5 }
}

---@ Global training parameters of the system.
local staminaTries = 1 --# on minutes
local skillTries = 7 --# tries by blow
local skillSpent = function() return math.random(425, 575) end --# mana consumed by blow
local slotForUse = CONST_SLOT_AMMO

---@ list of weapons to train.
local weapons = {
    [2401] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_POISON, skillType = SKILL_MAGLEVEL }, -- magicLevel Dru
    [2433] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_ENERGY, skillType = SKILL_MAGLEVEL }, -- magicLevel Sor
    [2404] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_SIMPLEARROW, skillType = SKILL_DISTANCE }, -- distance
    [2376] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_SWORD }, -- sword
    [2388] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_AXE }, -- axe
    [2382] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_CLUB } -- club
}

---@ EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

---@ functions to assign or obtain the training status of a player.
function getPlayerExerciseTrain(cid) return EDTE[cid] or false end
function setPlayerExerciseTrain(cid, status) EDTE[cid] = status return status end

---@ local training function.
local function exerciseDummyTrainEvent(params, weapon)
    if isPlayer(params.cid) and getPlayerSlotItem(params.cid, CONST_SLOT_LEFT).itemid == params.itemid then -- patch
        local item = getPlayerItemById(params.cid, true, params.itemid)
        local playerPosition = getCreaturePosition(params.cid)
        if getDistanceBetween(playerPosition, params.currentPos) == 0 then
            local weaponCharges = getItemAttribute(item.uid, "charges") or getItemInfo(params.itemid).charges
            local reloadMs = getVocationInfo(getPlayerVocation(params.cid)).attackSpeed * params.dummy.skillSpeed
            if weaponCharges >= 1 then
                doItemSetAttribute(item.uid, "charges", weaponCharges -1)
                if weapon.shootDistEffect then doSendDistanceShoot(playerPosition, params.dummyPos, weapon.shootDistEffect) end
                if weapon.shootEffect then doSendMagicEffect(params.dummyPos, weapon.shootEffect) end
                if weapon.skillType == SKILL_MAGLEVEL then
                    doPlayerAddSpentMana(params.cid, (skillSpent() * params.dummy.skillRate) * getConfigValue("rateMagic"))
                else
                if weapon.skillType == SKILL_NONE then
                return false
           
                else
                    doPlayerAddSkillTry(params.cid, weapon.skillType, (skillTries * params.dummy.skillRate) * getConfigValue("rateSkill"))
                end
                end
                local currentStamina = getPlayerStamina(params.cid)
                doPlayerSetStamina(params.cid, currentStamina + staminaTries)
                if weaponCharges <= 1 then
                    exerciseDummyTrainEvent(params, weapon)
                else
                    setPlayerExerciseTrain(params.cid, addEvent(exerciseDummyTrainEvent, reloadMs, params, weapon))
                end
                return true
            else
                doRemoveItem(item.uid)
                doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "Your exercise weapon has expired, therefore your training too.")
            end
        else
            doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "You have finished your training.")
        end
        else
        doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "Put weapon in your right hand.")
        return false
    end
    return setPlayerExerciseTrain(params.cid, nil)
end

function onUse(cid, item, fromPos, target, toPos, isHotkey)
    if not target then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    end
    local playerPosition = getCreaturePosition(cid)
    if not getTileInfo(playerPosition).protection then
        return doPlayerSendCancel(cid, "You can only train in protection zone.")
    end
    local dummy = dummies[target.itemid]
    local weapon = weapons[item.itemid]
    if not weapon or not dummy then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_CANNOTUSETHISOBJECT)
    end

    local dummyPosition = getThingPosition(target.uid)
    if getDistanceBetween(playerPosition, dummyPosition) > 1 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
    if not getPlayerExerciseTrain(cid) then
        local params = {}
        params.cid = cid
        params.currentPos = playerPosition
        params.dummyPos = dummyPosition
        params.item = item.uid
        params.itemid = item.itemid
        params.dummy = dummy
        exerciseDummyTrainEvent(params, weapon)
        doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have started training with dummy.")
    else
        doPlayerSendCancel(cid, "You can not train")
    end
    return true
end

data/npc
create this .xml file with the name of your npc

XML:
<npc name="Ralke" script="data/npc/scripts/dummy.lua" walkinterval="0" floorchange="0">
<health now="100" max="100"/>
<look type="128" head="116" body="69" legs="87" feet="20" addons="0"/>
<parameters>
        <parameter key="message_greet" value="Hello |PLAYERNAME|. Which skill would you like to train? Say {offer} for more information."/>
        <parameter key="message_farewell" value="Good bye, Arghhhh."/>
        <parameter key="message_walkaway" value="Good bye, Arghhhh." />
         <parameter key="module_keywords" value="1" />
<parameter key="keywords" value="trade;job;" />
  <parameter key="keyword_reply1" value="Here you can buy the following training items: {training sword}, {training axe}, {training club}, {training distance}, {training druid}, and {training sorcerer}. I also sell {dragon necklace}, {garlic necklace} and {stone skin amulet}." />
<parameter key="keyword_reply2" value="My job is to exchange and help people with getting better skills." />
</parameters>

and .lua file on data/npc/scripts to buy weapons with assigned action id

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)                npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)            npcHandler:onCreatureDisappear(cid)            end
function onCreatureSay(cid, type, msg)            npcHandler:onCreatureSay(cid, type, msg)        end
function onThink()                    npcHandler:onThink()                    end

item = 'You do not have the required items.'
done = 'Here you are.'

function creatureSayCallback(cid, type, msg)
    if(not npcHandler:isFocused(cid)) then
        return false
    end
 
        if msgcontains(msg, 'offer') then
        selfSay('Here you can buy the following training items: {training sword}, {training axe}, {training club}, {training distance}, {training druid}, and {training sorcerer}. Also I sell the following amulets: {stone skin amulet}, {dragon necklace} and {garlic necklace}.', cid)

            elseif msgcontains(msg, 'training sword') then
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
                selfSay('Are you willing to pay 60,000 gold coins for {training sword}?', cid)
                talk_state = 1
            else
                selfSay('I need 60,000 gold coins to give you the {training sword}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 1 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
            if doPlayerRemoveItem(cid,2160, 6) or doPlayerRemoveItem(cid,2152, 600) == TRUE then
                            selfSay(done, cid)
local xx = doPlayerAddItem(cid, 2376, 1)
doItemSetAttribute(xx, "aid", 1443)
doItemSetAttribute(xx, "charges", 50)
            end
            else
                selfSay(item, cid)
            end
-- axe ---
            elseif msgcontains(msg, 'training axe') then
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
                selfSay('Are you willing to pay 60,000 gold coins for {training axe}?', cid)
                talk_state = 2
            else
                selfSay('I need 60,000 gold coins to give you the {training axe}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 2 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
            if doPlayerRemoveItem(cid,2160, 6) or doPlayerRemoveItem(cid,2152, 600) == TRUE then
                            selfSay(done, cid)
local xa = doPlayerAddItem(cid, 2388, 1)
doItemSetAttribute(xa, "aid", 1443)
doItemSetAttribute(xa, "charges", 50)
            end
            else
                selfSay(item, cid)
            end
            -- club---
            elseif msgcontains(msg, 'training club') then
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
                selfSay('Are you willing to pay 60,000 gold coins for {training club}?', cid)
                talk_state = 3
            else
                selfSay('I need 60,000 gold coins to give you the {training club}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 3 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
            if doPlayerRemoveItem(cid,2160, 6) or doPlayerRemoveItem(cid,2152, 600) == TRUE then
                            selfSay(done, cid)
local xb = doPlayerAddItem(cid, 2382, 1)
doItemSetAttribute(xb, "aid", 1443)
doItemSetAttribute(xb, "charges", 50)
            end
            else
                selfSay(item, cid)
            end
-- pally--
            elseif msgcontains(msg, 'training distance') then
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
                selfSay('Are you willing to pay 60,000 gold coins for {training distance}?', cid)
                talk_state = 4
            else
                selfSay('I need 60,000 gold coins to give you the {training distance}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 4 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
            if doPlayerRemoveItem(cid,2160, 6) or doPlayerRemoveItem(cid,2152, 600) == TRUE then
                            selfSay(done, cid)
local xc = doPlayerAddItem(cid, 2404, 1)
doItemSetAttribute(xc, "aid", 1443)
doItemSetAttribute(xc, "charges", 50)
            end
            else
                selfSay(item, cid)
            end
            --druid--
            elseif msgcontains(msg, 'training druid') then
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
                selfSay('Are you willing to pay 60,000 gold coins for {training druid}?', cid)
                talk_state = 5
            else
                selfSay('I need 60,000 gold coins to give you the {training druid}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 5 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
            if doPlayerRemoveItem(cid,2160, 6) or doPlayerRemoveItem(cid,2152, 600) == TRUE then
                            selfSay(done, cid)
local xd = doPlayerAddItem(cid, 2401, 1)
doItemSetAttribute(xd, "aid", 1443)
doItemSetAttribute(xd, "charges", 50)
            end
            else
                selfSay(item, cid)
            end
            --- sorcerer--

            elseif msgcontains(msg, 'training sorcerer') then
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
                selfSay('Are you willing to pay 60,000 gold coins for {training sorcerer}?', cid)
                talk_state = 6
            else
                selfSay('I need 60,000 gold coins to give you the {training sorcerer}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 6 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 6 or getPlayerItemCount(cid,2152) >= 600 then
            if doPlayerRemoveItem(cid,2160, 6) or doPlayerRemoveItem(cid,2152, 600) == TRUE then
                            selfSay(done, cid)
local xf = doPlayerAddItem(cid, 2433, 1)
doItemSetAttribute(xf, "aid", 1443)
doItemSetAttribute(xf, "charges", 50)
            end
            else
                selfSay(item, cid)
            end

            elseif msgcontains(msg, 'stone skin amulet') then
            if getPlayerItemCount(cid,2160) >= 1 or getPlayerItemCount(cid,2152) >= 100 then
                selfSay('Are you willing to pay 10,000 gold coins for {stone skin amulet}?', cid)
                talk_state = 7
            else
                selfSay('I need 10,000 gold coins to give you the {stone skin amulet}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 7 then
            talk_state = 0
            if getPlayerItemCount(cid,2160) >= 1 or getPlayerItemCount(cid,2152) >= 100 then
            if doPlayerRemoveItem(cid,2160, 1) or doPlayerRemoveItem(cid,2152, 100) == TRUE then
                            selfSay(done, cid)
local aq = doPlayerAddItem(cid, 2197, 1)
doItemSetAttribute(aq, "charges", 5)
            end
            else
                selfSay(item, cid)
            end
-- axe ---
            elseif msgcontains(msg, 'dragon necklace') then
            if getPlayerItemCount(cid,2148) >= 200 or getPlayerItemCount(cid,2152) >= 2 then
                selfSay('Are you willing to pay 200 gold coins for {dragon necklace}?', cid)
                talk_state = 8
            else
                selfSay('I need 200 gold coins to give you the {dragon necklace}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 8 then
            talk_state = 0
            if getPlayerItemCount(cid,2148) >= 200 or getPlayerItemCount(cid,2152) >= 2 then
            if doPlayerRemoveItem(cid,2148, 200) or doPlayerRemoveItem(cid,2152, 2) == TRUE then
                            selfSay(done, cid)
local aw = doPlayerAddItem(cid, 2201, 1)
doItemSetAttribute(aw, "charges", 200)
            end
            else
                selfSay(item, cid)
            end
            -- club---
            elseif msgcontains(msg, 'garlic necklace') then
            if getPlayerItemCount(cid,2148) >= 200 or getPlayerItemCount(cid,2152) >= 2 then
                selfSay('Are you willing to pay 200 gold coins for {garlic necklace}?', cid)
                talk_state = 9
            else
                selfSay('I need 200 gold coins to give you the {garlic necklace}. Come back when you have them.', cid)
                talk_state = 0
            end

            elseif msgcontains(msg, 'yes') and talk_state == 9 then
            talk_state = 0
            if getPlayerItemCount(cid,2148) >= 200 or getPlayerItemCount(cid,2152) >= 2 then
            if doPlayerRemoveItem(cid,2148, 200) or doPlayerRemoveItem(cid,2152, 2) == TRUE then
                            selfSay(done, cid)
local ae = doPlayerAddItem(cid, 2199, 1)
doItemSetAttribute(ae, "charges", 150)
            end
            else
                selfSay(item, cid)
            end

        elseif msgcontains(msg, 'no') and (talk_state >= 1 and talk_state <= 6) then
            selfSay('Farewell.')
            talk_state = 0
        end
    -- Place all your code in here. Remember that hi, bye and all that stuff is already handled by the npcsystem, so you do not have to take care of that yourself.
    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Works perfect for me thanks!! only one thing how can i do to be more longer because the staff only have a duratin of 1 minute @Sarah Wesker @ralke by the way thanks for the npc!
 
Works perfect for me thanks!! only one thing how can i do to be more longer because the staff only have a duratin of 1 minute @Sarah Wesker @ralke by the way thanks for the npc!
hi, on the npc i pasted here change
Lua:
doItemSetAttribute(xx, "charges", 50)

to the amount of charges you want, to every weapon in offer, and decrease the skillSpeed = 0.5 to the value you want, that will make the train longer. You can also reduce the skillRate = 1 to get a better balance
 
@ralke yes i balanced more perfect the skills rates days ago, now with the charges are more perfect!!! thanks a lot
 
Hi! i get a problem with using the dummys in the houses...
So.. I created the script with click on the furniture package and this generated a monk exercise dummy, demon exercise dummy or ferumbras exercise dummy, each dummy with each script.

Also i develop one script that player click on the dummy and transform again in furniture package.

Well its works perfectly, but if player move the dummy he's to be continued training and not stop it.
If other player move the dummy or drag to away house he's to be continued training =/.

It's possible cancel the training when dummy is not in the position to started training or with fades away?
Post automatically merged:

Hi! i get a problem with using the dummys in the houses...
So.. I created the script with click on the furniture package and this generated a monk exercise dummy, demon exercise dummy or ferumbras exercise dummy, each dummy with each script.

Also i develop one script that player click on the dummy and transform again in furniture package.

Well its works perfectly, but if player move the dummy he's to be continued training and not stop it.
If other player move the dummy or drag to away house he's to be continued training =/.

It's possible cancel the training when dummy is not in the position to started training or with fades away?
Hi again i solved xD with the simple code:

Lua:
local position = getPlayerPosition(cid)
    local ammo = getPlayerSlotItem(cid, 10).itemid
    local axe = 12671
    local sword = 12674
    local club = 12673
    local bow = 12672
    local staff = 12675

    if ammo == axe or ammo == sword or ammo == club or ammo == bow or ammo == staff  then
        return doPlayerSendCancel(cid, "You can't transform package with exercise weapon it is equiped.")
    end

    if getHouseOwner(getHouseFromPos(position)) ~= getPlayerGUID(cid) then
            doPlayerSendCancel(cid, "You can't use this item if not owner house.")
            return true
    end

with this only the owner of house can use the dummys for transform in package again, and only transform with not equiped exercise weapons =)

And the movement of statue i select no move in the object builder =)

I believe it is useful for other members, therefore i share my code.
Post automatically merged:

Ok i Discovery other problem, with one player training in house and owner use the package he's still training, How o fix It? :/
 
Last edited:
Hi! i get a problem with using the dummys in the houses...
So.. I created the script with click on the furniture package and this generated a monk exercise dummy, demon exercise dummy or ferumbras exercise dummy, each dummy with each script.

Also i develop one script that player click on the dummy and transform again in furniture package.

Well its works perfectly, but if player move the dummy he's to be continued training and not stop it.
If other player move the dummy or drag to away house he's to be continued training =/.

It's possible cancel the training when dummy is not in the position to started training or with fades away?
Post automatically merged:


Hi again i solved xD with the simple code:

Lua:
local position = getPlayerPosition(cid)
    local ammo = getPlayerSlotItem(cid, 10).itemid
    local axe = 12671
    local sword = 12674
    local club = 12673
    local bow = 12672
    local staff = 12675

    if ammo == axe or ammo == sword or ammo == club or ammo == bow or ammo == staff  then
        return doPlayerSendCancel(cid, "You can't transform package with exercise weapon it is equiped.")
    end

    if getHouseOwner(getHouseFromPos(position)) ~= getPlayerGUID(cid) then
            doPlayerSendCancel(cid, "You can't use this item if not owner house.")
            return true
    end

with this only the owner of house can use the dummys for transform in package again, and only transform with not equiped exercise weapons =)

And the movement of statue i select no move in the object builder =)

I believe it is useful for other members, therefore i share my code.
Post automatically merged:

Ok i Discovery other problem, with one player training in house and owner use the package he's still training, How o fix It? :/
You can use something like this:
Lua:
local foundDummy = getThingfromPos(params.dummyPos, false)
if foundDummy.itemid ~= params.dummyId then
    doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "The training dummy moved.")
    return setPlayerExerciseTrain(params.cid, nil)
end

1611301038929.png

Lua:
params.dummyId = target.itemid

1611301076296.png

I haven't tried it, because I can't do it right now :/
 
Well... now, after using the weapon treiner in the dummy
The system show the message:
22:34 The training dummy moved.
22:34 You have started training with dummy.

and not start trein skills

show this in the console:
Code:
[Error - Action Interface]
data/actions/scripts/exercise_dummy.lua:onUse
Description:
(LuaInterface::luaGetThingFromPosition) Tile not found

My fully code of the exercise dummy:
Lua:
---@ Create by Sarah Wesker | Tested Version: TFS 0.4
---@ list of training dummies.
local dummies = {
    [12663] = {skillRate = 0.04, skillSpeed = 4}, -- exercise dummy
    [12664] = {skillRate = 0.1, skillSpeed = 4}, -- Ferumbras Exercise Dummy
    [12665] = {skillRate = 0.1, skillSpeed = 4}, -- Ferumbras Exercise Dummy
    [12666] = {skillRate = 0.08, skillSpeed = 4}, -- Demon Exercise Dummy
    [12667] = {skillRate = 0.08, skillSpeed = 4}, -- Demon Exercise Dummy
    [12668] = {skillRate = 0.06, skillSpeed = 4}, -- Monk Exercise Dummy
    [12669] = {skillRate = 0.06, skillSpeed = 4}, -- Monk Exercise Dummy
    [12670] = {skillRate = 0.04, skillSpeed = 4} -- exercise dummy
}

---@ Global training parameters of the system.
local staminaTries = 1 --# on minutes
local skillTries = 7 --# tries by blow
local skillSpent = function() return math.random(425, 575) end --# mana consumed by blow
local slotForUse = CONST_SLOT_AMMO

---@ list of weapons to train.
local weapons = {
    [12675] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_CAKE, skillType = SKILL_MAGLEVEL }, -- magicLevel Dru
    [12672] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_SMALLSTONE, skillType = SKILL_DISTANCE }, -- distance
    [12674] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_SWORD }, -- sword
    [12671] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_AXE }, -- axe
    [12673] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_CLUB } -- club
}

---@ EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

---@ functions to assign or obtain the training status of a player.
function getPlayerExerciseTrain(cid) return EDTE[cid] or false end
function setPlayerExerciseTrain(cid, status) EDTE[cid] = status return status end

---@ local training function.
local function exerciseDummyTrainEvent(params, weapon)
    if isPlayer(params.cid) then

        local foundDummy = getThingfromPos(params.dummyPos, false)
        if foundDummy.itemid ~= params.dummyId then
            doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "The training dummy moved.")
            return setPlayerExerciseTrain(params.cid, nil)
        end

        local item = getPlayerSlotItem(params.cid, slotForUse)
        local playerPosition = getCreaturePosition(params.cid)

        if getDistanceBetween(playerPosition, params.currentPos) == 0 and item.itemid == params.itemid then
            local weaponCharges = getItemAttribute(item.uid, "charges") or getItemInfo(params.itemid).charges
            local reloadMs = getVocationInfo(getPlayerVocation(params.cid)).attackSpeed * params.dummy.skillSpeed
            if weaponCharges >= 1 then
                doItemSetAttribute(item.uid, "charges", weaponCharges -1)
                if weapon.shootDistEffect then doSendDistanceShoot(playerPosition, params.dummyPos, weapon.shootDistEffect) end
                if weapon.shootEffect then doSendMagicEffect(params.dummyPos, weapon.shootEffect) end
                if weapon.skillType == SKILL_MAGLEVEL then
                    doPlayerAddSpentMana(params.cid, (skillSpent() * params.dummy.skillRate) * getConfigValue("rateMagic"))
                else
                    doPlayerAddSkillTry(params.cid, weapon.skillType, (skillTries * params.dummy.skillRate) * getConfigValue("rateSkill"))
                end
                local currentStamina = getPlayerStamina(params.cid)
                doPlayerSetStamina(params.cid, currentStamina + staminaTries)
                if weaponCharges <= 1 then
                    exerciseDummyTrainEvent(params, weapon)
                else
                    setPlayerExerciseTrain(params.cid, addEvent(exerciseDummyTrainEvent, reloadMs, params, weapon))
                end
                return true
            else
                doRemoveItem(item.uid)
                doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "Your exercise weapon has expired, therefore your training too.")
            end
        else
            doPlayerSendTextMessage(params.cid, MESSAGE_EVENT_ADVANCE, "You have finished your training.")
        end
    end
    return setPlayerExerciseTrain(params.cid, nil)
end

function onUse(cid, item, fromPos, target, toPos, isHotkey)
    local ammo = getPlayerSlotItem(cid, slotForUse)
    if ammo.uid ~= item.uid then
        return doPlayerSendCancel(cid, "The weapon must be located in your slot ammunition.")
    end
    if not target then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    end
    
    local playerPosition = getCreaturePosition(cid)
    if not getTileInfo(playerPosition).protection and not getTileInfo(getThingPos(cid)).optional then
        return doPlayerSendCancel(cid, "You can only train in protection zone or no-pvp zone.")
    end
    local dummy = dummies[target.itemid]

    local weapon = weapons[item.itemid]
    if not weapon or not dummy then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_CANNOTUSETHISOBJECT)
    end
    
    local dummyPosition = getThingPosition(target.uid)
    if getDistanceBetween(playerPosition, dummyPosition) > 5 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end

    if not getPlayerExerciseTrain(cid) then
        local params = {}
        params.cid = cid
        params.currentPos = playerPosition
        params.dummyPos = dummyPosition
        params.itemid = item.itemid
        params.dummy = dummy
        params.dummyId = target.itemid
        exerciseDummyTrainEvent(params, weapon)
        doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have started training with dummy.")
    else
        doPlayerSendCancel(cid, "You can not train")
    end
    return true
end

I applied something wrong?
 
change:
Lua:
local foundDummy = getThingfromPos(params.dummyPos, false)
for:
Lua:
local foundDummy = getThingFromPosition(params.dummyPos)
and change:
Lua:
params.dummyPos = dummyPosition
for:
Lua:
params.dummyPos = toPos
ready!
 
Back
Top