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

Monster Training Dummy with DPS calculation

oen432

Legendary OT User
Joined
Oct 3, 2014
Messages
1,900
Solutions
55
Reaction score
2,121
Location
Poland
GitHub
Oen44
Simple training dummy that is showing players DPS (Damage Per Second). The highest DPS is stored in storage and can be used for different things, like rewards or requirements for items or something, I don't know, use your brain.

  1. Open data/creaturescripts/creaturescripts.xml
  2. Add <event type="healthchange" name="EventDPS" script="dps.lua" />
  3. Open data/events/events.xml
  4. Enable onTargetCombat
  5. Open data/events/scripts/creature.lua
  6. Find function Creature:onTargetCombat(target)
  7. Add before return RETURNVALUE_NOERROR
    Lua:
    if target:getName() == "Training Dummy" then
        target:registerEvent("EventDPS")
    end
  8. Create file data/creaturescripts/scripts/dps.lua with this code
    Lua:
    DPS_STORAGE = 50392
    PLAYER_DPS = {}
    PLAYER_EVENTS = {}
    
    function ReadDPS(pid, cid)
        local player = Player(pid)
        local target = Monster(cid)
        if player and target then
            PLAYER_DPS[pid] = PLAYER_DPS[pid] * -1
            if PLAYER_DPS[pid] > player:getStorageValue(DPS_STORAGE) then
                player:setStorageValue(DPS_STORAGE, PLAYER_DPS[pid])
                target:say(string.format("New Record! DPS: %d", PLAYER_DPS[pid]), TALKTYPE_MONSTER_SAY, false, player, target:getPosition())
            else
                target:say(string.format("DPS: %d", PLAYER_DPS[pid]), TALKTYPE_MONSTER_SAY, false, player, target:getPosition())
            end
            PLAYER_DPS[pid] = 0
            PLAYER_EVENTS[pid] = nil
        end
    end
    
    function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
        if not creature then return primaryDamage, primaryType, secondaryDamage, secondaryType end
        if not attacker then return primaryDamage, primaryType, secondaryDamage, secondaryType end
    
        if creature:isMonster() and attacker:isPlayer() then
            if creature:getName() == "Training Dummy" then
                local damage = primaryDamage + secondaryDamage
                local pid = attacker:getId()
                if not PLAYER_DPS[pid] then PLAYER_DPS[pid] = 0 end
                PLAYER_DPS[pid] = PLAYER_DPS[pid] + damage
                if not PLAYER_EVENTS[pid] then
                    PLAYER_EVENTS[pid] = addEvent(ReadDPS, 1000, pid, creature:getId())
                end
            end
        end
    
        return primaryDamage, primaryType, secondaryDamage, secondaryType
    end
  9. Create new monster
    XML:
    <?xml version="1.0" encoding="UTF-8"?>
        <monster name="Training Dummy" nameDescription="a training dummy" race="undead" experience="0" speed="0">
        <health now="100000000" max="100000000" />
        <look typeex="5787" />
        <flags>
            <flag summonable="0" />
            <flag attackable="1" />
            <flag hostile="1" />
            <flag illusionable="0" />
            <flag convinceable="0" />
            <flag pushable="0" />
            <flag canpushitems="0" />
            <flag canpushcreatures="0" />
            <flag targetdistance="1" />
            <flag staticattack="100" />
            <flag runonhealth="0" />
            <flag canwalkonenergy="0" />
            <flag canwalkonfire="0" />
            <flag canwalkonpoison="0" />
        </flags>
        <attacks>
            <attack name="melee" interval="2000" min="0" max="-1" />
        </attacks>
        <defenses armor="0" defense="0">
            <defense name="healing" interval="5000" chance="100" min="100000000" max="100000000">
                <attribute key="areaEffect" value="blueshimmer" />
            </defense>
        </defenses>
        <immunities>
            <immunity invisible="1" />
        </immunities>
    </monster>
 
Last edited by a moderator:
Oii, can you do that for version 8.54? I really liked the system but I do not think it will work on my server.
 
Thanks for this, this will actually help me balance some vocations/spells!
 
