aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGiacomo Pozzoni <giacomopoz@gmail.com>2021-01-10 10:18:51 +0100
committerGitHub <noreply@github.com>2021-01-10 10:18:51 +0100
commitfc1a0d936888395f114028af3337e7d674e0a43c (patch)
tree2552ac79ed07810f8cc00995f965733ed24f02b5 /src
parent95a2b906b0bce6756c28334b6dadd051879c8587 (diff)
Core/Unit: Fix movement hiccups in water (#24020)
* Core/Unit: Allow to define Units which can enter water but cannot swim Allow to define Units which can enter water but cannot swim, i.e. crabs walking at the bottom of a sea. * Add UNIT_FLAG_SWIMMING to creatures when entering combat * Fix charmed creatures not entering water * Always allow Creatures controlled by players to enter water * Add swimming flag when possessing a unit and remove it properly at the end, even if the creature engaged combat before and after. When adding/removing UNIT_FLAG_SWIMMING manually calling Creature::RefreshSwimmingFlag(true) might be required.
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp36
-rw-r--r--src/server/game/Entities/Creature/Creature.h11
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp7
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp3
-rw-r--r--src/server/game/Movement/PathGenerator.cpp2
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 e5704936af8..eac1f315e0a 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -250,7 +250,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_grou
m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(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;
m_valuesCount = UNIT_END;
@@ -2682,7 +2682,7 @@ void Creature::UpdateMovementFlags()
if (!isInAir)
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
- SetSwim(GetMovementTemplate().IsSwimAllowed() && IsInWater());
+ SetSwim(CanSwim() && IsInWater());
}
CreatureMovementData const& Creature::GetMovementTemplate() const
@@ -2693,6 +2693,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 = !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING);
+
+ // 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())
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING);
+}
+
void Creature::AllLootRemovedFromCorpse()
{
if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
@@ -3297,6 +3327,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 b39ed00484b..90881842f1d 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -97,7 +97,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(); }
@@ -356,6 +357,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:
@@ -439,6 +446,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 4555c9ef48a..6d0ccc7bc37 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2165,6 +2165,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true) override;
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 d4b57c61487..ec7caa2fb1d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3131,7 +3131,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();
}
@@ -11615,6 +11615,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
@@ -12790,7 +12793,7 @@ bool Unit::CanSwim() const
return true;
if (HasFlag(UNIT_FIELD_FLAGS_2, 0x1000000))
return false;
- if (IsPet() && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT))
+ if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT))
return true;
return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME | UNIT_FLAG_SWIMMING);
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index dae93115775..bcafefc1dfd 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1639,6 +1639,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 cad38b6c698..2405f97cc59 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->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING);
+
owner->SetSpawnHealth();
owner->LoadCreaturesAddon();
if (owner->IsVehicle())
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index 04d047fc008..84c29b30736 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -656,7 +656,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