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

C++ How to use createSchedulerTask on monster.cpp

E

Evil Puncker

Guest
Hi everyone, I'm kinda breaking my head trying to understand how the createSchedulerTask works, as I'm trying to add it here:

C++:
void Monster::onAttackedCreatureDisappear(bool)
{
    attackTicks = 0;
    extraMeleeAttack = true;

    createSchedulerTask(15000, std::bind(&Game::internalTeleport, &g_game, this, getMasterPos()));
}

so the monster (this) is teleported back to its getMasterPos() 15 seconds after he loses the target, but I tried the above and get the following error:

Error C2664 'SchedulerTask createSchedulerTask(uint32_t,std::function<void (void)>)': cannot convert argument 2 from 'std::_Binder<std::_Unforced,ReturnValue (__cdecl Game:: )(Thing *,const Position &,bool,uint32_t),Game *,Monster *,const Position &>' to 'std::function<void (void)>' theforgottenserver C:\Users\x\Desktop\forgottenserver-master\src\monster.cpp 125


any help is appreciated, thanks in advance

Using latest tfs.
 
Solution
Similarly to Lua you can't guarantee Monster lifetime so please don't use "this" because you are writing unsafe code.

The task should look something like this:
C++:
createSchedulerTask(15000, std::bind([](uint32_t monsterId) {
        Monster* monster = g_game.getMonsterByID(monsterId);
        if (!monster || !monster->getIdleStatus()) {
            return;
        }

        g_game.internalTeleport(monster, monster->getMasterPos());
    }, getID()));
Also keep in mind you need to use "g_scheduler.addEvent" to actually run that created task because if you don't run that task it'll simply gets destroyed after stack unwinding.
on top
C++:
#include "scheduler.h"
and
C++:
createSchedulerTask(15000, std::bind(&Game::internalTeleport, &g_game, this, getMasterPos(), true, 0));
 
Similarly to Lua you can't guarantee Monster lifetime so please don't use "this" because you are writing unsafe code.

The task should look something like this:
C++:
createSchedulerTask(15000, std::bind([](uint32_t monsterId) {
        Monster* monster = g_game.getMonsterByID(monsterId);
        if (!monster || !monster->getIdleStatus()) {
            return;
        }

        g_game.internalTeleport(monster, monster->getMasterPos());
    }, getID()));
Also keep in mind you need to use "g_scheduler.addEvent" to actually run that created task because if you don't run that task it'll simply gets destroyed after stack unwinding.
 
Solution
Similarly to Lua you can't guarantee Monster lifetime so please don't use "this" because you are writing unsafe code.

The task should look something like this:
C++:
createSchedulerTask(15000, std::bind([](uint32_t monsterId) {
        Monster* monster = g_game.getMonsterByID(monsterId);
        if (!monster || !monster->getIdleStatus()) {
            return;
        }

        g_game.internalTeleport(monster, monster->getMasterPos());
    }, getID()));
Also keep in mind you need to use "g_scheduler.addEvent" to actually run that created task because if you don't run that task it'll simply gets destroyed after stack unwinding.
Nice way to create anonymous functions or lambda functions in c ++, thanks for teaching me this ;)
Post automatically merged:

@Evil Puncker Because this event will be executed many times, you don't want to have a long queue of events that will accumulate and this function will execute many times, at least up to the line where the state of the monster is verified: if (!monster || !monster->getIdleStatus()) {

then you can do the following, to cancel the redundant events:

EXAMPLE:

monster.h found -> static uint32_t monsterAutoID; and add:
C++:
uint32_t relocateEventId = 0;

after in monster.cpp
C++:
void Monster::onAttackedCreatureDisappear(bool)
{ 
    attackTicks = 0;
    extraMeleeAttack = true;
 
    if (relocateEventId != 0) {
        g_scheduler.stopEvent(relocateEventId);
        relocateEventId = 0;
    }
    SchedulerTask* task = createSchedulerTask(15000, std::bind([](uint32_t monsterId) {
        Monster* monster = g_game.getMonsterByID(monsterId);
        if (!monster || !monster->getIdleStatus()) {
            return;
        }

        const Position& spawnPos = monster->getMasterPos();
        const Position& monsterPos = monster->getPosition();
        g_game.addMagicEffect(monsterPos, CONST_ME_POFF);
        g_game.internalTeleport(monster, spawnPos);
        g_game.addMagicEffect(spawnPos, CONST_ME_TELEPORT);
        }, getID()));
    relocateEventId = task->getEventId();
    g_scheduler.addEvent(task);

}
 
Last edited:
Back
Top