aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorMachiavelli <machiavelli.trinity@gmail.com>2012-03-12 00:45:58 +0100
committerMachiavelli <machiavelli.trinity@gmail.com>2012-03-12 00:53:45 +0100
commit03a24a84e493f914d46488e8c4ae9e9d663c21d7 (patch)
tree6299dee664c6a97fa9fbbb3482aa7a97d6e7d0dd /src/server/game
parent5ca27f40cced56414900aaaf656b45353a41aaf8 (diff)
Core/Units:
- Implement UNIT_FIELD_HOVERHEIGHT (requires DB data). This field, sent in update object packet, will determine the height at which a creature hovers if it has movementflag_hover applied. Note that hovering will now update the server-sided z-coordinate by the value of this field, and that all subsequent positional updates to the client will need to send z coordinate MINUS the hover height offset, or the hoverheight will be visually doubled client side. - Correct our usage of movementflag_flying, movementflag_can_fly, movementflag_hover and movementflag_disable_gravity (previously levitate), and how they relate to InhabitType in the database. This fixes "flying creatures on steroids" bug (wings flapping too fast), and potentially a lot of visual issues in AI scripts. Note that a lot of scripts still set wrong movementflags, these need to be fixed on a case by case basis. - Send correct packets for SPELL_AURA_FEATHER_FALL, SPELL_AURA_WATER_WALK and SPELL_AURA_HOVER apply/unapply. - Send correct packet contents for movement update in Unit::SetSpeed. - Misc. cleanup in affected scripts.
Diffstat (limited to 'src/server/game')
-rwxr-xr-xsrc/server/game/AI/CoreAI/GuardAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp12
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp104
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h6
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp19
-rwxr-xr-xsrc/server/game/Entities/Object/Object.h3
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp20
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h9
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp109
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h45
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp49
-rwxr-xr-xsrc/server/game/Maps/Map.cpp12
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.cpp2
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.cpp6
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp41
19 files changed, 299 insertions, 148 deletions
diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp
index b78fec7c142..df29d485cba 100755
--- a/src/server/game/AI/CoreAI/GuardAI.cpp
+++ b/src/server/game/AI/CoreAI/GuardAI.cpp
@@ -54,7 +54,7 @@ bool GuardAI::CanSeeAlways(WorldObject const* obj)
void GuardAI::MoveInLineOfSight(Unit* unit)
{
// Ignore Z for flying creatures
- if (!me->canFly() && me->GetDistanceZ(unit) > CREATURE_Z_ATTACK_RANGE)
+ if (!me->CanFly() && me->GetDistanceZ(unit) > CREATURE_Z_ATTACK_RANGE)
return;
if (!me->getVictim() && me->IsValidAttackTarget(unit) &&
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index 1e0c3f5c1fc..688d48b41ad 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -95,7 +95,7 @@ void npc_escortAI::MoveInLineOfSight(Unit* who)
if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombat(who))
return;
- if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
+ if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
if (me->IsHostileTo(who))
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index e0fe12082f1..13bbbe2c338 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -93,7 +93,7 @@ void FollowerAI::MoveInLineOfSight(Unit* who)
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombat(who))
return;
- if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
+ if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
if (me->IsHostileTo(who))
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 50c7aba0360..4cf438da5a4 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -729,17 +729,7 @@ void SmartAI::SetRun(bool run)
void SmartAI::SetFly(bool fly)
{
- if (fly)
- {
- me->SetLevitate(true);
- me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x01);
- }
- else
- {
- me->SetLevitate(false);
- me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x01);
- }
- me->SetFlying(fly);
+ me->SetDisableGravity(fly);
me->SendMovementFlagUpdate();
}
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 2b4f1275993..1fb972ccfdf 100755
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -334,7 +334,8 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data
SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate
SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale);
- SetLevitate(canFly());
+
+ SetFloatValue(UNIT_FIELD_HOVERHEIGHT, cinfo->HoverHeight);
// checked at loading
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
@@ -418,10 +419,25 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data)
ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
}
- // TODO: In fact monster move flags should be set - not movement flags.
- if (cInfo->InhabitType & INHABIT_AIR)
- AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING);
-
+ //! Suspect it works this way:
+ //! If creature can walk and fly (usually with pathing)
+ //! Set MOVEMENTFLAG_CAN_FLY. Otherwise if it can only fly
+ //! Set MOVEMENTFLAG_DISABLE_GRAVITY
+ //! The only time I saw Movement Flags: DisableGravity, CanFly, Flying (50332672) on the same unit
+ //! it was a vehicle
+ if (cInfo->InhabitType & INHABIT_AIR && cInfo->InhabitType & INHABIT_GROUND)
+ SetCanFly(true);
+ else if (cInfo->InhabitType & INHABIT_AIR)
+ SetDisableGravity(true);
+ /*! Implemented in LoadCreatureAddon. Suspect there's a rule for UNIT_BYTE_1_FLAG_HOVER
+ in relation to DisableGravity also.
+
+ else if (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE_1_FLAG_HOVER)
+ SetHover(true);
+
+ */
+
+ // TODO: Shouldn't we check whether or not the creature is in water first?
if (cInfo->InhabitType & INHABIT_WATER)
AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
@@ -742,6 +758,14 @@ bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry,
return false;
}
+ //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0;
+ if (!CreateFromProto(guidlow, Entry, vehId, team, data))
+ return false;
+
+ //! Need to be called after CreateFromProto
+ if (HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
+ z += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+
Relocate(x, y, z, ang);
if (!IsPositionValid())
@@ -750,10 +774,6 @@ bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry,
return false;
}
- //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0;
- if (!CreateFromProto(guidlow, Entry, vehId, team, data))
- return false;
-
switch (GetCreatureTemplate()->rank)
{
case CREATURE_ELITE_RARE:
@@ -783,17 +803,6 @@ bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry,
SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
}
- if (GetCreatureTemplate()->InhabitType & INHABIT_AIR)
- {
- if (GetDefaultMovementType() == IDLE_MOTION_TYPE)
- AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
- else
- SetFlying(true);
- }
-
- if (GetCreatureTemplate()->InhabitType & INHABIT_WATER)
- AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
-
LastUsedScriptID = GetCreatureTemplate()->ScriptID;
// TODO: Replace with spell, handle from DB
@@ -1065,11 +1074,11 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
data.equipmentId = GetEquipmentId();
data.posX = GetPositionX();
data.posY = GetPositionY();
- data.posZ = GetPositionZ();
+ data.posZ = GetPositionZMinusOffset();
data.orientation = GetOrientation();
data.spawntimesecs = m_respawnDelay;
// prevent add data integrity problems
- data.spawndist = GetDefaultMovementType() == IDLE_MOTION_TYPE ? 0 : m_respawnradius;
+ data.spawndist = GetDefaultMovementType() == IDLE_MOTION_TYPE ? 0.0f : m_respawnradius;
data.currentwaypoint = 0;
data.curhealth = GetHealth();
data.curmana = GetPower(POWER_MANA);
@@ -1287,7 +1296,7 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap)
if (m_respawnTime) // respawn on Update
{
m_deathState = DEAD;
- if (canFly())
+ if (CanFly())
{
float tz = map->GetHeight(GetPhaseMask(), data->posX, data->posY, data->posZ, false);
if (data->posZ - tz > 0.1f)
@@ -1420,7 +1429,7 @@ bool Creature::canStartAttack(Unit const* who, bool force) const
if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
- if (!canFly() && (GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE + m_CombatDistance))
+ if (!CanFly() && (GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE + m_CombatDistance))
//|| who->IsControlledByPlayer() && who->IsFlying()))
// we cannot check flying for other creatures, too much map/vmap calculation
// TODO: should switch to range attack
@@ -1517,7 +1526,7 @@ void Creature::setDeathState(DeathState s)
if (m_formation && m_formation->getLeader() == this)
m_formation->FormationReset(true);
- if ((canFly() || IsFlying()))
+ if ((CanFly() || IsFlying()))
i_motionMaster.MoveFall();
Unit::setDeathState(CORPSE);
@@ -1532,7 +1541,7 @@ void Creature::setDeathState(DeathState s)
CreatureTemplate const* cinfo = GetCreatureTemplate();
SetWalk(true);
if (GetCreatureTemplate()->InhabitType & INHABIT_AIR)
- AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING);
+ SetDisableGravity(true);
if (GetCreatureTemplate()->InhabitType & INHABIT_WATER)
AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag);
@@ -2040,6 +2049,12 @@ bool Creature::LoadCreaturesAddon(bool reload)
SetByteValue(UNIT_FIELD_BYTES_1, 1, 0);
SetByteValue(UNIT_FIELD_BYTES_1, 2, uint8((cainfo->bytes1 >> 16) & 0xFF));
SetByteValue(UNIT_FIELD_BYTES_1, 3, uint8((cainfo->bytes1 >> 24) & 0xFF));
+
+ //! Suspected correlation between UNIT_FIELD_BYTES_1, offset 3, value 0x2:
+ //! If no inhabittype_fly (if no MovementFlag_DisableGravity flag found in sniffs)
+ //! Set MovementFlag_Hover. Otherwise do nothing.
+ if (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE1_FLAG_HOVER && !IsLevitating())
+ AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
}
if (cainfo->bytes2 != 0)
@@ -2088,6 +2103,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
sLog->outDebug(LOG_FILTER_UNITS, "Spell: %u added to creature (GUID: %u Entry: %u)", *itr, GetGUIDLow(), GetEntry());
}
}
+
return true;
}
@@ -2415,17 +2431,43 @@ bool Creature::SetWalk(bool enable)
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
data.append(GetPackGUID());
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
+ return true;
+}
+
+bool Creature::SetDisableGravity(bool disable, bool packetOnly/*=false*/)
+{
+ //! It's possible only a packet is sent but moveflags are not updated
+ //! Need more research on this
+ if (!packetOnly && !Unit::SetDisableGravity(disable))
+ return false;
+
+ if (!movespline->Initialized())
+ return true;
+
+ WorldPacket data(disable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
+ data.append(GetPackGUID());
+ SendMessageToSet(&data, false);
return true;
}
-bool Creature::SetLevitate(bool enable)
+bool Creature::SetHover(bool enable)
{
- if (!Unit::SetLevitate(enable))
+ if (!Unit::SetHover(enable))
return false;
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
+ //! Unconfirmed for players:
+ if (enable)
+ SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);
+ else
+ RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);
+
+ if (!movespline->Initialized())
+ return true;
+
+ //! Not always a packet is sent
+ WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9);
data.append(GetPackGUID());
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
return true;
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index f986e09e7cb..2f9549fd70a 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -134,6 +134,7 @@ struct CreatureTemplate
std::string AIName;
uint32 MovementType;
uint32 InhabitType;
+ float HoverHeight;
float ModHealth;
float ModMana;
float ModArmor;
@@ -467,7 +468,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
bool isGuard() const { return GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GUARD; }
bool canWalk() const { return GetCreatureTemplate()->InhabitType & INHABIT_GROUND; }
bool canSwim() const { return GetCreatureTemplate()->InhabitType & INHABIT_WATER; }
- //bool canFly() const { return GetCreatureTemplate()->InhabitType & INHABIT_AIR; }
+ bool CanFly() const { return GetCreatureTemplate()->InhabitType & INHABIT_AIR; }
void SetReactState(ReactStates st) { m_reactState = st; }
ReactStates GetReactState() { return m_reactState; }
@@ -521,7 +522,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
CreatureAI* AI() const { return (CreatureAI*)i_AI; }
bool SetWalk(bool enable);
- bool SetLevitate(bool enable);
+ bool SetDisableGravity(bool disable, bool packetOnly = false);
+ bool SetHover(bool enable);
uint32 GetShieldBlockValue() const //dunno mob block value
{
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 2a2b78f4630..56ddd14dc3a 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -340,7 +340,10 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
*data << ((WorldObject*)this)->GetPositionX();
*data << ((WorldObject*)this)->GetPositionY();
- *data << ((WorldObject*)this)->GetPositionZ();
+ if (isType(TYPEMASK_UNIT))
+ *data << ((Unit*)this)->GetPositionZMinusOffset();
+ else
+ *data << ((WorldObject*)this)->GetPositionZ();
if (transport)
{
@@ -352,7 +355,10 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
*data << ((WorldObject*)this)->GetPositionX();
*data << ((WorldObject*)this)->GetPositionY();
- *data << ((WorldObject*)this)->GetPositionZ();
+ if (isType(TYPEMASK_UNIT))
+ *data << ((Unit*)this)->GetPositionZMinusOffset();
+ else
+ *data << ((WorldObject*)this)->GetPositionZ();
}
*data << ((WorldObject*)this)->GetOrientation();
@@ -369,7 +375,10 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
*data << ((WorldObject*)this)->GetPositionX();
*data << ((WorldObject*)this)->GetPositionY();
- *data << ((WorldObject*)this)->GetPositionZ();
+ if (isType(TYPEMASK_UNIT))
+ *data << ((Unit*)this)->GetPositionZMinusOffset();
+ else
+ *data << ((WorldObject*)this)->GetPositionZ();
*data << ((WorldObject*)this)->GetOrientation();
}
}
@@ -1557,7 +1566,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
{
// non fly unit don't must be in air
// non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast
- if (!ToCreature()->canFly())
+ if (!ToCreature()->CanFly())
{
bool canSwim = ToCreature()->canSwim();
float ground_z = z;
@@ -1583,7 +1592,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
case TYPEID_PLAYER:
{
// for server controlled moves playr work same as creature (but it can always swim)
- if (!ToPlayer()->canFly())
+ if (!ToPlayer()->CanFly())
{
float ground_z = z;
float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK));
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index c243527570b..fd8deb1b841 100755
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -776,7 +776,8 @@ class WorldObject : public Object, public WorldLocation
GetClosePoint(x, y, z, GetObjectSize());
ang = GetOrientation();
}
- Position pos = {x, y, z, ang};
+ Position pos;
+ pos.Relocate(x, y, z, ang);
return SummonCreature(id, pos, spwtype, despwtime, 0);
}
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8318bd246d0..f3f376dae04 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -22170,6 +22170,18 @@ void Player::SendAurasForTarget(Unit* target)
if (!target || target->GetVisibleAuras()->empty()) // speedup things
return;
+ /*! Blizz sends certain movement packets sometimes even before CreateObject
+ These movement packets are usually found in SMSG_COMPRESSED_MOVES
+ */
+ if (target->HasAuraType(SPELL_AURA_FEATHER_FALL))
+ target->SendMovementFeatherFall();
+
+ if (target->HasAuraType(SPELL_AURA_WATER_WALK))
+ target->SendMovementWaterWalking();
+
+ if (target->HasAuraType(SPELL_AURA_HOVER))
+ target->SendMovementHover();
+
WorldPacket data(SMSG_AURA_UPDATE_ALL);
data.append(target->GetPackGUID());
@@ -25158,3 +25170,11 @@ bool Player::IsInWhisperWhiteList(uint64 guid)
}
return false;
}
+
+bool Player::SetHover(bool enable)
+{
+ if (!Unit::SetHover(enable))
+ return false;
+
+ return true;
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index bd58827c0e4..7f6b2322e93 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2287,6 +2287,8 @@ class Player : public Unit, public GridObject<Player>
m_mover->m_movedPlayer = this;
}
+ bool SetHover(bool enable);
+
void SetSeer(WorldObject* target) { m_seer = target; }
void SetViewpoint(WorldObject* target, bool apply);
WorldObject* GetViewpoint() const;
@@ -2479,6 +2481,10 @@ class Player : public Unit, public GridObject<Player>
void AddWhisperWhiteList(uint64 guid) { WhisperList.push_back(guid); }
bool IsInWhisperWhiteList(uint64 guid);
+ #pragma region Player Movement
+
+ bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
+
//! Return collision height sent to client
float GetCollisionHeight(bool mounted)
{
@@ -2511,8 +2517,9 @@ class Player : public Unit, public GridObject<Player>
return modelData->CollisionHeight;
}
- //! TODO: Need a proper calculation for collision height when mounted
}
+ #pragma endregion Player Movement
+
protected:
// Gamemaster whisper whitelist
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 3411d285b1e..6d4963f1960 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3049,7 +3049,7 @@ bool Unit::isInAccessiblePlaceFor(Creature const* c) const
if (IsInWater())
return c->canSwim();
else
- return c->canWalk() || c->canFly();
+ return c->canWalk() || c->CanFly();
}
bool Unit::IsInWater() const
@@ -12597,15 +12597,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
return;
}
- data.append(GetPackGUID());
- data << uint32(0); // movement flags
- data << uint16(0); // unk flags
- data << uint32(getMSTime());
- data << float(GetPositionX());
- data << float(GetPositionY());
- data << float(GetPositionZ());
- data << float(GetOrientation());
- data << uint32(0); // fall time
+ BuildMovementPacket(&data);
data << float(GetSpeed(mtype));
SendMessageToSet(&data, true);
}
@@ -12664,14 +12656,6 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
}
}
-void Unit::SetHover(bool on)
-{
- if (on)
- CastSpell(this, 11010, true);
- else
- RemoveAurasDueToSpell(11010);
-}
-
void Unit::setDeathState(DeathState s)
{
// death state needs to be updated before RemoveAllAurasOnDeath() calls HandleChannelDeathItem(..) so that
@@ -17058,12 +17042,12 @@ void Unit::_ExitVehicle(Position const* exitPosition)
void Unit::BuildMovementPacket(ByteBuffer *data) const
{
- *data << uint32(GetUnitMovementFlags()); // movement flags
- *data << uint16(m_movementInfo.flags2); // 2.3.0
- *data << uint32(getMSTime()); // time
+ *data << uint32(GetUnitMovementFlags()); // movement flags
+ *data << uint16(GetExtraUnitMovementFlags()); // 2.3.0
+ *data << uint32(getMSTime()); // time / counter
*data << GetPositionX();
*data << GetPositionY();
- *data << GetPositionZ();
+ *data << GetPositionZMinusOffset();
*data << GetOrientation();
// 0x00000200
@@ -17108,18 +17092,12 @@ void Unit::BuildMovementPacket(ByteBuffer *data) const
*data << (float)m_movementInfo.splineElevation;
}
-void Unit::SetFlying(bool apply)
+void Unit::SetCanFly(bool apply)
{
if (apply)
- {
- SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
- AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING);
- }
+ AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
else
- {
- RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
- RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING);
- }
+ RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
}
void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/)
@@ -17165,11 +17143,20 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
return (relocated || turn);
}
+//! Only server-side orientation update, does not broadcast to client
void Unit::UpdateOrientation(float orientation)
{
SetOrientation(orientation);
if (IsVehicle())
- GetVehicleKit()->RelocatePassengers(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
+ GetVehicleKit()->RelocatePassengers(GetPositionX(), GetPositionY(), GetPositionZ(), orientation);
+}
+
+//! Only server-side height update, does not broadcast to client
+void Unit::UpdateHeight(float newZ)
+{
+ Relocate(GetPositionX(), GetPositionY(), newZ);
+ if (IsVehicle())
+ GetVehicleKit()->RelocatePassengers(GetPositionX(), GetPositionY(), newZ, GetOrientation());
}
void Unit::SendThreatListUpdate()
@@ -17457,15 +17444,65 @@ bool Unit::SetWalk(bool enable)
return true;
}
-bool Unit::SetLevitate(bool enable)
+bool Unit::SetDisableGravity(bool disable)
+{
+ if (disable == IsLevitating())
+ return false;
+
+ if (disable)
+ AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
+
+ return true;
+}
+
+bool Unit::SetHover(bool enable)
{
- if (enable == IsLevitating())
+ if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
return false;
if (enable)
- AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ {
+ //! No need to check height on ascent
+ AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
+ if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT))
+ UpdateHeight(GetPositionZ() + hh);
+ }
else
- RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ {
+ RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER);
+ if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT))
+ {
+ float newZ = GetPositionZ() - hh;
+ UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ);
+ UpdateHeight(newZ);
+ }
+ }
return true;
}
+
+void Unit::SendMovementHover()
+{
+ WorldPacket data(MSG_MOVE_HOVER, 64);
+ data.append(GetPackGUID());
+ BuildMovementPacket(&data);
+ SendMessageToSet(&data, true);
+}
+
+void Unit::SendMovementWaterWalking()
+{
+ WorldPacket data(MSG_MOVE_WATER_WALK, 64);
+ data.append(GetPackGUID());
+ BuildMovementPacket(&data);
+ SendMessageToSet(&data, true);
+}
+
+void Unit::SendMovementFeatherFall()
+{
+ WorldPacket data(MSG_MOVE_FEATHER_FALL, 64);
+ data.append(GetPackGUID());
+ BuildMovementPacket(&data);
+ SendMessageToSet(&data, true);
+}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index b07f2ae1c16..79ed0ec2f3d 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -184,10 +184,10 @@ enum UnitStandFlags
// byte flags value (UNIT_FIELD_BYTES_1, 3)
enum UnitBytes1_Flags
{
- UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01,
- UNIT_BYTE1_FLAG_UNK_2 = 0x02,
- UNIT_BYTE1_FLAG_UNK_3 = 0x04,
- UNIT_BYTE1_FLAG_ALL = 0xFF
+ UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01,
+ UNIT_BYTE1_FLAG_HOVER = 0x02,
+ UNIT_BYTE1_FLAG_UNK_3 = 0x04,
+ UNIT_BYTE1_FLAG_ALL = 0xFF
};
// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2
@@ -676,7 +676,7 @@ enum MovementFlags
MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
MOVEMENTFLAG_WALKING = 0x00000100, // Walking
MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures
- MOVEMENTFLAG_LEVITATING = 0x00000400,
+ MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000400, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible.
MOVEMENTFLAG_ROOT = 0x00000800, // Must not be set along with MOVEMENTFLAG_MASK_MOVING
MOVEMENTFLAG_JUMPING = 0x00001000,
MOVEMENTFLAG_FALLING = 0x00002000, // damage dealt on that type of falling
@@ -690,8 +690,8 @@ enum MovementFlags
MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
MOVEMENTFLAG_ASCENDING = 0x00400000, // press "space" when flying
MOVEMENTFLAG_DESCENDING = 0x00800000,
- MOVEMENTFLAG_CAN_FLY = 0x01000000, // can fly
- MOVEMENTFLAG_FLYING = 0x02000000, // hover
+ MOVEMENTFLAG_CAN_FLY = 0x01000000, // Appears when unit can fly AND also walk
+ MOVEMENTFLAG_FLYING = 0x02000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity
MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths
MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths
MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
@@ -706,6 +706,10 @@ enum MovementFlags
MOVEMENTFLAG_MASK_TURNING =
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT,
+
+ //! TODO if needed: add more flags to this masks that are exclusive to players
+ MOVEMENTFLAG_MASK_PLAYER_ONLY =
+ MOVEMENTFLAG_FLYING,
};
enum MovementFlags2
{
@@ -1615,6 +1619,7 @@ class Unit : public WorldObject
// returns true if unit's position really changed
bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
void UpdateOrientation(float orientation);
+ void UpdateHeight(float newZ);
void KnockbackFrom(float x, float y, float speedXY, float speedZ);
void JumpTo(float speedXY, float speedZ, bool forward = true);
@@ -1626,10 +1631,14 @@ class Unit : public WorldObject
//void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
void SendMonsterMoveTransport(Unit* vehicleOwner);
void SendMovementFlagUpdate();
- bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_LEVITATING);}
+ void SendMovementHover();
+ void SendMovementFeatherFall();
+ void SendMovementWaterWalking();
+ bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);}
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);}
virtual bool SetWalk(bool enable);
- virtual bool SetLevitate(bool enable);
+ virtual bool SetDisableGravity(bool disable);
+ bool SetHover(bool enable);
void SetInFront(Unit const* target);
void SetFacingTo(float ori);
@@ -2053,7 +2062,6 @@ class Unit : public WorldObject
void SetSpeed(UnitMoveType mtype, float rate, bool forced = false);
float m_TempSpeed;
- void SetHover(bool on);
bool isHover() const { return HasAuraType(SPELL_AURA_HOVER); }
float ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index, float value) const;
@@ -2077,7 +2085,7 @@ class Unit : public WorldObject
void AddUnitMovementFlag(uint32 f) { m_movementInfo.flags |= f; }
void RemoveUnitMovementFlag(uint32 f) { m_movementInfo.flags &= ~f; }
- uint32 HasUnitMovementFlag(uint32 f) const { return m_movementInfo.flags & f; }
+ bool HasUnitMovementFlag(uint32 f) const { return (m_movementInfo.flags & f) == f; }
uint32 GetUnitMovementFlags() const { return m_movementInfo.flags; }
void SetUnitMovementFlags(uint32 f) { m_movementInfo.flags = f; }
@@ -2087,6 +2095,15 @@ class Unit : public WorldObject
uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.flags2; }
void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.flags2 = f; }
+ float GetPositionZMinusOffset() const
+ {
+ float offset = 0.0f;
+ if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
+ offset = GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+
+ return GetPositionZ() - offset;
+ }
+
void SetControlled(bool apply, UnitState state);
void AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); }
@@ -2171,9 +2188,9 @@ class Unit : public WorldObject
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING); }
bool isTurning() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_TURNING); }
- bool canFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
- bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING); }
- void SetFlying(bool apply);
+ virtual bool CanFly() const = 0;
+ bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); }
+ void SetCanFly(bool apply);
void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 11977280177..f2b867b91ff 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -377,9 +377,9 @@ void ObjectMgr::LoadCreatureTemplates()
// 54 55 56 57 58 59 60 61 62 63 64 65 66
"spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
// 67 68 69 70 71 72 73 74 75 76 77
- "InhabitType, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, "
+ "InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, "
// 78 79 80 81 82 83
- "movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName "
+ " questItem6, movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName "
"FROM creature_template;");
if (!result)
@@ -463,20 +463,21 @@ void ObjectMgr::LoadCreatureTemplates()
creatureTemplate.AIName = fields[65].GetString();
creatureTemplate.MovementType = uint32(fields[66].GetUInt8());
creatureTemplate.InhabitType = uint32(fields[67].GetUInt8());
- creatureTemplate.ModHealth = fields[68].GetFloat();
- creatureTemplate.ModMana = fields[69].GetFloat();
- creatureTemplate.ModArmor = fields[70].GetFloat();
- creatureTemplate.RacialLeader = fields[71].GetBool();
+ creatureTemplate.HoverHeight = fields[68].GetFloat();
+ creatureTemplate.ModHealth = fields[69].GetFloat();
+ creatureTemplate.ModMana = fields[70].GetFloat();
+ creatureTemplate.ModArmor = fields[71].GetFloat();
+ creatureTemplate.RacialLeader = fields[72].GetBool();
for (uint8 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
- creatureTemplate.questItems[i] = fields[72 + i].GetUInt32();
+ creatureTemplate.questItems[i] = fields[73 + i].GetUInt32();
- creatureTemplate.movementId = fields[78].GetUInt32();
- creatureTemplate.RegenHealth = fields[79].GetBool();
- creatureTemplate.equipmentId = fields[80].GetUInt32();
- creatureTemplate.MechanicImmuneMask = fields[81].GetUInt32();
- creatureTemplate.flags_extra = fields[82].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[83].GetCString());
+ creatureTemplate.movementId = fields[79].GetUInt32();
+ creatureTemplate.RegenHealth = fields[80].GetBool();
+ creatureTemplate.equipmentId = fields[81].GetUInt32();
+ creatureTemplate.MechanicImmuneMask = fields[82].GetUInt32();
+ creatureTemplate.flags_extra = fields[83].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[84].GetCString());
++count;
}
@@ -494,7 +495,7 @@ void ObjectMgr::LoadCreatureTemplateAddons()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6
+ // 0 1 2 3 4 5 6
QueryResult result = WorldDatabase.Query("SELECT entry, path_id, mount, bytes1, bytes2, emote, auras FROM creature_template_addon");
if (!result)
@@ -549,7 +550,10 @@ void ObjectMgr::LoadCreatureTemplateAddons()
}
if (!sEmotesStore.LookupEntry(creatureAddon.emote))
- sLog->outErrorDb("Creature (Entry: %u) has invalid emote (%u) defined in `creature_template_addon`.", entry, creatureAddon.emote);
+ {
+ sLog->outErrorDb("Creature (Entry: %u) has invalid emote (%u) defined in `creature_addon`.", entry, creatureAddon.emote);
+ creatureAddon.emote = 0;
+ }
++count;
}
@@ -793,6 +797,12 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->InhabitType = INHABIT_ANYWHERE;
}
+ if (cInfo->HoverHeight < 0.0f)
+ {
+ sLog->outErrorDb("Creature (Entry: %u) has wrong value (%f) in `HoverHeight`", cInfo->Entry, cInfo->HoverHeight);
+ const_cast<CreatureTemplate*>(cInfo)->HoverHeight = 1.0f;
+ }
+
if (cInfo->VehicleId)
{
VehicleEntry const* vehId = sVehicleStore.LookupEntry(cInfo->VehicleId);
@@ -862,7 +872,7 @@ void ObjectMgr::LoadCreatureAddons()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6
+ // 0 1 2 3 4 5 6
QueryResult result = WorldDatabase.Query("SELECT guid, path_id, mount, bytes1, bytes2, emote, auras FROM creature_addon");
if (!result)
@@ -899,7 +909,7 @@ void ObjectMgr::LoadCreatureAddons()
creatureAddon.bytes1 = fields[3].GetUInt32();
creatureAddon.bytes2 = fields[4].GetUInt32();
creatureAddon.emote = fields[5].GetUInt32();
-
+
Tokens tokens(fields[6].GetString(), ' ');
uint8 i = 0;
creatureAddon.auras.resize(tokens.size());
@@ -914,7 +924,7 @@ void ObjectMgr::LoadCreatureAddons()
creatureAddon.auras[i++] = uint32(atol(*itr));
}
- if (creatureAddon.mount)
+ if (creatureAddon.mount)
{
if (!sCreatureDisplayInfoStore.LookupEntry(creatureAddon.mount))
{
@@ -924,7 +934,10 @@ void ObjectMgr::LoadCreatureAddons()
}
if (!sEmotesStore.LookupEntry(creatureAddon.emote))
+ {
sLog->outErrorDb("Creature (GUID: %u) has invalid emote (%u) defined in `creature_addon`.", guid, creatureAddon.emote);
+ creatureAddon.emote = 0;
+ }
++count;
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 7f27a474534..7403a86a47f 100755
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -702,6 +702,12 @@ void Map::PlayerRelocation(Player* player, float x, float y, float z, float orie
Cell old_cell(player->GetPositionX(), player->GetPositionY());
Cell new_cell(x, y);
+ //! If hovering, always increase our server-side Z position
+ //! Client automatically projects correct position based on Z coord sent in monster move
+ //! and UNIT_FIELD_HOVERHEIGHT sent in object updates
+ if (player->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
+ z += player->GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+
player->Relocate(x, y, z, orientation);
if (player->IsVehicle())
player->GetVehicleKit()->RelocatePassengers(x, y, z, orientation);
@@ -731,6 +737,12 @@ void Map::CreatureRelocation(Creature* creature, float x, float y, float z, floa
if (!respawnRelocationOnFail && !getNGrid(new_cell.GridX(), new_cell.GridY()))
return;
+ //! If hovering, always increase our server-side Z position
+ //! Client automatically projects correct position based on Z coord sent in monster move
+ //! and UNIT_FIELD_HOVERHEIGHT sent in object updates
+ if (creature->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
+ z += creature->GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+
// delay creature move for grid/cell to grid/cell moves
if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
{
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
index fddfe5f8fb0..91b50344ccb 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -57,7 +57,7 @@ bool PointMovementGenerator<T>::Update(T &unit, const uint32 & /*diff*/)
}
template<class T>
-void PointMovementGenerator<T>:: Finalize(T &unit)
+void PointMovementGenerator<T>::Finalize(T &unit)
{
unit.ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index b65fa210723..e520253eb46 100755
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -42,7 +42,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
// For 2D/3D system selection
//bool is_land_ok = creature.CanWalk(); // not used?
//bool is_water_ok = creature.CanSwim(); // not used?
- bool is_air_ok = creature.canFly();
+ bool is_air_ok = creature.CanFly();
const float angle = float(rand_norm()) * static_cast<float>(M_PI*2.0f);
const float range = float(rand_norm()) * wander_distance;
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp
index b5ae923dc32..f5d2ae59329 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.cpp
+++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp
@@ -100,7 +100,7 @@ namespace Movement
{
// mix existing state into new
args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);
- args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_FLYING|MOVEMENTFLAG_LEVITATING));
+ args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_DISABLE_GRAVITY));
}
void MoveSplineInit::SetFacing(const Unit * target)
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index e5b5b20dcfa..c6ccfaa8004 100755
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -270,10 +270,10 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
+ /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
+ /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck },
- /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
+ /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 56bca65788c..387f76bbc7f 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2845,7 +2845,7 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode
}
if (target->GetTypeId() == TYPEID_UNIT)
- target->SetFlying(apply);
+ target->SetCanFly(apply);
if (Player* player = target->m_movedPlayer)
{
@@ -2856,7 +2856,7 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode
else
data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
data.append(target->GetPackGUID());
- data << uint32(0); // unk
+ data << uint32(0); // movement counter
player->SendDirectMessage(&data);
}
}
@@ -2875,14 +2875,16 @@ void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode,
return;
}
- WorldPacket data;
if (apply)
- data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
+ {
+ target->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ target->SendMovementWaterWalking();
+ }
else
- data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
- data.append(target->GetPackGUID());
- data << uint32(0);
- target->SendMessageToSet(&data, true);
+ {
+ target->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ target->SendMovementFlagUpdate();
+ }
}
void AuraEffect::HandleAuraFeatherFall(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -2899,14 +2901,16 @@ void AuraEffect::HandleAuraFeatherFall(AuraApplication const* aurApp, uint8 mode
return;
}
- WorldPacket data;
if (apply)
- data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
+ {
+ target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ target->SendMovementFeatherFall();
+ }
else
- data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
- data.append(target->GetPackGUID());
- data << uint32(0);
- target->SendMessageToSet(&data, true);
+ {
+ target->RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ target->SendMovementFlagUpdate();
+ }
// start fall from current height
if (!apply && target->GetTypeId() == TYPEID_PLAYER)
@@ -2927,14 +2931,11 @@ void AuraEffect::HandleAuraHover(AuraApplication const* aurApp, uint8 mode, bool
return;
}
- WorldPacket data;
+ target->SetHover(apply); //! Sets movementflags
if (apply)
- data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
+ target->SendMovementHover();
else
- data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
- data.append(target->GetPackGUID());
- data << uint32(0);
- target->SendMessageToSet(&data, true);
+ target->SendMovementFlagUpdate();
}
void AuraEffect::HandleWaterBreathing(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const