mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-13 03:32:28 -04:00
Core/Movement: Fixed creature hover
Closes #15177
(cherry picked from commit 2baa81065b)
This commit is contained in:
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
case TYPEID_PLAYER:
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMapHeight(x, y, z);
|
||||
if (std::fabs(z - ground_z) < GetCollisionHeight())
|
||||
z = ground_z;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user