Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize pathfinding #4637

Open
wants to merge 78 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 73 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
990ba89
Optimize pathfinding
NRH-AA Mar 23, 2024
00951d2
Minor fleeing monsters fix
NRH-AA Mar 23, 2024
89be1ad
Fix whitespace and else brackets
NRH-AA Mar 23, 2024
82ad8c9
More cleanup
NRH-AA Mar 23, 2024
632d202
Cleanup
NRH-AA Mar 23, 2024
e7b5725
Remove uneeded variable name change
NRH-AA Mar 23, 2024
bc36d30
Cleanup
NRH-AA Mar 23, 2024
68841aa
Move neighbor arrays back to map.cpp to fix unused variable failure
NRH-AA Mar 23, 2024
edc1746
Fix some compiling warnings
NRH-AA Mar 23, 2024
2476334
Fix incorrect method call in game.cpp
NRH-AA Mar 25, 2024
aa4153a
Update to new creature isDead method
NRH-AA Mar 25, 2024
9f882ca
Update to clang format
NRH-AA Mar 25, 2024
8d50780
Update to clang format
NRH-AA Mar 26, 2024
b89076b
Fix maxSearchDist=0 searches and delayed reaction to onFollowCreature
NRH-AA Mar 26, 2024
f4163e5
Fix fleeing monster randomly turning
NRH-AA Mar 26, 2024
cab2968
Reduce memory consumption and update pathmatching algorithm
NRH-AA Mar 30, 2024
3834fd5
Clang formatting
NRH-AA Mar 30, 2024
3009b52
Clang formatting
NRH-AA Mar 30, 2024
57ce003
Remove uneeded check on new nodes
NRH-AA Mar 30, 2024
a68e1f5
Normalize pathfinding algorithm
NRH-AA Apr 2, 2024
b832222
Merge branch 'otland:master' into Optimize_Pathfinding
NRH-AA Apr 2, 2024
9e53616
Final Changes: Move pathfinding call to onWalk
NRH-AA Apr 4, 2024
bf0cc40
Remove incorrect code
NRH-AA Apr 4, 2024
44a300d
Move from Euclidean to standard A*
NRH-AA Apr 5, 2024
e69384d
Fix overlooked typos and uneeded logic
NRH-AA Apr 5, 2024
8a9a093
Remove uneeded nullptr check and change iterations to int8_t
NRH-AA Apr 11, 2024
d0346d1
Revert int8_t
NRH-AA Apr 11, 2024
bf40672
Fix creature label error and update algorithm
NRH-AA Apr 12, 2024
40581af
Remove uneeded resizing
NRH-AA Apr 12, 2024
d5e6586
Revert comment
NRH-AA Apr 12, 2024
093b939
Add missing pathmatching call
NRH-AA Apr 13, 2024
d3fdf38
Allow force update path to be called more often
NRH-AA Apr 13, 2024
1e42f12
Fix sight blocked monsters path updating
NRH-AA Apr 14, 2024
1c38ce1
Additional blocked sight fix
NRH-AA Apr 14, 2024
9f924e1
Allow paths to be drawn a little farther like rl tibia
NRH-AA Apr 14, 2024
4f57e88
Add delay to pathfinding and optimize code
NRH-AA Apr 14, 2024
1d36c7b
Fix incorrect conditional
NRH-AA Apr 14, 2024
78aabb4
Move path delay to force update path
NRH-AA Apr 14, 2024
f6f0753
Change uint64_t to int64_t
NRH-AA Apr 14, 2024
e7efcfb
Add pathfinding interval and delay to config.lua
NRH-AA Apr 14, 2024
14d42f8
Add viewport check
NRH-AA Apr 14, 2024
920da7b
Fix memory leak
NRH-AA Apr 15, 2024
bebb988
Add memory management to follow list and pathmatching
NRH-AA Apr 15, 2024
dac4fc5
Replace std::sqrt for std::hypot
NRH-AA Apr 16, 2024
8327be7
Merge branch 'otland:master' into Optimize_Pathfinding
NRH-AA Apr 19, 2024
a6b3f25
Update to new constexpr position methods
NRH-AA Apr 19, 2024
4d891e9
Revert int declarations in pathmatching
NRH-AA Apr 20, 2024
60efba9
Change std::hypot for much faster std::sqrtf
NRH-AA Apr 20, 2024
c1d8530
Formatting
NRH-AA Apr 20, 2024
13e9d66
Add math.h
NRH-AA Apr 20, 2024
c3d86ca
Revert sqrtf and math.h
NRH-AA Apr 20, 2024
8efe712
Remove uneeded path call and add speed check
NRH-AA Apr 22, 2024
7f2f868
Merge branch 'otland:master' into Optimize_Pathfinding
NRH-AA Apr 22, 2024
3c42e94
Fix rainsalt review
NRH-AA Sep 8, 2024
297a1bb
Update configmanager
NRH-AA Sep 8, 2024
147d896
Update configmanager
NRH-AA Sep 8, 2024
7f74d9b
Merge branch 'master' into Optimize_Pathfinding
NRH-AA Sep 8, 2024
e1f35d5
Fix configmanager after merge
NRH-AA Sep 8, 2024
89f0402
Update to configermanager namespace methods
NRH-AA Sep 8, 2024
25b6a4b
Clang format
NRH-AA Sep 8, 2024
1b78b10
Use getX()/getY() and remove calculateHueristic from AStarNodes
NRH-AA Sep 8, 2024
87e3709
Replace AStarNodes:calculateHeuristic
NRH-AA Sep 8, 2024
f3cdd1a
Add a couple code optimizations
NRH-AA Sep 11, 2024
4b757d8
Move logic for better performance
NRH-AA Sep 11, 2024
591b5f4
Replace std::list for vector and modify datatypes
NRH-AA Sep 12, 2024
089df96
Replace push_back for emplace_back and revert calculateHeuristic
NRH-AA Sep 12, 2024
0d53483
Replace followedByCreature for followers and update std::array
NRH-AA Sep 12, 2024
b3698e4
Change addFollowedByCreature to addFollower
NRH-AA Sep 12, 2024
de8be87
Update method calls
NRH-AA Sep 13, 2024
523821a
Add additional checks for redundant pathfinding calls
NRH-AA Sep 13, 2024
7a07da2
Remove redundant check
NRH-AA Sep 13, 2024
fac752f
Clang Format
NRH-AA Sep 13, 2024
27a16c7
Change updateFollowingCreaturePaths to updateFollowersPaths
NRH-AA Sep 13, 2024
76241a5
Fix a problem in most recent path conditional
NRH-AA Sep 16, 2024
ef92d7a
Fix bug in pre path conditional check
NRH-AA Sep 17, 2024
2abf230
Fix logic in last commit
NRH-AA Sep 17, 2024
6bf2b1f
Add required nullptr check to stop crashes on creature death
NRH-AA Sep 20, 2024
3fdb59f
Revert crash unrelated
NRH-AA Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions config.lua.dist
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ replaceKickOnLogin = true
maxPacketsPerSecond = 25
enableTwoFactorAuth = true

