diff --git a/config.lua.dist b/config.lua.dist index 3bb7a1b3b7..d47cb9f2f1 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -40,10 +40,7 @@ enableTwoFactorAuth = true -- Pathfinding -- pathfindingInterval handles how often paths are force drawn --- pathfindingDelay delays any recently drawn paths from drawing again --- pathfindingDelay does not delay pathfindingInterval -pathfindingInterval = 200 -pathfindingDelay = 300 +pathfindingInterval = 500 -- Deaths -- NOTE: Leave deathLosePercent as -1 if you want to use the default diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 9e4fa245ac..1eef745cfb 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -286,8 +286,7 @@ bool ConfigManager::load() integer[QUEST_TRACKER_PREMIUM_LIMIT] = getGlobalNumber(L, "questTrackerPremiumLimit", 15); integer[STAMINA_REGEN_MINUTE] = getGlobalNumber(L, "timeToRegenMinuteStamina", 3 * 60); integer[STAMINA_REGEN_PREMIUM] = getGlobalNumber(L, "timeToRegenMinutePremiumStamina", 6 * 60); - integer[PATHFINDING_INTERVAL] = getGlobalNumber(L, "pathfindingInterval", 200); - integer[PATHFINDING_DELAY] = getGlobalNumber(L, "pathfindingDelay", 300); + integer[PATHFINDING_INTERVAL] = getGlobalNumber(L, "pathfindingInterval", 500); expStages = loadXMLStages(); if (expStages.empty()) { diff --git a/src/configmanager.h b/src/configmanager.h index c476f24b3c..aad67cd479 100644 --- a/src/configmanager.h +++ b/src/configmanager.h @@ -120,7 +120,6 @@ enum integer_config_t STAMINA_REGEN_MINUTE, STAMINA_REGEN_PREMIUM, PATHFINDING_INTERVAL, - PATHFINDING_DELAY, LAST_INTEGER_CONFIG /* this must be the last one */ }; diff --git a/src/creature.cpp b/src/creature.cpp index 1972c847b9..074e61d513 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -126,14 +126,18 @@ void Creature::onThink(uint32_t interval) tfs::events::creature::onThink(asCreature(), interval); } -void Creature::forceUpdatePath() +void Creature::updateFollowPath() { - if (attackedCreature.expired() && followCreature.expired()) { + if (eventFollowPath != 0) { return; } - lastPathUpdate = OTSYS_TIME() + getNumber(ConfigManager::PATHFINDING_DELAY); - g_dispatcher.addTask(createTask([id = getID()]() { g_game.updateCreatureWalk(id); })); + if (followCreature.expired()) { + return; + } + + eventFollowPath = g_scheduler.addEvent( + createSchedulerTask(EVENT_CHECK_CREATURE_INTERVAL, [id = getID()]() { g_game.updateCreatureWalk(id); })); } void Creature::onIdleStatus() @@ -166,8 +170,6 @@ void Creature::onWalk() } } - updateFollowersPaths(); - if (cancelNextWalk) { listWalkDir.clear(); onWalkAborted(); @@ -179,12 +181,7 @@ void Creature::onWalk() addEventWalk(); } - if (!attackedCreature.expired() || !followCreature.expired()) { - if (lastPathUpdate < OTSYS_TIME()) { - g_dispatcher.addTask(createTask([id = getID()]() { g_game.updateCreatureWalk(id); })); - lastPathUpdate = OTSYS_TIME() + getNumber(ConfigManager::PATHFINDING_DELAY); - } - } + updateFollowersPaths(); } void Creature::onWalk(Direction& dir) @@ -315,7 +312,8 @@ void Creature::updateFollowCreaturePath(FindPathParams& fpp) { listWalkDir.clear(); - if (const auto& followCreature = getFollowCreature(); getPathTo(followCreature->getPosition(), listWalkDir, fpp)) { + if (const auto& followCreature = getFollowCreature(); + followCreature && getPathTo(followCreature->getPosition(), listWalkDir, fpp)) { hasFollowPath = true; startAutoWalk(); } else { @@ -381,6 +379,8 @@ void Creature::onCreatureMove(const std::shared_ptr& creature, const s creature == followCreature || (creature.get() == this && followCreature)) { if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) { onCreatureDisappear(followCreature, false); + } else { + updateFollowPath(); } } @@ -688,15 +688,12 @@ void Creature::setAttackedCreature(const std::shared_ptr& creature) } attackedCreature = creature; - creature->addFollower(asCreature()); onAttackedCreature(creature); if (const auto& player = creature->asPlayer()) { player->addInFightTicks(); } - forceUpdatePath(); - for (const auto& summon : summons | tfs::views::lock_weak_ptrs) { summon->setAttackedCreature(creature); } @@ -740,15 +737,29 @@ void Creature::setFollowCreature(const std::shared_ptr& creature) return; } - followCreature = creature; + if (const auto& oldFollow = getFollowCreature()) { + oldFollow->removeFollower(asCreature()); + } creature->addFollower(asCreature()); + + followCreature = creature; hasFollowPath = false; onFollowCreature(creature); - forceUpdatePath(); + + updateFollowPath(); } void Creature::removeFollowCreature() { + if (const auto& oldFollow = getFollowCreature()) { + oldFollow->removeFollower(asCreature()); + } + + if (eventFollowPath != 0) { + g_scheduler.stopEvent(eventFollowPath); + eventFollowPath = 0; + } + followCreature.reset(); onUnfollowCreature(); } @@ -790,12 +801,7 @@ void Creature::updateFollowersPaths() std::ranges::to(); for (const auto& follower : followers | tfs::views::lock_weak_ptrs) { - if (follower->lastPathUpdate < OTSYS_TIME()) { - continue; - } - - g_dispatcher.addTask(createTask([id = follower->getID()]() { g_game.updateCreatureWalk(id); })); - follower->lastPathUpdate = OTSYS_TIME() + getNumber(ConfigManager::PATHFINDING_DELAY); + follower->updateFollowPath(); } } diff --git a/src/creature.h b/src/creature.h index 503880414f..2a1efca47b 100644 --- a/src/creature.h +++ b/src/creature.h @@ -213,6 +213,8 @@ class Creature : public Thing { return tfs::owner_equal(followCreature, creature); } + void completeEventFollowWalk() { eventFollowPath = 0; } + bool hasPathToFollow() const { return hasFollowPath; } // follow events virtual void onFollowCreature(const std::shared_ptr&); @@ -317,7 +319,7 @@ class Creature : public Thing virtual void onThink(uint32_t interval); virtual void onAttacking(uint32_t) {} - virtual void forceUpdatePath(); + void updateFollowPath(); virtual void onWalk(); virtual bool getNextStep(Direction& dir, uint32_t& flags); @@ -393,7 +395,7 @@ class Creature : public Thing std::vector listWalkDir; uint64_t lastStep = 0; - int64_t lastPathUpdate = 0; + uint32_t eventFollowPath = 0; uint32_t id = 0; uint32_t scriptEventsBitField = 0; uint32_t eventWalk = 0; diff --git a/src/game.cpp b/src/game.cpp index e3de8520dd..3a8d1858fa 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -52,8 +52,8 @@ void Game::start(ServiceManager* manager) serviceManager = manager; g_scheduler.addEvent(createSchedulerTask(EVENT_CREATURE_THINK_INTERVAL, [this]() { checkCreatures(0); })); - g_scheduler.addEvent( - createSchedulerTask(getNumber(ConfigManager::PATHFINDING_INTERVAL), [this]() { updateCreaturesPath(0); })); + g_scheduler.addEvent(createSchedulerTask(getNumber(ConfigManager::PATHFINDING_INTERVAL), + [this]() { updateCreaturesFollowPath(0); })); g_scheduler.addEvent(createSchedulerTask(EVENT_DECAYINTERVAL, [this]() { checkDecay(); })); } @@ -3182,8 +3182,6 @@ void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) } player->setAttackedCreature(attackCreature); - - g_dispatcher.addTask([this, id = player->getID()]() { updateCreatureWalk(id); }); } void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) @@ -3200,8 +3198,6 @@ void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) } else { player->removeFollowCreature(); } - - g_dispatcher.addTask([this, id = player->getID()]() { updateCreatureWalk(id); }); } void Game::playerSetFightModes(uint32_t playerId, fightMode_t fightMode, bool chaseMode, bool secureMode) @@ -3726,6 +3722,7 @@ void Game::updateCreatureWalk(uint32_t creatureId) if (const auto& creature = getCreatureByID(creatureId)) { if (!creature->isDead()) { creature->goToFollowCreature(); + creature->completeEventFollowWalk(); } } } @@ -3789,14 +3786,19 @@ void Game::checkCreatures(size_t index) cleanup(); } -void Game::updateCreaturesPath(size_t index) +void Game::updateCreaturesFollowPath(size_t index) { - g_scheduler.addEvent(createSchedulerTask(getNumber(ConfigManager::PATHFINDING_INTERVAL), - [=, this]() { updateCreaturesPath((index + 1) % EVENT_CREATURECOUNT); })); + g_scheduler.addEvent(createSchedulerTask(getNumber(ConfigManager::PATHFINDING_INTERVAL), [=, this]() { + updateCreaturesFollowPath((index + 1) % EVENT_CREATURECOUNT); + })); for (const auto& creature : checkCreatureLists[index] | tfs::views::lock_weak_ptrs) { - if (!creature->isDead()) { - creature->forceUpdatePath(); + if (creature->isDead()) { + continue; + } + + if (creature->getFollowCreature() && !creature->hasPathToFollow()) { + creature->updateFollowPath(); } } } diff --git a/src/game.h b/src/game.h index f196a7ba6d..7e16e334a8 100644 --- a/src/game.h +++ b/src/game.h @@ -423,7 +423,7 @@ class Game void updateCreatureWalk(uint32_t creatureId); void checkCreatureAttack(uint32_t creatureId); void checkCreatures(size_t index); - void updateCreaturesPath(size_t index); + void updateCreaturesFollowPath(size_t index); bool combatBlockHit(CombatDamage& damage, const std::shared_ptr& attacker, const std::shared_ptr& target, bool checkDefense, bool checkArmor, bool field, diff --git a/src/player.cpp b/src/player.cpp index b242a4ccf6..79613a0f7c 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -1267,11 +1267,6 @@ void Player::onCreatureMove(const std::shared_ptr& creature, const std { Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); - if (const auto& followCreature = getFollowCreature(); - hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) { - g_dispatcher.addTask([id = getID()]() { g_game.updateCreatureWalk(id); }); - } - if (creature.get() != this) { return; }