diff options
| author | Machiavelli <machiavelli.trinity@gmail.com> | 2012-03-12 00:45:58 +0100 |
|---|---|---|
| committer | Machiavelli <machiavelli.trinity@gmail.com> | 2012-03-12 00:53:45 +0100 |
| commit | 03a24a84e493f914d46488e8c4ae9e9d663c21d7 (patch) | |
| tree | 6299dee664c6a97fa9fbbb3482aa7a97d6e7d0dd /src/server/game | |
| parent | 5ca27f40cced56414900aaaf656b45353a41aaf8 (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')
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 |
