Skip to content

Commit

Permalink
fix: spawn monster cadence
Browse files Browse the repository at this point in the history
  • Loading branch information
luan committed Nov 23, 2023
1 parent 1f7f967 commit 21146cf
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 34 deletions.
63 changes: 30 additions & 33 deletions src/creatures/monsters/spawns/spawn_monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,7 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) {
weight = pugi::cast<uint32_t>(weightAttribute.value());
}

uint32_t interval = pugi::cast<uint32_t>(childMonsterNode.attribute("spawntime").value()) * 1000 * 100 / std::max((uint32_t)1, (g_configManager().getNumber(RATE_SPAWN) * boostedrate * eventschedule));
if (interval >= MONSTER_MINSPAWN_INTERVAL && interval <= MONSTER_MAXSPAWN_INTERVAL) {
spawnMonster.addMonster(nameAttribute.as_string(), pos, dir, static_cast<uint32_t>(interval), weight);
} else {
if (interval <= MONSTER_MINSPAWN_INTERVAL) {
g_logger().warn("[SpawnsMonster::loadFromXml] - {} {} spawntime cannot be less than {} seconds, set to {} by default.", nameAttribute.as_string(), pos.toString(), MONSTER_MINSPAWN_INTERVAL / 1000, MONSTER_MINSPAWN_INTERVAL / 1000);
spawnMonster.addMonster(nameAttribute.as_string(), pos, dir, MONSTER_MINSPAWN_INTERVAL, weight);
} else {
g_logger().warn("[SpawnsMonster::loadFromXml] - {} {} spawntime can not be more than {} seconds", nameAttribute.as_string(), pos.toString(), MONSTER_MAXSPAWN_INTERVAL / 1000);
}
}
spawnMonster.addMonster(nameAttribute.as_string(), pos, dir, pugi::cast<uint32_t>(childMonsterNode.attribute("spawntime").value()) * 1000, weight);
}
}
}
Expand Down Expand Up @@ -175,30 +165,30 @@ bool SpawnMonster::isInSpawnMonsterZone(const Position &pos) {
return SpawnsMonster::isInZone(centerPos, radius, pos);
}

bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, const std::shared_ptr<MonsterType> monsterType, const Position &pos, Direction dir, bool startup /*= false*/) {
bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr<MonsterType> monsterType, bool startup /*= false*/) {
if (spawnedMonsterMap.contains(spawnMonsterId)) {
return false;
}
auto monster = std::make_shared<Monster>(monsterType);
if (startup) {
// No need to send out events to the surrounding since there is no one out there to listen!
if (!g_game().internalPlaceCreature(monster, pos, true)) {
if (!g_game().internalPlaceCreature(monster, sb.pos, true)) {
return false;
}
} else {
if (!g_game().placeCreature(monster, pos, false, true)) {
if (!g_game().placeCreature(monster, sb.pos, false, true)) {
return false;
}
}

monster->setDirection(dir);
monster->setDirection(sb.direction);
monster->setSpawnMonster(this);
monster->setMasterPos(pos);
monster->setMasterPos(sb.pos);

spawnedMonsterMap[spawnMonsterId] = monster;
spawnMonsterMap[spawnMonsterId].lastSpawn = OTSYS_TIME();
g_events().eventMonsterOnSpawn(monster, pos);
g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, pos);
sb.lastSpawn = OTSYS_TIME();
g_events().eventMonsterOnSpawn(monster, sb.pos);
g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, sb.pos);
return true;
}

