diff --git a/common/ruletypes.h b/common/ruletypes.h index 016fefc7d..0636f2959 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -547,7 +547,8 @@ RULE_INT(Aggro, IntAggroThreshold, 75, "Int lesser or equal the value will aggro RULE_BOOL(Aggro, AllowTickPulling, false, "tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live") RULE_INT(Aggro, MinAggroLevel, 18, "Minimum level for use with UseLevelAggro") RULE_BOOL(Aggro, UseLevelAggro, true, "MinAggroLevel rule value+ and Undead will aggro regardless of level difference. This will disabled Rule:IntAggroThreshold if set to true") -RULE_INT(Aggro, ClientAggroCheckInterval, 6, "Interval in which clients actually check for aggro - in seconds") +RULE_INT(Aggro, ClientAggroCheckMovingInterval, 1000, "Interval in which clients actually check for aggro while moving - in milliseconds - this should be lower than ClientAggroCheckIdleInterval") +RULE_INT(Aggro, ClientAggroCheckIdleInterval, 6000, "Interval in which clients actually check for aggro while idle - in milliseconds - this should be higher than ClientAggroCheckMovingInterval") RULE_REAL(Aggro, PetAttackRange, 40000.0, "Maximum squared range /pet attack works at default is 200") RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level") RULE_CATEGORY_END() diff --git a/zone/bot.cpp b/zone/bot.cpp index 48e468a05..a45e575d9 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2211,12 +2211,12 @@ bool Bot::Process() return false; } - if (mob_scan_close.Check()) { + if (mob_close_scan_timer.Check()) { LogAIScanClose( "is_moving [{}] bot [{}] timer [{}]", moving ? "true" : "false", GetCleanName(), - mob_scan_close.GetDuration() + mob_close_scan_timer.GetDuration() ); entity_list.ScanCloseClientMobs(close_mobs, this); diff --git a/zone/client.cpp b/zone/client.cpp index fdc75cfe6..562e6de58 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -139,7 +139,7 @@ Client::Client(EQStreamInterface* ieqs) endupkeep_timer(1000), forget_timer(0), autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000), - client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000), + client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckIdleInterval)), client_zone_wide_full_position_update_timer(5 * 60 * 1000), tribute_timer(Tribute_duration), proximity_timer(ClientProximity_interval), diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 316c08cd9..511a94b7e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4533,23 +4533,63 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { rewind_timer.Start(30000, true); } - /* Handle client aggro scanning timers NPCs */ - is_client_moving = (cy == m_Position.y && cx == m_Position.x) ? false : true; + + is_client_moving = !(cy == m_Position.y && cx == m_Position.x); + + + /** + * Client aggro scanning + */ + const uint16 client_scan_npc_aggro_timer_idle = RuleI(Aggro, ClientAggroCheckIdleInterval); + const uint16 client_scan_npc_aggro_timer_moving = RuleI(Aggro, ClientAggroCheckMovingInterval); + + LogAggroDetail( + "ClientUpdate [{}] {}moving, scan timer [{}]", + GetCleanName(), + is_client_moving ? "" : "NOT ", + client_scan_npc_aggro_timer.GetRemainingTime() + ); if (is_client_moving) { - LogDebug("ClientUpdate: Client is moving - scan timer is: [{}]", client_scan_npc_aggro_timer.GetDuration()); - if (client_scan_npc_aggro_timer.GetDuration() > 1000) { + if (client_scan_npc_aggro_timer.GetRemainingTime() > client_scan_npc_aggro_timer_moving) { + LogAggroDetail("Client [{}] Restarting with moving timer", GetCleanName()); client_scan_npc_aggro_timer.Disable(); - client_scan_npc_aggro_timer.Start(500); + client_scan_npc_aggro_timer.Start(client_scan_npc_aggro_timer_moving); + client_scan_npc_aggro_timer.Trigger(); } } - else { - LogDebug("ClientUpdate: Client is NOT moving - scan timer is: [{}]", client_scan_npc_aggro_timer.GetDuration()); - if (client_scan_npc_aggro_timer.GetDuration() < 1000) { - client_scan_npc_aggro_timer.Disable(); - client_scan_npc_aggro_timer.Start(3000); + else if (client_scan_npc_aggro_timer.GetDuration() == client_scan_npc_aggro_timer_moving) { + LogAggroDetail("Client [{}] Restarting with idle timer", GetCleanName()); + client_scan_npc_aggro_timer.Disable(); + client_scan_npc_aggro_timer.Start(client_scan_npc_aggro_timer_idle); + } + + /** + * Client mob close list cache scan timer + */ + const uint16 client_mob_close_scan_timer_moving = 6000; + const uint16 client_mob_close_scan_timer_idle = 60000; + + LogAIScanCloseDetail( + "Client [{}] {}moving, scan timer [{}]", + GetCleanName(), + is_client_moving ? "" : "NOT ", + mob_close_scan_timer.GetRemainingTime() + ); + + if (is_client_moving) { + if (mob_close_scan_timer.GetRemainingTime() > client_mob_close_scan_timer_moving) { + LogAIScanCloseDetail("Client [{}] Restarting with moving timer", GetCleanName()); + mob_close_scan_timer.Disable(); + mob_close_scan_timer.Start(client_mob_close_scan_timer_moving); + mob_close_scan_timer.Trigger(); } } + else if (mob_close_scan_timer.GetDuration() == client_mob_close_scan_timer_moving) { + LogAIScanCloseDetail("Client [{}] Restarting with idle timer", GetCleanName()); + mob_close_scan_timer.Disable(); + mob_close_scan_timer.Start(client_mob_close_scan_timer_idle); + } /** * On a normal basis we limit mob movement updates based on distance diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 18ee9979f..ba62d470d 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -257,7 +257,7 @@ bool Client::Process() { * Used in aggro checks */ if (mob_close_scan_timer.Check()) { - entity_list.ScanCloseMobs(close_mobs, this, true); + entity_list.ScanCloseMobs(close_mobs, this, is_client_moving); } bool may_use_attacks = false; diff --git a/zone/entity.cpp b/zone/entity.cpp index b6d897ccb..417bac493 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -712,6 +712,8 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) npc_list.insert(std::pair(npc->GetID(), npc)); mob_list.insert(std::pair(npc->GetID(), npc)); + entity_list.ScanCloseMobs(npc->close_mobs, npc, true); + /* Zone controller process EVENT_SPAWN_ZONE */ if (RuleB(Zone, UseZoneController)) { if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ diff --git a/zone/mob.cpp b/zone/mob.cpp index 175f9a94f..08c4625c0 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -118,7 +118,7 @@ Mob::Mob( attack_anim_timer(500), position_update_melee_push_timer(500), hate_list_cleanup_timer(6000), - mob_scan_close(6000), + mob_close_scan_timer(6000), mob_check_moving_timer(1000) { mMovementManager = &MobMovementManager::Get(); @@ -463,7 +463,7 @@ Mob::Mob( m_manual_follow = false; #endif - mob_scan_close.Trigger(); + mob_close_scan_timer.Trigger(); } Mob::~Mob() diff --git a/zone/mob.h b/zone/mob.h index 6fd040175..1f8705a30 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -172,8 +172,8 @@ public: void DisplayInfo(Mob *mob); std::unordered_map close_mobs; - Timer mob_scan_close; - Timer mob_check_moving_timer; + Timer mob_close_scan_timer; + Timer mob_check_moving_timer; //Somewhat sorted: needs documenting! diff --git a/zone/npc.cpp b/zone/npc.cpp index 2cd5cd095..a5ccfac76 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -723,22 +723,27 @@ bool NPC::Process() SpellProcess(); - if (mob_scan_close.Check()) { - + if (mob_close_scan_timer.Check()) { entity_list.ScanCloseMobs(close_mobs, this); - - if (moving) { - mob_scan_close.Disable(); - mob_scan_close.Start(RandomTimer(3000, 6000)); - } - else { - mob_scan_close.Disable(); - mob_scan_close.Start(RandomTimer(6000, 60000)); - } } - if (mob_check_moving_timer.Check() && moving) { - mob_scan_close.Trigger(); + const uint16 npc_mob_close_scan_timer_moving = 6000; + const uint16 npc_mob_close_scan_timer_idle = 60000; + + if (mob_check_moving_timer.Check()) { + if (moving) { + if (mob_close_scan_timer.GetRemainingTime() > npc_mob_close_scan_timer_moving) { + LogAIScanCloseDetail("NPC [{}] Restarting with moving timer", GetCleanName()); + mob_close_scan_timer.Disable(); + mob_close_scan_timer.Start(npc_mob_close_scan_timer_moving); + mob_close_scan_timer.Trigger(); + } + } + else if (mob_close_scan_timer.GetDuration() == npc_mob_close_scan_timer_moving) { + LogAIScanCloseDetail("NPC [{}] Restarting with idle timer", GetCleanName()); + mob_close_scan_timer.Disable(); + mob_close_scan_timer.Start(npc_mob_close_scan_timer_idle); + } } if (tic_timer.Check()) {