diff --git a/src/map/latent_effect_container.cpp b/src/map/latent_effect_container.cpp index ed643ea804f..e666d103e62 100644 --- a/src/map/latent_effect_container.cpp +++ b/src/map/latent_effect_container.cpp @@ -662,6 +662,13 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) auto expression = false; auto latentFound = true; + // this gets the current zone ID or destination zone ID if zoning + uint16 playerZoneID = m_POwner->getZone(); + if (m_POwner == nullptr || playerZoneID == 0) + { + return false; + } + // find the latent type from the enum and find the expression to tests againts switch (latentEffect.GetConditionsID()) { @@ -1040,26 +1047,30 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) case LATENT::NATION_CONTROL: { // player is logging in/zoning - if (m_POwner->loc.zone == nullptr) + // checking the state of the user's current zone and + // the destination zone in tandem seems to work. + if (m_POwner->loc.zone == nullptr && static_cast(m_POwner->loc.destination) == 0) { break; } - auto region = m_POwner->loc.zone->GetRegionID(); + // Grab the user's destination if they're zoning. + // Otherwise, grab their current zone. + auto region = m_POwner->loc.zone == nullptr ? zoneutils::GetCurrentRegion(m_POwner->loc.destination) : 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 +1078,28 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) } case LATENT::ZONE_HOME_NATION: { + // player is logging in/zoning - if (m_POwner->loc.zone == nullptr) + // checking the state of the user's current zone and + // the destination zone in tandem seems to work. + if (m_POwner->loc.zone == nullptr && static_cast(m_POwner->loc.destination) == 0) { break; } - auto* PZone = m_POwner->loc.zone; - auto region = static_cast(latentEffect.GetConditionsValue()); + auto nationRegion = static_cast(latentEffect.GetConditionsValue()); + auto region = m_POwner->loc.zone == nullptr ? zoneutils::GetCurrentRegion(m_POwner->loc.destination) : 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