-- Pathfinding
-- NOTE: pathfindingInterval how often paths are force drawn
-- NOTE: pathfindingDelay delay recently force drawn paths from drawing again
pathfindingInterval = 100
pathfindingDelay = 200

-- Deaths
-- NOTE: Leave deathLosePercent as -1 if you want to use the default
-- death penalty formula. For the old formula, set it to 10. For
Expand Down
2 changes: 2 additions & 0 deletions src/configmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ 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", 100);
integer[PATHFINDING_DELAY] = getGlobalNumber(L, "pathfindingDelay", 200);

expStages = loadXMLStages();
if (expStages.empty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/configmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ enum integer_config_t
QUEST_TRACKER_PREMIUM_LIMIT,
STAMINA_REGEN_MINUTE,
STAMINA_REGEN_PREMIUM,
PATHFINDING_INTERVAL,
PATHFINDING_DELAY,

LAST_INTEGER_CONFIG /* this must be the last one */
};
Expand Down
70 changes: 44 additions & 26 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,27 +141,27 @@ void Creature::onThink(uint32_t interval)
blockTicks = 0;
}

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

if (isUpdatingPath) {
isUpdatingPath = false;
goToFollowCreature();
}

// scripting event - onThink
const CreatureEventList& thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
for (CreatureEvent* thinkEvent : thinkEvents) {
thinkEvent->executeOnThink(this, interval);
}
}

