Action Exercise Dummy for TFS 0.4 :o

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
Tested on TFS 0.4

Code:
[email protected] Create by Sarah Wesker | Tested Version: TFS 0.4
[email protected] list of training dummies.
local dummies = {
    [1443] = { skillRate = 1, skillSpeed = 1 },
    [26404] = { skillRate = 1, skillSpeed = 1 }
}

[email protected] 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

[email protected] 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
}

[email protected] EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

[email protected] 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

[email protected] 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
                    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)
    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
 

ralke

Felipe
Joined
Dec 17, 2011
Messages
269
Reaction score
32
Location
Chile
this system works good on 0.4, training magic level with this is just great
if someone is a bit lost on how to install this script, set this at items.xml

Lua:
<attribute key="charges" value="200" />
<attribute key="showcharges" value="1" /
on weapons listed as local weapons (example id 2376), the second thing is that you need to asign the action id on actions.xml to the item (use /attr aid "actionid" for testing), then use weapon on statue (has to be id 1443 or 26404) and it will start consume charges to train
 
Last edited:

zexus

Member
Joined
Oct 1, 2016
Messages
86
Reaction score
15
Just amazing...

But...
There is no much good sprites to use as train weapons on 8.6, i was thinking about using only one item (8980) as train weapon

Could you help me to give another version of this script?
If player clicks on train statue and have the item on BP checks witch weapon players have on hands
If he is using bow = train DIST, sword = train SWORD, wands or rods = train ML...

This code would help:
Code:
  -- get train type
  local traintype
  -- 1 = ML
  -- 2 = DIST
  -- 3 = SWORD
  -- 4 = AXE
  -- 5 = CLUB
  local item1 = getPlayerSlotItem(cid, CONST_SLOT_LEFT)
  local item2 = getPlayerSlotItem(cid, CONST_SLOT_RIGHT)
  local bowattack, hand1, hand2, atktotal = 0, 0, 0, 0
  if item1.uid ~= 0 then
    hand1 = getItemInfo(item1.itemid).???
  end
  if item2.uid ~= 0 then
    hand2 = getItemInfo(item2.itemid).???
  end
  if hand1 == CLUB or hand2 == CLUB then
    traintype = 5
  elseif hand1 == AXE or hand2 == AXE then
    traintype = 4
  elseif hand1 == AXE or hand2 == AXE then
    traintype = 3
  elseif hand1 == BOW or hand2 == BOW then
    traintype = 2
  elseif hand1 == WAND or hand2 == WAND or hand1 == ROD or hand2 == ROD then
    traintype = 1
  else
    doPlayerSendCancel(cid, "Put need a weapon in your hands to train (BOW=DIST) (WAND/ROD=ML) (SWORD/CLUB/AXE=MELEE).")
  end
That is more far i can go with i do know
 

maikons

Member
Joined
Aug 1, 2015
Messages
180
Reaction score
12
Not working here, i think i'm doing something wrong, in game is showing:
Code:
You cannot use this object.
Code:
<action actionid="7998" script="exercise_dummy.lua" />
 
OP
Sarah Wesker

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
The only items that need to have an actionid are weapons.
Code:
<action itemid="2376" event="script" value="exercise_dummy.lua"/>
the rest is configured in the script, remember to put loads on weapons through the file items.xml
 

maikons

Member
Joined
Aug 1, 2015
Messages
180
Reaction score
12
The only items that need to have an actionid are weapons.
Code:
<action itemid="2376" event="script" value="exercise_dummy.lua"/>
the rest is configured in the script, remember to put loads on weapons through the file items.xml
THANK YOU, you script is amazing!

But it growing skills too fast, even with:
[5777] = { skillRate = 1, skillSpeed = 1 },

How can i get it more slow?
Should i change local skillTries = 7 --# tries by blow
To local skillTries = 5 --# tries by blow

???
 
Last edited:

maikons

Member
Joined
Aug 1, 2015
Messages
180
Reaction score
12
2 others things:
1) When i use the mage weapon to train shows this error:
Code:
[16:19:48.987] [Error - Action Interface] 
[16:19:48.987] data/actions/scripts/exercise_dummy.lua:onUse
[16:19:48.987] Description: 
[16:19:48.987] data/actions/scripts/exercise_dummy.lua:44: attempt to call global 'doPlayerAddManaSpent' (a nil value)
[16:19:48.987] stack traceback:
[16:19:48.987]     data/actions/scripts/exercise_dummy.lua:44: in function 'exerciseDummyTrainEvent'
[16:19:48.987]     data/actions/scripts/exercise_dummy.lua:92: in function <data/actions/scripts/exercise_dummy.lua:67>
2) Paladin weapon just looks like the knight, don't shotting the arrow effect...
How to shot with spear effect?


