• 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+ Stop summon to follow master

zxmatzx

Advanced OT User
Joined
Dec 1, 2010
Messages
312
Solutions
27
Reaction score
155
Location
Brazil
GitHub
Mateuso8
Hi,
I added this commit the part that is related to creature:moveTo function. Im using this function to players move their summons. But the summon can't go to location because the natural behaviour of summon is stay close to master, i think i need to edit my onThink in monster.cpp, but don't know what i need to change. I want to summon move to position and stay there, if the player move, the summon back to near(natural behaviour).
This is my code to do summon go to position:

Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    local playerPet = cid:getSummonedPet()
    if playerPet then
        --functions before try move
    
        --MOVE
        if playerPet:getPathTo(toPosition) then
            if Tile(toPosition):isWalkable(true) then--Edited isWalkable to check if have creatures in the tile too
                playerPet:moveTo(toPosition)
                cid:say("Go there!", MESSAGE_EVENT_ORANGE)
                return true
            end
        end
        --can't reach destination
        return true
    else
        --don't have pet
    end
    return true
end
What happens when i use the action:
a.gif
I tested this function with Creatures(Monsters, Npcs and Players) and works well. The only problem is with summons...
Thanks for attention.
 
Solution
I've fixed this by setting an isWalking flag during the moveTo movement.

luascript.cpp
replace:
C++:
int32_t LuaScriptInterface::luaCreatureMoveTo(lua_State* L)
{
    //creature:moveTo(pos)
    Creature* creature = getUserdata<Creature>(L, 1);
    if (!creature) {
        lua_pushnil(L);
        return 1;
    }

    const Position& position = getPosition(L, 2);

    FindPathParams fpp;
    fpp.minTargetDist = getNumber<int32_t>(L, 3, 0);
    fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1);
    fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch);
    fpp.clearSight = getBoolean(L, 6, fpp.clearSight);
    fpp.maxSearchDist = getNumber<int32_t>(L, 7, 150);

    std::forward_list<Direction> dirList;
    if...
//creature:moveTo(pos)

POG. I can make use of this.
Thanks fam.

Not sure about your issue.
I think this might be the cause:

Test this theory by commenting out this line:

And seeing if the summon moves to the position properly.
Hi,
Idk, i still guess that the problem is in onThink, because the order to move to position is happening and the original behaviour is actived. I guess have to set a variable to check if creature is moving and only trigger the original behaviour if creature is not moving.
 
Hmm true.

Could be this:
or this:

I'll leave it to someone more familiar with the codebase.
There's too many isSummon() references for me to figure it out in a reasonable amount of time.
 
Hmm true.

Could be this:
or this:

I'll leave it to someone more familiar with the codebase.
There's too many isSummon() references for me to figure it out in a reasonable amount of time.
Thanks your efforts. Someone one time said: "TFS is a spiderweb". I looked for hours, but don't understood what i need to do, plus i lacking skills in C++, im realy stucked. Hope you do some nice system with the function!
 
I've fixed this by setting an isWalking flag during the moveTo movement.

luascript.cpp
replace:
C++:
int32_t LuaScriptInterface::luaCreatureMoveTo(lua_State* L)
{
    //creature:moveTo(pos)
    Creature* creature = getUserdata<Creature>(L, 1);
    if (!creature) {
        lua_pushnil(L);
        return 1;
    }

    const Position& position = getPosition(L, 2);

    FindPathParams fpp;
    fpp.minTargetDist = getNumber<int32_t>(L, 3, 0);
    fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1);
    fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch);
    fpp.clearSight = getBoolean(L, 6, fpp.clearSight);
    fpp.maxSearchDist = getNumber<int32_t>(L, 7, 150);

    std::forward_list<Direction> dirList;
    if (creature->getPathTo(position, dirList, fpp)) {
        creature->hasFollowPath = true;
        creature->isWalking = true; // Set the flag here
        creature->startAutoWalk(dirList);
        pushBoolean(L, true);
    }
    else {
        pushBoolean(L, false);
    }
    return 1;
}

creature.h
after:
C++:
bool hasFollowPath = false;
add:
C++:
bool isWalking = false;

