• 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

Active Member
Joined
Dec 12, 2018
Messages
442
Reaction score
40
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, 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.
@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.
 
@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>
 
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.
 
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.
 
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:
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
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?
 
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:
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.
 
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.
 
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
 
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
 
Back
Top