From f1bd380b2005c2074ca34d1f69f324a94069ae72 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Mon, 1 Jun 2020 15:10:13 +0200 Subject: [PATCH] Core/Players: update mount capabilties when the liquid status of players change * simplified checks for liquid restrictions in mount capability helper * handle missing case for liquid exclusive mounts * update position data on character login to avoid some edge case outdoors checks closes #95 --- src/server/game/Entities/Player/Player.cpp | 18 ++++++++-- src/server/game/Entities/Player/Player.h | 2 ++ src/server/game/Entities/Unit/Unit.cpp | 36 ++++++++----------- src/server/game/Handlers/CharacterHandler.cpp | 1 + 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 79e7fe23bb..d9416c966e 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -160,6 +160,7 @@ Player::Player(WorldSession* session): Unit(true) m_comboPoints = 0; m_foodEmoteTimerCount = 0; + m_previousLiquidStatus = GetLiquidStatus(); m_weaponChangeTimer = 0; m_zoneUpdateId = uint32(-1); @@ -6037,6 +6038,13 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t CheckAreaExploreAndOutdoor(); + // Update mount capabilities + if (m_previousLiquidStatus != GetLiquidStatus()) + { + UpdateMountCapabilities(); + m_previousLiquidStatus = GetLiquidStatus(); + } + return true; } @@ -18586,11 +18594,17 @@ void Player::UpdateMountCapabilities() { if (HasAuraType(SPELL_AURA_MOUNTED)) { - for (AuraEffect* aurEff : GetAuraEffectsByType(SPELL_AURA_MOUNTED)) + AuraEffectList mountEffects = GetAuraEffectsByType(SPELL_AURA_MOUNTED); + for (AuraEffect* aurEff : mountEffects) { MountCapabilityEntry const* capability = GetMountCapability(uint32(aurEff->GetMiscValueB())); if (!capability) + { + // No mount capabilitiy found, remove aura + if (Aura* aura = aurEff->GetBase()) + aura->Remove(); continue; + } if (capability->ID != uint32(aurEff->GetAmount())) { @@ -23441,8 +23455,6 @@ void Player::SendInitialPacketsAfterAddToMap() auraList.front()->HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); } - UpdateMountCapabilities(); - if (CanFly()) SendMovementSetCanTransitionBetweenSwimAndFly(true); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 9619de89cd..fb037fdc7f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -84,6 +84,7 @@ enum ItemClass : uint8; enum LootError : uint8; enum LootType : uint8; enum UpdateCollisionHeightReason : uint8; +enum ZLiquidStatus : uint32; typedef std::deque PlayerMails; @@ -2401,6 +2402,7 @@ class TC_GAME_API Player : public Unit, public GridObject GuidList WhisperList; uint32 m_foodEmoteTimerCount; uint32 m_contestedPvPTimer; + ZLiquidStatus m_previousLiquidStatus; /*********************************************************/ /*** BATTLEGROUND SYSTEM ***/ diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a1c1ad266f..71b9856b8d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8319,7 +8319,7 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const uint32 areaId = GetAreaId(); uint32 ridingSkill = 5000; uint32 mountFlags = 0; - bool isSubmerged = false; + bool isUnderwater = false; bool isInWater = false; if (GetTypeId() == TYPEID_PLAYER) @@ -8333,10 +8333,9 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const else if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(areaId)) mountFlags = areaTable->MountFlags; - LiquidData liquid; - ZLiquidStatus liquidStatus = GetMap()->GetLiquidStatus(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), MAP_ALL_LIQUIDS, &liquid); - isSubmerged = (liquidStatus & LIQUID_MAP_UNDER_WATER) != 0 || HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - isInWater = (liquidStatus & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; + ZLiquidStatus liquidStatus = GetLiquidStatus(); + isUnderwater = (liquidStatus & LIQUID_MAP_UNDER_WATER) != 0; + isInWater = (liquidStatus & LIQUID_MAP_IN_WATER) != 0; for (uint32 i = MAX_MOUNT_CAPABILITIES; i > 0; --i) { @@ -8359,23 +8358,16 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const continue; } - if (!isSubmerged) - { - if (!isInWater) - { - // player is completely out of water - if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_GROUND)) - continue; - } - else if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_UNDERWATER)) - continue; - } - else if (isInWater) - { - if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_UNDERWATER)) - continue; - } - else if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_FLOAT)) + // Do not allow underwater restricted capabilities when not underwater + if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_UNDERWATER) && isUnderwater) + continue; + + // Do not allow water surface restricted capabilities when not on water surface + if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_FLOAT) && isInWater) + continue; + + // Do not allow liquid restricted mounts on ground or in air + if (!(mountCapability->Flags & (MOUNT_CAPABILITY_FLAG_GROUND | MOUNT_CAPABILITY_FLAG_FLYING)) && !isUnderwater && !isInWater) continue; if (mountCapability->ReqMapID != -1 && diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 183a70e816..d8caf39f41 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -980,6 +980,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) } } + pCurrChar->UpdatePositionData(); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE);