Zone optimizations

This commit is contained in:
Akkadius 2024-11-14 05:30:33 -06:00
parent 75698a809f
commit 010ba01ee7
8 changed files with 116 additions and 4 deletions

View File

@ -225,6 +225,7 @@ int command_init(void)
command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", AccountStatus::GMLeadAdmin, command_suspend) ||
command_add("suspendmulti", "[Character Name One|Character Name Two|etc] [Days] [Reason] - Suspend multiple characters by name for specified number of days", AccountStatus::GMLeadAdmin, command_suspendmulti) ||
command_add("takeplatinum", "[Platinum] - Takes specified amount of platinum from you or your player target", AccountStatus::GMMgmt, command_takeplatinum) ||
command_add("test", "Test Command", AccountStatus::GMLeadAdmin, command_test) ||
command_add("task", "(subcommand) - Task system commands", AccountStatus::GMLeadAdmin, command_task) ||
command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_petname) ||
command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_traindisc) ||
@ -920,6 +921,7 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/suspend.cpp"
#include "gm_commands/suspendmulti.cpp"
#include "gm_commands/takeplatinum.cpp"
#include "gm_commands/test.cpp"
#include "gm_commands/task.cpp"
#include "gm_commands/traindisc.cpp"
#include "gm_commands/tune.cpp"

View File

@ -179,6 +179,7 @@ void command_summonitem(Client *c, const Seperator *sep);
void command_suspend(Client *c, const Seperator *sep);
void command_suspendmulti(Client *c, const Seperator *sep);
void command_takeplatinum(Client* c, const Seperator* sep);
void command_test(Client *c, const Seperator *sep);
void command_task(Client *c, const Seperator *sep);
void command_petname(Client *c, const Seperator *sep);
void command_traindisc(Client *c, const Seperator *sep);

View File

@ -2941,7 +2941,7 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
return;
}
float scan_range = RuleI(Range, MobCloseScanDistance) * RuleI(Range, MobCloseScanDistance);
float scan_range = zone->GetMaxUpdateRange();
// 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.
@ -2957,7 +2957,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
@ -2968,6 +2968,8 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
}
}
UpdateVisibility(scanning_mob);
LogAIScanClose(
"[{}] Scanning close list > list_size [{}] moving [{}]",
scanning_mob->GetCleanName(),
@ -2976,6 +2978,97 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
);
}
void EntityList::UpdateVisibility(Mob *scanning_mob)
{
if (!scanning_mob || !scanning_mob->IsClient()) {
return;
}
// 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());
}
// Update visibility for all mobs in the close list of `scanning_mob`
for (auto &e : scanning_mob->m_close_mobs) {
auto mob = e.second;
if (!mob) continue;
int mob_id = mob->GetID();
// Update visibility for `scanning_mob` to `mob`
auto [it_scanning_visible, inserted_scanning_visible] = scanning_mob->m_can_see_mob.try_emplace(mob_id, false);
bool scanning_last_known_visible = it_scanning_visible->second;
if (!scanning_last_known_visible) {
scanning_mob->SendAppearancePacket(
AppearanceType::Invisibility,
0,
false,
true,
mob->CastToClient()
);
it_scanning_visible->second = true;
scanning_mob->Shout(fmt::format("Setting scanning_mob visible to mob [{}]", mob->GetCleanName()).c_str());
}
// Now update the visibility for `mob` to `scanning_mob`
auto [it_mob_visible, inserted_mob_visible] = mob->m_can_see_mob.try_emplace(scanning_mob->GetID(), false);
bool mob_last_known_visible = it_mob_visible->second;
if (!mob_last_known_visible) {
mob->SendAppearancePacket(
AppearanceType::Invisibility,
0,
false,
true,
scanning_mob->CastToClient()
);
it_mob_visible->second = true;
mob->Shout(fmt::format("Setting mob visible to scanning_mob [{}]", scanning_mob->GetCleanName()).c_str());
}
}
// Check all other mobs to make invisible if they are no longer close
for (auto &e : mob_list) {
auto mob = e.second;
if (!mob) continue;
int mob_id = mob->GetID();
bool is_on_close_list = mob->m_close_mobs.find(scanning_mob->GetID()) != mob->m_close_mobs.end();
// Update scanning_mob's view of mob visibility
auto [it, inserted] = scanning_mob->m_can_see_mob.try_emplace(mob_id, false);
bool last_known_visible = it->second;
if (!is_on_close_list && last_known_visible) {
scanning_mob->SendAppearancePacket(
AppearanceType::Invisibility,
3001,
false,
true,
mob->CastToClient()
);
it->second = false;
scanning_mob->Shout(fmt::format("Setting mob [{}] invisible to scanning_mob", mob->GetCleanName()).c_str());
}
// Inverse: Update mob's view of scanning_mob visibility
auto it_mob = mob->m_can_see_mob.find(scanning_mob->GetID());
if (it_mob != mob->m_can_see_mob.end() && !scanning_mob->m_close_mobs.count(mob_id) && it_mob->second) {
mob->SendAppearancePacket(
AppearanceType::Invisibility,
3001,
false,
true,
scanning_mob->CastToClient()
);
it_mob->second = false;
mob->Shout(fmt::format("Setting scanning_mob [{}] invisible to mob", scanning_mob->GetCleanName()).c_str());
}
}
}
bool EntityList::RemoveMerc(uint16 delete_id)
{
auto it = merc_list.find(delete_id);

View File

@ -570,6 +570,7 @@ public:
void RefreshClientXTargets(Client *c);
void SendAlternateAdvancementStats();
void ScanCloseMobs(Mob *scanning_mob);
void UpdateVisibility(Mob *scanning_mob);
void GetTrapInfo(Client* c);
bool IsTrapGroupSpawned(uint32 trap_id, uint8 group);

14
zone/gm_commands/test.cpp Executable file
View File

@ -0,0 +1,14 @@
void command_test(Client *c, const Seperator *sep)
{
const int arguments = sep->argnum;
for (auto &e : entity_list.GetMobList()) {
auto mob = e.second;
if (Distance(c->GetPosition(), mob->GetPosition()) > 100) {
mob->SendAppearancePacket(AppearanceType::Invisibility, 3001);
} else {
mob->SendAppearancePacket(AppearanceType::Invisibility, 0);
}
}
}

View File

@ -202,6 +202,7 @@ public:
void DisplayInfo(Mob *mob);
std::unordered_map<uint16, Mob *> m_close_mobs;
std::unordered_map<int, bool> m_can_see_mob;
Timer m_scan_close_mobs_timer;
Timer m_mob_check_moving_timer;

View File

@ -2780,7 +2780,7 @@ void Zone::CalculateNpcUpdateDistanceSpread()
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()));
int update_distance = EQ::ClampLower(int(combined_spread / 4), int(zone->GetMaxUpdateRange()));
SetNpcPositionUpdateDistance(update_distance);

View File

@ -417,7 +417,7 @@ public:
SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message));
};
double GetMaxMovementUpdateRange() const { return max_movement_update_range; }
double GetMaxUpdateRange() const { return max_movement_update_range; }
void SetIsHotzone(bool is_hotzone);