diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 36 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 11 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Movement/PathGenerator.cpp | 2 |
7 files changed, 55 insertions, 6 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 513137767a4..f33ed67c810 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -305,7 +305,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_grou m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0), m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _lastDamagedTime(0), - _regenerateHealth(true), _regenerateHealthLock(false) + _regenerateHealth(true), _regenerateHealthLock(false), _isMissingSwimmingFlagOutOfCombat(false) { m_regenTimer = CREATURE_REGEN_INTERVAL; @@ -2829,7 +2829,7 @@ void Creature::UpdateMovementFlags() if (!isInAir) RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING); - SetSwim(GetMovementTemplate().IsSwimAllowed() && IsInWater()); + SetSwim(CanSwim() && IsInWater()); } CreatureMovementData const& Creature::GetMovementTemplate() const @@ -2840,6 +2840,36 @@ CreatureMovementData const& Creature::GetMovementTemplate() const return GetCreatureTemplate()->Movement; } +bool Creature::CanSwim() const +{ + if (Unit::CanSwim()) + return true; + + if (IsPet()) + return true; + + return false; +} + +bool Creature::CanEnterWater() const +{ + if (CanSwim()) + return true; + + return GetMovementTemplate().IsSwimAllowed(); +} + +void Creature::RefreshSwimmingFlag(bool recheck) +{ + if (!_isMissingSwimmingFlagOutOfCombat || recheck) + _isMissingSwimmingFlagOutOfCombat = !HasUnitFlag(UNIT_FLAG_CAN_SWIM); + + // Check if the creature has UNIT_FLAG_SWIMMING and add it if it's missing + // Creatures must be able to chase a target in water if they can enter water + if (_isMissingSwimmingFlagOutOfCombat && CanEnterWater()) + AddUnitFlag(UNIT_FLAG_CAN_SWIM); +} + void Creature::AllLootRemovedFromCorpse() { if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient()) @@ -3418,6 +3448,8 @@ void Creature::AtEngage(Unit* target) if (!(GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_MOUNTED_COMBAT_ALLOWED)) Dismount(); + RefreshSwimmingFlag(); + if (IsPet() || IsGuardian()) // update pets' speed for catchup OOC speed { UpdateSpeed(MOVE_RUN); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 1a67853ebf1..61f3e64a41b 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -111,7 +111,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma CreatureMovementData const& GetMovementTemplate() const; bool CanWalk() const { return GetMovementTemplate().IsGroundAllowed(); } - bool CanSwim() const override { return GetMovementTemplate().IsSwimAllowed() || IsPet(); } + bool CanSwim() const override; + bool CanEnterWater() const override; bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); } bool CanHover() const { return GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || IsHovering(); } @@ -369,6 +370,12 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma void AtEngage(Unit* target) override; void AtDisengage() override; + bool HasSwimmingFlagOutOfCombat() const + { + return !_isMissingSwimmingFlagOutOfCombat; + } + void RefreshSwimmingFlag(bool recheck = false); + std::string GetDebugInfo() const override; protected: @@ -452,6 +459,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma // Regenerate health bool _regenerateHealth; // Set on creation bool _regenerateHealthLock; // Dynamically set + + bool _isMissingSwimmingFlagOutOfCombat; }; class TC_GAME_API AssistDelayEvent : public BasicEvent diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index f4f33fd9526..89b08802e4f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2623,6 +2623,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SendMovementSetCollisionHeight(float height, WorldPackets::Movement::UpdateCollisionHeightReason reason); bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); } + bool CanEnterWater() const override { return true; } std::string GetMapAreaAndZoneString() const; std::string GetCoordsMapAreaAndZoneString() const; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 41efb7de14a..c103c41770d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3006,7 +3006,7 @@ bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const bool Unit::isInAccessiblePlaceFor(Creature const* c) const { if (IsInWater()) - return c->CanSwim(); + return c->CanEnterWater(); else return c->CanWalk() || c->CanFly(); } @@ -11150,6 +11150,9 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au AddUnitState(UNIT_STATE_CHARMED); + if (Creature* creature = ToCreature()) + creature->RefreshSwimmingFlag(); + if ((GetTypeId() != TYPEID_PLAYER) || (charmer->GetTypeId() != TYPEID_PLAYER)) { // AI will schedule its own change if appropriate @@ -12107,7 +12110,7 @@ bool Unit::CanSwim() const return true; if (HasUnitFlag2(UnitFlags2(0x1000000))) return false; - if (IsPet() && HasUnitFlag(UNIT_FLAG_PET_IN_COMBAT)) + if (HasUnitFlag(UNIT_FLAG_PET_IN_COMBAT)) return true; return HasUnitFlag(UnitFlags(UNIT_FLAG_RENAME | UNIT_FLAG_CAN_SWIM)); } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 655b8f4edaf..8c579aa29b1 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1807,6 +1807,7 @@ class TC_GAME_API Unit : public WorldObject virtual bool CanFly() const = 0; bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); } bool IsFalling() const; + virtual bool CanEnterWater() const = 0; virtual bool CanSwim() const; float GetHoverOffset() const diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 5e06c084028..c49c7cc1fdd 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -144,6 +144,9 @@ void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, b if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) { + if (!owner->HasSwimmingFlagOutOfCombat()) + owner->RemoveUnitFlag(UNIT_FLAG_CAN_SWIM); + owner->SetSpawnHealth(); owner->LoadCreaturesAddon(); if (owner->IsVehicle()) diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 8519649bdf4..fb64779e70f 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -657,7 +657,7 @@ void PathGenerator::CreateFilter() includeFlags |= NAV_GROUND; // walk // creatures don't take environmental damage - if (creature->CanSwim()) + if (creature->CanEnterWater()) includeFlags |= (NAV_WATER | NAV_MAGMA_SLIME); // swim } else // assume Player |