• Sign up for October Mapping Competition! The prize includes Otland Premium time.
  • 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!

getCombatValue caused global crash

SixNine

Member
Joined
Dec 12, 2018
Messages
233
Reaction score
20
Pretty sure that no one will be able to help with it because its not a full crash log but it didnt made the crash log because crashlog wasnt setup properly but i will give it a shot maybe someone with 5head brain, had a similar error and know how to avoid this stuff again. So im using TFS 1.2 8.6 Ninjaluz version maybe it will help a little bit because we all know this source is fucked so maybe someone had same crash and managed to fix it.
435d5d5ee8f118d5ce23ed8f53228279-png.jpg
C++:
CombatDamage Combat::getCombatDamage(Creature* creature, Creature* target) const
{
    CombatDamage damage;
    damage.origin = params.origin;
    damage.primary.type = params.combatType;
    if (formulaType == COMBAT_FORMULA_DAMAGE) {
        damage.primary.value = normal_random(
            static_cast<int32_t>(mina),
            static_cast<int32_t>(maxa)
        );
    } else if (creature) {
        int32_t min, max;
        if (creature->getCombatValues(min, max)) {
            damage.primary.value = normal_random(min, max);
        } else if (Player* player = creature->getPlayer()) {
            if (params.valueCallback) {
                params.valueCallback->getMinMaxValues(player, damage, params.useCharges);
            } else if (formulaType == COMBAT_FORMULA_LEVELMAGIC) {
                int32_t levelFormula = player->getLevel() * 2 + player->getMagicLevel() * 3;
                damage.primary.value = normal_random(
                    static_cast<int32_t>(levelFormula * mina + minb),
                    static_cast<int32_t>(levelFormula * maxa + maxb)
                );
            } else if (formulaType == COMBAT_FORMULA_SKILL) {
                Item* tool = player->getWeapon();
                const Weapon* weapon = g_weapons->getWeapon(tool);
                if (weapon) {
                    damage.primary.value = normal_random(
                        static_cast<int32_t>(minb),
                        static_cast<int32_t>(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb)
                    );
                    damage.secondary.type = weapon->getElementType();
                    damage.secondary.value = weapon->getElementDamage(player, target, tool);
                    if (params.useCharges) {
                        uint16_t charges = tool->getCharges();
                        if (charges != 0) {
                            g_game.transformItem(tool, tool->getID(), charges - 1);
                        }
                    }
                } else {
                    damage.primary.value = normal_random(
                        static_cast<int32_t>(minb),
                        static_cast<int32_t>(maxb)
                    );
                }
            }
        }
    }
    return damage;
}
 
Solution
So it looks like the situation is this:

Creature uses spell on a target (spell waits 1 second to cast with add event)
Target dies before 1 second
Debug happens when the spell tries to execute

