diff --git a/zone/client.cpp b/zone/client.cpp index 7cfdf512f..eebe204ee 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -44,6 +44,7 @@ extern volatile bool RunLoops; #include "zonedb.h" #include "petitions.h" #include "command.h" +#include "water_map.h" #ifdef BOTS #include "bot_command.h" #endif @@ -156,7 +157,8 @@ Client::Client(EQStreamInterface* ieqs) m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), - m_lastsave(-1) + m_lastsave(-1), + last_region_type(RegionTypeUnsupported) { for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; @@ -2482,13 +2484,15 @@ uint16 Client::GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skil return Result; } -void Client::SetPVP(bool toggle) { +void Client::SetPVP(bool toggle, bool message) { m_pp.pvp = toggle ? 1 : 0; - if(GetPVP()) - this->Message_StringID(MT_Shout,PVP_ON); - else - Message(13, "You no longer follow the ways of discord."); + if (message) { + if(GetPVP()) + this->Message_StringID(MT_Shout,PVP_ON); + else + Message(13, "You no longer follow the ways of discord."); + } SendAppearancePacket(AT_PVP, GetPVP()); Save(); @@ -8533,3 +8537,27 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) { int Client::GetAccountAge() { return (time(nullptr) - GetAccountCreation()); } + +void Client::CheckRegionTypeChanges() +{ + if (!zone->HasWaterMap()) + return; + + auto new_region = zone->watermap->ReturnRegionType(glm::vec3(m_Position)); + + // still same region, do nothing + if (last_region_type == new_region) + return; + + // region type changed + last_region_type = new_region; + + // PVP is the only state we need to keep track of, so we can just return now for PVP servers + if (RuleI(World, PVPSettings) > 0) + return; + + if (last_region_type == RegionTypePVP) + SetPVP(true, false); + else if (GetPVP()) + SetPVP(false, false); +} diff --git a/zone/client.h b/zone/client.h index e7b7b50b9..3bd2b29c5 100644 --- a/zone/client.h +++ b/zone/client.h @@ -27,6 +27,7 @@ class Object; class Raid; class Seperator; class ServerPacket; +enum WaterRegionType : int; namespace EQEmu { @@ -360,9 +361,9 @@ public: int32 LevelRegen(); void HPTick(); void SetGM(bool toggle); - void SetPVP(bool toggle); + void SetPVP(bool toggle, bool message = true); - inline bool GetPVP() const { return zone->GetZoneID() == 77 ? true : (m_pp.pvp != 0); } + inline bool GetPVP() const { return m_pp.pvp != 0; } inline bool GetGM() const { return m_pp.gm != 0; } inline void SetBaseClass(uint32 i) { m_pp.class_=i; } @@ -1233,6 +1234,8 @@ public: void SendHPUpdateMarquee(); + void CheckRegionTypeChanges(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1417,6 +1420,7 @@ private: uint8 zonesummon_ignorerestrictions; ZoneMode zone_mode; + WaterRegionType last_region_type; Timer position_timer; uint8 position_timer_counter; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a827a3008..2da75b364 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4576,8 +4576,11 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) safe_delete(outapp); } - if(zone->watermap && zone->watermap->InLiquid(glm::vec3(m_Position))) - CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); + if (zone->watermap) { + if (zone->watermap->InLiquid(glm::vec3(m_Position))) + CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); + CheckRegionTypeChanges(); + } return; } diff --git a/zone/water_map.h b/zone/water_map.h index 2b6e0ce3c..1d6f6a34f 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -8,7 +8,7 @@ extern const ZoneConfig *Config; -enum WaterRegionType { +enum WaterRegionType : int { RegionTypeUnsupported = -2, RegionTypeUntagged = -1, RegionTypeNormal = 0, @@ -33,6 +33,7 @@ public: virtual bool InVWater(const glm::vec3& location) const = 0; virtual bool InLava(const glm::vec3& location) const = 0; virtual bool InLiquid(const glm::vec3& location) const = 0; + virtual bool InPvP(const glm::vec3& location) const = 0; protected: virtual bool Load(FILE *fp) { return false; } diff --git a/zone/water_map_v1.cpp b/zone/water_map_v1.cpp index 431df4224..dd2e1539c 100644 --- a/zone/water_map_v1.cpp +++ b/zone/water_map_v1.cpp @@ -30,6 +30,10 @@ bool WaterMapV1::InLiquid(const glm::vec3& location) const { return InWater(location) || InLava(location); } +bool WaterMapV1::InPvP(const glm::vec3& location) const { + return ReturnRegionType(location) == RegionTypePVP; +} + bool WaterMapV1::Load(FILE *fp) { uint32 bsp_tree_size; if (fread(&bsp_tree_size, sizeof(bsp_tree_size), 1, fp) != 1) { diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index 6697aa0c8..e4cb167d7 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -24,6 +24,7 @@ public: virtual bool InVWater(const glm::vec3& location) const; virtual bool InLava(const glm::vec3& location) const; virtual bool InLiquid(const glm::vec3& location) const; + virtual bool InPvP(const glm::vec3& location) const; protected: virtual bool Load(FILE *fp); diff --git a/zone/water_map_v2.cpp b/zone/water_map_v2.cpp index a57999a48..48383fe3c 100644 --- a/zone/water_map_v2.cpp +++ b/zone/water_map_v2.cpp @@ -33,6 +33,10 @@ bool WaterMapV2::InLiquid(const glm::vec3& location) const { return InWater(location) || InLava(location); } +bool WaterMapV2::InPvP(const glm::vec3& location) const { + return ReturnRegionType(location) == RegionTypePVP; +} + bool WaterMapV2::Load(FILE *fp) { uint32 region_count; if (fread(®ion_count, sizeof(region_count), 1, fp) != 1) { diff --git a/zone/water_map_v2.h b/zone/water_map_v2.h index 6429937f0..523191fe3 100644 --- a/zone/water_map_v2.h +++ b/zone/water_map_v2.h @@ -17,6 +17,7 @@ public: virtual bool InVWater(const glm::vec3& location) const; virtual bool InLava(const glm::vec3& location) const; virtual bool InLiquid(const glm::vec3& location) const; + virtual bool InPvP(const glm::vec3& location) const; protected: virtual bool Load(FILE *fp);