aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2017-11-23 18:12:44 +0100
committerShauren <shauren.trinity@gmail.com>2021-08-24 12:44:38 +0200
commit2e2b29861878fda2d27156c71a1d8ed7dbe0b4fe (patch)
tree19cd6b07b575781b68e42284dfe5cd7a1a59f825
parent028f9b47807e2e2527c2c183105a033a6129b4d3 (diff)
Core/Movement: Fixed creature hover
Closes #15177 (cherry picked from commit 2baa81065ba27f0a6d278a8dd8a79b7c831e0a2b)
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp11
-rw-r--r--src/server/game/Entities/Object/Object.cpp80
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp15
-rw-r--r--src/server/game/Entities/Unit/Unit.h7
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp5
-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
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp13
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp2
10 files changed, 59 insertions, 93 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 40e26027ba0..329ec612800 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -446,6 +446,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);
}
@@ -1151,11 +1152,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, Posit
LoadCreaturesAddon();
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
- if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- {
- //! Relocate again with updated Z coord
- m_positionZ += m_unitData->HoverHeight;
- }
+ m_positionZ += GetHoverOffset();
LastUsedScriptID = GetScriptId();
@@ -1769,7 +1766,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;
@@ -3112,7 +3109,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 e4e13390c78..985d079826c 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1303,7 +1303,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
@@ -1312,66 +1314,44 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
if (GetTransport())
return;
- switch (GetTypeId())
+ if (Unit const* unit = ToUnit())
{
- case TYPEID_UNIT:
- {
- // 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:
+ if (!unit->CanFly())
{
- // 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
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 2115fc96aa3..20a398649bd 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -566,7 +566,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) + GetTotalAuraModifier(SPELL_AURA_MOD_AUTOATTACK_RANGE);
@@ -11574,15 +11574,6 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
}
}
-float Unit::GetPositionZMinusOffset() const
-{
- float offset = 0.0f;
- if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- offset = m_unitData->HoverHeight;
-
- return GetPositionZ() - offset;
-}
-
void Unit::SetControlled(bool apply, UnitState state)
{
if (apply)
@@ -13294,7 +13285,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 (GetTransport())
init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
init.SetFacing(ori);
@@ -13309,7 +13300,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 75d7e60897e..da63f0558c7 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1768,8 +1768,6 @@ class TC_GAME_API Unit : public WorldObject
void SetExtraUnitMovementFlags(uint32 f) { m_movementInfo.SetExtraMovementFlags(f); }
bool IsSplineEnabled() const;
- float GetPositionZMinusOffset() const;
-
void SetControlled(bool apply, UnitState state);
void ApplyControlStatesIfNeeded();
@@ -1828,6 +1826,11 @@ class TC_GAME_API Unit : public WorldObject
bool IsFalling() const;
virtual bool CanSwim() const;
+ float GetHoverOffset() const
+ {
+ return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? *m_unitData->HoverHeight : 0.0f;
+ }
+
void RewardRage(uint32 baseRage);
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 9fe6808defb..ac873eb6d01 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -90,10 +90,7 @@ void WorldSession::HandleMoveWorldportAck()
return;
}
- float z = loc.GetPositionZ();
- if (GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- z += GetPlayer()->m_unitData->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 10a1eb2e6ce..fc2c950b57c 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1138,12 +1138,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 HoverHeight sent in object updates
- if (player->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- z += player->m_unitData->HoverHeight;
-
player->Relocate(x, y, z, orientation);
if (player->IsVehicle())
player->GetVehicleKit()->RelocatePassengers();
@@ -1173,12 +1167,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 HoverHeight sent in object updates
- if (creature->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- z += creature->m_unitData->HoverHeight;
-
Cell old_cell = creature->GetCurrentCell();
// 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 7df25b72817..d7be55b03e7 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -346,7 +346,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);
@@ -510,7 +510,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);
}
@@ -615,7 +615,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 191877289c8..df1adb19684 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -51,6 +51,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 0465c958990..102a4728fc9 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -124,29 +124,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
{
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 250e2f64cac..062b5c4a003 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -613,7 +613,7 @@ class boss_mimiron : public CreatureScript
{
if (Creature* aerial = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AERIAL_COMMAND_UNIT)))
{
- aerial->GetMotionMaster()->MoveLand(0, (aerial->GetPositionX(), aerial->GetPositionY(), aerial->GetPositionZMinusOffset()));
+ aerial->GetMotionMaster()->MoveLand(0, (aerial->GetPositionX(), aerial->GetPositionY(), aerial->GetPositionZ()));
aerial->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false);
aerial->CastSpell(vx001, SPELL_MOUNT_VX_001);
aerial->CastSpell(aerial, SPELL_HALF_HEAL);