Core/Movement: Fixed creature hover

Closes #15177

(cherry picked from commit 2baa81065b)
This commit is contained in:
Shauren
2017-11-23 18:12:44 +01:00
parent 028f9b4780
commit 2e2b298618
10 changed files with 59 additions and 93 deletions

View File

@@ -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())
{

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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); }

View File

@@ -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());

View File

@@ -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))

View File

@@ -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);

View File

@@ -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();

View File

@@ -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
{

View File

@@ -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);