Last edited:
Thanks! i really like this script, also for anyone that wants it, i added in a "DPS" log, and adjusted the DPS texts position to be on the player.

Firstly change this
Lua:
            target:say(string.format("New Record! DPS: %d", PLAYER_DPS[pid]), TALKTYPE_MONSTER_SAY, false, player, target:getPosition())
            else
            target:say(string.format("DPS: %d", PLAYER_DPS[pid]), TALKTYPE_MONSTER_SAY, false, player, target:getPosition())

to this
Lua:
            player:openChannel(11)
            target:say(string.format("New Record! DPS: %d", PLAYER_DPS[pid]), TALKTYPE_MONSTER_SAY, false, player, player:getPosition())
            player:sendChannelMessage(target, (string.format("New Record! DPS: %d", PLAYER_DPS[pid])), TALKTYPE_CHANNEL_O, 11)
            else
            player:openChannel(11)
            target:say(string.format("DPS: %d", PLAYER_DPS[pid]), TALKTYPE_MONSTER_SAY, false, player, player:getPosition())
            player:sendChannelMessage(target, (string.format("DPS: %d", PLAYER_DPS[pid])), TALKTYPE_CHANNEL_O, 11)
now goto "data\chatchannels\chatchannels.xml"

and add this to the bottom
XML:
<channel id="11" name="DPS" script="dps.lua" />

Next in "data\chatchannels\scripts\"

Make "dps.lua" and add this

Lua:
function onSpeak(player, type, message)
    return false
end

and thats it, customize as you like.
 
Is it posible to TFS 1.3 ?

ERROR:
Lua:
Lua Script Error: [Event Interface]
data/events/scripts/creature.lua:Creature@onTargetCombat
data/events/scripts/creature.lua:10: attempt to index global 'creature' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/events/scripts/creature.lua:10: in function <data/events/scripts/creature.lua:9>

Im coming from: DPS script TFS 1.2
 
Show me your onTargetCombat function from data/events/scripts/creature.lua.
This script was made on TFS 1.3.
 
Lua:
function Creature:onChangeOutfit(outfit)
    return true
end

function Creature:onAreaCombat(tile, isAggressive)
    return RETURNVALUE_NOERROR
end

function Creature:onTargetCombat(target)
    if creature:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
    if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
    if target:getName() == "Training Dummy" then
    target:registerEvent("EventDPS")
        end
        return RETURNVALUE_NOERROR
        elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
            creature:sendCancelMessage("You cannot attack someone that is on your team.")
            return false
        end
    elseif creature:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
        if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            return RETURNVALUE_NOERROR
        elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
            creature:sendCancelMessage("You cannot attack someone that is on your team.")
            return false
        end
    end
end
 
Lua:
function Creature:onChangeOutfit(outfit)
    return true
end

function Creature:onAreaCombat(tile, isAggressive)
    return RETURNVALUE_NOERROR
end

function Creature:onTargetCombat(target)
    if creature:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
    if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
    if target:getName() == "Training Dummy" then
    target:registerEvent("EventDPS")
        end
        return RETURNVALUE_NOERROR
        elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
            creature:sendCancelMessage("You cannot attack someone that is on your team.")
            return false
        end
    elseif creature:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
        if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            return RETURNVALUE_NOERROR
        elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
            creature:sendCancelMessage("You cannot attack someone that is on your team.")
            return false
        end
    end
end
Not related to this thread.
 
Not related to this thread.



I have reviewed and followed the instructions based on this post and I have received the same errors, can someone help me with the TFS 1.3 version?
Lua:
Lua Script Error: [Event Interface]
data/events/scripts/creature.lua:Creature@onTargetCombat
data/events/scripts/creature.lua:10: attempt to index global 'creature' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/events/scripts/creature.lua:10: in function <data/events/scripts/creature.lua:9>
This is my:
Lua:
data/events/scripts/creature.lua
Lua:
function Creature:onChangeOutfit(outfit)
    return true
end

function Creature:onAreaCombat(tile, isAggressive)
    return RETURNVALUE_NOERROR
end

