Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions scripts/globals/colonization_reives.lua
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ xi.reives.enableReive = function(zoneID, reiveNum)
for _, entryId in pairs(reiveData.mob) do
local mob = GetMobByID(entryId)
if mob then
mob:setFixedSpawnPosition(true)

if not mob:isAlive() then
SpawnMob(entryId) -- Spawn the reive defenders
-- TODO: Set name flags (sword)
Expand Down
5 changes: 5 additions & 0 deletions scripts/specs/core/CBaseEntity.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3758,6 +3758,11 @@ end
function CBaseEntity:setSpawn(x, y, z, rot)
end

---@param isFixed boolean
---return nil
function CBaseEntity:setFixedSpawnPosition(isFixed)
end

---@nodiscard
---@return integer
function CBaseEntity:getRespawnTime()
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/Escha_RuAun/mobs/Eschan_Gargouille.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onMobSpawn = function(mob)
mob:hideName(true)
mob:setUntargetable(true)
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/Grand_Palace_of_HuXzoi/mobs/Eozdei.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ mixins = { require('scripts/mixins/families/zdei') }
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onPath = function(mob)
local spawnPos = mob:getSpawnPos()
mob:pathThrough({ spawnPos.x, spawnPos.y, spawnPos.z })
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/Grand_Palace_of_HuXzoi/mobs/Eozdei_Still.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ mixins = { require('scripts/mixins/families/zdei') }
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onPath = function(mob)
local spawnPos = mob:getSpawnPos()
mob:pathThrough({ spawnPos.x, spawnPos.y, spawnPos.z })
Expand Down
16 changes: 12 additions & 4 deletions scripts/zones/RuAun_Gardens/mobs/Groundskeeper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ local ID = zones[xi.zone.RUAUN_GARDENS]
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true) -- TODO: change this to only apply to "wall" groundskeepers
end

entity.onMobDeath = function(mob, player, optParams)
xi.regime.checkRegime(player, mob, 143, 2, xi.regime.type.FIELDS)
xi.regime.checkRegime(player, mob, 144, 1, xi.regime.type.FIELDS)
Expand All @@ -20,10 +24,14 @@ entity.onMobDespawn = function(mob)
local params = {}
params.immediate = true
if xi.mob.phOnDespawn(mob, ID.mob.DESPOT, 5, 7200, params) then -- 2 hours
local phId = mob:getID()
GetMobByID(ID.mob.DESPOT):addListener('SPAWN', 'PH_VAR', function(m)
m:setLocalVar('ph', phId)
end)
local phId = mob:getID()
local despot = GetMobByID(ID.mob.DESPOT)

if despot then
despot:addListener('SPAWN', 'PH_VAR', function(m)
m:setLocalVar('ph', phId)
end)
end
end
end

Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Awzdei.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ mixins = { require('scripts/mixins/families/zdei') }
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onPath = function(mob)
local spawnPos = mob:getSpawnPos()
mob:pathThrough({ spawnPos.x, spawnPos.y, spawnPos.z })
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Awzdei_Fast.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ mixins = { require('scripts/mixins/families/zdei') }
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onPath = function(mob)
local spawnPos = mob:getSpawnPos()
mob:pathThrough({ spawnPos.x, spawnPos.y, spawnPos.z })
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Awzdei_Still.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ mixins = { require('scripts/mixins/families/zdei') }
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onPath = function(mob)
local spawnPos = mob:getSpawnPos()
mob:pathThrough({ spawnPos.x, spawnPos.y, spawnPos.z })
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Ixzdei_BLM.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ mixins = { require('scripts/mixins/job_special') }
---@type TMobEntity
local entity = {}

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

local chargeOptic = function(mob)
mob:setAutoAttackEnabled(false)
mob:setMobAbilityEnabled(false)
Expand Down
4 changes: 4 additions & 0 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Ixzdei_RDM.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ local chargeOptic = function(mob)
end
end

entity.onMobInitialize = function(mob)
mob:setFixedSpawnPosition(true)
end

