• 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+ [TFS 1.3] New creatureevent not working

Ovnyx

Member
Joined
Jul 25, 2017
Messages
163
Solutions
2
Reaction score
7
Hi everyone,
I was trying to add another creature event to allow me to handle with lua when a creature actually gets experience. I know there is already a onGainExperience function under the /events/player.lua file, but I'm trying to handle this even for summons and I was wondering if I could get some help here.

What I was trying was the following:
on the creatureevent.h

C++:
enum CreatureEventType_t {
    CREATURE_EVENT_NONE,
    CREATURE_EVENT_LOGIN,
    CREATURE_EVENT_LOGOUT,
    CREATURE_EVENT_THINK,
    CREATURE_EVENT_PREPAREDEATH,
    CREATURE_EVENT_DEATH,
    CREATURE_EVENT_KILL,
    CREATURE_EVENT_ADVANCE,
    CREATURE_EVENT_MODALWINDOW,
    CREATURE_EVENT_TEXTEDIT,
    CREATURE_EVENT_HEALTHCHANGE,
    CREATURE_EVENT_MANACHANGE,
    CREATURE_EVENT_GAINEXPERIENCE,// ADDED THIS LINE
    CREATURE_EVENT_EXTENDED_OPCODE,
};

C++:
class CreatureEvent final : public Event
.....
//scripting
        bool executeOnLogin(Player* player) const;
        bool executeOnLogout(Player* player) const;
        bool executeOnThink(Creature* creature, uint32_t interval);
        bool executeOnPrepareDeath(Creature* creature, Creature* killer);
        bool executeOnDeath(Creature* creature, Item* corpse, Creature* killer, Creature* mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified);
        void executeOnKill(Creature* creature, Creature* target);
        bool executeAdvance(Player* player, skills_t, uint32_t, uint32_t);
        void executeModalWindow(Player* player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId);
        bool executeTextEdit(Player* player, Item* item, const std::string& text);
        void executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage);
        void executeManaChange(Creature* creature, Creature* attacker, CombatDamage& damage);
        void executeOnGainExperience(Creature* creature, uint32_t value); //ADDED THIS LINE
        void executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer);

on the creatureevent.cpp
Below

C++:
void CreatureEvent::executeManaChange(Creature* creature, Creature* attacker, CombatDamage& damage) {
.....

    scriptInterface->resetScriptEnv();
}

I added:
C++:
void CreatureEvent::executeOnGainExperience(Creature* creature, uint32_t value)
{
    //onGainExperience(creature, value)
    if (!scriptInterface->reserveScriptEnv()) {
        std::cout << "[Error - CreatureEvent::executeOnGainExperience] Call stack overflow" << std::endl;
        return;
    }

    ScriptEnvironment* env = scriptInterface->getScriptEnv();
    env->setScriptId(scriptId, scriptInterface);

    lua_State* L = scriptInterface->getLuaState();

    scriptInterface->pushFunction(scriptId);
    LuaScriptInterface::pushUserdata<Creature>(L, creature);
    LuaScriptInterface::setCreatureMetatable(L, -1, creature);
    lua_pushnumber(L, value);

    scriptInterface->callFunction(2);
}

on creature.cpp

At the end of the function:

C++:
void Creature::onGainExperience(uint64_t gainExp, Creature* target)

Added:
C++:
    //scripting event - onGainExperience
    const CreatureEventList& thinkEvents = getCreatureEvents(CREATURE_EVENT_GAINEXPERIENCE);
    for (CreatureEvent* thinkEvent : thinkEvents) {
        thinkEvent->executeOnGainExperience(this, gainExp);
    }

Next, on the /lib/compat/compat.lua file

Lua:
elseif key == "onHealthChange" then
            self:type("healthchange")
            self:onHealthChange(value)
            return
        elseif key == "onManaChange" then
            self:type("manachange")
            self:onManaChange(value)
            return
        elseif key == "onGainExperience" then --ADDED THIS ELSIF CLAUSE
            self:type("gainexperience")
            self:onGainExperience(value)
            return
        elseif key == "onExtendedOpcode" then
            self:type("extendedopcode")
            self:onExtendedOpcode(value)
            return
        end

Finally, under the /creaturescripts/screaturescripts.xml
I added my "new Function" to the events

XML:
<?xml version="1.0" encoding="UTF-8"?>
<creaturescripts>
    <event type="login" name="PlayerLogin" script="login.lua" />
    <event type="logout" name="PlayerLogout" script="logout.lua" />
    <event type="login" name="FirstItems" script="firstitems.lua" />
    <event type="login" name="OfflineTraining" script="offlinetraining.lua" />
    <event type="login" name="RegenerateStamina" script="regeneratestamina.lua" />
    <event type="death" name="PlayerDeath" script="playerdeath.lua" />
    <event type="death" name="DropLoot" script="droploot.lua" />
    <event type="gainexperience" name="GainExperience" script="gain_experience.lua" /> <!-- ADDED THIS -->
    <event type="extendedopcode" name="ExtendedOpcode" script="extendedopcode.lua" />
</creaturescripts>

and added the scrip on the /creaturescripts/scripts:

Lua:
function onGainExperience(creature, gainExp)
    local name = creature:getName()
    print(name.." GAINED "..gainExp.." EXPERIENCE!!!!")
    return true
end

Unfortunately after compiling the sources and testing them, it didn't worked at all. I tried registering the event for every spawned creature
like this:

Lua:
creature:registerEvent("GainExperience")

without success.
I also tried using the script as a bool function instead of a void one, but I got the same results.

Honestly I don't know if this is the correct way to accomplish this, so I'll appreciate any help or tip that could guide me to follow the correct path.
Thanks in advance!
 
Lua:
Player::onGainExperience?
i think you can use some checks for summons, if player has summons then execute the creature event from there
 
Last edited:
Back
Top