aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp11
-rw-r--r--src/server/game/Entities/Object/Object.cpp88
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp17
-rw-r--r--src/server/game/Entities/Unit/Unit.h7
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp4
-rw-r--r--src/server/game/Maps/Map.cpp12
-rw-r--r--src/server/game/Movement/MotionMaster.cpp6
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp13
9 files changed, 60 insertions, 99 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 3a061c816bc..9cdef4266d4 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -404,6 +404,7 @@ void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers)
transport->CalculatePassengerPosition(x, y, z, &o);
}
+ UpdateAllowedPositionZ(x, y, z);
SetHomePosition(x, y, z, o);
GetMap()->CreatureRelocation(this, x, y, z, o);
}
@@ -1096,11 +1097,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
}
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
- if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- {
- //! Relocate again with updated Z coord
- m_positionZ += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
- }
+ m_positionZ += GetHoverOffset();
LastUsedScriptID = GetScriptId();
@@ -1631,7 +1628,7 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
return false;
//We should set first home position, because then AI calls home movement
- SetHomePosition(data->spawnPoint);
+ SetHomePosition(*this);
m_deathState = ALIVE;
@@ -2975,7 +2972,7 @@ void Creature::UpdateMovementFlags()
// 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(GetPositionZMinusOffset(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
+ bool isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
if (GetCreatureTemplate()->InhabitType & INHABIT_AIR && isInAir && !IsFalling())
{
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 61d2da10c88..4f124f96e15 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -390,9 +390,6 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
*data << object->GetPositionX();
*data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
*data << object->GetPositionZ();
if (transport)
@@ -405,9 +402,6 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
*data << object->GetPositionX();
*data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
*data << object->GetPositionZ();
}
@@ -1463,7 +1457,9 @@ Position WorldObject::GetRandomPoint(Position const& srcPos, float distance) con
void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
{
- z = GetMapHeight(x, y, z);
+ float new_z = GetMapHeight(x, y, z);
+ if (new_z > INVALID_HEIGHT)
+ z = new_z + (isType(TYPEMASK_UNIT) ? static_cast<Unit const*>(this)->GetHoverOffset() : 0.0f);
}
void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
@@ -1472,66 +1468,44 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
if (GetTransport())
return;
- switch (GetTypeId())
+ if (Unit const* unit = ToUnit())
{
- case TYPEID_UNIT:
+ if (!unit->CanFly())
{
- // 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())
- {
- bool canSwim = ToCreature()->CanSwim();
- float ground_z = z;
- float max_z = canSwim
- ? GetMapWaterOrGroundLevel(x, y, z, &ground_z)
- : (ground_z = GetMapHeight(x, y, z));
- if (max_z > INVALID_HEIGHT)
- {
- if (z > max_z)
- z = max_z;
- else if (z < ground_z)
- z = ground_z;
- }
- }
- else
- {
- float ground_z = GetMapHeight(x, y, z);
- if (std::fabs(z - ground_z) < GetCollisionHeight())
- z = ground_z;
- }
- break;
- }
- case TYPEID_PLAYER:
- {
- // for server controlled moves playr work same as creature (but it can always swim)
- if (!ToPlayer()->CanFly())
- {
- float ground_z = z;
- float max_z = GetMapWaterOrGroundLevel(x, y, z, &ground_z);
- if (max_z > INVALID_HEIGHT)
- {
- if (z > max_z)
- z = max_z;
- else if (z < ground_z)
- z = ground_z;
- }
- }
+ bool canSwim = unit->CanSwim();
+ float ground_z = z;
+ float max_z;
+ if (canSwim)
+ max_z = GetMapWaterOrGroundLevel(x, y, z, &ground_z);
else
+ max_z = ground_z = GetMapHeight(x, y, z);
+
+ if (max_z > INVALID_HEIGHT)
{
- float ground_z = GetMapHeight(x, y, z);
- if (std::fabs(z - ground_z) < GetCollisionHeight())
+ // hovering units cannot go below their hover height
+ float hoverOffset = unit->GetHoverOffset();
+ max_z += hoverOffset;
+ ground_z += hoverOffset;
+
+ if (z > max_z)
+ z = max_z;
+ else if (z < ground_z)
z = ground_z;
}
- break;
}
- default:
+ else
{
- float ground_z = GetMapHeight(x, y, z);
- if (ground_z > INVALID_HEIGHT)
+ float ground_z = GetMapHeight(x, y, z) + unit->GetHoverOffset();
+ if (z < ground_z)
z = ground_z;
- break;
}
}
+ else
+ {
+ float ground_z = GetMapHeight(x, y, z);
+ if (ground_z > INVALID_HEIGHT)
+ z = ground_z;
+ }
}
float WorldObject::GetGridActivationRange() const
@@ -2322,7 +2296,7 @@ float WorldObject::SelectBestZForDestination(float x, float y, float z, bool exc
if (Unit const* unit = ToUnit())
{
float const ground = GetFloorZ();
- bool const isInAir = (G3D::fuzzyGt(unit->GetPositionZMinusOffset(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(unit->GetPositionZMinusOffset(), ground - GROUND_HEIGHT_TOLERANCE));
+ bool const isInAir = (G3D::fuzzyGt(unit->GetPositionZ(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(unit->GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE));
if (unit->IsFlying() && isInAir)
return z;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e811a87e227..c55e6f49459 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -545,7 +545,7 @@ bool Unit::IsWithinMeleeRange(Unit const* obj) const
float dx = GetPositionX() - obj->GetPositionX();
float dy = GetPositionY() - obj->GetPositionY();
- float dz = GetPositionZMinusOffset() - obj->GetPositionZMinusOffset();
+ float dz = GetPositionZ() - obj->GetPositionZ();
float distsq = dx*dx + dy*dy + dz*dz;
float maxdist = GetMeleeRange(obj);
@@ -11979,15 +11979,6 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
}
}
-float Unit::GetPositionZMinusOffset() const
-{
- float offset = 0.0f;
- if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- offset = GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
-
- return GetPositionZ() - offset;
-}
-
void Unit::SetControlled(bool apply, UnitState state)
{
if (apply)
@@ -13549,7 +13540,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
void Unit::BuildMovementPacket(ByteBuffer *data) const
{
- Unit::BuildMovementPacket(Position(GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation()), m_movementInfo.transport.pos, m_movementInfo, data);
+ Unit::BuildMovementPacket(*this, m_movementInfo.transport.pos, m_movementInfo, data);
}
void Unit::BuildMovementPacket(Position const& pos, Position const& transportPos, MovementInfo const& movementInfo, ByteBuffer* data)
@@ -13959,7 +13950,7 @@ void Unit::SetFacingTo(float ori, bool force)
return;
Movement::MoveSplineInit init(this);
- init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), false);
+ init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && GetTransGUID())
init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
init.SetFacing(ori);
@@ -13974,7 +13965,7 @@ void Unit::SetFacingToObject(WorldObject const* object, bool force)
/// @todo figure out under what conditions creature will move towards object instead of facing it where it currently is.
Movement::MoveSplineInit init(this);
- init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), false);
+ init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
init.SetFacing(GetAngle(object)); // when on transport, GetAngle will still return global coordinates (and angle) that needs transforming
init.Launch();
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index d464861f2ea..9186551a23d 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1596,8 +1596,6 @@ class TC_GAME_API Unit : public WorldObject
uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.flags2; }
void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.flags2 = f; }
- float GetPositionZMinusOffset() const;
-
void SetControlled(bool apply, UnitState state);
void ApplyControlStatesIfNeeded();
@@ -1675,6 +1673,11 @@ class TC_GAME_API Unit : public WorldObject
bool IsFalling() const;
virtual bool CanSwim() const;
+ float GetHoverOffset() const
+ {
+ return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f;
+ }
+
void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);
virtual float GetFollowAngle() const { return static_cast<float>(M_PI/2); }
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 5f641d6951d..720733249e3 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -86,9 +86,7 @@ void WorldSession::HandleMoveWorldportAck()
return;
}
- float z = loc.GetPositionZ();
- if (GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- z += GetPlayer()->GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+ float z = loc.GetPositionZ() + GetPlayer()->GetHoverOffset();
GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 589dce1ed32..347882d34c6 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1029,12 +1029,6 @@ 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();
@@ -1065,12 +1059,6 @@ 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/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 131c96cce22..c10870703fa 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -356,7 +356,7 @@ void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance)
{
// we are already close enough. We just need to turn toward the target without changing position.
Movement::MoveSplineInit init(_owner);
- init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZMinusOffset());
+ init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ());
init.SetFacing(target);
init.Launch();
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
@@ -499,7 +499,7 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool
if (_owner->IsFlying())
point.z = z;
else
- point.z = _owner->GetMapHeight(point.x, point.y, z);
+ point.z = _owner->GetMapHeight(point.x, point.y, z) + _owner->GetHoverOffset();
init.Path().push_back(point);
}
@@ -600,7 +600,7 @@ void MotionMaster::MoveFall(uint32 id /*=0*/)
}
Movement::MoveSplineInit init(_owner);
- init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz, false);
+ init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz + _owner->GetHoverOffset(), false);
init.SetFall();
init.Launch();
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index 809c8b8bccd..dd72838c247 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -52,6 +52,7 @@ void HomeMovementGenerator<Creature>::SetTargetLocation(Creature* owner)
owner->GetHomePosition(x, y, z, o);
init.SetFacing(o);
}
+ owner->UpdateAllowedPositionZ(x, y, z);
init.MoveTo(x, y, z);
init.SetWalk(false);
init.Launch();
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index de0a16e1910..4de930e56b6 100644
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -125,29 +125,38 @@ void TargetedMovementGenerator<T, D>::SetTargetLocation(T* owner, bool updateDes
float x, y, z;
if (updateDestination || !_path)
{
+ float size = owner->GetCombatReach();
+ float hoverDiff = owner->GetHoverOffset() - GetTarget()->GetHoverOffset();
if (!_offset)
{
if (GetTarget()->IsWithinDistInMap(owner, CONTACT_DISTANCE))
return;
- GetTarget()->GetContactPoint(owner, x, y, z);
+ if (hoverDiff)
+ size = size > hoverDiff ? std::sqrt(size * size - hoverDiff * hoverDiff) : 0.0f;
+
+ GetTarget()->GetNearPoint(owner, x, y, z, size, CONTACT_DISTANCE, GetTarget()->GetAngle(owner));
}
else
{
float distance = _offset + 1.0f;
- float size = owner->GetCombatReach();
if (owner->IsPet() && GetTarget()->GetTypeId() == TYPEID_PLAYER)
{
distance = 1.0f;
size = 1.0f;
}
+ else if (hoverDiff)
+ size = size > hoverDiff ? std::sqrt(size * size - hoverDiff * hoverDiff) : 0.0f;
if (GetTarget()->IsWithinDistInMap(owner, distance))
return;
GetTarget()->GetClosePoint(x, y, z, size, _offset, _angle);
}
+
+ if (owner->IsHovering())
+ owner->UpdateAllowedPositionZ(x, y, z);
}
else
{