entity.onMobSpawn = function(mob)
xi.mix.jobSpecial.config(mob, {
specials =
Expand Down
2 changes: 2 additions & 0 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Qnzdei.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ entity.onMobInitialize = function(mob)
if subLinkValue then
mob:setMobMod(xi.mobMod.SUBLINK, subLinkValue)
end

mob:setFixedSpawnPosition(true)
end

local changeState = function(mob, idle)
Expand Down
3 changes: 3 additions & 0 deletions settings/default/map.lua
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ xi.settings.map =
-- Allow mobs to walk back home instead of despawning
MOB_NO_DESPAWN = false,

-- Enable randomized spawn position for non-popped mobs (experimental)
MOB_RANDOMIZE_SPAWN_LOCATION = false,

-- Adds extra time to mob despawn in seconds. Base time is 25s, so a setting of 5 here would be a total of 30 seconds.
MOB_ADDITIONAL_TIME_TO_DEAGGRO = 0,

Expand Down
2 changes: 2 additions & 0 deletions src/map/battlefield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ bool CBattlefield::InsertEntity(CBaseEntity* PEntity, bool enter, BATTLEFIELDMOB
m_AdditionalEnemyList.emplace_back(mob);
}

mob.PMob->fixedSpawnPoint = true; // mobs spawn at fixed positions in battlefields

// todo: this can be greatly improved
if (mob.PMob->isAlive())
{
Expand Down
21 changes: 21 additions & 0 deletions src/map/entities/mobentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "mob_spell_container.h"
#include "mob_spell_list.h"
#include "mobskill.h"
#include "navmesh.h"
#include "packets/action.h"
#include "packets/entity_update.h"
#include "packets/pet_sync.h"
Expand Down Expand Up @@ -134,6 +135,8 @@ CMobEntity::CMobEntity()
, m_bcnmID(0)
, m_giveExp(false)
, m_neutral(false)
, m_SpawnPoint()
, fixedSpawnPoint(false)
, m_Element(0)
, m_HiPCLvl(0)
, m_HiPartySize(0)
Expand Down Expand Up @@ -662,6 +665,24 @@ void CMobEntity::Spawn()
// spawn somewhere around my point
loc.p = m_SpawnPoint;

if (loc.zone && loc.zone->m_navMesh && !loc.zone->loadingMobs && // If we have a navmesh and the zone isn't doing initialization (don't randomize spawns on map load)
settings::get<bool>("map.MOB_RANDOMIZE_SPAWN_LOCATION") && // check settings
!fixedSpawnPoint) // Does not have a fixed spawn position
{
float spawnRadius = 10.f; // TODO: mobmods?

if ((loc.zone->GetTypeMask() & ZONE_TYPE::DUNGEON) == ZONE_TYPE::DUNGEON)
{
spawnRadius = 5.f;
}

auto status = loc.zone->m_navMesh->findRandomPosition(m_SpawnPoint, spawnRadius);
if (status.first == 0) // Only try once
{
loc.p = status.second;
}
}

if (m_roamFlags & ROAMFLAG_STEALTH)
{
HideName(true);
Expand Down
3 changes: 2 additions & 1 deletion src/map/entities/mobentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ class CMobEntity : public CBattleEntity
bool m_giveExp; // prevent exp gain
bool m_neutral; // stop linking / aggroing

position_t m_SpawnPoint; // spawn point of mob
position_t m_SpawnPoint; // spawn point of mob
bool fixedSpawnPoint; // popped from QM or otherwise has a fixed position

uint8 m_Element;
uint8 m_HiPCLvl; // Highest Level of Player Character that hit the Monster
Expand Down
22 changes: 22 additions & 0 deletions src/map/lua/lua_baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17344,6 +17344,27 @@ void CLuaBaseEntity::setSpawn(float x, float y, float z, const sol::object& rot)
PMob->m_SpawnPoint.y = y;
PMob->m_SpawnPoint.z = z;
PMob->m_SpawnPoint.rotation = (rot != sol::lua_nil) ? rot.as<uint8>() : 0;
PMob->fixedSpawnPoint = true; // TODO: add more functionality around this. setSpawn is primarily used for very precise spawns.
}

/************************************************************************
* Function: setFixedSpawnPosition()
* Purpose : Set whether or not the mob will spawn only at their spawn points in the db
* Example : mob:setFixedSpawnPosition(true)
* Notes :
************************************************************************/

void CLuaBaseEntity::setFixedSpawnPosition(bool isFixed)
{
if (m_PBaseEntity->objtype != TYPE_MOB)
{
ShowWarning("Attempting to set spawn for invalid entity type (%s).", m_PBaseEntity->getName());
return;
}

auto* PMob = static_cast<CMobEntity*>(m_PBaseEntity);

PMob->fixedSpawnPoint = isFixed; // TODO: add more functionality around this.
}

/************************************************************************
Expand Down Expand Up @@ -20223,6 +20244,7 @@ void CLuaBaseEntity::Register()
SOL_REGISTER("isSpawned", CLuaBaseEntity::isSpawned);
SOL_REGISTER("getSpawnPos", CLuaBaseEntity::getSpawnPos);
SOL_REGISTER("setSpawn", CLuaBaseEntity::setSpawn);
SOL_REGISTER("setFixedSpawnPosition", CLuaBaseEntity::setFixedSpawnPosition);
SOL_REGISTER("getRespawnTime", CLuaBaseEntity::getRespawnTime);
SOL_REGISTER("setRespawnTime", CLuaBaseEntity::setRespawnTime);

Expand Down
1 change: 1 addition & 0 deletions src/map/lua/lua_baseentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,7 @@ class CLuaBaseEntity
bool isSpawned();
auto getSpawnPos() -> sol::table;
void setSpawn(float x, float y, float z, const sol::object& rot);
void setFixedSpawnPosition(bool isFixed);
uint32 getRespawnTime();
void setRespawnTime(uint32 seconds);

Expand Down
4 changes: 4 additions & 0 deletions src/map/utils/zoneutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,8 @@ void LoadMOBList(const std::vector<uint16>& zoneIds)
// clang-format off
ForEachZone(zoneIds, [](CZone* PZone)
{
PZone->loadingMobs = true;

for (auto &spawnGroup : PZone->m_spawnGroups)
{
spawnGroup.second->fillSpawnPool();
Expand Down Expand Up @@ -714,6 +716,8 @@ void LoadMOBList(const std::vector<uint16>& zoneIds)
}
}
});

PZone->loadingMobs = false;
});
// clang-format on
}
Expand Down
3 changes: 2 additions & 1 deletion src/map/zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,8 @@ class CZone
std::unique_ptr<ZoneLos> lineOfSight;
std::map<uint32_t, std::unique_ptr<spawnGroup>> m_spawnGroups;

timer::time_point m_LoadedAt; // The time the zone was loaded
timer::time_point m_LoadedAt; // The time the zone was loaded
bool loadingMobs; // Zone is doing initial mob load

void LoadNavMesh();
void LoadZoneLos();
Expand Down
Loading