diff --git a/sql/updates/world/4.3.4/2025_03_09_00_world.sql b/sql/updates/world/4.3.4/2025_03_09_00_world.sql new file mode 100644 index 0000000000..f5aa92754d --- /dev/null +++ b/sql/updates/world/4.3.4/2025_03_09_00_world.sql @@ -0,0 +1,26 @@ +-- Add new movement settings +ALTER TABLE `creature_template_movement` + ADD COLUMN `HoverInitiallyEnabled` TINYINT UNSIGNED NULL AFTER `CreatureId`; + +UPDATE `creature_template_movement` SET `HoverInitiallyEnabled`= 1 WHERE `Ground` = 2; + +ALTER TABLE `creature_movement_override` + ADD COLUMN `HoverInitiallyEnabled` TINYINT UNSIGNED NULL AFTER `SpawnId`; + +UPDATE `creature_movement_override` SET `HoverInitiallyEnabled`= 1 WHERE `Ground` = 2; + +-- Remove deprecated CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE +UPDATE `creature_template` SET `flags_extra`= `flags_extra` &~ 0x200; + +-- Conversion done. Drop old columns +ALTER TABLE `creature_movement_override` + DROP COLUMN `Ground`, + DROP COLUMN `Swim`, + DROP COLUMN `Flight`, + DROP COLUMN `Rooted`; + +ALTER TABLE `creature_template_movement` + DROP COLUMN `Ground`, + DROP COLUMN `Swim`, + DROP COLUMN `Flight`, + DROP COLUMN `Rooted`; diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index dddd56e57c..e5a765dd68 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -128,7 +128,8 @@ enum ZLiquidStatus : uint32 LIQUID_MAP_ABOVE_WATER = 0x00000001, LIQUID_MAP_WATER_WALK = 0x00000002, LIQUID_MAP_IN_WATER = 0x00000004, - LIQUID_MAP_UNDER_WATER = 0x00000008 + LIQUID_MAP_UNDER_WATER = 0x00000008, + LIQUID_MAP_OCEAN_FLOOR = 0x00000010 }; #define MAP_LIQUID_STATUS_SWIMMING (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER) diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index a27ca82c26..918eb8296a 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp @@ -76,7 +76,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, femaleName, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, StaticFlags, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, femaleName, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.HoverInitiallyEnabled, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, StaticFlags, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", 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); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index fa5bd2302b..69c3c16e3a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -145,9 +145,9 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff) { if (siege->IsAlive()) { - if (siege->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_CANNOT_SWIM|UNIT_FLAG_IMMUNE_TO_PC)) + if (siege->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_CANT_SWIM | UNIT_FLAG_IMMUNE_TO_PC)) // following sniffs the vehicle always has UNIT_FLAG_CANNOT_SWIM - siege->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_IMMUNE_TO_PC); + siege->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); else siege->SetHealth(siege->GetMaxHealth()); } @@ -753,7 +753,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* node, bool recapture) if (Creature* siegeEngine = GetBGCreature(siegeType)) { - siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_CANNOT_SWIM); + siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_CANT_SWIM); siegeEngine->SetImmuneToPC(true); siegeEngine->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); } diff --git a/src/server/game/Combat/CombatManager.cpp b/src/server/game/Combat/CombatManager.cpp index 9926191050..7ae9aa6abc 100644 --- a/src/server/game/Combat/CombatManager.cpp +++ b/src/server/game/Combat/CombatManager.cpp @@ -368,14 +368,14 @@ bool CombatManager::UpdateOwnerCombatState() const if (combatState) { - _owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + _owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT | UNIT_FLAG_PET_IN_COMBAT); _owner->AtEnterCombat(); if (_owner->GetTypeId() != TYPEID_UNIT) _owner->AtEngage(GetAnyTarget()); } else { - _owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + _owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT | UNIT_FLAG_PET_IN_COMBAT); _owner->AtExitCombat(); if (_owner->GetTypeId() != TYPEID_UNIT) _owner->AtDisengage(); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 543678f816..892cb4b0f3 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -61,24 +61,18 @@ VendorItemCount::VendorItemCount(uint32 _item, uint32 _count) : itemId(_item), count(_count), lastIncrementTime(GameTime::GetGameTime()) { } -CreatureMovementData::CreatureMovementData() : Ground(CreatureGroundMovementType::Run), Flight(CreatureFlightMovementType::None), -Swim(true), Rooted(false), Random(CreatureRandomMovementType::Walk), InteractionPauseTimer(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER)) { } +CreatureMovementData::CreatureMovementData() : HoverInitiallyEnabled(false), 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 RandomStates[] = { "Walk", "CanRun", "AlwaysRun" }; std::ostringstream str; str << std::boolalpha - << "Ground: " << GroundStates[AsUnderlyingType(Ground)] - << ", Swim: " << Swim - << ", Flight: " << FlightStates[AsUnderlyingType(Flight)] - << ", Random: " << RandomStates[AsUnderlyingType(Random)]; - if (Rooted) - str << ", Rooted"; + << ", HoverInitiallyEnabled: " << HoverInitiallyEnabled + << "Random: " << RandomStates[AsUnderlyingType(Random)]; + str << ", InteractionPauseTimer: " << InteractionPauseTimer; return str.str(); @@ -589,8 +583,8 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, SetFaction(cInfo->faction); - uint32 npcflag, unit_flags, dynamicflags; - ObjectMgr::ChooseCreatureFlags(cInfo, npcflag, unit_flags, dynamicflags, data); + uint32 npcflag, unit_flags, unit_flags2, dynamicflags; + ObjectMgr::ChooseCreatureFlags(cInfo, npcflag, unit_flags, unit_flags2, dynamicflags, _staticFlags, data); if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT) SetUInt32Value(UNIT_NPC_FLAGS, npcflag | sGameEventMgr->GetNPCFlag(this)); @@ -603,7 +597,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, unit_flags |= UNIT_FLAG_IN_COMBAT; SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); - SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2); + SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2 | unit_flags2); SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynamicflags); @@ -662,13 +656,12 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); } - if (GetMovementTemplate().IsRooted()) - SetControlled(true, UNIT_STATE_ROOT); if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_COMBAT) SetIgnoringCombat(true); - InitializeMovementFlags(); + InitializeMovementCapabilities(); + LoadCreaturesAddon(); LoadTemplateImmunities(); @@ -680,8 +673,7 @@ 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); } void Creature::Update(uint32 diff) @@ -694,7 +686,7 @@ void Creature::Update(uint32 diff) AI()->JustAppeared(); } - UpdateMovementFlags(false); + UpdateMovementCapabilities(); GetThreatManager().Update(diff); @@ -1110,7 +1102,7 @@ bool Creature::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool if (!Unit::SetDisableGravity(disable, packetOnly, updateAnimationTier)) return false; - if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !GetMovementTemplate().IsRooted()) + if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT)) { if (IsGravityDisabled()) SetAnimationTier(AnimationTier::Fly); @@ -1132,7 +1124,7 @@ bool Creature::SetHover(bool enable, bool packetOnly /*= false*/, bool updateAni if (!Unit::SetHover(enable, packetOnly, updateAnimationTier)) return false; - if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !GetMovementTemplate().IsRooted()) + if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT)) { if (IsGravityDisabled()) SetAnimationTier(AnimationTier::Fly); @@ -1727,17 +1719,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); @@ -1968,7 +1949,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); @@ -1988,7 +1969,7 @@ void Creature::setDeathState(DeathState s) ResetPlayerDamageReq(); SetCannotReachTarget(false); - UpdateMovementFlags(true); + UpdateMovementCapabilities(); ClearUnitState(UNIT_STATE_ALL_ERASABLE); @@ -1997,11 +1978,12 @@ void Creature::setDeathState(DeathState s) CreatureData const* creatureData = GetCreatureData(); CreatureTemplate const* cinfo = GetCreatureTemplate(); - uint32 npcflag, unit_flags, dynamicflags; - ObjectMgr::ChooseCreatureFlags(cinfo, npcflag, unit_flags, dynamicflags, creatureData); + uint32 npcflag, unit_flags, unit_flags2, dynamicflags; + ObjectMgr::ChooseCreatureFlags(cinfo, npcflag, unit_flags, unit_flags2, dynamicflags, _staticFlags, creatureData); SetUInt32Value(UNIT_NPC_FLAGS, npcflag); SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); + SetUInt32Value(UNIT_FIELD_FLAGS_2, cinfo->unit_flags2 | unit_flags2); SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynamicflags); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); @@ -2527,7 +2509,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); @@ -2561,14 +2543,6 @@ bool Creature::LoadCreaturesAddon() SetAnimationTier(AnimationTier(creatureAddon->animTier)); SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_VIS_FLAG, creatureAddon->visFlags); - //! 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); - // UNIT_FIELD_BYTES_2 values SetSheath(SheathState(creatureAddon->sheathState)); SetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, creatureAddon->pvpFlags); @@ -2672,6 +2646,45 @@ void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, floa } } +void Creature::InitializeMovementCapabilities() +{ + SetHover(GetMovementTemplate().IsHoverInitiallyEnabled()); + SetDisableGravity(IsFloating()); + SetControlled(IsSessile(), UNIT_STATE_ROOT); + + if (IsSwimPrevented()) + { + SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS); + SetSwim(false); + } + else + RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS); + + UpdateMovementCapabilities(); +} + +void Creature::UpdateMovementCapabilities() +{ + // Do not update movement flags if creature is controlled by a player (charm/vehicle) + if (IsMovedByClient()) + 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 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); + + if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS)) + if (GetVictim() && GetVictim()->IsInWater() && !GetVictim()->IsOnOceanFloor()) + RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS); + + if (IsInWater() && CanSwim()) + SetSwim(true); + else if (!IsInWater()) // We do not want to disable swimming again when a creature is in water - may to lead some nasty bugs + SetSwim(false); +} + CreatureMovementData const& Creature::GetMovementTemplate() const { if (CreatureMovementData const* movementOverride = sObjectMgr->GetCreatureMovementOverride(m_spawnId)) @@ -2691,25 +2704,6 @@ bool Creature::CanSwim() const 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::InitializeCreatureMovementInfo(uint32 movementId) { if (CreatureMovementInfoOverride const* movementInfoOverride = sObjectMgr->GetCreatureMovementInfoOverride(movementId)) @@ -3001,56 +2995,6 @@ float Creature::GetNativeObjectScale() const return GetCreatureTemplate()->scale; } -void Creature::InitializeMovementFlags() -{ - LoadTemplateRoot(); - // It does the same, for now - UpdateMovementFlags(true); -} - -void Creature::UpdateMovementFlags(bool initializeDBStates) -{ - // Do not update movement flags if creature is controlled by a player (charm/vehicle) - if (IsMovedByClient()) - 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; - - // These movement states are static and should only get applied when initializing a creature's entry (when spawning or transforming) - if (initializeDBStates) - { - if (GetMovementTemplate().IsFlightAllowed()) - { - if (GetMovementTemplate().IsGravityDisabled()) - SetDisableGravity(true); - - if (GetMovementTemplate().CanFly()) - SetCanFly(true); - } - - if (GetMovementTemplate().IsGroundAllowed()) - { - // Hovering always requires the creature to be alive to avoid visual issues. The IsAlive() check can be removed when respawn compatability has been removed. - // @todo: sniffed spawn locations have applied hover offsets to the position z value so either substract them when parsing sniffs or skip the initial relocation from Unit::SetHover - if (IsAlive() && GetMovementTemplate().IsHoverEnabled()) - SetHover(true); - } - } - else - { - // These are realtime movement flag updates which are being updated per tick - // 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 isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + (IsHovering() ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f) + 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()); -} - void Creature::SetObjectScale(float scale) { Unit::SetObjectScale(scale); @@ -3130,7 +3074,7 @@ void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target) _spellFocusInfo.FocusSpell = focusSpell; // Block target based focusing when the attributes or unit flags say so. - bool dontFaceTarget = spellInfo->HasAttribute(SPELL_ATTR5_AI_DOESNT_FACE_TARGET)|| spellInfo->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL) || HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN); + bool dontFaceTarget = spellInfo->HasAttribute(SPELL_ATTR5_AI_DOESNT_FACE_TARGET)|| spellInfo->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL) || HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CANNOT_TURN); ObjectGuid newTarget = (dontFaceTarget || target == this || target == nullptr) ? ObjectGuid::Empty : target->GetGUID(); @@ -3185,7 +3129,7 @@ void Creature::ReleaseSpellFocus(Spell const* focusSpell, bool withDelay) if (IsPet()) // player pets do not use delay system { - if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN)) + if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CANNOT_TURN)) ReacquireSpellFocusTarget(); } else // don't allow re-target right away to prevent visual bugs @@ -3204,7 +3148,7 @@ void Creature::ReacquireSpellFocusTarget() SetGuidValue(UNIT_FIELD_TARGET, _spellFocusInfo.OriginalUnitTarget); - if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN)) + if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CANNOT_TURN)) { if (_spellFocusInfo.OriginalUnitTarget) { @@ -3284,8 +3228,6 @@ void Creature::AtEngage(Unit* target) if (!(GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_MOUNTED_COMBAT_ALLOWED)) Dismount(); - RefreshSwimmingFlag(); - MovementGeneratorType const movetype = GetMotionMaster()->GetCurrentMovementGeneratorType(); if (movetype == WAYPOINT_MOTION_TYPE || movetype == CYCLIC_SPLINE_MOTION_TYPE || movetype == POINT_MOTION_TYPE || (IsAIEnabled() && AI()->IsEscorted())) SetHomePosition(GetPosition()); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 663c85253d..e0ce02e44c 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -80,9 +80,6 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma void UpdateLevelDependantStats(); 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; } @@ -99,12 +96,39 @@ class TC_GAME_API Creature : public Unit, public GridObject, 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 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); } + void SetFloating(bool floating) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_FLOATING, floating); SetDisableGravity(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); } + void SetSessile(bool sessile) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_SESSILE, sessile); SetControlled(sessile, UNIT_STATE_ROOT); } + + // 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); } + void SetCannotPenetrateWater(bool cannotPenetrateWater) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_3_CANNOT_PENETRATE_WATER, cannotPenetrateWater); } + + // 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().IsHoverEnabled() || IsHovering(); } + bool CanEnterWater() const override { return (CanSwim() || IsAmphibious()); }; + bool CanFly() const override { return (IsFlying() || HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)); } + bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override; bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true) override; bool SetCanFly(bool enable, bool packetOnly = false) override; @@ -166,9 +190,6 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma bool UpdateEntry(uint32 entry, CreatureData const* data = nullptr, bool updateLevel = true); - void InitializeMovementFlags(); - void UpdateMovementFlags(bool initializeDBStates); - bool UpdateStats(Stats stat) override; bool UpdateAllStats() override; void UpdateResistances(uint32 school) override; @@ -379,12 +400,6 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma bool HasStaticFlag(CreatureStaticFlags4 flag) const { return _staticFlags.HasFlag(flag); } bool HasStaticFlag(CreatureStaticFlags5 flag) const { return _staticFlags.HasFlag(flag); } - bool HasSwimmingFlagOutOfCombat() const - { - return !_isMissingSwimmingFlagOutOfCombat; - } - void RefreshSwimmingFlag(bool recheck = false); - CreatureMovementInfo const& GetCreatureMovementInfo() const { return _creatureMovementInfo; } // Sets the the max health percentage threshold at which uncontrolled/unowned creatures can no longer deal damage to the creature diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 31bd3db24d..e9f04802e6 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -45,7 +45,7 @@ enum CreatureFlagsExtra : uint32 CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and effect attack me - 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 be only visible for 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 @@ -296,24 +296,6 @@ private: EnumFlag _flags5; }; -enum class CreatureGroundMovementType : uint8 -{ - None, - Run, - Hover, - - Max -}; - -enum class CreatureFlightMovementType : uint8 -{ - None, - DisableGravity, - CanFly, - - Max -}; - enum class CreatureRandomMovementType : uint8 { Walk, @@ -327,23 +309,14 @@ struct TC_GAME_API CreatureMovementData { CreatureMovementData(); - CreatureGroundMovementType Ground; - CreatureFlightMovementType Flight; - bool Swim; - bool Rooted; + bool HoverInitiallyEnabled; 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; } - bool IsGravityDisabled() const { return Flight == CreatureFlightMovementType::DisableGravity; } - bool CanFly() const { return Flight == CreatureFlightMovementType::CanFly; } - bool IsHoverEnabled() const { return Ground == CreatureGroundMovementType::Hover; } - 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/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 5a009a6c16..758a8bdfc3 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -3710,9 +3710,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(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 9fbe2e8699..aa2e3dfb0a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2940,10 +2940,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->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CANT_SWIM)) + return false; + + return true; } bool Unit::IsInWater() const @@ -2956,6 +2969,11 @@ bool Unit::IsUnderWater() const return GetLiquidStatus() & LIQUID_MAP_UNDER_WATER; } +bool Unit::IsOnOceanFloor() const +{ + return GetLiquidStatus() & LIQUID_MAP_OCEAN_FLOOR; +} + void Unit::ProcessPositionDataChanged(PositionFullTerrainStatus const& data) { ZLiquidStatus oldLiquidStatus = GetLiquidStatus(); @@ -8673,6 +8691,10 @@ void Unit::UpdatePetCombatState() { ASSERT(!IsPet()); // player pets do not use UNIT_FLAG_PET_IN_COMBAT for this purpose - but player pets should also never have minions of their own to call this + // UNIT_FLAG_PET_IN_COMBAT is set by default when the summoner is in combat by himself + if (IsInCombat()) + return; + bool state = false; for (Unit* minion : m_Controlled) if (minion->IsInCombat()) @@ -11325,7 +11347,7 @@ void Unit::SetControlled(bool apply, UnitState state) SetStunned(false); break; case UNIT_STATE_ROOT: - if (HasAuraType(SPELL_AURA_MOD_ROOT) || GetVehicle() || (ToCreature() && ToCreature()->GetMovementTemplate().IsRooted())) + if (HasAuraType(SPELL_AURA_MOD_ROOT) || GetVehicle() || (IsCreature() && ToCreature()->IsSessile())) return; ClearUnitState(state); @@ -12972,15 +12994,15 @@ bool Unit::IsFalling() const bool Unit::CanSwim() const { // Mirror client behavior, if this method returns false then client will not use swimming animation and for players will apply gravity as if there was no water - if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CANNOT_SWIM)) + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CANT_SWIM)) return false; if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) // is player return true; - if (HasFlag(UNIT_FIELD_FLAGS_2, 0x1000000)) + if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS)) return false; if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT)) return true; - return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME | UNIT_FLAG_SWIMMING); + return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME | UNIT_FLAG_CAN_SWIM); } void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 331689d1c5..ec3fb463d3 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1124,6 +1124,7 @@ class TC_GAME_API Unit : public WorldObject bool IsInWater() const; bool IsUnderWater() const; + bool IsOnOceanFloor() const; bool isInAccessiblePlaceFor(Creature const* c) const; void SendHealSpellLog(HealInfo& healInfo, bool critical = false); @@ -1715,10 +1716,7 @@ class TC_GAME_API Unit : public WorldObject virtual bool CanEnterWater() const = 0; virtual bool CanSwim() const; - float GetHoverOffset() const - { - return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f; - } + float GetHoverOffset() const { return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f; } uint32 GetMovementCounterAndInc() { return m_movementCounter++; } uint32 GetMovementCounter() { return m_movementCounter; } diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h index 2a6c4871bd..d42326ed74 100644 --- a/src/server/game/Entities/Unit/UnitDefines.h +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -138,8 +138,8 @@ enum UnitFlags : uint32 UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // on player pets: whether the pet is chasing a target to attack || on other units: whether any of the unit's minions is in combat UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 - UNIT_FLAG_CANNOT_SWIM = 0x00004000, // 2.0.8 - UNIT_FLAG_SWIMMING = 0x00008000, // shows swim animation in water + UNIT_FLAG_CANT_SWIM = 0x00004000, // 2.0.8 + UNIT_FLAG_CAN_SWIM = 0x00008000, // shows swim animation in water UNIT_FLAG_NOT_ATTACKABLE_2 = 0x00010000, UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok @@ -162,27 +162,32 @@ enum UnitFlags : uint32 // Value masks for UNIT_FIELD_FLAGS_2 enum UnitFlags2 : uint32 { - UNIT_FLAG2_FEIGN_DEATH = 0x00000001, - UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip) - UNIT_FLAG2_IGNORE_REPUTATION = 0x00000004, - UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, - UNIT_FLAG2_MIRROR_IMAGE = 0x00000010, - UNIT_FLAG2_INSTANTLY_APPEAR_MODEL = 0x00000020, // Unit model instantly appears when summoned (does not fade in) - UNIT_FLAG2_FORCE_MOVEMENT = 0x00000040, - UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, - UNIT_FLAG2_DISABLE_PRED_STATS = 0x00000100, // Player has disabled predicted stats (Used by raid frames) - UNIT_FLAG2_DISARM_RANGED = 0x00000400, // this does not disable ranged weapon display (maybe additional flag needed?) - UNIT_FLAG2_REGENERATE_POWER = 0x00000800, - UNIT_FLAG2_RESTRICT_PARTY_INTERACTION = 0x00001000, // Restrict interaction to party or raid - UNIT_FLAG2_PREVENT_SPELL_CLICK = 0x00002000, // Prevent spellclick - UNIT_FLAG2_ALLOW_ENEMY_INTERACT = 0x00004000, - UNIT_FLAG2_DISABLE_TURN = 0x00008000, - UNIT_FLAG2_UNK2 = 0x00010000, - UNIT_FLAG2_PLAY_DEATH_ANIM = 0x00020000, // Plays special death animation upon death - UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000, // Allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL - UNIT_FLAG2_NO_ACTIONS = 0x00800000, - UNIT_FLAG2_DISABLE_UNIT_FRAME = 0x04000000, // Disables the unit frame when selecting the target - UNIT_FLAG2_IGNORE_SPELL_MIN_RANGE_RESTRICTIONS = 0x08000000 // Allows spells with a min range restriction to be cast when closer than given range value + UNIT_FLAG2_FEIGN_DEATH = 0x00000001, + UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip) + UNIT_FLAG2_IGNORE_REPUTATION = 0x00000004, + UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, + UNIT_FLAG2_MIRROR_IMAGE = 0x00000010, + UNIT_FLAG2_INSTANTLY_APPEAR_MODEL = 0x00000020, // Unit model instantly appears when summoned (does not fade in) + UNIT_FLAG2_FORCE_MOVEMENT = 0x00000040, + UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, + UNIT_FLAG2_DISABLE_PRED_STATS = 0x00000100, // Player has disabled predicted stats (Used by raid frames) + UNIT_FLAG2_DISARM_RANGED = 0x00000400, // this does not disable ranged weapon display (maybe additional flag needed?) + UNIT_FLAG2_REGENERATE_POWER = 0x00000800, + UNIT_FLAG2_RESTRICT_PARTY_INTERACTION = 0x00001000, // Restrict interaction to party or raid + UNIT_FLAG2_PREVENT_SPELL_CLICK = 0x00002000, // Prevent spellclick + UNIT_FLAG2_ALLOW_ENEMY_INTERACT = 0x00004000, + UNIT_FLAG2_CANNOT_TURN = 0x00008000, + UNIT_FLAG2_UNK2 = 0x00010000, + UNIT_FLAG2_PLAY_DEATH_ANIM = 0x00020000, // Plays special death animation upon death + UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000, // Allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL + UNIT_FLAG2_SUPPRESS_HIGHLIGHT_WHEN_TARGETED_OR_MOUSED_OVER = 0x00080000, // Suppress highlight when targeted or moused over + UNIT_FLAG2_TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS = 0x00100000, // Treat as Raid Unit For Helpful Spells (Instances ONLY) + UNIT_FLAG2_LARGE_AOI = 0x00200000, // Large (AOI) + UNIT_FLAG2_GIGANTIC_AOI = 0x00400000, // Gigantic (AOI) + UNIT_FLAG2_NO_ACTIONS = 0x00800000, + UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS = 0x01000000, // AI will only swim if target swims + UNIT_FLAG2_DISABLE_UNIT_FRAME = 0x04000000, // Disables the unit frame when selecting the target + UNIT_FLAG2_IGNORE_SPELL_MIN_RANGE_RESTRICTIONS = 0x08000000 // Allows spells with a min range restriction to be cast when closer than given range value }; /// Non Player Character flags diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 4f91c4ef03..2c0fbdc97e 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -433,11 +433,11 @@ void ObjectMgr::LoadCreatureTemplates() "dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, " // 48 49 50 51 52 53 54 55 56 57 58 59 60 61 "spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, " - // 62 63 64 65 66 67 68 69 70 71 72 - "ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, " - // 73 74 75 76 77 78 79 80 + // 62 63 64 65 66 67 68 69 + "ctm.HoverInitiallyEnabled, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, " + // 70 71 72 73 74 75 76 77 "ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, " - // 81 82 83 84 85 86 87 + // 78 79 80 81 82 83 84 "flags_extra, StaticFlags, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId"); if (!result) @@ -528,41 +528,32 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields) creatureTemplate.AIName = fields[60].GetString(); creatureTemplate.MovementType = uint32(fields[61].GetUInt8()); if (!fields[62].IsNull()) - creatureTemplate.Movement.Ground = static_cast(fields[62].GetUInt8()); + creatureTemplate.Movement.HoverInitiallyEnabled = fields[62].GetBool(); if (!fields[63].IsNull()) - creatureTemplate.Movement.Swim = fields[63].GetBool(); + creatureTemplate.Movement.Random = static_cast(fields[63].GetUInt8()); if (!fields[64].IsNull()) - creatureTemplate.Movement.Flight = static_cast(fields[64].GetUInt8()); + creatureTemplate.Movement.InteractionPauseTimer = fields[64].GetUInt32(); - if (!fields[65].IsNull()) - creatureTemplate.Movement.Rooted = fields[65].GetBool(); + creatureTemplate.HoverHeight = fields[65].GetFloat(); + creatureTemplate.ModHealth = fields[66].GetFloat(); + creatureTemplate.ModHealthExtra = fields[67].GetFloat(); + creatureTemplate.ModMana = fields[68].GetFloat(); + creatureTemplate.ModManaExtra = fields[69].GetFloat(); + creatureTemplate.ModArmor = fields[70].GetFloat(); + creatureTemplate.ModDamage = fields[71].GetFloat(); + creatureTemplate.ModExperience = fields[72].GetFloat(); - if (!fields[66].IsNull()) - creatureTemplate.Movement.Random = static_cast(fields[66].GetUInt8()); - - if (!fields[67].IsNull()) - creatureTemplate.Movement.InteractionPauseTimer = fields[67].GetUInt32(); - - creatureTemplate.HoverHeight = fields[68].GetFloat(); - creatureTemplate.ModHealth = fields[69].GetFloat(); - creatureTemplate.ModHealthExtra = fields[70].GetFloat(); - creatureTemplate.ModMana = fields[71].GetFloat(); - creatureTemplate.ModManaExtra = fields[72].GetFloat(); - creatureTemplate.ModArmor = fields[73].GetFloat(); - creatureTemplate.ModDamage = fields[74].GetFloat(); - creatureTemplate.ModExperience = fields[75].GetFloat(); - - creatureTemplate.RacialLeader = fields[76].GetBool(); - creatureTemplate.movementId = fields[77].GetUInt32(); - creatureTemplate.RegenHealth = fields[78].GetBool(); - creatureTemplate.MechanicImmuneMask = fields[79].GetUInt32(); - creatureTemplate.SpellSchoolImmuneMask = fields[80].GetUInt32(); - creatureTemplate.flags_extra = fields[81].GetUInt32(); - creatureTemplate.StaticFlags = CreatureStaticFlagsHolder(CreatureStaticFlags(fields[82].GetUInt32()), CreatureStaticFlags2(fields[83].GetUInt32()), - CreatureStaticFlags3(fields[84].GetUInt32()), CreatureStaticFlags4(fields[85].GetUInt32()), CreatureStaticFlags5(fields[86].GetUInt32())); - creatureTemplate.ScriptID = GetScriptId(fields[87].GetCString()); + creatureTemplate.RacialLeader = fields[73].GetBool(); + creatureTemplate.movementId = fields[74].GetUInt32(); + creatureTemplate.RegenHealth = fields[75].GetBool(); + creatureTemplate.MechanicImmuneMask = fields[76].GetUInt32(); + creatureTemplate.SpellSchoolImmuneMask = fields[77].GetUInt32(); + creatureTemplate.flags_extra = fields[78].GetUInt32(); + creatureTemplate.StaticFlags = CreatureStaticFlagsHolder(CreatureStaticFlags(fields[79].GetUInt32()), CreatureStaticFlags2(fields[80].GetUInt32()), + CreatureStaticFlags3(fields[81].GetUInt32()), CreatureStaticFlags4(fields[82].GetUInt32()), CreatureStaticFlags5(fields[83].GetUInt32())); + creatureTemplate.ScriptID = GetScriptId(fields[84].GetCString()); } void ObjectMgr::LoadCreatureTemplateModels() @@ -757,7 +748,7 @@ void ObjectMgr::LoadCreatureSparringTemplate() { uint32 oldMSTime = getMSTime(); - // 0 1 + // 0 1 QueryResult result = WorldDatabase.Query("SELECT CreatureID, HealthLimitPct FROM creature_sparring_template"); if (!result) @@ -1129,20 +1120,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", "`%s`.`Ground` wrong value (%u) for Id " UI64FMTD ", setting to Run.", - table, uint32(creatureMovement.Ground), id); - creatureMovement.Ground = CreatureGroundMovementType::Run; - } - - if (creatureMovement.Flight >= CreatureFlightMovementType::Max) - { - TC_LOG_ERROR("sql.sql", "`%s`.`Flight` wrong value (%u) for Id " UI64FMTD ", setting to None.", - table, uint32(creatureMovement.Flight), id); - creatureMovement.Flight = CreatureFlightMovementType::None; - } - if (creatureMovement.Random >= CreatureRandomMovementType::Max) { TC_LOG_ERROR("sql.sql", "`%s`.`Random` wrong value (%u) for Id " UI64FMTD ", setting to Walk.", @@ -1513,10 +1490,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.Random, ctm.Random)," "COALESCE(cmo.InteractionPauseTimer, ctm.InteractionPauseTimer) " "FROM creature_movement_override AS cmo " @@ -1541,17 +1515,11 @@ void ObjectMgr::LoadCreatureMovementOverrides() CreatureMovementData& movement = _creatureMovementOverrides[spawnId]; if (!fields[1].IsNull()) - movement.Ground = static_cast(fields[1].GetUInt8()); + movement.HoverInitiallyEnabled = fields[1].GetBool(); if (!fields[2].IsNull()) - movement.Swim = fields[2].GetBool(); + movement.Random = static_cast(fields[3].GetUInt8()); if (!fields[3].IsNull()) - movement.Flight = static_cast(fields[3].GetUInt8()); - if (!fields[4].IsNull()) - movement.Rooted = fields[4].GetBool(); - if (!fields[5].IsNull()) - movement.Random = static_cast(fields[6].GetUInt8()); - if (!fields[6].IsNull()) - movement.InteractionPauseTimer = fields[6].GetUInt32(); + movement.InteractionPauseTimer = fields[4].GetUInt32(); CheckCreatureMovement("creature_movement_override", spawnId, movement); } while (result->NextRow()); @@ -1617,11 +1585,12 @@ CreatureModel const* ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, C return cinfo->GetFirstInvisibleModel(); } -void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data /*= nullptr*/) +void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& unitFlags2, uint32& dynamicflags, CreatureStaticFlagsHolder const& staticFlags, CreatureData const* data /*= nullptr*/) { npcflag = cinfo->npcflag; unit_flags = cinfo->unit_flags; dynamicflags = cinfo->dynamicflags; + unitFlags2 = 0; if (data) { @@ -1634,6 +1603,18 @@ void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcfl if (data->dynamicflags) dynamicflags = data->dynamicflags; } + + if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_CAN_SWIM)) + unit_flags |= UNIT_FLAG_CAN_SWIM; + + if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_3_CANNOT_SWIM)) + unit_flags |= UNIT_FLAG_CANT_SWIM; + + if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_3_CANNOT_TURN)) + unitFlags2 |= UNIT_FLAG2_CANNOT_TURN; + + if (staticFlags.HasFlag(CREATURE_STATIC_FLAG_4_PREVENT_SWIM)) + unitFlags2 |= UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS; } CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const @@ -10153,7 +10134,7 @@ void ObjectMgr::LoadTaxiNodeLevelData() uint8 level = fields[1].GetUInt8(); TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(taxiNodeId); - + if (!node) { TC_LOG_ERROR("sql.sql", "Table `taxi_level_data` has data for nonexistent taxi node (ID: %u), skipped", taxiNodeId); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 489e7ab773..ade70fce86 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -851,7 +851,7 @@ struct QuestPOIWrapper void InitializeQueryData(); ByteBuffer BuildQueryData() const; - + QuestPOIWrapper() : QueryDataBuffer(0) { } }; @@ -1015,7 +1015,7 @@ class TC_GAME_API ObjectMgr CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId) const; CreatureModelInfo const* GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const; static CreatureModel const* ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr); - static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = nullptr); + static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& unitFlags2, uint32& dynamicflags, 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/Maps/GridMap.cpp b/src/server/game/Maps/GridMap.cpp index c4bbaf643c..3bba849d82 100644 --- a/src/server/game/Maps/GridMap.cpp +++ b/src/server/game/Maps/GridMap.cpp @@ -599,6 +599,8 @@ float GridMap::getLiquidLevel(float x, float y) const return _liquidMap[cx_int*_liquidWidth + cy_int]; } +constexpr float GROUND_LEVEL_OFFSET_HACK = 0.02f; // due to floating point precision issues, we have to resort to a small hack to fix inconsistencies in liquids + // Get water state on map ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, Optional ReqLiquidType, LiquidData* data, float collisionHeight) const { @@ -661,12 +663,12 @@ ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, Optional store data @@ -681,12 +683,18 @@ ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, Optional collisionHeight) // Under water - return LIQUID_MAP_UNDER_WATER; - if (delta > 0.0f) // In water - return LIQUID_MAP_IN_WATER; - if (delta > -0.1f) // Walk on water - return LIQUID_MAP_WATER_WALK; - // Above water - return LIQUID_MAP_ABOVE_WATER; + uint32 status = LIQUID_MAP_ABOVE_WATER; // Above water + + if (delta > collisionHeight) // Under water + status = LIQUID_MAP_UNDER_WATER; + else if (delta > 0.0f) // In water + status = LIQUID_MAP_IN_WATER; + else if (delta > -0.1f) // Walk on water + status = LIQUID_MAP_WATER_WALK; + + if (status != LIQUID_MAP_ABOVE_WATER) + if (std::fabs(ground_level - z) <= GROUND_HEIGHT_TOLERANCE) + status |= LIQUID_MAP_OCEAN_FLOOR; + + return static_cast(status); } diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp index 36ba26630e..9007faec9a 100644 --- a/src/server/game/Maps/TerrainMgr.cpp +++ b/src/server/game/Maps/TerrainMgr.cpp @@ -431,14 +431,19 @@ void TerrainInfo::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, data.liquidInfo->type_flags = map_liquidHeaderTypeFlags(1 << liquidFlagType); float delta = wmoData->liquidInfo->level - z; + uint32 status = LIQUID_MAP_ABOVE_WATER; if (delta > collisionHeight) - data.liquidStatus = LIQUID_MAP_UNDER_WATER; + status = LIQUID_MAP_UNDER_WATER; else if (delta > 0.0f) - data.liquidStatus = LIQUID_MAP_IN_WATER; + status = LIQUID_MAP_IN_WATER; else if (delta > -0.1f) - data.liquidStatus = LIQUID_MAP_WATER_WALK; - else - data.liquidStatus = LIQUID_MAP_ABOVE_WATER; + status = LIQUID_MAP_WATER_WALK; + + if (status != LIQUID_MAP_ABOVE_WATER) + if (std::fabs(wmoData->floorZ - z) <= GROUND_HEIGHT_TOLERANCE) + status |= LIQUID_MAP_OCEAN_FLOOR; + + data.liquidStatus = static_cast(status); } // look up liquid data from grid map if (gmap && useGridLiquid) @@ -513,12 +518,23 @@ ZLiquidStatus TerrainInfo::GetLiquidStatus(PhaseShift const& phaseShift, uint32 float delta = liquid_level - z; // Get position delta - if (delta > collisionHeight) // Under water - return LIQUID_MAP_UNDER_WATER; - if (delta > 0.0f) // In water - return LIQUID_MAP_IN_WATER; - if (delta > -0.1f) // Walk on water - return LIQUID_MAP_WATER_WALK; + uint32 status = LIQUID_MAP_ABOVE_WATER; + if (delta > collisionHeight) // Under water + status = LIQUID_MAP_UNDER_WATER; + else if (delta > 0.0f) // In water + status = LIQUID_MAP_IN_WATER; + else if (delta > -0.1f) // Walk on water + status = LIQUID_MAP_WATER_WALK; + + if (status != LIQUID_MAP_ABOVE_WATER) + { + if (status != LIQUID_MAP_ABOVE_WATER) + if (std::fabs(ground_level - z) <= GROUND_HEIGHT_TOLERANCE) + status |= LIQUID_MAP_OCEAN_FLOOR; + + return static_cast(status); + } + result = LIQUID_MAP_ABOVE_WATER; } } diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 87c317bf1e..aa8863fa50 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -81,12 +81,9 @@ void HomeMovementGenerator::DoFinalize(Creature* owner) { if (_arrived) { - if (!owner->HasSwimmingFlagOutOfCombat()) - owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING); - owner->ClearUnitState(UNIT_STATE_EVADE); owner->SetWalk(true); - owner->UpdateMovementFlags(true); + owner->InitializeMovementCapabilities(); owner->LoadCreaturesAddon(); if (owner->IsVehicle()) owner->GetVehicleKit()->Reset(true); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index de13a24843..f97f0860e7 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -191,7 +191,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 @@ -670,7 +670,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 @@ -696,7 +696,7 @@ void PathGenerator::UpdateFilter() // allow creatures to cheat and use different movement types if they are moved // forcefully into terrain they can't normally move in - if (const Unit* _sourceUnit = _source->ToUnit()) + if (Unit const* _sourceUnit = _source->ToUnit()) { if (_sourceUnit->IsInWater() || _sourceUnit->IsUnderWater()) { diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index d2bdb4a7ad..a1ce73725e 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -135,8 +135,8 @@ EnumName const unitFlags[MAX_UNIT_FLAGS] = CREATE_NAMED_ENUM(UNIT_FLAG_PET_IN_COMBAT), CREATE_NAMED_ENUM(UNIT_FLAG_PVP), CREATE_NAMED_ENUM(UNIT_FLAG_SILENCED), - CREATE_NAMED_ENUM(UNIT_FLAG_CANNOT_SWIM), - CREATE_NAMED_ENUM(UNIT_FLAG_SWIMMING), + CREATE_NAMED_ENUM(UNIT_FLAG_CANT_SWIM), + CREATE_NAMED_ENUM(UNIT_FLAG_CAN_SWIM), CREATE_NAMED_ENUM(UNIT_FLAG_NOT_ATTACKABLE_2), CREATE_NAMED_ENUM(UNIT_FLAG_PACIFIED), CREATE_NAMED_ENUM(UNIT_FLAG_STUNNED), @@ -166,7 +166,7 @@ EnumName const flagsExtra[] = CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_XP_AT_KILL), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_TRIGGER), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_TAUNT), - CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_UNUSED_9), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_SELL_VENDOR), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_COMBAT), CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_WORLDEVENT), diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp index d0cbd03095..8df3d96e44 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp @@ -536,7 +536,7 @@ public: me->RestoreFaction(); CombatAI::Reset(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CAN_SWIM); } void SpellHit(WorldObject* pCaster, SpellInfo const* pSpell) override @@ -631,7 +631,7 @@ public: } me->SetImmuneToPC(false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CAN_SWIM); player->CastSpell(me, SPELL_DUEL, false); player->CastSpell(player, SPELL_DUEL_FLAG, true); diff --git a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp index 8be01f2064..1166195969 100644 --- a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp +++ b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp @@ -348,7 +348,7 @@ class npc_shard_of_torment : public CreatureScript { me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN); + me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CANNOT_TURN); me->SetDisplayFromModel(1); _instance = creature->GetInstanceScript(); } diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp index e58e986256..243c72cc30 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp @@ -282,10 +282,10 @@ class spell_varos_centrifuge_shield : public SpellScriptLoader if (Unit* caster = GetCaster()) { // flags taken from sniffs - if (caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_UNK_6)) + if (caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CAN_SWIM | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_UNK_6)) { caster->ToCreature()->SetReactState(REACT_PASSIVE); - caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING | UNIT_FLAG_UNK_6); + caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CAN_SWIM | UNIT_FLAG_UNK_6); caster->SetImmuneToAll(true, true); } } @@ -296,7 +296,7 @@ class spell_varos_centrifuge_shield : public SpellScriptLoader if (Unit* caster = GetCaster()) { caster->ToCreature()->SetReactState(REACT_AGGRESSIVE); - caster->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SWIMMING | UNIT_FLAG_UNK_6); + caster->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CAN_SWIM | UNIT_FLAG_UNK_6); caster->SetImmuneToAll(false); } }