Code:
Combat:getCombatDamage(this, creature...

Ralumbi

apt install nubmod
Content Editor
Premium User
Joined
Jun 8, 2011
Messages
173
Solutions
6
Reaction score
59
Location
Netherlands
@SixNine I remember something similiar I have experienced. You must check if you can reproduce this bug by training distance with stones and shield and putting the stones back into your hand as fast as possible.
 
OP
SixNine

SixNine

Member
Joined
Dec 12, 2018
Messages
233
Reaction score
20
@SixNine I remember something similiar I have experienced. You must check if you can reproduce this bug by training distance with stones and shield and putting the stones back into your hand as fast as possible.
I dont have stones and shields in my game :/ to train distance i only have a simple items
Lua:
    <item id="5353" article="a" name="Staff">
        <attribute key="weight" value="2000" />
        <attribute key="attack" value="18"/>
        <attribute key="hitChance" value="100"/>
        <attribute key="weaponType" value="distance" />
        <attribute key="shootType" value="whirlwindsword" />
        <attribute key="range" value="7" />
    </item>
 

fabian766

Advanced OT User
Joined
Apr 22, 2008
Messages
102
Solutions
18
Reaction score
212
Location
Poland
Looking at full crash log you're getting crash in addEvent
Code:
#8 0x00005555556a248e in LuaEnvironment::executeTimerEvent
my guess is that you have some spell with unsafe addEvent that passes userdata directly instead of creatureid and player logouts/dies.
 

Stanos

Advanced OT User
Joined
Jun 12, 2018
Messages
444
Reaction score
165
Looking at full crash log you're getting crash in addEvent
Code:
#8 0x00005555556a248e in LuaEnvironment::executeTimerEvent
my guess is that you have some spell with unsafe addEvent that passes userdata directly instead of creatureid and player logouts/dies.
Helps if you say what is done in-game that causes the crash. Post creature::getCombatValues
Had same issue like this dude it was with addEvent. But cant remember because it wasnt me that fixed it.
 
OP
SixNine

SixNine

Member
Joined
Dec 12, 2018
Messages
233
Reaction score
20
Looking at full crash log you're getting crash in addEvent
Code:
#8 0x00005555556a248e in LuaEnvironment::executeTimerEvent
my guess is that you have some spell with unsafe addEvent that passes userdata directly instead of creatureid and player logouts/dies.
Checked addEvent i didnt found anything that can cause this
Helps if you say what is done in-game that causes the crash. Post creature::getCombatValues
Thats the point i dont know what caused it because i was off for two days and when i logged in i saw two logs in log files thats server crashed. I dont have creature::getCombatValues
Had same issue like this dude it was with addEvent. But cant remember because it wasnt me that fixed it.
No its not addEvent probably we have different situation or im just to dumb and i assume i have correct addEvent in spells

Whaat should i mention is that all monster spells have exhaustion="1" but it doesnt mean anything when i use spell cooldown interval in monsters. What next about monster spells is some of them have
Lua:
addEvent(onCastSpell1, 0, parameters)
but i would doubt it effects something. From player sides all spells are correct with min 1sec cooldown
 
Last edited:

Itutorial

Veteran OT User
Joined
Dec 23, 2014
Messages
1,751
Solutions
47
Reaction score
473
So it looks like the situation is this:

Creature uses spell on a target (spell waits 1 second to cast with add event)
Target dies before 1 second
Debug happens when the spell tries to execute

Code:
Combat:getCombatDamage(this, creature, target) -- normal operation

 Combat:getCombatDamage(this, creature, 0x0[nil]) -- Operation actually happening

Thats what the crash seems to say. The target is nil (because its dead or just doesn't exist whatever).

Look at any spells that cast with an addevent delay and make sure they all know how to STOP if the target or creature is gone.
 
Solution
OP
SixNine

SixNine

Member
Joined
Dec 12, 2018
Messages
233
Reaction score
20
So it looks like the situation is this:

Creature uses spell on a target (spell waits 1 second to cast with add event)
Target dies before 1 second
Debug happens when the spell tries to execute

Code:
Combat:getCombatDamage(this, creature, target) -- normal operation

Combat:getCombatDamage(this, creature, 0x0[nil]) -- Operation actually happening

Thats what the crash seems to say. The target is nil (because its dead or just doesn't exist whatever).

Look at any spells that cast with an addevent delay and make sure they all know how to STOP if the target or creature is gone.
It do make sense.
Code:
Look at any spells that cast with an addevent delay and make sure they all know how to STOP if the target or creature is gone.
About this part how do i stop the target if creature is gone tho?
 

Itutorial

Veteran OT User
Joined
Dec 23, 2014
Messages
1,751
Solutions
47
Reaction score
473
It would be like this:

Lua:
addEvent(damageTarget, 1000, creature, variant)

function damageTarget(creature, variant)
    -- This check is REQUIRED --
    if not creature:getId() or not variant:getId() then
        return true
    end
 
    doStuff
return true
end
 
Last edited:

Nekiro

Legendary OT User
TFS Developer
Joined
Sep 7, 2015
Messages
2,214
Solutions
96
Reaction score
1,127
It would be like this:

Lua:
addEvent(damageTarget, 1000, creature, variant)

function damageTarget(creature, variant)
    -- This check is REQUIRED --
    if not creature or not variant then
        return true
    end
 
    doStuff
return true
end
Your code will also crash the server. You cannot check object validity with simple if. Pass creature id not object.
 

Itutorial

Veteran OT User
Joined
Dec 23, 2014
Messages
1,751
Solutions
47
Reaction score
473
It may show a warning in the console but it won't crash anything. At-least not since I just changed it. It is also just an example.
 

Nekiro

Legendary OT User
TFS Developer
Joined
Sep 7, 2015
Messages
2,214
Solutions
96
Reaction score
1,127
Proper way of writting code using addEvents
Lua:
addEvent(delayedFunc, 1000, creature:getId(), variant)

function delayedFunc(creatureId, variant)
    local creature = Creature(creatureId)
    if not creature then
        return false
    end

    print(creature:getId())
    return true
end
 

Infernum

Senator
Joined
Feb 14, 2015
Messages
5,593
Solutions
555
Reaction score
3,506
It may show a warning in the console but it won't crash anything. At-least not since I just changed it. It is also just an example.
try this out and get back to me
Lua:
function crash()
    local monster = Game.createMonster('Demon', Position(x, y, z))
    addEvent(function(m)
        if m:getId() then
            -- this is completely safe kappa just run it :)
            print(m:getName())
        end
    end, 3000, monster)
end
make sure to change the position and /r the monster after it spawns
 
Top