aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOvahlord <dreadkiller@gmx.de>2024-02-29 14:43:37 +0100
committerGitHub <noreply@github.com>2024-02-29 14:43:37 +0100
commitc541eda54d7e0dddeec329a6beac2948e0b0a40b (patch)
tree90bead53d03937a1c55f4c12cd7f370a8ca13d8d /src
parent792a4d6c8bab4a8e874c6f0e583f915d05b8d8b3 (diff)
Core/Creatures: implemented most movement related static flags and migrated existing movement data into static flags (#29541)
* implemented CREATURE_STATIC_FLAG_AQUATIC - creatures cannot leave liquids * implemented CREATURE_STATIC_FLAG_AMPHIBIOUS - creatures can enter and leave liquids but remain on the ocean floor when swimming is not enabled until engaged * implemented CREATURE_STATIC_FLAG_FLOATING - creatures have their gravity on spawn / reset disabled * implemented CREATURE_STATIC_FLAG_SESSILE - creatures are rooted in place * implemented CREATURE_STATIC_FLAG_CAN_SWIM - creature can swim in liquids * implemented CREATURE_STATIC_FLAG_3_CANNOT_SWIM - Amphibious creatures cannot toggle on swimming * implemented CREATURE_STATIC_FLAG_3_CANNOT_TURN - Creatures cannot turn at all * implemented CREATURE_STATIC_FLAG_4_PREVENT_SWIM - Amphibious creatures won't toggle on swimming until their victim starts leaving the ocean floor * partially implemented CREATURE_STATIC_FLAG_3_CANNOT_PENETRATE_WATER * deprecated CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE as this flag was a hackfix to a wrong implementation that is now gone
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp119
-rw-r--r--src/server/game/Entities/Creature/Creature.h37
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h38
-rw-r--r--src/server/game/Entities/Creature/enuminfo_CreatureData.cpp6
-rw-r--r--src/server/game/Entities/Object/Object.cpp14
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp30
-rw-r--r--src/server/game/Entities/Unit/Unit.h5
-rw-r--r--src/server/game/Entities/Unit/UnitDefines.h4
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp94
-rw-r--r--src/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp4
-rw-r--r--src/server/game/Movement/PathGenerator.cpp4
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp2
-rw-r--r--src/server/scripts/ExilesReach/zone_exiles_reach.cpp12
-rw-r--r--src/server/scripts/Kalimdor/zone_durotar.cpp1
17 files changed, 143 insertions, 241 deletions
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index 63d4c4cc872..2438bc1c1e1 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -62,7 +62,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID, "SELECT guid FROM creature_addon WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, help FROM command", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, Classification, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, family, trainer_class, type, VehicleId, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, ExperienceModifier, RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, CreatureImmunitiesId, flags_extra, ScriptName, StringId FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ? OR 1 = ?", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, Classification, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, family, trainer_class, type, VehicleId, AIName, MovementType, ctm.HoverInitiallyEnabled, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, ExperienceModifier, RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, CreatureImmunitiesId, flags_extra, ScriptName, StringId FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ? OR 1 = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 1b31295f5e8..79455004e33 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -55,25 +55,19 @@
#include <G3D/g3dmath.h>
#include <sstream>
-CreatureMovementData::CreatureMovementData() : Ground(CreatureGroundMovementType::Run), Flight(CreatureFlightMovementType::None), Swim(true), Rooted(false), Chase(CreatureChaseMovementType::Run),
+CreatureMovementData::CreatureMovementData() : HoverInitiallyEnabled(false), Chase(CreatureChaseMovementType::Run),
Random(CreatureRandomMovementType::Walk), InteractionPauseTimer(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER)) { }
std::string CreatureMovementData::ToString() const
{
- char const* const GroundStates[] = { "None", "Run", "Hover" };
- char const* const FlightStates[] = { "None", "DisableGravity", "CanFly" };
- char const* const ChaseStates[] = { "Run", "CanWalk", "AlwaysWalk" };
+ char const* const ChaseStates[] = { "Run", "CanWalk", "AlwaysWalk" };
char const* const RandomStates[] = { "Walk", "CanRun", "AlwaysRun" };
std::ostringstream str;
str << std::boolalpha
- << "Ground: " << GroundStates[AsUnderlyingType(Ground)]
- << ", Swim: " << Swim
- << ", Flight: " << FlightStates[AsUnderlyingType(Flight)]
+ << ", HoverInitiallyEnabled: " << HoverInitiallyEnabled
<< ", Chase: " << ChaseStates[AsUnderlyingType(Chase)]
<< ", Random: " << RandomStates[AsUnderlyingType(Random)];
- if (Rooted)
- str << ", Rooted";
str << ", InteractionPauseTimer: " << InteractionPauseTimer;
return str.str();
@@ -314,7 +308,7 @@ Creature::Creature(bool isWorldObject) : Unit(isWorldObject), MapObject(), m_Pla
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), m_creatureDifficulty(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0),
m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _lastDamagedTime(0),
- _regenerateHealth(true), _isMissingCanSwimFlagOutOfCombat(false), _creatureImmunitiesId(0), _gossipMenuId(0), _sparringHealthPct(0)
+ _regenerateHealth(true), _creatureImmunitiesId(0), _gossipMenuId(0), _sparringHealthPct(0)
{
m_regenTimer = CREATURE_REGEN_INTERVAL;
@@ -595,7 +589,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
uint64 npcFlags;
uint32 unitFlags, unitFlags2, unitFlags3;
- ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, data);
+ ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, _staticFlags, data);
if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT)
npcFlags |= sGameEventMgr->GetNPCFlag(this);
@@ -686,7 +680,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
SetIsCombatDisallowed((cInfo->flags_extra & CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT) != 0);
- InitializeMovementFlags();
+ InitializeMovementCapabilities();
LoadCreaturesAddon();
LoadCreaturesSparringHealth();
@@ -707,7 +701,6 @@ void Creature::ApplyAllStaticFlags(CreatureStaticFlagsHolder const& flags)
_staticFlags = flags;
// Apply all other side effects of flag changes
- SetTemplateRooted(flags.HasFlag(CREATURE_STATIC_FLAG_SESSILE));
m_updateFlag.NoBirthAnim = flags.HasFlag(CREATURE_STATIC_FLAG_4_NO_BIRTH_ANIM);
}
@@ -724,7 +717,7 @@ void Creature::Update(uint32 diff)
AI()->JustAppeared();
}
- UpdateMovementFlags();
+ UpdateMovementCapabilities();
switch (m_deathState)
{
@@ -1993,17 +1986,6 @@ void Creature::SetSpawnHealth()
SetHealth((m_deathState == ALIVE || m_deathState == JUST_RESPAWNED) ? curhealth : 0);
}
-void Creature::LoadTemplateRoot()
-{
- SetTemplateRooted(GetMovementTemplate().IsRooted());
-}
-
-void Creature::SetTemplateRooted(bool rooted)
-{
- _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_SESSILE, rooted);
- SetControlled(rooted, UNIT_STATE_ROOT);
-}
-
bool Creature::hasQuest(uint32 quest_id) const
{
return sObjectMgr->GetCreatureQuestRelations(GetEntry()).HasQuest(quest_id);
@@ -2253,7 +2235,7 @@ void Creature::setDeathState(DeathState s)
if (m_formation && m_formation->GetLeader() == this)
m_formation->FormationReset(true);
- bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater();
+ bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater() && !HasUnitState(UNIT_STATE_ROOT);
SetHover(false, false);
SetDisableGravity(false, false);
@@ -2273,7 +2255,7 @@ void Creature::setDeathState(DeathState s)
ResetPlayerDamageReq();
SetCannotReachTarget(false);
- UpdateMovementFlags();
+ UpdateMovementCapabilities();
ClearUnitState(UNIT_STATE_ALL_ERASABLE);
@@ -2284,7 +2266,7 @@ void Creature::setDeathState(DeathState s)
uint64 npcFlags;
uint32 unitFlags, unitFlags2, unitFlags3;
- ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, creatureData);
+ ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, _staticFlags, creatureData);
if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT)
npcFlags |= sGameEventMgr->GetNPCFlag(this);
@@ -2736,7 +2718,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
dist += GetCombatReach() + victim->GetCombatReach();
// to prevent creatures in air ignore attacks because distance is already too high...
- if (GetMovementTemplate().IsFlightAllowed())
+ if (CanFly())
return victim->IsInDist2d(&m_homePosition, dist);
else
return victim->IsInDist(&m_homePosition, dist);
@@ -2768,14 +2750,6 @@ bool Creature::LoadCreaturesAddon()
ReplaceAllVisFlags(UnitVisFlags(creatureAddon->visFlags));
SetAnimTier(AnimTier(creatureAddon->animTier), false);
- //! Suspected correlation between UNIT_FIELD_BYTES_1, offset 3, value 0x2:
- //! If no inhabittype_fly (if no MovementFlag_DisableGravity or MovementFlag_CanFly flag found in sniffs)
- //! Check using InhabitType as movement flags are assigned dynamically
- //! basing on whether the creature is in air or not
- //! Set MovementFlag_Hover. Otherwise do nothing.
- if (CanHover())
- AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
-
SetSheath(SheathState(creatureAddon->sheathState));
ReplaceAllPvpFlags(UnitPVPStateFlags(creatureAddon->pvpFlags));
@@ -2920,51 +2894,37 @@ void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, floa
}
}
-void Creature::InitializeMovementFlags()
+void Creature::InitializeMovementCapabilities()
{
- LoadTemplateRoot();
- // It does the same, for now
- UpdateMovementFlags();
+ SetHover(GetMovementTemplate().IsHoverInitiallyEnabled());
+ SetDisableGravity(IsFloating());
+ SetControlled(IsSessile(), UNIT_STATE_ROOT);
+
+ // If an amphibious creatures was swimming while engaged, disable swimming again
+ if (IsAmphibious() && !_staticFlags.HasFlag(CREATURE_STATIC_FLAG_CAN_SWIM))
+ RemoveUnitFlag(UNIT_FLAG_CAN_SWIM);
+
+ UpdateMovementCapabilities();
}
-void Creature::UpdateMovementFlags()
+void Creature::UpdateMovementCapabilities()
{
// Do not update movement flags if creature is controlled by a player (charm/vehicle)
if (m_playerMovingMe)
return;
- // Creatures with CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE should control MovementFlags in your own scripts
- if (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE)
- return;
-
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
float ground = GetFloorZ();
-
- bool canHover = CanHover();
- bool isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + (canHover ? *m_unitData->HoverHeight : 0.0f) + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
-
- if (GetMovementTemplate().IsFlightAllowed() && (isInAir || !GetMovementTemplate().IsGroundAllowed()) && !IsFalling())
- {
- if (GetMovementTemplate().Flight == CreatureFlightMovementType::CanFly)
- SetCanFly(true);
- else
- SetDisableGravity(true);
-
- if (!HasAuraType(SPELL_AURA_HOVER) && GetMovementTemplate().Ground != CreatureGroundMovementType::Hover)
- SetHover(false);
- }
- else
- {
- SetCanFly(false);
- SetDisableGravity(false);
- if (IsAlive() && (CanHover() || HasAuraType(SPELL_AURA_HOVER)))
- SetHover(true);
- }
-
+ bool isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + GetHoverOffset() + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
if (!isInAir)
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
- SetSwim(CanSwim() && IsInWater());
+ // Some Amphibious creatures toggle swimming while engaged
+ if (IsAmphibious() && !HasUnitFlag(UNIT_FLAG_CANT_SWIM) && !HasUnitFlag(UNIT_FLAG_CAN_SWIM))
+ if (!IsSwimPrevented() || (GetVictim() && !GetVictim()->IsOnOceanFloor()))
+ SetUnitFlag(UNIT_FLAG_CAN_SWIM);
+
+ SetSwim(IsInWater() && CanSwim());
}
CreatureMovementData const& Creature::GetMovementTemplate() const
@@ -2986,25 +2946,6 @@ bool Creature::CanSwim() const
return false;
}
-bool Creature::CanEnterWater() const
-{
- if (CanSwim())
- return true;
-
- return GetMovementTemplate().IsSwimAllowed();
-}
-
-void Creature::RefreshCanSwimFlag(bool recheck)
-{
- if (!_isMissingCanSwimFlagOutOfCombat || recheck)
- _isMissingCanSwimFlagOutOfCombat = !HasUnitFlag(UNIT_FLAG_CAN_SWIM);
-
- // Check if the creature has UNIT_FLAG_CAN_SWIM and add it if it's missing
- // Creatures must be able to chase a target in water if they can enter water
- if (_isMissingCanSwimFlagOutOfCombat && CanEnterWater())
- SetUnitFlag(UNIT_FLAG_CAN_SWIM);
-}
-
void Creature::AllLootRemovedFromCorpse()
{
time_t now = GameTime::GetGameTime();
@@ -3633,8 +3574,6 @@ void Creature::AtEngage(Unit* target)
if (!HasFlag(CREATURE_STATIC_FLAG_2_ALLOW_MOUNTED_COMBAT))
Dismount();
- RefreshCanSwimFlag();
-
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 c2d0eda0dfe..156ead57fa6 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -94,9 +94,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void SelectWildBattlePetLevel();
void LoadEquipment(int8 id = 1, bool force = false);
void SetSpawnHealth();
- void LoadTemplateRoot();
- bool IsTemplateRooted() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_SESSILE); }
- void SetTemplateRooted(bool rooted);
ObjectGuid::LowType GetSpawnId() const { return m_spawnId; }
@@ -116,15 +113,29 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool IsTrigger() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) != 0; }
bool IsGuard() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GUARD) != 0; }
- void InitializeMovementFlags();
- void UpdateMovementFlags();
+ void InitializeMovementCapabilities();
+ void UpdateMovementCapabilities();
CreatureMovementData const& GetMovementTemplate() const;
- bool CanWalk() const { return GetMovementTemplate().IsGroundAllowed(); }
+
+ // Returns true if CREATURE_STATIC_FLAG_AQUATIC is set which strictly binds the creature to liquids
+ bool IsAquatic() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_AQUATIC); }
+ // Returns true if CREATURE_STATIC_FLAG_AMPHIBIOUS is set which allows a creature to enter and leave liquids while sticking to the ocean floor. These creatures will become able to swim when engaged
+ bool IsAmphibious() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_AMPHIBIOUS); }
+ // Returns true if CREATURE_STATIC_FLAG_FLOATING is set which is disabling the gravity of the creature on spawn and reset
+ bool IsFloating() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_FLOATING); }
+ // Returns true if CREATURE_STATIC_FLAG_SESSILE is set which permanently roots the creature in place
+ bool IsSessile() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_SESSILE); }
+ // Returns true if CREATURE_STATIC_FLAG_3_CANNOT_PENETRATE_WATER is set which does not allow the creature to go below liquid surfaces
+ bool CannotPenetrateWater() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_3_CANNOT_PENETRATE_WATER); }
+ // Returns true if CREATURE_STATIC_FLAG_3_CANNOT_SWIM is set which prevents 'Amphibious' creatures from swimming when engaged
+ bool IsSwimDisabled() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_3_CANNOT_SWIM); }
+ // Returns true if CREATURE_STATIC_FLAG_4_PREVENT_SWIM is set which prevents 'Amphibious' creatures from swimming when engaged until the victim is no longer on the ocean floor
+ bool IsSwimPrevented() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_4_PREVENT_SWIM); }
+
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(); }
+ bool CanEnterWater() const override { return (CanSwim() || IsAmphibious()); };
+ bool CanFly() const override { return (IsFlying() || HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)); }
MovementGeneratorType GetDefaultMovementType() const override { return m_defaultMovementType; }
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
@@ -415,12 +426,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
uint32 CalculateDamageForSparring(Unit* attacker, uint32 damage);
bool ShouldFakeDamageFrom(Unit* attacker);
- bool HasCanSwimFlagOutOfCombat() const
- {
- return !_isMissingCanSwimFlagOutOfCombat;
- }
- void RefreshCanSwimFlag(bool recheck = false);
-
std::string GetDebugInfo() const override;
void ExitVehicle(Position const* exitPosition = nullptr) override;
@@ -535,8 +540,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
// Regenerate health
bool _regenerateHealth; // Set on creation
- bool _isMissingCanSwimFlagOutOfCombat;
-
Optional<uint32> _defaultMountDisplayIdOverride;
int32 _creatureImmunitiesId;
uint32 _gossipMenuId;
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 8a3d8655069..79cdc6bdb8d 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -43,7 +43,7 @@ enum CreatureStaticFlags
CREATURE_STATIC_FLAG_IMMUNE_TO_PC = 0x00000020, // UNIT_FLAG_IMMUNE_TO_PC
CREATURE_STATIC_FLAG_IMMUNE_TO_NPC = 0x00000040, // UNIT_FLAG_IMMUNE_TO_NPC
CREATURE_STATIC_FLAG_CAN_WIELD_LOOT = 0x00000080,
- CREATURE_STATIC_FLAG_SESSILE = 0x00000100, // creature_template_movement.Rooted = 1
+ CREATURE_STATIC_FLAG_SESSILE = 0x00000100, // Rooted movementflag, creature is permanently rooted in place
CREATURE_STATIC_FLAG_UNINTERACTIBLE = 0x00000200, // UNIT_FLAG_UNINTERACTIBLE
CREATURE_STATIC_FLAG_NO_AUTOMATIC_REGEN = 0x00000400, // Creatures with that flag uses no UNIT_FLAG2_REGENERATE_POWER
CREATURE_STATIC_FLAG_DESPAWN_INSTANTLY = 0x00000800, // Creature instantly disappear when killed
@@ -54,7 +54,7 @@ enum CreatureStaticFlags
CREATURE_STATIC_FLAG_BOSS_MOB = 0x00010000, // CREATURE_TYPE_FLAG_BOSS_MOB, original description: Raid Boss Mob
CREATURE_STATIC_FLAG_COMBAT_PING = 0x00020000,
CREATURE_STATIC_FLAG_AQUATIC = 0x00040000, // aka Water Only, creature_template_movement.Ground = 0
- CREATURE_STATIC_FLAG_AMPHIBIOUS = 0x00080000, // creature_template_movement.Swim = 1
+ CREATURE_STATIC_FLAG_AMPHIBIOUS = 0x00080000, // Creatures will be able to enter and leave water but can only move on the ocean floor when CREATURE_STATIC_FLAG_CAN_SWIM is not present
CREATURE_STATIC_FLAG_NO_MELEE_FLEE = 0x00100000, // "No Melee (Flee)" Prevents melee (moves as-if feared, does not make creature passive)
CREATURE_STATIC_FLAG_VISIBLE_TO_GHOSTS = 0x00200000, // CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS
CREATURE_STATIC_FLAG_PVP_ENABLING = 0x00400000, // Old UNIT_FLAG_PVP_ENABLING, now UNIT_BYTES_2_OFFSET_PVP_FLAG from UNIT_FIELD_BYTES_2
@@ -64,7 +64,7 @@ enum CreatureStaticFlags
CREATURE_STATIC_FLAG_ONLY_ATTACK_PVP_ENABLING = 0x04000000, // "Only attack targets that are PvP enabling"
CREATURE_STATIC_FLAG_CALLS_GUARDS = 0x08000000, // Creature will summon a guard if player is within its aggro range (even if creature doesn't attack per se)
CREATURE_STATIC_FLAG_CAN_SWIM = 0x10000000, // UnitFlags 0x8000 UNIT_FLAG_CAN_SWIM
- CREATURE_STATIC_FLAG_FLOATING = 0x20000000, // creature_template_movement.Flight = 1
+ CREATURE_STATIC_FLAG_FLOATING = 0x20000000, // sets DisableGravity movementflag on spawn/reset
CREATURE_STATIC_FLAG_MORE_AUDIBLE = 0x40000000, // CREATURE_TYPE_FLAG_MORE_AUDIBLE
CREATURE_STATIC_FLAG_LARGE_AOI = 0x80000000 // UnitFlags2 0x200000
};
@@ -340,7 +340,7 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_NO_XP = 0x00000040, // creature kill does not provide XP
CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature
CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and 'attack me' effects
- CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE = 0x00000200, // creature won't update movement flags
+ CREATURE_FLAG_EXTRA_UNUSED_9 = 0x00000200,
CREATURE_FLAG_EXTRA_GHOST_VISIBILITY = 0x00000400, // creature will only be visible to dead players
CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK = 0x00000800, // creature will use offhand attacks
CREATURE_FLAG_EXTRA_NO_SELL_VENDOR = 0x00001000, // players can't sell items to this vendor
@@ -372,24 +372,6 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS)) // SKIP
};
-enum class CreatureGroundMovementType : uint8
-{
- None,
- Run,
- Hover,
-
- Max
-};
-
-enum class CreatureFlightMovementType : uint8
-{
- None,
- DisableGravity,
- CanFly,
-
- Max
-};
-
enum class CreatureChaseMovementType : uint8
{
Run,
@@ -412,22 +394,16 @@ struct TC_GAME_API CreatureMovementData
{
CreatureMovementData();
- CreatureGroundMovementType Ground;
- CreatureFlightMovementType Flight;
- bool Swim;
- bool Rooted;
+ bool HoverInitiallyEnabled;
CreatureChaseMovementType Chase;
CreatureRandomMovementType Random;
uint32 InteractionPauseTimer;
- bool IsGroundAllowed() const { return Ground != CreatureGroundMovementType::None; }
- bool IsSwimAllowed() const { return Swim; }
- bool IsFlightAllowed() const { return Flight != CreatureFlightMovementType::None; }
- bool IsRooted() const { return Rooted; }
-
CreatureChaseMovementType GetChase() const { return Chase; }
CreatureRandomMovementType GetRandom() const { return Random; }
+ bool IsHoverInitiallyEnabled() const { return HoverInitiallyEnabled; }
+
uint32 GetInteractionPauseTimer() const { return InteractionPauseTimer; }
std::string ToString() const;
diff --git a/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp b/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp
index 86b2bae5d5a..c04e7cedd5b 100644
--- a/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp
+++ b/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp
@@ -40,7 +40,7 @@ TC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
case CREATURE_FLAG_EXTRA_NO_XP: return { "CREATURE_FLAG_EXTRA_NO_XP", "CREATURE_FLAG_EXTRA_NO_XP", "creature kill does not provide XP" };
case CREATURE_FLAG_EXTRA_TRIGGER: return { "CREATURE_FLAG_EXTRA_TRIGGER", "CREATURE_FLAG_EXTRA_TRIGGER", "trigger creature" };
case CREATURE_FLAG_EXTRA_NO_TAUNT: return { "CREATURE_FLAG_EXTRA_NO_TAUNT", "CREATURE_FLAG_EXTRA_NO_TAUNT", "creature is immune to taunt auras and 'attack me' effects" };
- case CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE: return { "CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE", "CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE", "creature won't update movement flags" };
+ case CREATURE_FLAG_EXTRA_UNUSED_9: return { "CREATURE_FLAG_EXTRA_UNUSED_9", "CREATURE_FLAG_EXTRA_UNUSED_9", "creature won't update movement flags" };
case CREATURE_FLAG_EXTRA_GHOST_VISIBILITY: return { "CREATURE_FLAG_EXTRA_GHOST_VISIBILITY", "CREATURE_FLAG_EXTRA_GHOST_VISIBILITY", "creature will only be visible to dead players" };
case CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK: return { "CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK", "CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK", "creature will use offhand attacks" };
case CREATURE_FLAG_EXTRA_NO_SELL_VENDOR: return { "CREATURE_FLAG_EXTRA_NO_SELL_VENDOR", "CREATURE_FLAG_EXTRA_NO_SELL_VENDOR", "players can't sell items to this vendor" };
@@ -84,7 +84,7 @@ TC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(size_t
case 6: return CREATURE_FLAG_EXTRA_NO_XP;
case 7: return CREATURE_FLAG_EXTRA_TRIGGER;
case 8: return CREATURE_FLAG_EXTRA_NO_TAUNT;
- case 9: return CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE;
+ case 9: return CREATURE_FLAG_EXTRA_UNUSED_9;
case 10: return CREATURE_FLAG_EXTRA_GHOST_VISIBILITY;
case 11: return CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK;
case 12: return CREATURE_FLAG_EXTRA_NO_SELL_VENDOR;
@@ -125,7 +125,7 @@ TC_API_EXPORT size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsExtra v
case CREATURE_FLAG_EXTRA_NO_XP: return 6;
case CREATURE_FLAG_EXTRA_TRIGGER: return 7;
case CREATURE_FLAG_EXTRA_NO_TAUNT: return 8;
- case CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE: return 9;
+ case CREATURE_FLAG_EXTRA_UNUSED_9: return 9;
case CREATURE_FLAG_EXTRA_GHOST_VISIBILITY: return 10;
case CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK: return 11;
case CREATURE_FLAG_EXTRA_NO_SELL_VENDOR: return 12;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index fa9ed374883..4cd114f170d 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -3741,9 +3741,17 @@ float WorldObject::GetFloorZ() const
float WorldObject::GetMapWaterOrGroundLevel(float x, float y, float z, float* ground/* = nullptr*/) const
{
- return GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ground,
- isType(TYPEMASK_UNIT) ? !static_cast<Unit const*>(this)->HasAuraType(SPELL_AURA_WATER_WALK) : false,
- GetCollisionHeight());
+ bool swimming = [&]()
+ {
+ if (Creature const* creature = ToCreature())
+ return (!creature->CannotPenetrateWater() && !creature->HasAuraType(SPELL_AURA_WATER_WALK));
+ else if (Unit const* unit = ToUnit())
+ return !unit->HasAuraType(SPELL_AURA_WATER_WALK);
+
+ return true;
+ }();
+
+ return GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ground, swimming, GetCollisionHeight());
}
float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 36a1d1545ed..2eb9b88538f 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3161,10 +3161,23 @@ bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
bool Unit::isInAccessiblePlaceFor(Creature const* c) const
{
- if (IsInWater())
- return c->CanEnterWater();
- else
- return c->CanWalk() || c->CanFly();
+ // Aquatic creatures are not allowed to leave liquids
+ if (!IsInWater() && c->IsAquatic())
+ return false;
+
+ // Underwater special case. Some creatures may not go below liquid surfaces
+ if (IsUnderWater() && c->CannotPenetrateWater())
+ return false;
+
+ // Water checks
+ if (IsInWater() && !c->CanEnterWater())
+ return false;
+
+ // Some creatures are tied to the ocean floor and cannot chase swimming targets.
+ if (!IsOnOceanFloor() && c->IsUnderWater() && c->HasUnitFlag(UNIT_FLAG_CANT_SWIM))
+ return false;
+
+ return true;
}
bool Unit::IsInWater() const
@@ -10883,7 +10896,7 @@ void Unit::SetControlled(bool apply, UnitState state)
SetStunned(false);
break;
case UNIT_STATE_ROOT:
- if (HasAuraType(SPELL_AURA_MOD_ROOT) || HasAuraType(SPELL_AURA_MOD_ROOT_2) || HasAuraType(SPELL_AURA_MOD_ROOT_DISABLE_GRAVITY) || GetVehicle() || (ToCreature() && ToCreature()->IsTemplateRooted()))
+ if (HasAuraType(SPELL_AURA_MOD_ROOT) || HasAuraType(SPELL_AURA_MOD_ROOT_2) || HasAuraType(SPELL_AURA_MOD_ROOT_DISABLE_GRAVITY) || GetVehicle() || (ToCreature() && ToCreature()->IsSessile()))
return;
ClearUnitState(state);
@@ -11224,9 +11237,6 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
AddUnitState(UNIT_STATE_CHARMED);
- if (Creature* creature = ToCreature())
- creature->RefreshCanSwimFlag();
-
if ((GetTypeId() != TYPEID_PLAYER) || (charmer->GetTypeId() != TYPEID_PLAYER))
{
// AI will schedule its own change if appropriate
@@ -12681,7 +12691,7 @@ bool Unit::SetDisableGravity(bool disable, bool updateAnimTier /*= true*/)
SendMessageToSet(packet.Write(), true);
}
- if (IsCreature() && updateAnimTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !ToCreature()->IsTemplateRooted())
+ if (IsCreature() && updateAnimTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT))
{
if (IsGravityDisabled())
SetAnimTier(AnimTier::Fly);
@@ -12907,7 +12917,7 @@ bool Unit::SetHover(bool enable, bool updateAnimTier /*= true*/)
SendMessageToSet(packet.Write(), true);
}
- if (IsCreature() && updateAnimTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !ToCreature()->IsTemplateRooted())
+ if (IsCreature() && updateAnimTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT))
{
if (IsGravityDisabled())
SetAnimTier(AnimTier::Fly);
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 5d1fbd9e64a..18eabd6f75f 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1721,10 +1721,7 @@ class TC_GAME_API Unit : public WorldObject
virtual bool CanEnterWater() const = 0;
virtual bool CanSwim() const;
- float GetHoverOffset() const
- {
- return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? *m_unitData->HoverHeight : 0.0f;
- }
+ float GetHoverOffset() const { return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? *m_unitData->HoverHeight : 0.0f; }
void RewardRage(uint32 baseRage);
diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h
index 348a9f6d611..c675a39bd06 100644
--- a/src/server/game/Entities/Unit/UnitDefines.h
+++ b/src/server/game/Entities/Unit/UnitDefines.h
@@ -177,7 +177,7 @@ enum UnitFlags : uint32
UNIT_FLAG_DISALLOWED = (UNIT_FLAG_SERVER_CONTROLLED | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL |
UNIT_FLAG_PLAYER_CONTROLLED | UNIT_FLAG_RENAME | UNIT_FLAG_PREPARATION | /* UNIT_FLAG_UNK_6 | */
UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_LOOTING | UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_PVP_ENABLING |
- UNIT_FLAG_NON_ATTACKABLE_2 | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED |
+ UNIT_FLAG_CANT_SWIM | UNIT_FLAG_CAN_SWIM | UNIT_FLAG_NON_ATTACKABLE_2 | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED |
UNIT_FLAG_IN_COMBAT | UNIT_FLAG_ON_TAXI | UNIT_FLAG_DISARMED | UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING |
UNIT_FLAG_POSSESSED | UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT | UNIT_FLAG_UNK_28 |
UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT | UNIT_FLAG_SHEATHE | UNIT_FLAG_IMMUNE), // SKIP
@@ -227,7 +227,7 @@ enum UnitFlags2 : uint32
UNIT_FLAG2_DISALLOWED = (UNIT_FLAG2_FEIGN_DEATH | UNIT_FLAG2_IGNORE_REPUTATION | UNIT_FLAG2_COMPREHEND_LANG |
UNIT_FLAG2_MIRROR_IMAGE | UNIT_FLAG2_FORCE_MOVEMENT | UNIT_FLAG2_DISARM_OFFHAND |
UNIT_FLAG2_DISABLE_PRED_STATS | UNIT_FLAG2_ALLOW_CHANGING_TALENTS | UNIT_FLAG2_DISARM_RANGED |
- /* UNIT_FLAG2_REGENERATE_POWER | */ UNIT_FLAG2_RESTRICT_PARTY_INTERACTION |
+ /* UNIT_FLAG2_REGENERATE_POWER | */ UNIT_FLAG2_RESTRICT_PARTY_INTERACTION | UNIT_FLAG2_CANNOT_TURN |
UNIT_FLAG2_PREVENT_SPELL_CLICK | /* UNIT_FLAG2_INTERACT_WHILE_HOSTILE | */ /* UNIT_FLAG2_UNK2 | */
/* UNIT_FLAG2_PLAY_DEATH_ANIM | */ UNIT_FLAG2_ALLOW_CHEAT_SPELLS | UNIT_FLAG2_SUPPRESS_HIGHLIGHT_WHEN_TARGETED_OR_MOUSED_OVER |
UNIT_FLAG2_TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS | UNIT_FLAG2_LARGE_AOI | UNIT_FLAG2_GIGANTIC_AOI | UNIT_FLAG2_NO_ACTIONS |
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 70c1d64c309..75b4da4172c 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -363,13 +363,13 @@ void ObjectMgr::LoadCreatureTemplates()
// "unit_class, unit_flags, unit_flags2, unit_flags3, "
// 25 26 27 28 29 30
// "family, trainer_class, type, VehicleId, AIName, MovementType, "
- // 31 32 33 34 35 36 37 38
- // "ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, ExperienceModifier, "
- // 39 40 41 42 43
+ // 31 32 33 34 35
+ // "ctm.HoverInitiallyEnabled, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, ExperienceModifier, "
+ // 36 37 38 39 40
// "RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, "
- // 44 45
+ // 41 42
// "CreatureImmunitiesId, flags_extra, "
- // 46 47
+ // 43 44
// "ScriptName, StringId FROM creature_template WHERE entry = ? OR 1 = ?");
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEMPLATE);
@@ -448,37 +448,29 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.VehicleId = fields[28].GetUInt32();
creatureTemplate.AIName = fields[29].GetString();
creatureTemplate.MovementType = uint32(fields[30].GetUInt8());
+
if (!fields[31].IsNull())
- creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[31].GetUInt8());
+ creatureTemplate.Movement.HoverInitiallyEnabled = fields[31].GetBool();
if (!fields[32].IsNull())
- creatureTemplate.Movement.Swim = fields[32].GetBool();
+ creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[32].GetUInt8());
if (!fields[33].IsNull())
- creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[33].GetUInt8());
+ creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[33].GetUInt8());
if (!fields[34].IsNull())
- creatureTemplate.Movement.Rooted = fields[34].GetBool();
-
- if (!fields[35].IsNull())
- creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[35].GetUInt8());
-
- if (!fields[36].IsNull())
- creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[36].GetUInt8());
+ creatureTemplate.Movement.InteractionPauseTimer = fields[34].GetUInt32();
- if (!fields[37].IsNull())
- creatureTemplate.Movement.InteractionPauseTimer = fields[37].GetUInt32();
-
- creatureTemplate.ModExperience = fields[38].GetFloat();
- creatureTemplate.RacialLeader = fields[39].GetBool();
- creatureTemplate.movementId = fields[40].GetUInt32();
- creatureTemplate.WidgetSetID = fields[41].GetInt32();
- creatureTemplate.WidgetSetUnitConditionID = fields[42].GetInt32();
- creatureTemplate.RegenHealth = fields[43].GetBool();
- creatureTemplate.CreatureImmunitiesId = fields[44].GetInt32();
- creatureTemplate.flags_extra = fields[45].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[46].GetString());
- creatureTemplate.StringId = fields[47].GetString();
+ creatureTemplate.ModExperience = fields[35].GetFloat();
+ creatureTemplate.RacialLeader = fields[36].GetBool();
+ creatureTemplate.movementId = fields[37].GetUInt32();
+ creatureTemplate.WidgetSetID = fields[38].GetInt32();
+ creatureTemplate.WidgetSetUnitConditionID = fields[39].GetInt32();
+ creatureTemplate.RegenHealth = fields[40].GetBool();
+ creatureTemplate.CreatureImmunitiesId = fields[41].GetInt32();
+ creatureTemplate.flags_extra = fields[42].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[43].GetString());
+ creatureTemplate.StringId = fields[44].GetString();
}
void ObjectMgr::LoadCreatureTemplateGossip()
@@ -1171,20 +1163,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
void ObjectMgr::CheckCreatureMovement(char const* table, uint64 id, CreatureMovementData& creatureMovement)
{
- if (creatureMovement.Ground >= CreatureGroundMovementType::Max)
- {
- TC_LOG_ERROR("sql.sql", "`{}`.`Ground` wrong value ({}) for Id {}, setting to Run.",
- table, uint32(creatureMovement.Ground), id);
- creatureMovement.Ground = CreatureGroundMovementType::Run;
- }
-
- if (creatureMovement.Flight >= CreatureFlightMovementType::Max)
- {
- TC_LOG_ERROR("sql.sql", "`{}`.`Flight` wrong value ({}) for Id {}, setting to None.",
- table, uint32(creatureMovement.Flight), id);
- creatureMovement.Flight = CreatureFlightMovementType::None;
- }
-
if (creatureMovement.Chase >= CreatureChaseMovementType::Max)
{
TC_LOG_ERROR("sql.sql", "`{}`.`Chase` wrong value ({}) for Id {}, setting to Run.",
@@ -1581,10 +1559,7 @@ void ObjectMgr::LoadCreatureMovementOverrides()
// Load the data from creature_movement_override and if NULL fallback to creature_template_movement
QueryResult result = WorldDatabase.Query(
"SELECT cmo.SpawnId,"
- "COALESCE(cmo.Ground, ctm.Ground),"
- "COALESCE(cmo.Swim, ctm.Swim),"
- "COALESCE(cmo.Flight, ctm.Flight),"
- "COALESCE(cmo.Rooted, ctm.Rooted),"
+ "COALESCE(cmo.HoverInitiallyEnabled, ctm.HoverInitiallyEnabled),"
"COALESCE(cmo.Chase, ctm.Chase),"
"COALESCE(cmo.Random, ctm.Random),"
"COALESCE(cmo.InteractionPauseTimer, ctm.InteractionPauseTimer) "
@@ -1610,19 +1585,13 @@ void ObjectMgr::LoadCreatureMovementOverrides()
CreatureMovementData& movement = _creatureMovementOverrides[spawnId];
if (!fields[1].IsNull())
- movement.Ground = static_cast<CreatureGroundMovementType>(fields[1].GetUInt8());
+ movement.HoverInitiallyEnabled = fields[1].GetBool();
if (!fields[2].IsNull())
- movement.Swim = fields[2].GetBool();
+ movement.Chase = static_cast<CreatureChaseMovementType>(fields[2].GetUInt8());
if (!fields[3].IsNull())
- movement.Flight = static_cast<CreatureFlightMovementType>(fields[3].GetUInt8());
+ movement.Random = static_cast<CreatureRandomMovementType>(fields[3].GetUInt8());
if (!fields[4].IsNull())
- movement.Rooted = fields[4].GetBool();
- if (!fields[5].IsNull())
- movement.Chase = static_cast<CreatureChaseMovementType>(fields[5].GetUInt8());
- if (!fields[6].IsNull())
- movement.Random = static_cast<CreatureRandomMovementType>(fields[6].GetUInt8());
- if (!fields[7].IsNull())
- movement.InteractionPauseTimer = fields[7].GetUInt32();
+ movement.InteractionPauseTimer = fields[4].GetUInt32();
CheckCreatureMovement("creature_movement_override", spawnId, movement);
}
@@ -1659,7 +1628,7 @@ CreatureModel const* ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, C
return cinfo->GetFirstInvisibleModel();
}
-void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64* npcFlags, uint32* unitFlags, uint32* unitFlags2, uint32* unitFlags3, CreatureData const* data /*= nullptr*/)
+void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64* npcFlags, uint32* unitFlags, uint32* unitFlags2, uint32* unitFlags3, CreatureStaticFlagsHolder const& staticFlags, CreatureData const* data /*= nullptr*/)
{
#define ChooseCreatureFlagSource(field) ((data && data->field.has_value()) ? *data->field : cInfo->field)
@@ -1667,10 +1636,21 @@ void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64* npcFl
*npcFlags = ChooseCreatureFlagSource(npcflag);
if (unitFlags)
+ {
*unitFlags = ChooseCreatureFlagSource(unit_flags);
+ if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_CAN_SWIM))
+ *unitFlags |= UNIT_FLAG_CAN_SWIM;
+
+ if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_3_CANNOT_SWIM))
+ *unitFlags |= UNIT_FLAG_CANT_SWIM;
+ }
if (unitFlags2)
+ {
*unitFlags2 = ChooseCreatureFlagSource(unit_flags2);
+ if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_3_CANNOT_TURN))
+ *unitFlags2 |= UNIT_FLAG2_CANNOT_TURN;
+ }
if (unitFlags3)
*unitFlags3 = ChooseCreatureFlagSource(unit_flags3);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 7a570135431..392fb9abaef 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -1132,7 +1132,7 @@ class TC_GAME_API ObjectMgr
CreatureModelInfo const* GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const;
CreatureSummonedData const* GetCreatureSummonedData(uint32 entryId) const;
static CreatureModel const* ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr);
- static void ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64* npcFlags, uint32* unitFlags, uint32* unitFlags2, uint32* unitFlags3, CreatureData const* data = nullptr);
+ static void ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64* npcFlags, uint32* unitFlags, uint32* unitFlags2, uint32* unitFlags3, CreatureStaticFlagsHolder const& staticFlags, CreatureData const* data = nullptr);
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id) const;
CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid) const;
GameObjectAddon const* GetGameObjectAddon(ObjectGuid::LowType lowguid) const;
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index a62f0700f48..4c9a3648bc3 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -144,11 +144,9 @@ void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, b
if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))
{
- if (!owner->HasCanSwimFlagOutOfCombat())
- owner->RemoveUnitFlag(UNIT_FLAG_CAN_SWIM);
-
if (owner->IsStateRestoredOnEvade())
{
+ owner->InitializeMovementCapabilities();
owner->SetSpawnHealth();
owner->LoadCreaturesAddon();
owner->LoadCreaturesSparringHealth();
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index a5967cf5867..17ff6c7a864 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -179,7 +179,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
BuildShortcut();
bool path = _source->GetTypeId() == TYPEID_UNIT && _source->ToCreature()->CanFly();
- bool waterPath = _source->GetTypeId() == TYPEID_UNIT && _source->ToCreature()->CanSwim();
+ bool waterPath = _source->GetTypeId() == TYPEID_UNIT && _source->ToCreature()->CanEnterWater();
if (waterPath)
{
// Check both start and end points, if they're both in water, then we can *safely* let the creature move
@@ -653,7 +653,7 @@ void PathGenerator::CreateFilter()
if (_source->GetTypeId() == TYPEID_UNIT)
{
Creature* creature = (Creature*)_source;
- if (creature->CanWalk())
+ if (!creature->IsAquatic())
includeFlags |= NAV_GROUND; // walk
// creatures don't take environmental damage
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index e86637c6780..c9ceb470b9d 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2985,10 +2985,7 @@ void AuraEffect::HandleAuraModRootAndDisableGravity(AuraApplication const* aurAp
target->SetControlled(apply, UNIT_STATE_ROOT);
// Do not remove DisableGravity if there are more than this auraEffect of that kind on the unit or if it's a creature with DisableGravity on its movement template.
- if (!apply
- && (target->HasAuraType(GetAuraType())
- || target->HasAuraType(SPELL_AURA_MOD_STUN_DISABLE_GRAVITY)
- || (target->IsCreature() && target->ToCreature()->GetMovementTemplate().Flight == CreatureFlightMovementType::DisableGravity)))
+ if (!apply && (target->HasAuraType(GetAuraType()) || target->HasAuraType(SPELL_AURA_MOD_STUN_DISABLE_GRAVITY) || (target->IsCreature() && target->ToCreature()->IsFloating())))
return;
if (target->SetDisableGravity(apply))
@@ -3009,10 +3006,7 @@ void AuraEffect::HandleAuraModStunAndDisableGravity(AuraApplication const* aurAp
target->GetThreatManager().EvaluateSuppressed();
// Do not remove DisableGravity if there are more than this auraEffect of that kind on the unit or if it's a creature with DisableGravity on its movement template.
- if (!apply
- && (target->HasAuraType(GetAuraType())
- || target->HasAuraType(SPELL_AURA_MOD_ROOT_DISABLE_GRAVITY)
- || (target->IsCreature() && target->ToCreature()->GetMovementTemplate().Flight == CreatureFlightMovementType::DisableGravity)))
+ if (!apply && (target->HasAuraType(GetAuraType()) || target->HasAuraType(SPELL_AURA_MOD_ROOT_DISABLE_GRAVITY) || (target->IsCreature() && target->ToCreature()->IsFloating())))
return;
if (target->SetDisableGravity(apply))
diff --git a/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp b/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp
index 541ec3c53b0..7ab449b9191 100644
--- a/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp
@@ -492,8 +492,6 @@ struct npc_joren_ironstock : public ScriptedAI
void JustAppeared() override
{
- me->SetTemplateRooted(true);
-
_scheduler.Schedule(1s, [this](TaskContext task)
{
if (Creature* invader = me->SummonCreature(NPC_ROCKJAW_INVADER, Trinity::Containers::SelectRandomContainerElement(RockjawInvaderSpawnPoints), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 18s))
diff --git a/src/server/scripts/ExilesReach/zone_exiles_reach.cpp b/src/server/scripts/ExilesReach/zone_exiles_reach.cpp
index 0ec3d94693f..e5f0e36616d 100644
--- a/src/server/scripts/ExilesReach/zone_exiles_reach.cpp
+++ b/src/server/scripts/ExilesReach/zone_exiles_reach.cpp
@@ -4460,7 +4460,7 @@ struct npc_briarpatch_prisoner : public ScriptedAI
void JustAppeared() override
{
me->SetDisableGravity(true);
- me->SetTemplateRooted(true);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->CastSpell(me, SPELL_NECROTIC_RITUAL_DNT);
}
@@ -4470,7 +4470,7 @@ struct npc_briarpatch_prisoner : public ScriptedAI
{
me->RemoveAllAuras();
me->SetDisableGravity(false);
- me->SetTemplateRooted(false);
+ me->SetControlled(false, UNIT_STATE_ROOT);
me->GetMotionMaster()->MoveJump(BriarpatchPrisonerJumpToPosition, 7.9894905f, 19.29110336303710937f);
Talk(SAY_GET_OUT_OF_HERE);
_events.ScheduleEvent(EVENT_RUN_TO_PLAINS, 4s);
@@ -6277,7 +6277,7 @@ struct npc_captain_garrick_q55879 : public ScriptedAI
if (!boar)
return;
- boar->SetTemplateRooted(false);
+ boar->SetControlled(false, UNIT_STATE_ROOT);
me->CastSpell(boar, SPELL_RIDE_VEHICLE_CAPTIAN_BOAR);
}
break;
@@ -6372,7 +6372,7 @@ struct npc_giant_boar_vehicle_q55879 : public VehicleAI
{
if (apply && passenger->IsPlayer())
{
- me->SetTemplateRooted(true);
+ me->SetControlled(true, UNIT_STATE_ROOT);
passenger->SetMovedUnit(me);
passenger->CastSpell(passenger, SPELL_PING_GARRICK_TO_RIDE_BOAR); // Ping Garrick to ride Boar (DNT)
passenger->CastSpell(passenger, SPELL_UPDATE_PHASE_SHIFT);
@@ -6388,7 +6388,7 @@ struct npc_giant_boar_vehicle_q55879 : public VehicleAI
if (spellInfo->Id == SPELL_ENHANCED_BOAR_PING_VEHICLE)
{
me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOM_SPELL_01);
- me->SetTemplateRooted(true);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->CastSpell(me, SPELL_ENHANCED_BOAR_CHARGE);
_endOfScene = true;
_events.ScheduleEvent(EVENT_GIANT_BOAR_SIZE_ONE, 4s);
@@ -6434,7 +6434,7 @@ struct npc_giant_boar_vehicle_q55879 : public VehicleAI
_events.ScheduleEvent(EVENT_GIANT_BOAR_UNROOT, 500ms);
break;
case EVENT_GIANT_BOAR_UNROOT:
- me->SetTemplateRooted(false);
+ me->SetControlled(false, UNIT_STATE_ROOT);
break;
default:
break;
diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp
index 0a774e75a1e..4d959dce9c1 100644
--- a/src/server/scripts/Kalimdor/zone_durotar.cpp
+++ b/src/server/scripts/Kalimdor/zone_durotar.cpp
@@ -211,7 +211,6 @@ struct npc_durotar_tiki_target : public ScriptedAI
void JustAppeared() override
{
me->SetReactState(REACT_PASSIVE);
- me->SetTemplateRooted(true);
DoCastSelf(TiKiTargetMask[urand(0, 2)]);
DoCastSelf(SPELL_ARCANE_MISSILES_TRAINER);
}