Full code:
Code:
[email protected] Create by Sarah Wesker | Tested Version: TFS 0.4
[email protected] list of training dummies.
local dummies = {
    [5777] = { skillRate = 1, skillSpeed = 1 },
    [5778] = { skillRate = 1, skillSpeed = 1 },
    [5787] = { skillRate = 1, skillSpeed = 1 },
    [5788] = { skillRate = 1, skillSpeed = 1 }
}

[email protected] 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

[email protected] list of weapons to train.
local weapons = {
    [2433] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_CAKE, skillType = SKILL_MAGLEVEL }, -- magicLevel
    [2414] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_SIMPLEARROW, skillType = SKILL_DISTANCE }, -- distance
    [2446] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_SWORD }, -- sword
    [2443] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_AXE }, -- axe
    [2444] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_CLUB } -- club
}

[email protected] EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

[email protected] 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

[email protected] 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
                    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)
    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
 

ralke

Felipe
Joined
Dec 17, 2011
Messages
269
Reaction score
32
Location
Chile
having the same trouble that maikons, with magic level training, hope it can be fixed 😁
 
OP
Sarah Wesker

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
Search your sources for the corresponding function to add mana spent and replace this ->
Code:
doPlayerAddManaSpent
for the function.
36868
Here you can notice that there is no function in the variable.
 

zexus

Member
Joined
Oct 1, 2016
Messages
86
Reaction score
15
Even changing to DoPlayerAddSpentMana
There is on: https://github.com/Fir3element/3777/blob/master/src/luascript.cpp

It is showing:
Code:
[0:2:40.935] [Error - Action Interface] 
[0:2:40.935] data/actions/scripts/exercise_dummy.lua:onUse
[0:2:40.935] Description: 
[0:2:40.935] data/actions/scripts/exercise_dummy.lua:44: attempt to call global 'DoPlayerAddSpentMana' (a nil value)
[0:2:40.935] stack traceback:
[0:2:40.935]     data/actions/scripts/exercise_dummy.lua:44: in function 'exerciseDummyTrainEvent'
[0:2:40.935]     data/actions/scripts/exercise_dummy.lua:92: in function <data/actions/scripts/exercise_dummy.lua:67>
What about paladin train dont shot a spear?
 
OP
Sarah Wesker

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
Even changing to DoPlayerAddSpentMana
There is on: https://github.com/Fir3element/3777/blob/master/src/luascript.cpp

It is showing:
Code:
[0:2:40.935] [Error - Action Interface]
[0:2:40.935] data/actions/scripts/exercise_dummy.lua:onUse
[0:2:40.935] Description:
[0:2:40.935] data/actions/scripts/exercise_dummy.lua:44: attempt to call global 'DoPlayerAddSpentMana' (a nil value)
[0:2:40.935] stack traceback:
[0:2:40.935]     data/actions/scripts/exercise_dummy.lua:44: in function 'exerciseDummyTrainEvent'
[0:2:40.935]     data/actions/scripts/exercise_dummy.lua:92: in function <data/actions/scripts/exercise_dummy.lua:67>
What about paladin train dont shot a spear?
correct ->
Code:
doPlayerAddSpentMana
incorrect ->
Code:
DoPlayerAddSpentMana
you must respect the uppercase and lowercase letters
 

maikons

Member
Joined
Aug 1, 2015
Messages
180
Reaction score
12
correct ->
Code:
doPlayerAddSpentMana
incorrect ->
Code:
DoPlayerAddSpentMana
you must respect the uppercase and lowercase letters
Oh i didn't know, thanks

U didn't answer 2 things to me:

1) How can i set skills upgrade more slow?
Could i change local skillTries = 7 --# tries by blow
To local skillTries = 5 --# tries by blow
???

2) How to shot with spear effect?
Paladin weapon just looks like the knight, don't shotting the arrow dist effect...
 
OP
Sarah Wesker

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
So that the weapon of the paladins can be shot from afar you must add the following tag on actions.xml
Code:
allowfaruse="1"
per example:36871

You must also change something in the action.lua
Code:
if getDistanceBetween(playerPosition, dummyPosition) > 1 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
for
Code:
if getDistanceBetween(playerPosition, dummyPosition) > 6 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
 

maikons

