Skip to content

Commit

Permalink
Make monsters walk to spawn by chunked path (otland#3612)
Browse files Browse the repository at this point in the history
Issues addressed: otland#3600
Supersedes PR: otland#3610
  • Loading branch information
marmichalski committed Sep 17, 2021
1 parent 7f138ff commit 9ad973e
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/creature.cpp
Expand Up @@ -211,11 +211,11 @@ void Creature::onWalk()
forceUpdateFollowPath = true;
}
} else {
stopEventWalk();

if (listWalkDir.empty()) {
onWalkComplete();
}

stopEventWalk();
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/luascript.cpp
Expand Up @@ -2558,6 +2558,9 @@ void LuaScriptInterface::registerFunctions()
registerMethod("Monster", "selectTarget", LuaScriptInterface::luaMonsterSelectTarget);
registerMethod("Monster", "searchTarget", LuaScriptInterface::luaMonsterSearchTarget);

registerMethod("Monster", "isWalkingToSpawn", LuaScriptInterface::luaMonsterIsWalkingToSpawn);
registerMethod("Monster", "walkToSpawn", LuaScriptInterface::luaMonsterWalkToSpawn);

// Npc
registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate);
registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare);
Expand Down Expand Up @@ -10635,6 +10638,30 @@ int LuaScriptInterface::luaMonsterSearchTarget(lua_State* L)
return 1;
}

int LuaScriptInterface::luaMonsterIsWalkingToSpawn(lua_State* L)
{
// monster:isWalkingToSpawn()
Monster* monster = getUserdata<Monster>(L, 1);
if (monster) {
pushBoolean(L, monster->isWalkingToSpawn());
} else {
lua_pushnil(L);
}
return 1;
}

int LuaScriptInterface::luaMonsterWalkToSpawn(lua_State* L)
{
// monster:walkToSpawn()
Monster* monster = getUserdata<Monster>(L, 1);
if (monster) {
pushBoolean(L, monster->walkToSpawn());
} else {
lua_pushnil(L);
}
return 1;
}

// Npc
int LuaScriptInterface::luaNpcCreate(lua_State* L)
{
Expand Down
3 changes: 3 additions & 0 deletions src/luascript.h
Expand Up @@ -1064,6 +1064,9 @@ class LuaScriptInterface
static int luaMonsterSelectTarget(lua_State* L);
static int luaMonsterSearchTarget(lua_State* L);

static int luaMonsterIsWalkingToSpawn(lua_State* L);
static int luaMonsterWalkToSpawn(lua_State* L);

// Npc
static int luaNpcCreate(lua_State* L);

Expand Down
52 changes: 37 additions & 15 deletions src/monster.cpp
Expand Up @@ -517,17 +517,13 @@ void Monster::onCreatureLeave(Creature* creature)
//update targetList
if (isOpponent(creature)) {
removeTarget(creature);
if (targetList.empty()) {
updateIdleStatus();

if (!isSummon() && targetList.empty()) {
int32_t walkToSpawnRadius = g_config.getNumber(ConfigManager::DEFAULT_WALKTOSPAWNRADIUS);
if (walkToSpawnRadius > 0 && !Position::areInRange(position, masterPos, walkToSpawnRadius, walkToSpawnRadius)) {
std::vector<Direction> dirList;
if (getPathTo(masterPos, dirList, 0, 0, true, true)) {
startAutoWalk(dirList);
return;
}
walkToSpawn();
}

updateIdleStatus();
}
}
}
Expand Down Expand Up @@ -718,10 +714,6 @@ void Monster::updateIdleStatus()
}) == conditions.end();
}

if (idle) {
idle = listWalkDir.empty();
}

setIdle(idle);
}

Expand Down Expand Up @@ -1059,11 +1051,41 @@ void Monster::onThinkYell(uint32_t interval)
}
}

bool Monster::walkToSpawn()
{
if (walkingToSpawn || !spawn || !targetList.empty()) {
return false;
}

int32_t distance = std::max<int32_t>(Position::getDistanceX(position, masterPos), Position::getDistanceY(position, masterPos));
if (distance == 0) {
return false;
}

listWalkDir.clear();
if (!getPathTo(masterPos, listWalkDir, 0, std::max<int32_t>(0, distance - 5), true, true, distance)) {
return false;
}

walkingToSpawn = true;
startAutoWalk();
return true;
}

void Monster::onWalk()
{
Creature::onWalk();
}

void Monster::onWalkComplete()
{
// Continue walking to spawn
if (walkingToSpawn) {
walkingToSpawn = false;
walkToSpawn();
}
}

bool Monster::pushItem(Item* item)
{
const Position& centerPos = item->getPosition();
Expand Down Expand Up @@ -1168,20 +1190,20 @@ void Monster::pushCreatures(Tile* tile)

bool Monster::getNextStep(Direction& direction, uint32_t& flags)
{
if (listWalkDir.empty() && (isIdle || getHealth() <= 0)) {
if (!walkingToSpawn && (isIdle || getHealth() <= 0)) {
//we don't have anyone watching, might as well stop walking
eventWalk = 0;
return false;
}

bool result = false;
if (listWalkDir.empty() && (!followCreature || !hasFollowPath) && (!isSummon() || !isMasterInRange)) {
if (!walkingToSpawn && (!followCreature || !hasFollowPath) && (!isSummon() || !isMasterInRange)) {
if (getTimeSinceLastMove() >= 1000) {
randomStepping = true;
//choose a random direction
result = getRandomStep(getPosition(), direction);
}
} else if ((isSummon() && isMasterInRange) || followCreature || !listWalkDir.empty()) {
} else if ((isSummon() && isMasterInRange) || followCreature || walkingToSpawn) {
randomStepping = false;
result = Creature::getNextStep(direction, flags);
if (result) {
Expand Down
9 changes: 8 additions & 1 deletion src/monster.h
Expand Up @@ -134,7 +134,13 @@ class Monster final : public Creature

void drainHealth(Creature* attacker, int32_t damage) override;
void changeHealth(int32_t healthChange, bool sendHealthChange = true) override;

bool isWalkingToSpawn() const {
return walkingToSpawn;
}
bool walkToSpawn();
void onWalk() override;
void onWalkComplete() override;
bool getNextStep(Direction& direction, uint32_t& flags) override;
void onFollowCreatureComplete(const Creature* creature) override;

Expand Down Expand Up @@ -203,10 +209,11 @@ class Monster final : public Creature

Position masterPos;

bool ignoreFieldDamage = false;
bool isIdle = true;
bool isMasterInRange = false;
bool randomStepping = false;
bool ignoreFieldDamage = false;
bool walkingToSpawn = false;

void onCreatureEnter(Creature* creature);
void onCreatureLeave(Creature* creature);
Expand Down

0 comments on commit 9ad973e

Please sign in to comment.