creature.cpp
replace:
C++:
void Creature::onWalk()
{
    if (getWalkDelay() <= 0) {
        Direction dir;
        uint32_t flags = FLAG_IGNOREFIELDDAMAGE;
        if (getNextStep(dir, flags)) {
            ReturnValue ret = g_game.internalMoveCreature(this, dir, flags);
            if (ret != RETURNVALUE_NOERROR) {
                if (Player* player = getPlayer()) {
                    player->sendCancelMessage(ret);
                    player->sendCancelWalk();
                }

                forceUpdateFollowPath = true;
            }
        } else {
            if (listWalkDir.empty()) {
                onWalkComplete();
            }
            isWalking = false; // Turn flag off here
            stopEventWalk();
        }
    }

    if (cancelNextWalk) {
        listWalkDir.clear();
        onWalkAborted();
        cancelNextWalk = false;
        isWalking = false; // Turn flag off here too
    }

    if (eventWalk != 0) {
        eventWalk = 0;
        addEventWalk();
    }
}
replace:
C++:
void Creature::onThink(uint32_t interval)
{
    if (!isMapLoaded && useCacheMap()) {
        isMapLoaded = true;
        updateMapCache();
    }

    if (followCreature && master != followCreature && !canSeeCreature(followCreature)) {
        onCreatureDisappear(followCreature, false);
    }

    if (attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature)) {
        onCreatureDisappear(attackedCreature, false);
    }

    blockTicks += interval;
    if (blockTicks >= 1000) {
        blockCount = std::min<uint32_t>(blockCount + 1, 2);
        blockTicks = 0;
    }

    if (followCreature) {
        walkUpdateTicks += interval;
        if (forceUpdateFollowPath || walkUpdateTicks >= 2000) {
            walkUpdateTicks = 0;
            forceUpdateFollowPath = false;
            isUpdatingPath = true;
        }
    }

    if (isUpdatingPath) {
        isUpdatingPath = false;
        if (!isWalking) { // Check if flag is true before moving back to player
            goToFollowCreature();
        }
    }

    //scripting event - onThink
    const CreatureEventList& thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
    for (CreatureEvent* thinkEvent : thinkEvents) {
        thinkEvent->executeOnThink(this, interval);
    }
}
 
Last edited:
Solution
I've fixed this by setting an isWalking flag during the moveTo movement.

luascript.cpp
replace:
C++:
int32_t LuaScriptInterface::luaCreatureMoveTo(lua_State* L)
{
    //creature:moveTo(pos)
    Creature* creature = getUserdata<Creature>(L, 1);
    if (!creature) {
        lua_pushnil(L);
        return 1;
    }

    const Position& position = getPosition(L, 2);

    FindPathParams fpp;
    fpp.minTargetDist = getNumber<int32_t>(L, 3, 0);
    fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1);
    fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch);
    fpp.clearSight = getBoolean(L, 6, fpp.clearSight);
    fpp.maxSearchDist = getNumber<int32_t>(L, 7, 150);

    std::forward_list<Direction> dirList;
    if (creature->getPathTo(position, dirList, fpp)) {
        creature->hasFollowPath = true;
        creature->isWalking = true; // Set the flag here
        creature->startAutoWalk(dirList);
        pushBoolean(L, true);
    }
    else {
        pushBoolean(L, false);
    }
    return 1;
}

creature.h
after:
C++:
bool hasFollowPath = false;
add:
C++:
bool isWalking = false;

creature.cpp
replace:
C++:
void Creature::onWalk()
{
    if (getWalkDelay() <= 0) {
        Direction dir;
        uint32_t flags = FLAG_IGNOREFIELDDAMAGE;
        if (getNextStep(dir, flags)) {
            ReturnValue ret = g_game.internalMoveCreature(this, dir, flags);
            if (ret != RETURNVALUE_NOERROR) {
                if (Player* player = getPlayer()) {
                    player->sendCancelMessage(ret);
                    player->sendCancelWalk();
                }

                forceUpdateFollowPath = true;
            }
        } else {
            if (listWalkDir.empty()) {
                onWalkComplete();
            }
            isWalking = false; // Turn flag off here
            stopEventWalk();
        }
    }

    if (cancelNextWalk) {
        listWalkDir.clear();
        onWalkAborted();
        cancelNextWalk = false;
        isWalking = false; // Turn flag off here too
    }

    if (eventWalk != 0) {
        eventWalk = 0;
        addEventWalk();
    }
}
replace:
C++:
void Creature::onThink(uint32_t interval)
{
    if (!isMapLoaded && useCacheMap()) {
        isMapLoaded = true;
        updateMapCache();
    }

    if (followCreature && master != followCreature && !canSeeCreature(followCreature)) {
        onCreatureDisappear(followCreature, false);
    }

    if (attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature)) {
        onCreatureDisappear(attackedCreature, false);
    }

    blockTicks += interval;
    if (blockTicks >= 1000) {
        blockCount = std::min<uint32_t>(blockCount + 1, 2);
        blockTicks = 0;
    }

    if (followCreature) {
        walkUpdateTicks += interval;
        if (forceUpdateFollowPath || walkUpdateTicks >= 2000) {
            walkUpdateTicks = 0;
            forceUpdateFollowPath = false;
            isUpdatingPath = true;
        }
    }

    if (isUpdatingPath) {
        isUpdatingPath = false;
        if (!isWalking) { // Check if flag is true before moving back to player
            goToFollowCreature();
        }
    }

    //scripting event - onThink
    const CreatureEventList& thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
    for (CreatureEvent* thinkEvent : thinkEvents) {
        thinkEvent->executeOnThink(this, interval);
    }
}
Working nice! Thank you Leo32!
Will fit my needs! When the summon reach the destination, the isWalking flag is turned off and the summon back to original behaviour and go near player, but i think i can solve this with LUA. When i solve this, i will post here the solution.
Again, really thanks!
 
Back
Top