• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ GetAttackSpeed Problem

Svira

Active Member
Joined
Jan 27, 2008
Messages
268
Solutions
11
Reaction score
36
Hello, please help me how to correctly read the attackspeed of a weapon?

yes, yes I have it added to src.

error: attempt to perform artihmetic on a nil value

TFS 1.2 - 8.0

code:
Lua:
local attrkeys = {
    ['charges'] = ITEM_ATTRIBUTE_CHARGES,
    ['time'] = ITEM_ATTRIBUTE_DURATION,
    ['atk'] = ITEM_ATTRIBUTE_ATTACK,
    ['atk speed'] = ITEM_ATTRIBUTE_ATTACKSPEED,
    ['def'] = ITEM_ATTRIBUTE_DEFENSE,
    ['extra def'] = ITEM_ATTRIBUTE_EXTRADEFENSE,
    ['arm'] = ITEM_ATTRIBUTE_ARMOR,
    ['accuracy'] = ITEM_ATTRIBUTE_HITCHANCE,
    ['range'] = ITEM_ATTRIBUTE_SHOOTRANGE
}

function Item.addStat(item, spellname, spellvalue, suffix, cid)
    if isInArray({'charges', 'time', 'atk', 'atk speed', 'def', 'extra def', 'arm', 'accuracy', 'range'}, spellname) then
        local basestats = item:getBaseStatsInfo()
        local basestats2 = {
            ['charges'] = basestats.charges,
            ['time'] = basestats.duration,
            ['atk'] = basestats.attack,
            ['atk speed'] = basestats.attackSpeed,
            ['def'] = basestats.defense,
            ['extra def'] = basestats.extraDefense,
            ['arm'] = basestats.armor,
            ['accuracy'] = basestats.hitChance,
            ['range'] = basestats.shootRange
        }

        local uid = item:getUniqueId()
        local fullstats = {
            ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES),
            ['time'] = item:getBaseDuration(),
            ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK),
            ['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED),
            ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE),
            ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE),
            ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR),
            ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE),
            ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE)
        }

        if suffix == "%" then
            if basestats2[spellname] == 0 then
                if cid then
                    Player(cid):sendTextMessage(MESSAGE_INFO_DESCR, "Spell " .. spellname .. "% is not available for this item.")
                end
                return false
            end
            item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(math.floor((basestats2[spellname] * spellvalue/100)))) -- error here
        else
            item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(spellvalue))  -- or here
        end
    end
    item:addStatSlot(spellname, spellvalue, suffix)
    return true
end
 
Solution
I edited the post now. Take a look.
Suffix is empty


edit:
I am convinced that the error occurs here:
Code:
['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED),

I suspect these uids. I have defined local uid = item:getUniqueId() and it should be like this: ItemType(Item(uid):getId())
but then I have an attempt to global getAttakSpeed

Lua:
local uid = item:getUniqueId()
        local fullstats = {
            ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES),
            ['time'] = item:getBaseDuration(),
            ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK),
            ['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED),
            ['def'] = getItemAttribute(uid...
I made some corrections and added 'print' so that you can see the output in your console. This will help you easily identify the error and make the necessary corrections accurately.

Lua:
local ITEM_ATTRIBUTE_CHARGES = 1
local ITEM_ATTRIBUTE_DURATION = 2
local ITEM_ATTRIBUTE_ATTACK = 3
local ITEM_ATTRIBUTE_ATTACKSPEED = 4
local ITEM_ATTRIBUTE_DEFENSE = 5
local ITEM_ATTRIBUTE_EXTRADEFENSE = 6
local ITEM_ATTRIBUTE_ARMOR = 7
local ITEM_ATTRIBUTE_HITCHANCE = 8
local ITEM_ATTRIBUTE_SHOOTRANGE = 9

local attrkeys = {
    ['charges'] = ITEM_ATTRIBUTE_CHARGES,
    ['time'] = ITEM_ATTRIBUTE_DURATION,
    ['atk'] = ITEM_ATTRIBUTE_ATTACK,
    ['atk speed'] = ITEM_ATTRIBUTE_ATTACKSPEED,
    ['def'] = ITEM_ATTRIBUTE_DEFENSE,
    ['extra def'] = ITEM_ATTRIBUTE_EXTRADEFENSE,
    ['arm'] = ITEM_ATTRIBUTE_ARMOR,
    ['accuracy'] = ITEM_ATTRIBUTE_HITCHANCE,
    ['range'] = ITEM_ATTRIBUTE_SHOOTRANGE
}

function Item.addStat(item, spellname, spellvalue, suffix, cid)
    print("Spellname: " .. spellname)
    print("Spellvalue: " .. spellvalue)
    print("Suffix: " .. suffix)

    if attrkeys[spellname] then
        local basestats = item:getBaseStatsInfo()
        local basestats2 = {
            ['charges'] = basestats.charges,
            ['time'] = basestats.duration,
            ['atk'] = basestats.attack,
            ['atk speed'] = basestats.attackSpeed,
            ['def'] = basestats.defense,
            ['extra def'] = basestats.extraDefense,
            ['arm'] = basestats.armor,
            ['accuracy'] = basestats.hitChance,
            ['range'] = basestats.shootRange
        }

        local uid = item:getUniqueId()
        local fullstats = {
            ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES) or 0,
            ['time'] = item:getBaseDuration(),
            ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK) or 0,
            ['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED) or 0,
            ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE) or 0,
            ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE) or 0,
            ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR) or 0,
            ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE) or 0,
            ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE) or 0
        }

        if suffix == "%" then
            if spellname == 'atk speed' then
                item:setAttribute(attrkeys[spellname], basestats2[spellname] * (1 + spellvalue / 100))
            else
                item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(math.floor((basestats2[spellname] * spellvalue / 100))))
            end
        else
            item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(spellvalue))
        end
    else
        if cid then
            Player(cid):sendTextMessage(MESSAGE_INFO_DESCR, "Invalid spellname: " .. spellname)
        end
        return false
    end

    print("New value of " .. spellname .. ": " .. item:getAttribute(attrkeys[spellname]))

    item:addStatSlot(spellname, spellvalue, suffix)
    return true