void Creature::forceUpdatePath()
{
if (!attackedCreature && !followCreature) {
return;
}

if (lastPathUpdate > OTSYS_TIME()) {
return;
}

lastPathUpdate = OTSYS_TIME() + getNumber(ConfigManager::PATHFINDING_DELAY);
g_dispatcher.addTask(createTask([id = getID()]() { g_game.updateCreatureWalk(id); }));
}

void Creature::onAttacking(uint32_t interval)
{
if (!attackedCreature) {
Expand Down Expand Up @@ -196,8 +196,6 @@ void Creature::onWalk()
player->sendCancelMessage(ret);
player->sendCancelWalk();
}

forceUpdateFollowPath = true;
}
} else {
stopEventWalk();
Expand All @@ -208,6 +206,8 @@ void Creature::onWalk()
}
}

updateFollowersPaths();

if (cancelNextWalk) {
listWalkDir.clear();
onWalkAborted();
Expand All @@ -218,6 +218,10 @@ void Creature::onWalk()
eventWalk = 0;
addEventWalk();
}

if (attackedCreature || followCreature) {
g_dispatcher.addTask(createTask([id = getID()]() { g_game.updateCreatureWalk(id); }));
}
}

void Creature::onWalk(Direction& dir)
Expand Down Expand Up @@ -619,10 +623,6 @@ void Creature::onCreatureMove(Creature* creature, const Tile* newTile, const Pos
}

if (creature == followCreature || (creature == this && followCreature)) {
if (hasFollowPath) {
isUpdatingPath = true;
}

if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) {
onCreatureDisappear(followCreature, false);
}
Expand Down Expand Up @@ -939,6 +939,7 @@ bool Creature::setAttackedCreature(Creature* creature)
}

attackedCreature = creature;
creature->addFollower(this);
onAttackedCreature(attackedCreature);
attackedCreature->onAttacked();
} else {
Expand All @@ -955,7 +956,7 @@ void Creature::getPathSearchParams(const Creature*, FindPathParams& fpp) const
{
fpp.fullPathSearch = !hasFollowPath;
fpp.clearSight = true;
fpp.maxSearchDist = 12;
fpp.maxSearchDist = Map::maxViewportX + Map::maxViewportY;
NRH-AA marked this conversation as resolved.
Show resolved Hide resolved
fpp.minTargetDist = 1;
fpp.maxTargetDist = 1;
}
Expand Down Expand Up @@ -1025,19 +1026,36 @@ bool Creature::setFollowCreature(Creature* creature)
onWalkAborted();
}

hasFollowPath = false;
forceUpdateFollowPath = false;
followCreature = creature;
isUpdatingPath = true;
creature->addFollower(this);
hasFollowPath = false;
} else {
isUpdatingPath = false;
followCreature = nullptr;
}

onFollowCreature(creature);
return true;
}

// Pathfinding Events
void Creature::updateFollowersPaths()
{
if (followers.empty()) {
return;
}

const Position& thisPosition = getPosition();
for (const auto follower : followers) {
const Position& followerPosition = follower->getPosition();
if (thisPosition.getDistanceX(followerPosition) >= Map::maxViewportX + 2 ||
thisPosition.getDistanceY(followerPosition) >= Map::maxViewportY + 2) {
continue;
}

g_dispatcher.addTask(createTask([id = follower->getID()]() { g_game.updateCreatureWalk(id); }));
}
}

