From bf5e93aea3564b7289a089d89f5b1b2442a04fa0 Mon Sep 17 00:00:00 2001 From: Radegast-FFXIV <58457062+Radegast-FFXIV@users.noreply.github.com> Date: Mon, 28 Aug 2023 14:14:06 -0700 Subject: [PATCH] [core] Fix nation zone/login issues. * Checks for destination region when zoning, to avoid issues with latent effects not triggering * Fixes log spam for players in these non conquest but still latent applying regions --- documentation/wiki | 1 + src/map/latent_effect_container.cpp | 52 +++++++++++++++-------------- src/map/utils/zoneutils.cpp | 5 +++ src/map/utils/zoneutils.h | 5 +-- 4 files changed, 36 insertions(+), 27 deletions(-) create mode 160000 documentation/wiki diff --git a/documentation/wiki b/documentation/wiki new file mode 160000 index 00000000000..e38c5ee2fbb --- /dev/null +++ b/documentation/wiki @@ -0,0 +1 @@ +Subproject commit e38c5ee2fbb00d8338f404ebba413a41906fc22b diff --git a/src/map/latent_effect_container.cpp b/src/map/latent_effect_container.cpp index ed643ea804f..3a919b1cbf9 100644 --- a/src/map/latent_effect_container.cpp +++ b/src/map/latent_effect_container.cpp @@ -662,6 +662,18 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) auto expression = false; auto latentFound = true; + if (m_POwner == nullptr) + { + return false; + } + + // this gets the current zone ID or destination zone ID if zoning + uint16 playerZoneID = m_POwner->getZone(); + if (playerZoneID == 0) + { + return false; + } + // find the latent type from the enum and find the expression to tests againts switch (latentEffect.GetConditionsID()) { @@ -1039,27 +1051,23 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) break; case LATENT::NATION_CONTROL: { - // player is logging in/zoning - if (m_POwner->loc.zone == nullptr) - { - break; - } - - auto region = m_POwner->loc.zone->GetRegionID(); - auto hasSignet = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET); - auto hasSanction = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SANCTION); - auto hasSigil = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SIGIL); - + // playerZoneId represents the player's destination if they're zoning. + // Otherwise, it represents their current zone. + auto region = zoneutils::GetCurrentRegion(playerZoneID); + auto hasSignet = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET); + auto hasSanction = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SANCTION); + auto hasSigil = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SIGIL); + auto regionAlwaysOutOfControl = zoneutils::IsAlwaysOutOfNationControl(region); switch (latentEffect.GetConditionsValue()) { case 0: // under own nation's control - expression = region < REGION_TYPE::WEST_AHT_URHGAN && conquest::GetRegionOwner(region) == m_POwner->profile.nation && + expression = region < REGION_TYPE::WEST_AHT_URHGAN && (!regionAlwaysOutOfControl || conquest::GetRegionOwner(region) == m_POwner->profile.nation) && (hasSignet || hasSanction || hasSigil); break; case 1: // outside of own nation's control - expression = region < REGION_TYPE::WEST_AHT_URHGAN && m_POwner->profile.nation != conquest::GetRegionOwner(region) && + expression = region < REGION_TYPE::WEST_AHT_URHGAN && (regionAlwaysOutOfControl || m_POwner->profile.nation != conquest::GetRegionOwner(region)) && (hasSignet || hasSanction || hasSigil); break; } @@ -1067,25 +1075,19 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) } case LATENT::ZONE_HOME_NATION: { - // player is logging in/zoning - if (m_POwner->loc.zone == nullptr) - { - break; - } - - auto* PZone = m_POwner->loc.zone; - auto region = static_cast(latentEffect.GetConditionsValue()); + auto nationRegion = static_cast(latentEffect.GetConditionsValue()); + auto region = zoneutils::GetCurrentRegion(playerZoneID); - switch (region) + switch (nationRegion) { case REGION_TYPE::SANDORIA: - expression = m_POwner->profile.nation == 0 && PZone->GetRegionID() == region; + expression = m_POwner->profile.nation == 0 && region == nationRegion; break; case REGION_TYPE::BASTOK: - expression = m_POwner->profile.nation == 1 && PZone->GetRegionID() == region; + expression = m_POwner->profile.nation == 1 && region == nationRegion; break; case REGION_TYPE::WINDURST: - expression = m_POwner->profile.nation == 2 && PZone->GetRegionID() == region; + expression = m_POwner->profile.nation == 2 && region == nationRegion; break; default: break; diff --git a/src/map/utils/zoneutils.cpp b/src/map/utils/zoneutils.cpp index 9c2148485e8..f1431276dfa 100644 --- a/src/map/utils/zoneutils.cpp +++ b/src/map/utils/zoneutils.cpp @@ -1212,4 +1212,9 @@ namespace zoneutils luautils::AfterZoneIn(PChar); } + bool IsAlwaysOutOfNationControl(REGION_TYPE region) + { + return region >= REGION_TYPE::SANDORIA && region <= REGION_TYPE::LIMBUS; + } + }; // namespace zoneutils diff --git a/src/map/utils/zoneutils.h b/src/map/utils/zoneutils.h index b03ae335329..85c6e573e34 100644 --- a/src/map/utils/zoneutils.h +++ b/src/map/utils/zoneutils.h @@ -57,8 +57,9 @@ namespace zoneutils CCharEntity* GetChar(uint32 id); // returns pointer to character by id CCharEntity* GetCharToUpdate(uint32 primary, uint32 ternary); // returns pointer to preferred char to update for party changes void ForEachZone(const std::function& func); - uint64 GetZoneIPP(uint16 zoneid); // returns IPP for zone ID - bool IsResidentialArea(CCharEntity*); // returns whether or not the area is a residential zone + uint64 GetZoneIPP(uint16 zoneid); // returns IPP for zone ID + bool IsResidentialArea(CCharEntity*); // returns whether or not the area is a residential zone + bool IsAlwaysOutOfNationControl(REGION_TYPE region); // returns true if a region should never trigger "in areas outside own nation's control" latent effect; false otherwise. void AfterZoneIn(CBaseEntity* PEntity); // triggers after a player has finished zoning in