Expand Down Expand Up @@ -247,7 +237,6 @@ void SpawnMonster::checkSpawnMonster() {

checkSpawnMonsterEvent = 0;
cleanup();
uint32_t spawnMonsterCount = 0;

for (auto &[spawnMonsterId, sb] : spawnMonsterMap) {
if (spawnedMonsterMap.contains(spawnMonsterId)) {
Expand All @@ -258,11 +247,7 @@ void SpawnMonster::checkSpawnMonster() {
if (!mType) {
continue;
}
if (!mType->canSpawn(sb.pos)) {
sb.lastSpawn = OTSYS_TIME();
continue;
}
if (mType->info.isBlockable && findPlayer(sb.pos)) {
if (!mType->canSpawn(sb.pos) || (mType->info.isBlockable && findPlayer(sb.pos))) {
sb.lastSpawn = OTSYS_TIME();
continue;
}
Expand All @@ -271,14 +256,10 @@ void SpawnMonster::checkSpawnMonster() {
}

if (mType->info.isBlockable) {
spawnMonster(spawnMonsterId, mType, sb.pos, sb.direction, true);
spawnMonster(spawnMonsterId, sb, mType, true);
} else {
scheduleSpawn(spawnMonsterId, sb, mType, 3 * NONBLOCKABLE_SPAWN_MONSTER_INTERVAL);
}

if (++spawnMonsterCount >= static_cast<uint32_t>(g_configManager().getNumber(RATE_SPAWN))) {
break;
}
}

if (spawnedMonsterMap.size() < spawnMonsterMap.size()) {
Expand All @@ -288,10 +269,10 @@ void SpawnMonster::checkSpawnMonster() {

void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr<MonsterType> mType, uint16_t interval) {
if (interval <= 0) {
spawnMonster(spawnMonsterId, mType, sb.pos, sb.direction);
spawnMonster(spawnMonsterId, sb, mType, startup);

Check failure on line 272 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-release

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’

Check failure on line 272 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / windows-2022-windows-release

'SpawnMonster::startup': non-standard syntax; use '&' to create a pointer to member

Check failure on line 272 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’

Check failure on line 272 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-release

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’

Check failure on line 272 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’
} else {
g_game().addMagicEffect(sb.pos, CONST_ME_TELEPORT);
g_dispatcher().scheduleEvent(1400, std::bind(&SpawnMonster::scheduleSpawn, this, spawnMonsterId, sb, mType, interval - NONBLOCKABLE_SPAWN_MONSTER_INTERVAL), "SpawnMonster::scheduleSpawn");
g_dispatcher().scheduleEvent(NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, std::bind(&SpawnMonster::scheduleSpawn, this, spawnMonsterId, sb, mType, interval - NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, startup), "SpawnMonster::scheduleSpawn");

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-release

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / windows-2022-windows-release

'SpawnMonster::startup': non-standard syntax; use '&' to create a pointer to member

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / windows-2022-windows-release

'std::bind': no matching overloaded function found

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / windows-2022-windows-release

'Dispatcher::scheduleEvent': no overloaded function takes 2 arguments

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-release

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’

Check failure on line 275 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

invalid use of non-static member function ‘void SpawnMonster::startup(bool)’
}
}

Expand All @@ -303,6 +284,7 @@ void SpawnMonster::cleanup() {
}
}
for (const auto &spawnMonsterId : removeList) {
spawnMonsterMap[spawnMonsterId].lastSpawn = OTSYS_TIME();
spawnedMonsterMap.erase(spawnMonsterId);
}
}
Expand All @@ -321,7 +303,22 @@ bool SpawnMonster::addMonster(const std::string &name, const Position &pos, Dire
return false;
}

this->interval = std::min(this->interval, scheduleInterval);
uint32_t eventschedule = g_eventsScheduler().getSpawnMonsterSchedule();
std::string boostedMonster = g_game().getBoostedMonsterName();
int32_t boostedrate = 1;
if (name == boostedMonster) {
boostedrate = 2;
}
// eventschedule is a whole percentage, so we need to multiply by 100 to match the order of magnitude of the other values
scheduleInterval = scheduleInterval * 100 / std::max((uint32_t)1, (g_configManager().getNumber(RATE_SPAWN) * boostedrate * eventschedule));
if (scheduleInterval < MONSTER_MINSPAWN_INTERVAL) {
g_logger().warn("[SpawnsMonster::addMonster] - {} {} spawntime cannot be less than {} seconds, set to {} by default.", name, pos.toString(), MONSTER_MINSPAWN_INTERVAL / 1000, MONSTER_MINSPAWN_INTERVAL / 1000);
scheduleInterval = MONSTER_MINSPAWN_INTERVAL;
} else if (scheduleInterval > MONSTER_MAXSPAWN_INTERVAL) {
g_logger().warn("[SpawnsMonster::addMonster] - {} {} spawntime can not be more than {} seconds, set to {} by default", name, pos.toString(), MONSTER_MAXSPAWN_INTERVAL / 1000, MONSTER_MAXSPAWN_INTERVAL / 1000);
scheduleInterval = MONSTER_MAXSPAWN_INTERVAL;
}
this->interval = std::gcd(this->interval, scheduleInterval);

Check failure on line 321 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / windows-2022-windows-release

'gcd': is not a member of 'std'

Check failure on line 321 in src/creatures/monsters/spawns/spawn_monster.cpp

View workflow job for this annotation

GitHub Actions / windows-2022-windows-release

'gcd': identifier not found

spawnBlock_t* sb = nullptr;
uint32_t spawnMonsterId = spawnMonsterMap.size() + 1;
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/monsters/spawns/spawn_monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class SpawnMonster {
uint32_t checkSpawnMonsterEvent = 0;

static bool findPlayer(const Position &pos);
bool spawnMonster(uint32_t spawnMonsterId, const std::shared_ptr<MonsterType> monsterType, const Position &pos, Direction dir, bool startup = false);
bool spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr<MonsterType> monsterType, bool startup = false);
void checkSpawnMonster();
void scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr<MonsterType> monsterType, uint16_t interval);
};
Expand Down

0 comments on commit 21146cf

Please sign in to comment.