Member
Joined
Aug 1, 2015
Messages
180
Reaction score
12
So that the weapon of the paladins can be shot from afar you must add the following tag on actions.xml
Code:
allowfaruse="1"
per example:View attachment 36871

You must also change something in the action.lua
Code:
if getDistanceBetween(playerPosition, dummyPosition) > 1 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
for
Code:
if getDistanceBetween(playerPosition, dummyPosition) > 6 then
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_THEREISNOWAY)
    end
1) How can i set skills upgrade more slow?
Could i change local skillTries = 7 --# tries by blow
To local skillTries = 5 --# tries by blow
???
 
OP
Sarah Wesker

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
Yes friend, you can change this amounts to your liking, remember that the system is also affected by the global multiplier in your config.lua
 
Last edited:

runsicky

Member
Joined
Apr 19, 2018
Messages
55
Reaction score
11
just amazing!

could you help with only one stuff?
i want to add it in my server but not pay to win as normal is...

so i want to when player finishes his 900 charges, he can only train again after 6 hours

how to do it?
 

siusiaczek

Banned User
Joined
Jun 22, 2019
Messages
108
Reaction score
36
ok bug:
if player use this on exercise dummy it removes charges
if player remove weapon from bp exception :
luaDoSetItemAttribute Item not found ( and keeps training getting ticks but doesnt remove charges)
also if player use from ground doesnt remove charges ( and trains)
need to check if item that is used is indeed in backpack<-

omg fixed. now it checks IF YOU HAVE IT IN RIGHT HAND! IF YOU DO NOT IT STOPS
BUGS THAT WERE THERE I FIXED:
YOU COULD HAVE REPLACED ITEMS AND IT WOULD NOT TAKE TICKS
YOU COULD HAVE HAD WAND AND IT WOULD TRAIN FIST FIGHT BECAUSE OF SkiLL TYPE OF SWORD IN RIGHT HAND
bug that persists: you started training message even if weapon is not in your right hand but i keep it for now

Lua:
[email protected] Create by Sarah Wesker | Tested Version: TFS 0.4  || patched by siusiaczek
[email protected] list of training dummies.
local dummies = {
    [6431] = { skillRate = 1, skillSpeed = 1 },
    [6432] = { skillRate = 1, skillSpeed = 1 }
}

[email protected] Global training parameters of the system.
local staminaTries = 1 --# on minutes
local skillTries = 7 --# tries by blow
local skillSpent = function() return math.random(10, 100) end --# mana consumed by blow

--getCreatureStorage(uid, key)
--doCreatureSetStorage(uid, key, value)
[email protected] list of weapons to train.
local weapons = {
    [5850] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_POISON, skillType = SKILL_MAGLEVEL }, -- magicLevel Dru
    [5852] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_ENERGY, skillType = SKILL_MAGLEVEL }, -- magicLevel Sor
    [5796] = { shootEffect = CONST_ME_HITAREA, shootDistEffect = CONST_ANI_ARROW, skillType = SKILL_DISTANCE }, -- distance
    [5774] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_SWORD }, -- sword
    [5773] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_AXE }, -- axe
    [5775] = { shootEffect = CONST_ME_HITAREA, skillType = SKILL_CLUB } -- club
}

[email protected] EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

[email protected] 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

[email protected] local training function.
local function exerciseDummyTrainEvent(params, weapon)
    if isPlayer(params.cid) and getPlayerSlotItem(params.cid, CONST_SLOT_RIGHT).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
 
Last edited:
OP
Sarah Wesker

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Joined
Mar 16, 2017
Messages
409
Reaction score
231
Location
London
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:
[email protected] Create by Sarah Wesker | Tested Version: TFS 0.4
[email protected] list of training dummies.
local dummies = {
    [1443] = { skillRate = 1, skillSpeed = 1 },
    [26404] = { skillRate = 1, skillSpeed = 1 }
}

[email protected] 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

[email protected] 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
}

[email protected] EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

[email protected] 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

[email protected] 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.
 

siusiaczek

Banned User
Joined
Jun 22, 2019
Messages
108
Reaction score
36
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:
[email protected] Create by Sarah Wesker | Tested Version: TFS 0.4
[email protected] list of training dummies.
local dummies = {
    [1443] = { skillRate = 1, skillSpeed = 1 },
    [26404] = { skillRate = 1, skillSpeed = 1 }
}

[email protected] 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

[email protected] 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
}

[email protected] EDTE is the global event table to control the system correctly.
if not EDTE then EDTE = {} end

[email protected] 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

[email protected] 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 also changed simplearrow and cake in mine to arrow and poison ( for older version clients i work on 7.4)
 
Top