diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 87b98d599..b568d11af 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -32,6 +32,7 @@ #endif #include "map.h" +#include "water_map.h" extern Zone* zone; //#define LOSDEBUG 6 @@ -237,6 +238,11 @@ bool Mob::CheckWillAggro(Mob *mob) { if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->bZoning) return false; } + + // We don't want to aggro clients outside of water if we're water only. + if (mob->IsClient() && mob->CastToClient()->GetLastRegion() != RegionTypeWater && IsUnderwaterOnly()) { + return false; + } /** * Pets shouldn't scan for aggro diff --git a/zone/client.cpp b/zone/client.cpp index 8c4b42957..a270d6579 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8756,6 +8756,11 @@ void Client::CheckRegionTypeChanges() // still same region, do nothing if (last_region_type == new_region) return; + + // If we got out of water clear any water aggro for water only npcs + if (last_region_type == RegionTypeWater) { + entity_list.ClearWaterAggro(this); + } // region type changed last_region_type = new_region; diff --git a/zone/client.h b/zone/client.h index 58b0d9af8..edc3f18c0 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1293,6 +1293,8 @@ public: void SendHPUpdateMarquee(); void CheckRegionTypeChanges(); + + WaterRegionType GetLastRegion() { return last_region_type; } int32 CalcATK(); diff --git a/zone/entity.cpp b/zone/entity.cpp index b13fb5649..b3805ad63 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -3277,13 +3277,15 @@ void EntityList::Evade(Mob *who) void EntityList::ClearAggro(Mob* targ) { Client *c = nullptr; - if (targ->IsClient()) + if (targ->IsClient()) { c = targ->CastToClient(); + } auto it = npc_list.begin(); while (it != npc_list.end()) { if (it->second->CheckAggro(targ)) { - if (c) + if (c) { c->RemoveXTarget(it->second, false); + } it->second->RemoveFromHateList(targ); } if (c && it->second->IsOnFeignMemory(c)) { @@ -3294,6 +3296,32 @@ void EntityList::ClearAggro(Mob* targ) } } +//removes "targ" from all hate lists of mobs that are water only. +void EntityList::ClearWaterAggro(Mob* targ) +{ + Client *c = nullptr; + if (targ->IsClient()) { + c = targ->CastToClient(); + } + auto it = npc_list.begin(); + while (it != npc_list.end()) { + if (it->second->IsUnderwaterOnly()) { + if (it->second->CheckAggro(targ)) { + if (c) { + c->RemoveXTarget(it->second, false); + } + it->second->RemoveFromHateList(targ); + } + if (c && it->second->IsOnFeignMemory(c)) { + it->second->RemoveFromFeignMemory(c); //just in case we feigned + c->RemoveXTarget(it->second, false); + } + } + ++it; + } +} + + void EntityList::ClearFeignAggro(Mob *targ) { auto it = npc_list.begin(); diff --git a/zone/entity.h b/zone/entity.h index 505f34963..3c182be29 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -447,6 +447,7 @@ public: void Process(); void ClearAggro(Mob* targ); + void ClearWaterAggro(Mob* targ); void ClearFeignAggro(Mob* targ); void ClearZoneFeignAggro(Client* targ); void AggroZone(Mob* who, uint32 hate = 0);