Compare commits

...

15 Commits

Author SHA1 Message Date
Akkadius 78b0c86442 Don't send update to self while in group 2025-01-20 21:34:49 -06:00
Akkadius ce3d3153d8 Little bit of cleanup 2025-01-20 21:34:49 -06:00
Akkadius 92cc457067 Add rule Zone:EnableEntityClipping 2025-01-20 21:34:49 -06:00
Akkadius 9780623fea Update client.cpp 2025-01-20 21:34:49 -06:00
Akkadius d89bcf4f6c Update client.cpp 2025-01-20 21:34:49 -06:00
Akkadius 34b3a3fc88 Updates 2025-01-20 21:34:49 -06:00
Akkadius 8f54abec61 Update mob.cpp 2025-01-20 21:34:17 -06:00
Akkadius ed4d72c54b Broadcast to group 2025-01-20 21:34:17 -06:00
Akkadius 2d8ef8d286 Feature flag all logic 2025-01-20 21:34:16 -06:00
Akkadius 6424e6a3f3 Amazing 2025-01-20 21:34:00 -06:00
Akkadius 8606ccffc9 Beautiful 2025-01-20 21:34:00 -06:00
Akkadius 2bf02a5be5 Update entity.cpp 2025-01-20 21:33:38 -06:00
Akkadius abc507d173 More 2025-01-20 21:33:38 -06:00
Akkadius c18cba4faf More changes 2025-01-20 21:33:10 -06:00
Akkadius 010ba01ee7 Zone optimizations 2025-01-20 21:31:13 -06:00
19 changed files with 240 additions and 162 deletions
+3 -2
View File
@@ -457,10 +457,11 @@ enum ServerLockType : int {
Unlock
};
enum Invisibility : uint8 {
enum Invisibility : uint16 {
Visible,
Invisible,
Special = 255
Special = 255,
GMInvis = 3001
};
enum AugmentActions : int {
+3 -1
View File
@@ -143,6 +143,7 @@ namespace Logs {
Corpses,
XTargets,
EvolveItem,
Visibility,
MaxCategoryID /* Don't Remove this */
};
@@ -244,7 +245,8 @@ namespace Logs {
"EqTime",
"Corpses",
"XTargets",
"EvolveItem"
"EvolveItem",
"Visibility"
};
}
+10
View File
@@ -854,6 +854,16 @@
OutF(LogSys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogVisibility(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::Visibility))\
OutF(LogSys, Logs::General, Logs::Visibility, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogVisibilityDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::Visibility))\
OutF(LogSys, Logs::Detail, Logs::Visibility, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.IsLogEnabled(debug_level, log_category))\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
+2
View File
@@ -373,6 +373,8 @@ RULE_BOOL(Zone, AllowCrossZoneSpellsOnBots, false, "Set to true to allow cross z
RULE_BOOL(Zone, AllowCrossZoneSpellsOnMercs, false, "Set to true to allow cross zone spells (cast/remove) to affect mercenaries")
RULE_BOOL(Zone, AllowCrossZoneSpellsOnPets, false, "Set to true to allow cross zone spells (cast/remove) to affect pets")
RULE_BOOL(Zone, ZoneShardQuestMenuOnly, false, "Set to true if you only want quests to show the zone shard menu")
RULE_BOOL(Zone, AkkadiusTempPerformanceFeatureFlag, true, "Enable or disable the Akkadius Temp Performance Feature Flag")
RULE_BOOL(Zone, EnableEntityClipping, true, "Enable or disable visual entity clipping server side")
RULE_CATEGORY_END()
RULE_CATEGORY(Map)
+3
View File
@@ -86,6 +86,9 @@ struct BenchTimer
void reset() { start_time = clock::now(); }
// this is seconds
double elapsed() { return std::chrono::duration<double> (clock::now() - start_time).count(); }
std::chrono::milliseconds::rep elapsedMilliseconds() { return std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - start_time).count(); }
std::chrono::microseconds::rep elapsedMicroseconds() { return std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - start_time).count(); }
std::chrono::nanoseconds::rep elapsedNanoseconds() { return std::chrono::duration_cast<std::chrono::nanoseconds>(clock::now() - start_time).count(); }
private:
std::chrono::time_point<std::chrono::high_resolution_clock> start_time;
};
+1 -1
View File
@@ -679,7 +679,7 @@ int ZoneStore::GetZoneNPCMaximumAggroDistance(uint32 zone_id, int version)
uint32 ZoneStore::GetZoneMaximumMovementUpdateRange(uint32 zone_id, int version)
{
const auto& z = GetZoneVersionWithFallback(zone_id, version);
return z ? z->max_movement_update_range : DEFAULT_ZONE_MAX_MOVEMENT_UPDATE_RANGE;
return z ? z->npc_update_range : DEFAULT_ZONE_MAX_MOVEMENT_UPDATE_RANGE;
}
int8 ZoneStore::GetZoneMinimumExpansion(uint32 zone_id, int version)
-33
View File
@@ -7390,39 +7390,6 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) {
return;
}
/**
* @param close_mobs
* @param scanning_mob
*/
void EntityList::ScanCloseClientMobs(std::unordered_map<uint16, Mob*>& close_mobs, Mob* scanning_mob)
{
float scan_range = RuleI(Range, MobCloseScanDistance) * RuleI(Range, MobCloseScanDistance);
close_mobs.clear();
for (auto& e : mob_list) {
auto mob = e.second;
if (!mob->IsClient()) {
continue;
}
if (mob->GetID() <= 0) {
continue;
}
float distance = DistanceSquared(scanning_mob->GetPosition(), mob->GetPosition());
if (distance <= scan_range) {
close_mobs.insert(std::pair<uint16, Mob*>(mob->GetID(), mob));
}
else if (mob->GetAggroRange() >= scan_range) {
close_mobs.insert(std::pair<uint16, Mob*>(mob->GetID(), mob));
}
}
LogAIScanCloseDetail("Close Client Mob List Size [{}] for mob [{}]", close_mobs.size(), scanning_mob->GetCleanName());
}
uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid) {
uint8 need_healed = 0;
+72 -17
View File
@@ -12939,17 +12939,10 @@ void Client::SendTopLevelInventory()
}
}
// On a normal basis we limit mob movement updates based on distance
// This ensures we send a periodic full zone update to a client that has started moving after 5 or so minutes
//
// For very large zones we will also force a full update based on distance
//
// We ignore a small distance around us so that we don't interrupt already pathing deltas as those npcs will appear
// to full stop when they are actually still pathing
void Client::CheckSendBulkClientPositionUpdate()
{
float distance_moved = DistanceNoZ(m_last_position_before_bulk_update, GetPosition());
bool moved_far_enough_before_bulk_update = distance_moved >= zone->GetNpcPositionUpdateDistance();
bool moved_far_enough_before_bulk_update = distance_moved >= zone->GetMaxNpcUpdateRange();
bool is_ready_to_update = (
m_client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update
);
@@ -12958,31 +12951,54 @@ void Client::CheckSendBulkClientPositionUpdate()
LogDebug("[[{}]] Client Zone Wide Position Update NPCs", GetCleanName());
auto &mob_movement_manager = MobMovementManager::Get();
auto &mob_list = entity_list.GetMobList();
for (auto &it : mob_list) {
Mob *entity = it.second;
if (!entity->IsNPC()) {
for (auto &e: entity_list.GetMobList()) {
Mob *mob = e.second;
if (!mob->IsNPC()) {
continue;
}
int animation_speed = 0;
if (entity->IsMoving()) {
if (entity->IsRunning()) {
animation_speed = (entity->IsFeared() ? entity->GetFearSpeed() : entity->GetRunspeed());
if (mob->IsMoving()) {
if (mob->IsRunning()) {
animation_speed = (mob->IsFeared() ? mob->GetFearSpeed() : mob->GetRunspeed());
}
else {
animation_speed = entity->GetWalkspeed();
animation_speed = mob->GetWalkspeed();
}
}
mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, animation_speed, ClientRangeAny, this);
// if we have seen this mob before, and it hasn't moved, skip it
if (RuleB(Zone, AkkadiusTempPerformanceFeatureFlag)) {
if (m_last_seen_mob_position.contains(mob->GetID())) {
if (m_last_seen_mob_position[mob->GetID()] == mob->GetPosition()) {
LogVisibilityDetail(
"Mob [{}] has already been sent to client [{}] at this position, skipping",
mob->GetCleanName(),
GetCleanName()
);
continue;
}
}
}
mob_movement_manager.SendCommandToClients(
mob,
0.0,
0.0,
0.0,
0.0,
animation_speed,
ClientRangeAny,
this
);
}
m_last_position_before_bulk_update = GetPosition();
}
}
const uint16 scan_npc_aggro_timer_idle = RuleI(Aggro, ClientAggroCheckIdleInterval);
const uint16 scan_npc_aggro_timer_moving = RuleI(Aggro, ClientAggroCheckMovingInterval);
@@ -13123,3 +13139,42 @@ void Client::SetAAEXPPercentage(uint8 percentage)
SendAlternateAdvancementStats();
SendAlternateAdvancementTable();
}
void Client::BroadcastPositionUpdate()
{
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct *spu = (PlayerPositionUpdateServer_Struct *) outapp.pBuffer;
memset(spu, 0x00, sizeof(PlayerPositionUpdateServer_Struct));
spu->spawn_id = GetID();
spu->x_pos = FloatToEQ19(GetX());
spu->y_pos = FloatToEQ19(GetY());
spu->z_pos = FloatToEQ19(GetZ());
spu->heading = FloatToEQ12(GetHeading());
spu->delta_x = FloatToEQ13(0);
spu->delta_y = FloatToEQ13(0);
spu->delta_z = FloatToEQ13(0);
spu->delta_heading = FloatToEQ10(0);
spu->animation = 0;
entity_list.QueueCloseClients(this, &outapp, true, zone->GetMaxClientUpdateRange());
Group *g = GetGroup();
if (g) {
for (auto & m : g->members) {
if (m && m->IsClient() && m != this) {
m->CastToClient()->QueuePacket(&outapp);
}
}
}
}
void Client::SetVisibility(Mob* mob, bool visible) {
mob->SendAppearancePacket(
AppearanceType::Invisibility,
visible ? m_invisibility_state : Invisibility::GMInvis, // reset back to original visibility state when visible
false,
true,
this
);
}
+2
View File
@@ -1828,6 +1828,7 @@ public:
void DoEvolveTransferXP(const EQApplicationPacket* app);
void SendEvolveXPTransferWindow();
void SendEvolveTransferResults(const EQ::ItemInstance &inst_from, const EQ::ItemInstance &inst_to, const EQ::ItemInstance &inst_from_new, const EQ::ItemInstance &inst_to_new, const uint32 compatibility, const uint32 max_transfer_level);
void SetVisibility(Mob* mob, bool visible);
protected:
friend class Mob;
@@ -2087,6 +2088,7 @@ private:
Timer m_client_npc_aggro_scan_timer;
void CheckClientToNpcAggroTimer();
void ClientToNpcAggroProcess();
void BroadcastPositionUpdate();
// bulk position updates
glm::vec4 m_last_position_before_bulk_update;
+19
View File
@@ -971,6 +971,10 @@ void Client::CompleteConnect()
RecordStats();
AutoGrantAAPoints();
if (RuleB(Zone, AkkadiusTempPerformanceFeatureFlag)) {
m_last_seen_mob_position.reserve(entity_list.GetMobList().size());
}
// enforce some rules..
if (!CanEnterZone()) {
LogInfo("Kicking character [{}] from zone, not allowed here (missing requirements)", GetCleanName());
@@ -4956,6 +4960,21 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
CheckScanCloseMobsMovingTimer();
}
if (RuleB(Zone, EnableEntityClipping)) {
if (moving) {
if (m_see_close_mobs_timer.GetRemainingTime() > 1000) {
m_see_close_mobs_timer.Disable();
m_see_close_mobs_timer.Start(1000);
m_see_close_mobs_timer.Trigger();
}
}
else if (m_see_close_mobs_timer.GetDuration() == 1000) {
m_see_close_mobs_timer.Disable();
m_see_close_mobs_timer.Start(60000);
m_see_close_mobs_timer.Trigger();
}
}
CheckSendBulkClientPositionUpdate();
int32 new_animation = ppu->animation;
+9 -1
View File
@@ -122,7 +122,11 @@ bool Client::Process() {
/* I haven't naturally updated my position in 10 seconds, updating manually */
if (!IsMoving() && m_position_update_timer.Check()) {
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
if (RuleB(Zone, AkkadiusTempPerformanceFeatureFlag)) {
CastToClient()->BroadcastPositionUpdate();
} else {
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
}
}
if (mana_timer.Check())
@@ -285,6 +289,10 @@ bool Client::Process() {
entity_list.ScanCloseMobs(this);
}
if (RuleB(Zone, EnableEntityClipping) && m_see_close_mobs_timer.Check() && RuleB(Zone, AkkadiusTempPerformanceFeatureFlag)) {
entity_list.UpdateVisibility(this);
}
if (RuleB(Inventory, LazyLoadBank)) {
// poll once a second to see if we are close to a banker and we haven't loaded the bank yet
if (!m_lazy_load_bank && lazy_load_bank_check_timer.Check()) {
+1 -1
View File
@@ -1122,7 +1122,7 @@ void EntityList::AESpell(
LogAoeCast(
"Close scan distance [{}] cast distance [{}]",
RuleI(Range, MobCloseScanDistance),
zone->GetMaxNpcUpdateRange(),
distance
);
+69 -20
View File
@@ -1717,15 +1717,6 @@ void EntityList::QueueClientsByXTarget(Mob *sender, const EQApplicationPacket *a
}
}
/**
* @param sender
* @param app
* @param ignore_sender
* @param distance
* @param skipped_mob
* @param is_ack_required
* @param filter
*/
void EntityList::QueueCloseClients(
Mob *sender,
const EQApplicationPacket *app,
@@ -1742,7 +1733,7 @@ void EntityList::QueueCloseClients(
}
if (distance <= 0) {
distance = 600;
distance = zone->GetMaxClientUpdateRange();
}
float distance_squared = distance * distance;
@@ -2878,6 +2869,9 @@ bool EntityList::RemoveMobFromCloseLists(Mob *mob)
);
it->second->m_close_mobs.erase(entity_id);
it->second->m_can_see_mob.erase(entity_id);
it->second->m_last_seen_mob_position.erase(entity_id);
++it;
}
@@ -2931,6 +2925,9 @@ void EntityList::RemoveAuraFromMobs(Mob *aura)
// All of the above makes a tremendous impact on the bottom line of cpu cycle performance because we run an order of magnitude
// less checks by focusing our hot path logic down to a very small subset of relevant entities instead of looping an entire
// entity list (zone wide)
BenchTimer g_scan_bench_timer;
void EntityList::ScanCloseMobs(Mob *scanning_mob)
{
if (!scanning_mob) {
@@ -2941,7 +2938,9 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
return;
}
float scan_range = RuleI(Range, MobCloseScanDistance) * RuleI(Range, MobCloseScanDistance);
g_scan_bench_timer.reset();
float scan_range = std::max(zone->GetMaxNpcUpdateRange(), zone->GetMaxClientUpdateRange());
// Reserve memory in m_close_mobs to avoid frequent re-allocations if not already reserved.
// Assuming mob_list.size() as an upper bound for reservation.
@@ -2949,7 +2948,7 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
scanning_mob->m_close_mobs.reserve(mob_list.size());
}
scanning_mob->m_close_mobs.clear();
scanning_mob->m_close_mobs.clear();
for (auto &e : mob_list) {
auto mob = e.second;
@@ -2957,7 +2956,7 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
continue;
}
float distance = DistanceSquared(scanning_mob->GetPosition(), mob->GetPosition());
float distance = Distance(scanning_mob->GetPosition(), mob->GetPosition());
if (distance <= scan_range || mob->GetAggroRange() >= scan_range) {
// add mob to scanning_mob's close list and vice versa
// check if the mob is already in the close mobs list before inserting
@@ -2969,10 +2968,64 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
}
LogAIScanClose(
"[{}] Scanning close list > list_size [{}] moving [{}]",
"[{}] Scanning close list > list_size [{}] moving [{}] elapsed [{}] us",
scanning_mob->GetCleanName(),
scanning_mob->m_close_mobs.size(),
scanning_mob->IsMoving() ? "true" : "false"
scanning_mob->IsMoving() ? "true" : "false",
g_scan_bench_timer.elapsedMicroseconds()
);
}
BenchTimer g_vis_bench_timer;
#define STATE_HIDDEN (-1)
#define STATE_VISIBLE 1
void EntityList::UpdateVisibility(Mob *scanning_mob) {
if (!scanning_mob) {
return;
}
g_vis_bench_timer.reset();
// Ensure sufficient capacity in the visibility map
if (scanning_mob->m_can_see_mob.bucket_count() < scanning_mob->m_close_mobs.size()) {
scanning_mob->m_can_see_mob.reserve(scanning_mob->m_close_mobs.size());
}
// Iterate through all mobs in the zone
for (auto &e: mob_list) {
auto mob = e.second;
if (!mob || mob == scanning_mob) { continue; }
// Update scanning_mob's visibility of mob
auto it_scanning_visible = scanning_mob->m_can_see_mob.find(mob->GetID());
int8_t scanning_visibility = (it_scanning_visible != scanning_mob->m_can_see_mob.end())
? it_scanning_visible->second : 0;
if (scanning_mob->CalculateDistance(mob) <= mob->GetUpdateRange()) {
if (scanning_visibility != STATE_VISIBLE) { // Become visible
if (scanning_mob->IsClient()) {
scanning_mob->CastToClient()->SetVisibility(mob, true);
}
scanning_mob->m_can_see_mob[mob->GetID()] = STATE_VISIBLE;
}
}
else {
if (scanning_visibility != STATE_HIDDEN) { // Become invisible
if (scanning_mob->IsClient()) {
scanning_mob->CastToClient()->SetVisibility(mob, false);
}
scanning_mob->m_can_see_mob[mob->GetID()] = STATE_HIDDEN;
}
}
}
LogVisibility(
"[{}] Visibility > list_size [{}] moving [{}] elapsed [{}] us",
scanning_mob->GetCleanName(),
scanning_mob->m_can_see_mob.size(),
scanning_mob->IsMoving() ? "true" : "false",
g_vis_bench_timer.elapsedMicroseconds()
);
}
@@ -5759,14 +5812,10 @@ void EntityList::ReloadMerchants() {
* then we return the full list
*
* See comments @EntityList::ScanCloseMobs for system explanation
*
* @param mob
* @param distance
* @return
*/
std::unordered_map<uint16, Mob *> &EntityList::GetCloseMobList(Mob *mob, float distance)
{
if (distance <= RuleI(Range, MobCloseScanDistance)) {
if (distance <= zone->GetMaxNpcUpdateRange()) {
return mob->m_close_mobs;
}
+2 -2
View File
@@ -570,6 +570,8 @@ public:
void RefreshClientXTargets(Client *c);
void SendAlternateAdvancementStats();
void ScanCloseMobs(Mob *scanning_mob);
void UpdateVisibility(Mob *scanning_mob);
void UpdateKnownPositions(Mob *scanning_mob);
void GetTrapInfo(Client* c);
bool IsTrapGroupSpawned(uint32 trap_id, uint8 group);
@@ -631,8 +633,6 @@ private:
bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes); // TODO: Evaluate this closesly in hopes to eliminate
void ShowSpawnWindow(Client* client, int Distance, bool NamedOnly); // TODO: Implement ShowSpawnWindow in the bot class but it needs entity list stuff
void ScanCloseClientMobs(std::unordered_map<uint16, Mob*>& close_mobs, Mob* scanning_mob);
void GetBotList(std::list<Bot*> &b_list);
private:
std::list<Bot*> bot_list;
+12 -3
View File
@@ -129,6 +129,7 @@ Mob::Mob(
position_update_melee_push_timer(500),
hate_list_cleanup_timer(6000),
m_scan_close_mobs_timer(6000),
m_see_close_mobs_timer(1000),
m_mob_check_moving_timer(1000),
bot_attack_flag_timer(10000)
{
@@ -4126,6 +4127,10 @@ void Mob::SendAppearancePacket(
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
auto* a = (SpawnAppearance_Struct*)outapp->pBuffer;
if (type == AppearanceType::Invisibility && value != Invisibility::GMInvis) {
m_invisibility_state = value;
}
a->spawn_id = GetID();
a->type = type;
a->parameter = value;
@@ -8612,17 +8617,21 @@ std::unordered_map<uint16, Mob *> &Mob::GetCloseMobList(float distance)
void Mob::ClearDataBucketCache()
{
if (IsOfClientBot()) {
uint64 id = 0;
uint64 id = 0;
DataBucketLoadType::Type t{};
if (IsBot()) {
id = CastToBot()->GetBotID();
t = DataBucketLoadType::Bot;
t = DataBucketLoadType::Bot;
}
else if (IsClient()) {
id = CastToClient()->CharacterID();
t = DataBucketLoadType::Client;
t = DataBucketLoadType::Client;
}
DataBucket::DeleteFromCache(id, t);
}
}
float Mob::GetUpdateRange() {
return IsClient() ? zone->GetMaxClientUpdateRange() : zone->GetMaxNpcUpdateRange();
}
+9 -3
View File
@@ -201,9 +201,12 @@ public:
void DisplayInfo(Mob *mob);
std::unordered_map<uint16, Mob *> m_close_mobs;
Timer m_scan_close_mobs_timer;
Timer m_mob_check_moving_timer;
std::unordered_map<uint16, Mob *> m_close_mobs;
std::unordered_map<int, int8> m_can_see_mob;
std::unordered_map<int, glm::vec4> m_last_seen_mob_position;
Timer m_scan_close_mobs_timer;
Timer m_see_close_mobs_timer;
Timer m_mob_check_moving_timer;
// Bot attack flag
Timer bot_attack_flag_timer;
@@ -1490,6 +1493,7 @@ public:
std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f);
void CheckScanCloseMobsMovingTimer();
float GetUpdateRange();
void ClearDataBucketCache();
@@ -1907,6 +1911,8 @@ protected:
MobMovementManager *mMovementManager;
bool m_invisibility_state = 0;
private:
Mob* target;
EQ::InventoryProfile m_inv;
+7 -1
View File
@@ -852,11 +852,14 @@ void MobMovementManager::SendCommandToClients(
}
c->QueuePacket(&outapp, false);
if (RuleB(Zone, AkkadiusTempPerformanceFeatureFlag)) {
c->m_last_seen_mob_position[mob->GetID()] = mob->GetPosition();
}
}
}
else {
float short_range = RuleR(Pathing, ShortMovementUpdateRange);
float long_range = zone->GetNpcPositionUpdateDistance();
float long_range = zone->GetMaxNpcUpdateRange();
for (auto &c : _impl->Clients) {
if (single_client && c != single_client) {
@@ -902,6 +905,9 @@ void MobMovementManager::SendCommandToClients(
}
c->QueuePacket(&outapp, false);
if (RuleB(Zone, AkkadiusTempPerformanceFeatureFlag)) {
c->m_last_seen_mob_position[mob->GetID()] = mob->GetPosition();
}
}
}
}
+12 -72
View File
@@ -1091,7 +1091,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
mMovementManager = &MobMovementManager::Get();
SetNpcPositionUpdateDistance(0);
SetQuestHotReloadQueued(false);
}
@@ -1374,17 +1373,18 @@ bool Zone::LoadZoneCFG(const char* filename, uint16 instance_version)
newzone_data.suspend_buffs = z->suspendbuffs;
// local attributes
can_bind = z->canbind != 0;
is_city = z->canbind == 2;
can_combat = z->cancombat != 0;
can_levitate = z->canlevitate != 0;
can_castoutdoor = z->castoutdoor != 0;
is_hotzone = z->hotzone != 0;
max_movement_update_range = z->max_movement_update_range;
default_ruleset = z->ruleset;
allow_mercs = true;
m_graveyard_id = z->graveyard_id;
m_max_clients = z->maxclients;
can_bind = z->canbind != 0;
is_city = z->canbind == 2;
can_combat = z->cancombat != 0;
can_levitate = z->canlevitate != 0;
can_castoutdoor = z->castoutdoor != 0;
is_hotzone = z->hotzone != 0;
m_npc_update_range = z->npc_update_range;
m_client_update_range = z->client_update_range;
default_ruleset = z->ruleset;
allow_mercs = true;
m_graveyard_id = z->graveyard_id;
m_max_clients = z->maxclients;
SetIdleWhenEmpty(z->idle_when_empty);
SetSecondsBeforeIdle(z->seconds_before_idle);
@@ -1538,10 +1538,6 @@ bool Zone::Process() {
if (adv_data && !did_adventure_actions) {
DoAdventureActions();
}
if (GetNpcPositionUpdateDistance() == 0) {
CalculateNpcUpdateDistanceSpread();
}
}
if (hot_reload_timer.Check() && IsQuestHotReloadQueued()) {
@@ -2735,62 +2731,6 @@ void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
m_ucss_available = ucss_available;
}
int Zone::GetNpcPositionUpdateDistance() const
{
return npc_position_update_distance;
}
void Zone::SetNpcPositionUpdateDistance(int in_npc_position_update_distance)
{
Zone::npc_position_update_distance = in_npc_position_update_distance;
}
void Zone::CalculateNpcUpdateDistanceSpread()
{
float max_x = 0;
float max_y = 0;
float min_x = 0;
float min_y = 0;
auto &mob_list = entity_list.GetMobList();
for (auto &it : mob_list) {
Mob *entity = it.second;
if (!entity->IsNPC()) {
continue;
}
if (entity->GetX() <= min_x) {
min_x = entity->GetX();
}
if (entity->GetY() <= min_y) {
min_y = entity->GetY();
}
if (entity->GetX() >= max_x) {
max_x = entity->GetX();
}
if (entity->GetY() >= max_y) {
max_y = entity->GetY();
}
}
int x_spread = int(std::abs(max_x - min_x));
int y_spread = int(std::abs(max_y - min_y));
int combined_spread = int(std::abs((x_spread + y_spread) / 2));
int update_distance = EQ::ClampLower(int(combined_spread / 4), int(zone->GetMaxMovementUpdateRange()));
SetNpcPositionUpdateDistance(update_distance);
Log(Logs::General, Logs::Debug,
"NPC update spread distance set to [%i] combined_spread [%i]",
update_distance,
combined_spread
);
}
bool Zone::IsQuestHotReloadQueued() const
{
return quest_hot_reload_queued;
+4 -5
View File
@@ -156,9 +156,6 @@ public:
bool SaveZoneCFG();
bool DoesAlternateCurrencyExist(uint32 currency_id);
int GetNpcPositionUpdateDistance() const;
void SetNpcPositionUpdateDistance(int in_npc_position_update_distance);
char *adv_data;
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
@@ -417,7 +414,8 @@ public:
SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message));
};
double GetMaxMovementUpdateRange() const { return max_movement_update_range; }
double GetMaxNpcUpdateRange() const { return m_npc_update_range; }
double GetMaxClientUpdateRange() const { return m_client_update_range; }
void SetIsHotzone(bool is_hotzone);
@@ -469,7 +467,8 @@ private:
bool staticzone;
bool zone_has_current_time;
bool quest_hot_reload_queued;
double max_movement_update_range;
double m_npc_update_range;
double m_client_update_range;
char *long_name;
char *map_name;
char *short_name;