function Creature:onTargetCombat(target)
    if creature:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
    if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
    if target:getName() == "Training Dummy" then
    target:registerEvent("EventDPS")
        end
        return RETURNVALUE_NOERROR
        elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
            creature:sendCancelMessage("You cannot attack someone that is on your team.")
            return false
        end
    elseif creature:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
        if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            return RETURNVALUE_NOERROR
        elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
            creature:sendCancelMessage("You cannot attack someone that is on your team.")
            return false
        end
    end
end
 
Replace creature with self
That won't be enough. Eh, newbies..

Lua:
function Creature:onTargetCombat(target)
    if self:isPlayer() then
        if self:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        elseif self:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        end
    end
    
    if target:getName() == "Training Dummy" then
        target:registerEvent("EventDPS")
    end
    return RETURNVALUE_NOERROR
end
 
That won't be enough. Eh, newbies..

Lua:
function Creature:onTargetCombat(target)
    if self:isPlayer() then
        if self:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        elseif self:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        end
    end
   
    if target:getName() == "Training Dummy" then
        target:registerEvent("EventDPS")
    end
    return RETURNVALUE_NOERROR
end

Thank you very much for sharing the knowledge you have acquired, I understand that whenever you share, you receive in doubles or in other ways. It's a law!

I am very grateful
😍🥰😘
 
That won't be enough. Eh, newbies..

Lua:
function Creature:onTargetCombat(target)
    if self:isPlayer() then
        if self:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        elseif self:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        end
    end
   
    if target:getName() == "Training Dummy" then
        target:registerEvent("EventDPS")
    end
    return RETURNVALUE_NOERROR
end



The dummy is working, but when the char receives the poisoned condition "You are poisoned" and RELOG the following error occurs:
Lua:
Lua Script Error: [Event Interface]
data/events/scripts/creature.lua:Creature@onTargetCombat
data/events/scripts/creature.lua:11: attempt to index local 'self' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/events/scripts/creature.lua:11: in function <data/events/scripts/creature.lua:10>

data/events/scripts/creature.lua:
Lua:
function Creature:onChangeOutfit(outfit)
    return true
end

function Creature:onAreaCombat(tile, isAggressive)
    return RETURNVALUE_NOERROR
end


function Creature:onTargetCombat(target)
    if self:isPlayer() then
        if self:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        elseif self:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        end
    end
    
    if target:getName() == "Training Dummy" then
        target:registerEvent("EventDPS")
    end
target:registerEvent("UpgradeSystemHealth")
target:registerEvent("UpgradeSystemDeath")
    return RETURNVALUE_NOERROR
end
 
The dummy is working, but when the char receives the poisoned condition "You are poisoned" and RELOG the following error occurs:
Lua:
Lua Script Error: [Event Interface]
data/events/scripts/creature.lua:Creature@onTargetCombat
data/events/scripts/creature.lua:11: attempt to index local 'self' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/events/scripts/creature.lua:11: in function <data/events/scripts/creature.lua:10>

data/events/scripts/creature.lua:
Lua:
function Creature:onChangeOutfit(outfit)
    return true
end

function Creature:onAreaCombat(tile, isAggressive)
    return RETURNVALUE_NOERROR
end


function Creature:onTargetCombat(target)
    if self:isPlayer() then
        if self:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        elseif self:getStorageValue(STORAGEVALUE_WAR_REDPLAYER_BOOL) == 1 then
            if target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 1 then
                return RETURNVALUE_NOERROR
            elseif target:getStorageValue(STORAGEVALUE_WAR_GREENPLAYER_BOOL) == 0 then
                self:sendCancelMessage("You cannot attack someone that is on your team.")
                return false
            end
        end
    end
  
    if target:getName() == "Training Dummy" then
        target:registerEvent("EventDPS")
    end
target:registerEvent("UpgradeSystemHealth")
target:registerEvent("UpgradeSystemDeath")
    return RETURNVALUE_NOERROR
end
Stop posting here. These errors are not caused by my script. Make new thread and ask for help there.
 
It works but it doesn't show new DPS record, I didn't edit it at all just copied everything to latest TFS.
 
Doesn't seem to be the issue, I am using fresh tfs database and tried with different characters, Also cleared the storages at player_storage but still doesn't show damage record.
 
Back
Top