end
 
Last edited:
I made some corrections and added 'print' so that you can see the output in your console. This will help you easily identify the error and make the necessary corrections accurately.

Lua:
local ITEM_ATTRIBUTE_CHARGES = 1
local ITEM_ATTRIBUTE_DURATION = 2
local ITEM_ATTRIBUTE_ATTACK = 3
local ITEM_ATTRIBUTE_ATTACKSPEED = 4
local ITEM_ATTRIBUTE_DEFENSE = 5
local ITEM_ATTRIBUTE_EXTRADEFENSE = 6
local ITEM_ATTRIBUTE_ARMOR = 7
local ITEM_ATTRIBUTE_HITCHANCE = 8
local ITEM_ATTRIBUTE_SHOOTRANGE = 9

local attrkeys = {
    ['charges'] = ITEM_ATTRIBUTE_CHARGES,
    ['time'] = ITEM_ATTRIBUTE_DURATION,
    ['atk'] = ITEM_ATTRIBUTE_ATTACK,
    ['atk speed'] = ITEM_ATTRIBUTE_ATTACKSPEED,
    ['def'] = ITEM_ATTRIBUTE_DEFENSE,
    ['extra def'] = ITEM_ATTRIBUTE_EXTRADEFENSE,
    ['arm'] = ITEM_ATTRIBUTE_ARMOR,
    ['accuracy'] = ITEM_ATTRIBUTE_HITCHANCE,
    ['range'] = ITEM_ATTRIBUTE_SHOOTRANGE
}

function Item.addStat(item, spellname, spellvalue, suffix, cid)
    print("Spellname: " .. spellname)
    print("Spellvalue: " .. spellvalue)
    print("Suffix: " .. suffix)

    if attrkeys[spellname] then
        local basestats = item:getBaseStatsInfo()
        local basestats2 = {
            ['charges'] = basestats.charges,
            ['time'] = basestats.duration,
            ['atk'] = basestats.attack,
            ['atk speed'] = basestats.attackSpeed,
            ['def'] = basestats.defense,
            ['extra def'] = basestats.extraDefense,
            ['arm'] = basestats.armor,
            ['accuracy'] = basestats.hitChance,
            ['range'] = basestats.shootRange
        }

        local uid = item:getUniqueId()
        local fullstats = {
            ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES) or 0,
            ['time'] = item:getBaseDuration(),
            ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK) or 0,
            ['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED) or 0,
            ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE) or 0,
            ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE) or 0,
            ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR) or 0,
            ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE) or 0,
            ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE) or 0
        }

        if suffix == "%" then
            if basestats2[spellname] == 0 then
                if cid then
                    Player(cid):sendTextMessage(MESSAGE_INFO_DESCR, "Spell " .. spellname .. "% is not available for this item.")
                end
                return false
            end
            item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(math.floor((basestats2[spellname] * spellvalue / 100))))
        else
            item:setAttribute(attrkeys[spellname], fullstats[spellname] + math.abs(spellvalue))
        end
    else
        if cid then
            Player(cid):sendTextMessage(MESSAGE_INFO_DESCR, "Invalid spellname: " .. spellname)
        end
        return false
    end

   -- Checking values after calculations
    print("New value of " .. spellname .. ": " .. item:getAttribute(attrkeys[spellname]))

    item:addStatSlot(spellname, spellvalue, suffix)
    return true
end
suffix for atk speed gives no result the others correctly give unit or % information and represent the new value.

all except atk speed...
 
I edited the post now. Take a look.
Suffix is empty


edit:
I am convinced that the error occurs here:
Code:
['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED),

I suspect these uids. I have defined local uid = item:getUniqueId() and it should be like this: ItemType(Item(uid):getId())
but then I have an attempt to global getAttakSpeed

Lua:
local uid = item:getUniqueId()
        local fullstats = {
            ['charges'] = getItemAttribute(uid, ITEM_ATTRIBUTE_CHARGES),
            ['time'] = item:getBaseDuration(),
            ['atk'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACK),
            ['atk speed'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ATTACKSPEED),
            ['def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_DEFENSE),
            ['extra def'] = getItemAttribute(uid, ITEM_ATTRIBUTE_EXTRADEFENSE),
            ['arm'] = getItemAttribute(uid, ITEM_ATTRIBUTE_ARMOR),
            ['accuracy'] = getItemAttribute(uid, ITEM_ATTRIBUTE_HITCHANCE),
            ['range'] = getItemAttribute(uid, ITEM_ATTRIBUTE_SHOOTRANGE)
        }



edit 2:

Okay, after a few days of fighting, I realize it's bullshit...

My solution = Set the attack speed based on the Fist skill when attack speed is not available in the weapon, then I rebuilt the slots for the fist skill and edited the client window to show attack speed instead of fist fighting.

my code may be useful to someone:
C++:
uint32_t getAttackSpeed() const {
            Item* weapon = getWeapon(false);

                if (weapon && weapon->getAttackSpeed() > 0) {
                    return weapon->getAttackSpeed();
                }

                int32_t skillBasedSpeed = vocation->getAttackSpeed() - (getSkillLevel(SKILL_FIST) * 8);

                if (skillBasedSpeed < 400) {
                    return 400;
                } else {
                    return static_cast<uint32_t>(skillBasedSpeed);
                }
        }
Limit attack speed = 400.
 
Last edited:
Solution
Back
Top