double Creature::getDamageRatio(Creature* attacker) const
{
uint32_t totalDamage = 0;
Expand Down Expand Up @@ -1663,7 +1681,7 @@ bool Creature::isInvisible() const

bool Creature::getPathTo(const Position& targetPos, std::vector<Direction>& dirList, const FindPathParams& fpp) const
{
return g_game.map.getPathMatching(*this, dirList, FrozenPathingConditionCall(targetPos), fpp);
return g_game.map.getPathMatching(*this, targetPos, dirList, FrozenPathingConditionCall(targetPos), fpp);
}

bool Creature::getPathTo(const Position& targetPos, std::vector<Direction>& dirList, int32_t minTargetDist,
Expand Down
12 changes: 10 additions & 2 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct FindPathParams
static constexpr int32_t EVENT_CREATURECOUNT = 10;
static constexpr int32_t EVENT_CREATURE_THINK_INTERVAL = 1000;
static constexpr int32_t EVENT_CHECK_CREATURE_INTERVAL = (EVENT_CREATURE_THINK_INTERVAL / EVENT_CREATURECOUNT);

static constexpr uint32_t CREATURE_ID_MIN = 0x10000000;
static constexpr uint32_t CREATURE_ID_MAX = std::numeric_limits<uint32_t>::max();

Expand Down Expand Up @@ -195,6 +196,12 @@ class Creature : virtual public Thing
virtual void onFollowCreature(const Creature*) {}
virtual void onFollowCreatureComplete(const Creature*) {}

// Pathfinding functions
void addFollower(Creature* creature) { followers.emplace_back(creature); };

// Pathfinding events
void updateFollowersPaths();

// combat functions
Creature* getAttackedCreature() { return attackedCreature; }
virtual bool setAttackedCreature(Creature* creature);
Expand Down Expand Up @@ -278,6 +285,7 @@ class Creature : virtual public Thing
void setCreatureLight(LightInfo lightInfo);

virtual void onThink(uint32_t interval);
virtual void forceUpdatePath();
void onAttacking(uint32_t interval);
virtual void onWalk();
virtual bool getNextStep(Direction& dir, uint32_t& flags);
Expand Down Expand Up @@ -384,8 +392,10 @@ class Creature : virtual public Thing
Creature* attackedCreature = nullptr;
Creature* master = nullptr;
Creature* followCreature = nullptr;
std::vector<Creature*> followers;

uint64_t lastStep = 0;
int64_t lastPathUpdate = 0;
uint32_t referenceCounter = 0;
uint32_t id = 0;
uint32_t scriptEventsBitField = 0;
Expand Down Expand Up @@ -414,14 +424,12 @@ class Creature : virtual public Thing
bool localMapCache[mapWalkHeight][mapWalkWidth] = {{false}};
bool isInternalRemoved = false;
bool isMapLoaded = false;
bool isUpdatingPath = false;
bool creatureCheck = false;
bool inCheckCreaturesVector = false;
bool skillLoss = true;
bool lootDrop = true;
bool cancelNextWalk = false;
bool hasFollowPath = false;
bool forceUpdateFollowPath = false;
bool hiddenHealth = false;
bool canUseDefense = true;
bool movementBlocked = false;
Expand Down
17 changes: 17 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,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(EVENT_DECAYINTERVAL, [this]() { checkDecay(); }));
}

Expand Down Expand Up @@ -3873,6 +3875,21 @@ void Game::checkCreatures(size_t index)
cleanup();
}

void Game::updateCreaturesPath(size_t index)
{
g_scheduler.addEvent(createSchedulerTask(getNumber(ConfigManager::PATHFINDING_INTERVAL),
[=, this]() { updateCreaturesPath((index + 1) % EVENT_CREATURECOUNT); }));

auto& checkCreatureList = checkCreatureLists[index];
for (Creature* creature : checkCreatureList) {
if (!creature->isDead()) {
creature->forceUpdatePath();
}
}
NRH-AA marked this conversation as resolved.
Show resolved Hide resolved

cleanup();
}

void Game::changeSpeed(Creature* creature, int32_t varSpeedDelta)
{
int32_t varSpeed = creature->getSpeed() - creature->getBaseSpeed();
Expand Down
1 change: 1 addition & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ class Game
void updateCreatureWalk(uint32_t creatureId);
void checkCreatureAttack(uint32_t creatureId);
void checkCreatures(size_t index);
void updateCreaturesPath(size_t index);
void checkLight();

bool combatBlockHit(CombatDamage& damage, Creature* attacker, Creature* target, bool checkDefense, bool checkArmor,
Expand Down
Loading
Loading