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

[SOLVED] OTClient Lua Exception: attempt to index local 'spell' (a nil value)

eupharias

New Member
Joined
Apr 17, 2023
Messages
13
Reaction score
1
Location
USA
Hey everyone, good morning/afternoon/evening.

I created a thread in the Support forums earlier today regarding an issue I'm seeing. Attaching the post below.


I realized that OTClient is causing the issue after troubleshooting for a while. I'm getting some error logs from OTClient, but I'm not sure what to make of them, as I'm not very experienced with how OTClient works under the hood. Any help dissecting this would be very much appreciated. Cheers.


Code:
== application started at Apr 23 2023 23:42:04
== operating system: Windows
OTClient - Redemption 1.0 rev 0.000 (desenv) built on Apr 19 2023 for arch x64
Startup done :]
ERROR: Lua exception: /game_actionbar/game_actionbar.lua:931: attempt to index local 'spell' (a nil value)
stack traceback:
    [C]: in function '__index'
    /game_actionbar/game_actionbar.lua:931: in function </game_actionbar/game_actionbar.lua:927>
ERROR: protected lua call failed: LUA ERROR:
/game_actionbar/game_actionbar.lua:931: attempt to index local 'spell' (a nil value)
stack traceback:
    [C]: in function '__index'
    /game_actionbar/game_actionbar.lua:931: in function </game_actionbar/game_actionbar.lua:927>
ERROR: ProtocolGame parse message exception (257 bytes unread, last opcode is 128, prev opcode is 164): unhandled opcode 128
ERROR: Lua exception: /game_actionbar/game_actionbar.lua:931: attempt to index local 'spell' (a nil value)
stack traceback:
    [C]: in function '__index'
    /game_actionbar/game_actionbar.lua:931: in function </game_actionbar/game_actionbar.lua:927>
ERROR: protected lua call failed: LUA ERROR:
/game_actionbar/game_actionbar.lua:931: attempt to index local 'spell' (a nil value)
stack traceback:
    [C]: in function '__index'
    /game_actionbar/game_actionbar.lua:931: in function </game_actionbar/game_actionbar.lua:927>
ERROR: ProtocolGame parse message exception (124 bytes unread, last opcode is 128, prev opcode is 164): unhandled opcode 128
ERROR: Lua exception: /game_actionbar/game_actionbar.lua:931: attempt to index local 'spell' (a nil value)
stack traceback:
    [C]: in function '__index'
    /game_actionbar/game_actionbar.lua:931: in function </game_actionbar/game_actionbar.lua:927>
ERROR: protected lua call failed: LUA ERROR:
/game_actionbar/game_actionbar.lua:931: attempt to index local 'spell' (a nil value)
stack traceback:
    [C]: in function '__index'
    /game_actionbar/game_actionbar.lua:931: in function </game_actionbar/game_actionbar.lua:927>
ERROR: ProtocolGame parse message exception (182 bytes unread, last opcode is 128, prev opcode is 164): unhandled opcode 128
ERROR: no thing at pos:32064 32192 7, stackpos:2
at:
    [C++]: ?getMappedThing@ProtocolGame@@QEBA?AV?$shared_ptr@VThing@@@std@@AEBV?$shared_ptr@VInputMessage@@@3@@Z
ERROR: no thing
at:
    [C++]: ?parseTileTransformThing@ProtocolGame@@AEAAXAEBV?$shared_ptr@VInputMessage@@@std@@@Z
 
Add in modules/game_actionbar/game_actionbar.lua after line 930:
Code:
        if not spell then
        return true
    end

This has partially resolved the issue, as I don't see the spell nil value error any more with this addition to the code. However, the monster freeze issue is still happening, so that must be caused by the only remaining OTClient error.

Updated OTClient Logs
C:\otclient\otclient.txt

Code:
== application started at Apr 24 2023 10:49:51
== operating system: Windows
OTClient - Redemption 1.0 rev 0.000 (desenv) built on Apr 19 2023 for arch x64
Startup done :]
ERROR: ProtocolGame parse message exception (233 bytes unread, last opcode is 128, prev opcode is 164): unhandled opcode 128
ERROR: no thing at pos:32055 32192 7, stackpos:3
at:
    [C++]: ?getMappedThing@ProtocolGame@@QEBA?AV?$shared_ptr@VThing@@@std@@AEBV?$shared_ptr@VInputMessage@@@3@@Z
ERROR: no thing
at:
    [C++]: ?parseTileTransformThing@ProtocolGame@@AEAAXAEBV?$shared_ptr@VInputMessage@@@std@@@Z
ERROR: ProtocolGame parse message exception (223 bytes unread, last opcode is 128, prev opcode is 164): unhandled opcode 128

Thoughts?
 
The client is probably not handling message 164 correctly which is the spell cooldown message. It is either reading more or less bytes than it should causing other messages in the same packet to be discarded (after getting an unhandled opcode error). The message to remove the creature and create it's corpse is probably in the middle of these discarded messages thus causing the issue.

Now, if you're using mehah's client, the problem should be in this function:
C++:
void ProtocolGame::parseSpellCooldown(const InputMessagePtr& msg)
{
    uint16_t spellId = msg->getU8();
    if (g_game.getFeature(Otc::GameUshortSpell)) {
        spellId = msg->getU16();
    } else {
        spellId = msg->getU8();
    }
    const uint32_t delay = msg->getU32();

    g_lua.callGlobalField("g_game", "onSpellCooldown", spellId, delay);
}

Now, giving it a proper look, it does an extra U8 read for the spellId so it should probably be:
C++:
void ProtocolGame::parseSpellCooldown(const InputMessagePtr& msg)
{
    uint16_t spellId;
    if (g_game.getFeature(Otc::GameUshortSpell)) {
        spellId = msg->getU16();
    } else {
        spellId = msg->getU8();
    }
    const uint32_t delay = msg->getU32();

    g_lua.callGlobalField("g_game", "onSpellCooldown", spellId, delay);
}
 
You, sir, are a god-send. This is the correct solution.
The client is probably not handling message 164 correctly which is the spell cooldown message. It is either reading more or less bytes than it should causing other messages in the same packet to be discarded (after getting an unhandled opcode error). The message to remove the creature and create it's corpse is probably in the middle of these discarded messages thus causing the issue.

Now, if you're using mehah's client, the problem should be in this function:
C++:
void ProtocolGame::parseSpellCooldown(const InputMessagePtr& msg)
{
    uint16_t spellId = msg->getU8();
    if (g_game.getFeature(Otc::GameUshortSpell)) {
        spellId = msg->getU16();
    } else {
        spellId = msg->getU8();
    }
    const uint32_t delay = msg->getU32();

    g_lua.callGlobalField("g_game", "onSpellCooldown", spellId, delay);
}

Now, giving it a proper look, it does an extra U8 read for the spellId so it should probably be:
C++:
void ProtocolGame::parseSpellCooldown(const InputMessagePtr& msg)
{
    uint16_t spellId;
    if (g_game.getFeature(Otc::GameUshortSpell)) {
        spellId = msg->getU16();
    } else {
        spellId = msg->getU8();
    }
    const uint32_t delay = msg->getU32();

    g_lua.callGlobalField("g_game", "onSpellCooldown", spellId, delay);
}
Post automatically merged:

If someone will tell me how to mark this thread as solved (I just added it to the title), and mark the comment by @fusion32 as the solution, I will do so.
 
Back
Top