Core/Movement: first part of porting the new creature hover handling

This commit is contained in:
Ovahlord committed 2019-02-18 01:52:15 +01:00
1 parent 50a91bd590
commit eb15db4522
25 files changed
+144 -167

No files matched your search

@@ -358,6 +358,7 @@ void Creature::RemoveCorpse(bool setSpawnTime)
transport->CalculatePassengerPosition(x, y, z, &o);
}
UpdateAllowedPositionZ(x, y, z);
SetHomePosition(x, y, z, o);
GetMap()->CreatureRelocation(this, x, y, z, o);
}
@@ -1030,11 +1031,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 /*phaseMask*
LoadCreaturesAddon();
//! 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();
@@ -1504,7 +1501,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;
@@ -1836,7 +1833,10 @@ void Creature::setDeathState(DeathState s)
if (m_formation && m_formation->getLeader() == this)
m_formation->FormationReset(true);
if ((CanFly() || IsFlying()) && !IsUnderWater())
bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater();
SetHover(false);
if (needsFalling)
GetMotionMaster()->MoveFall();
Unit::setDeathState(CORPSE);
@@ -2867,7 +2867,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 - 0.05f)); // 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())
{
+1 -1
View File
@@ -93,7 +93,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool IsTrigger() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) != 0; }
bool IsGuard() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GUARD) != 0; }
bool CanWalk() const { return (GetCreatureTemplate()->InhabitType & INHABIT_GROUND) != 0; }
bool CanSwim() const { return (GetCreatureTemplate()->InhabitType & INHABIT_WATER) != 0 || IsPet(); }
bool CanSwim() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_WATER) != 0 || IsPet(); }
bool CanFly() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_AIR) != 0; }
bool IsDungeonBoss() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS) != 0; }
bool IsAffectedByDiminishingReturns() const override { return Unit::IsAffectedByDiminishingReturns() || (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH) != 0; }
+60 -60
View File
@@ -507,7 +507,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
if (hasSpline)
Movement::PacketBuilder::WriteCreateData(*self->movespline, *data);
*data << float(self->GetPositionZMinusOffset());
*data << float(self->GetPositionZ());
data->WriteByteSeq(guid[5]);
if (self->m_movementInfo.transport.guid)
@@ -1646,7 +1646,9 @@ Position WorldObject::GetRandomPoint(const Position &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
@@ -1655,66 +1657,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 (z < ground_z)
// 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 (z < ground_z)
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
@@ -2397,18 +2377,38 @@ void WorldObject::GetPlayerListInGrid(Container& playerContainer, float maxSearc
Cell::VisitWorldObjects(this, searcher, maxSearchRange);
}
void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle) const
void WorldObject::GetNearPoint2D(WorldObject const* searcher, float &x, float &y, float distance2d, float absAngle) const
{
x = GetPositionX() + (GetCombatReach() + distance2d) * std::cos(absAngle);
y = GetPositionY() + (GetCombatReach() + distance2d) * std::sin(absAngle);
float effectiveReach = GetCombatReach();
if (searcher)
{
effectiveReach += searcher->GetCombatReach();
if (this != searcher)
{
float myHover = 0.0f, searcherHover = 0.0f;
if (Unit const* unit = ToUnit())
myHover = unit->GetHoverOffset();
if (Unit const* searchUnit = searcher->ToUnit())
searcherHover = searchUnit->GetHoverOffset();
float hoverDelta = myHover - searcherHover;
if (hoverDelta != 0.0f)
effectiveReach = std::sqrt(effectiveReach * effectiveReach - hoverDelta * hoverDelta);
}
}
x = GetPositionX() + (effectiveReach + distance2d) * std::cos(absAngle);
y = GetPositionY() + (effectiveReach + distance2d) * std::sin(absAngle);
Trinity::NormalizeMapCoord(x);
Trinity::NormalizeMapCoord(y);
}
void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle) const
void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
{
GetNearPoint2D(x, y, distance2d+searcher_size, absAngle);
GetNearPoint2D(searcher, x, y, distance2d, absAngle);
z = GetPositionZ();
// Should "searcher" be used instead of "this" when updating z coordinate ?
UpdateAllowedPositionZ(x, y, z);
@@ -2429,7 +2429,7 @@ void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float &x, float
// loop in a circle to look for a point in LoS using small steps
for (float angle = float(M_PI) / 8; angle < float(M_PI) * 2; angle += float(M_PI) / 8)
{
GetNearPoint2D(x, y, distance2d + searcher_size, absAngle + angle);
GetNearPoint2D(searcher, x, y, distance2d, absAngle + angle);
z = GetPositionZ();
UpdateAllowedPositionZ(x, y, z);
if (IsWithinLOS(x, y, z))
@@ -2442,10 +2442,10 @@ void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float &x, float
z = first_z;
}
void WorldObject::GetClosePoint(float &x, float &y, float &z, float size, float distance2d /*= 0*/, float angle /*= 0*/) const
void WorldObject::GetClosePoint(float &x, float &y, float &z, float size, float distance2d /*= 0*/, float relAngle /*= 0*/) const
{
// angle calculated from current orientation
GetNearPoint(nullptr, x, y, z, size, distance2d, GetOrientation() + angle);
GetNearPoint(nullptr, x, y, z, distance2d + size, GetOrientation() + relAngle);
}
Position WorldObject::GetNearPosition(float dist, float angle)
@@ -2472,7 +2472,7 @@ Position WorldObject::GetRandomNearPosition(float radius)
void WorldObject::GetContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d /*= CONTACT_DISTANCE*/) const
{
// angle to face `obj` to `this` using distance includes size of `obj`
GetNearPoint(obj, x, y, z, obj->GetCombatReach(), distance2d, GetAngle(obj));
GetNearPoint(obj, x, y, z, distance2d, GetAngle(obj));
}
void WorldObject::MovePosition(Position &pos, float dist, float angle)
+2 -2
View File
@@ -282,8 +282,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
void AddToWorld() override;
void RemoveFromWorld() override;
void GetNearPoint2D(float &x, float &y, float distance, float absAngle) const;
void GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle) const;
void GetNearPoint2D(WorldObject const* searcher, float &x, float &y, float distance, float absAngle) const;
void GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float distance2d, float absAngle) const;
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d = 0, float angle = 0) const;
void MovePosition(Position &pos, float dist, float angle);
Position GetNearPosition(float dist, float angle);
+22 -33
View File
@@ -631,12 +631,8 @@ bool Unit::IsWithinMeleeRangeAt(Position const& pos, Unit const* obj) const
float dx = pos.GetPositionX() - obj->GetPositionX();
float dy = pos.GetPositionY() - obj->GetPositionY();
float dz = GetPositionZ() - obj->GetPositionZ();
float z = pos.GetPositionZ();
if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
z -= GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
float dz = z - obj->GetPositionZMinusOffset();
float distsq = dx*dx + dy*dy + dz*dz;
float maxdist = GetMeleeRange(obj);
@@ -660,20 +656,7 @@ bool Unit::IsWithinBoundaryRadius(const Unit* obj) const
return IsInDist(obj, objBoundaryRadius);
}
void Unit::GetRandomContactPoint(Unit const* obj, float &x, float &y, float &z, float distance2dMin, float distance2dMax) const
{
float combat_reach = GetCombatReach();
if (combat_reach < 0.1f) // sometimes bugged for players
combat_reach = DEFAULT_COMBAT_REACH;
uint32 attacker_number = getAttackers().size();
if (attacker_number > 0)
--attacker_number;
GetNearPoint(obj, x, y, z, obj->GetCombatReach(), distance2dMin+(distance2dMax-distance2dMin) * (float)rand_norm()
, GetAngle(obj) + (attacker_number ? (static_cast<float>(M_PI/2) - static_cast<float>(M_PI) * (float)rand_norm()) * float(attacker_number) / combat_reach * 0.3f : 0));
}
AuraApplication * Unit::GetVisibleAura(uint8 slot) const
AuraApplication* Unit::GetVisibleAura(uint8 slot) const
{
VisibleAuraMap::const_iterator itr = m_visibleAuras.find(slot);
if (itr != m_visibleAuras.end())
@@ -11897,15 +11880,6 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
}
}
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)
@@ -13562,6 +13536,20 @@ bool Unit::IsFalling() const
return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR) || movespline->isFalling();
}
bool Unit::CanSwim() const
{
// Mirror client behavior, if this method returns false then client will not use swimming animation and for players will apply gravity as if there was no water
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CANNOT_SWIM))
return false;
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) // is player
return true;
if (HasFlag(UNIT_FIELD_FLAGS_2, 0x1000000))
return false;
if (IsPet() && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT))
return true;
return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME | UNIT_FLAG_UNK_15);
}
void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/)
{
DisableSpline();
@@ -13803,7 +13791,7 @@ void Unit::SendTeleportPacket(Position const& pos)
// MSG_MOVE_TELEPORT is sent to self in order to trigger MSG_MOVE_TELEPORT_ACK and update the position server side
// This oldPos actually contains the destination position if the Unit is a Player.
Position oldPos = {GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation()};
Position oldPos = {GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()};
if (GetTypeId() == TYPEID_UNIT)
Relocate(&pos); // Relocate the unit to its new position in order to build the packets correctly.
@@ -13861,7 +13849,7 @@ void Unit::SendTeleportPacket(Position const& pos)
data2.WriteByteSeq(guid[4]);
data2 << float(GetOrientation());
data2.WriteByteSeq(guid[7]);
data2 << float(GetPositionZMinusOffset());
data2 << float(GetPositionZ());
data2.WriteByteSeq(guid[0]);
data2.WriteByteSeq(guid[6]);
data2 << float(GetPositionY());
@@ -14215,7 +14203,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);
@@ -14230,7 +14218,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();
}
@@ -14409,7 +14397,8 @@ bool Unit::SetHover(bool enable, bool packetOnly /*= false*/)
else
{
RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER);
if (hoverHeight)
//! Dying creatures will MoveFall from setDeathState
if (hoverHeight && (!isDying() || GetTypeId() != TYPEID_UNIT))
{
float newZ = GetPositionZ() - hoverHeight;
UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ);
+6 -3
View File
@@ -1011,7 +1011,6 @@ class TC_GAME_API Unit : public WorldObject
bool IsWithinMeleeRangeAt(Position const& pos, Unit const* obj) const;
bool IsWithinBoundaryRadius(const Unit* obj) const;
float GetMeleeRange(Unit const* target) const;
void GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, float distance2dMin, float distance2dMax) const;
uint32 m_extraAttacks;
bool m_canDualWield;
@@ -1787,8 +1786,6 @@ class TC_GAME_API Unit : public WorldObject
void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.SetExtraMovementFlags(f); }
bool IsSplineEnabled() const;
float GetPositionZMinusOffset() const;
void SetControlled(bool apply, UnitState state);
void ApplyControlStatesIfNeeded();
@@ -1859,6 +1856,12 @@ class TC_GAME_API Unit : public WorldObject
virtual bool CanFly() const = 0;
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); }
bool IsFalling() const;
virtual bool CanSwim() const;
float GetHoverOffset() const
{
return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f;
}
void RewardRage(uint32 baseRage, bool attacker);
+1 -3
View File
@@ -90,11 +90,9 @@ void WorldSession::HandleMoveWorldportAckOpcode()
float x = loc.GetPositionX();
float y = loc.GetPositionY();
float z = loc.GetPositionZ();
float o = loc.GetOrientation();
float z = loc.GetPositionZ() + GetPlayer()->GetHoverOffset();
if (GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
z += GetPlayer()->GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
GetPlayer()->Relocate(x, y, z, o);
GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
-12
View File
@@ -1117,12 +1117,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();
@@ -1153,12 +1147,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))
{
+5 -5
View File
@@ -337,7 +337,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);
@@ -417,7 +417,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
float dist = 2 * moveTimeHalf * speedXY;
float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ);
_owner->GetNearPoint(_owner, x, y, z, _owner->GetCombatReach(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI));
_owner->GetNearPoint(_owner, x, y, z, dist, _owner->GetAngle(srcX, srcY) + float(M_PI));
Movement::MoveSplineInit init(_owner);
init.MoveTo(x, y, z);
@@ -438,7 +438,7 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
float moveTimeHalf = speedZ / Movement::gravity;
float dist = 2 * moveTimeHalf * speedXY;
_owner->GetNearPoint2D(x, y, dist, _owner->GetOrientation() + angle);
_owner->GetNearPoint2D(nullptr, x, y, dist, _owner->GetOrientation() + angle);
z = _owner->GetPositionZ();
_owner->UpdateAllowedPositionZ(x, y, z);
MoveJump(x, y, z, 0.0f, speedXY, speedZ);
@@ -483,7 +483,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);
}
@@ -588,7 +588,7 @@ void MotionMaster::MoveFall(uint32 id /*=0*/)
_owner->SetFall(true);
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);
@@ -158,7 +158,7 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff)
else
{
// otherwise, we fall back to nearpoint finding
target->GetNearPoint(owner, x, y, z, target->GetCombatReach(), (moveToward ? maxTarget : minTarget) - hitboxSum, angle ? target->NormalizeOrientation(target->GetOrientation() - angle->RelativeAngle) : target->GetAngle(owner));
target->GetNearPoint(owner, x, y, z, (moveToward ? maxTarget : minTarget) - hitboxSum, angle ? target->NormalizeOrientation(target->GetOrientation() - angle->RelativeAngle) : target->GetAngle(owner));
shortenPath = false;
}
@@ -114,7 +114,7 @@ bool FollowMovementGenerator::Update(Unit* owner, uint32 diff)
tAngle = _angle.LowerBound();
}
target->GetNearPoint(owner, x, y, z, target->GetCombatReach(), _range, target->NormalizeOrientation(target->GetOrientation() + tAngle));
target->GetNearPoint(owner, x, y, z, _range, target->NormalizeOrientation(target->GetOrientation() + tAngle));
if (owner->IsHovering())
owner->UpdateAllowedPositionZ(x, y, z);
@@ -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();
@@ -510,11 +510,9 @@ class npc_halfus_enslaved_dragon : public CreatureScript
case EVENT_LIFTOFF:
{
Position pos = me->GetPosition();
me->SetDisableGravity(true);
me->SendSetPlayHoverAnim(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
pos.m_positionZ += 5.5f;
me->GetMotionMaster()->MoveTakeoff(0, pos);
_events.ScheduleEvent(EVENT_CAST_DEBUFF, Seconds(1) + Milliseconds(750));
_events.ScheduleEvent(EVENT_CAST_DEBUFF, Seconds(1) + Milliseconds(800));
break;
}
case EVENT_MOVE_OUT_OF_CAGE:
@@ -535,6 +533,15 @@ class npc_halfus_enslaved_dragon : public CreatureScript
if (!halfus || !protoBehemoth)
break;
if (me->GetEntry() != NPC_ORPHANED_EMERALD_WELP)
{
me->SetDisableGravity(true);
me->SendSetPlayHoverAnim(true);
me->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
me->AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
}
switch (me->GetEntry())
{
case NPC_NETHER_SCION_ENCOUNTER:
@@ -421,7 +421,7 @@ struct npc_mandokir_chained_spirit : public PassiveAI
Position pos;
if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
{
target->GetNearPoint(me, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 5.0f, target->GetAngle(me));
target->GetNearPoint(me, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 5.0f, target->GetAngle(me));
me->GetMotionMaster()->MovePoint(POINT_START_REVIVE, pos);
}
}
@@ -972,7 +972,7 @@ void hyjalAI::WaypointReached(uint32 waypointId, uint32 /*pathId*/)
(*itr)->GetMotionMaster()->Initialize();
float range = 10;
if (me->GetEntry() == THRALL)range = 20;
me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr)));
me->GetNearPoint(nullptr, x, y, z, range, me->GetAngle((*itr)));
(*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5, 5), y+irand(-5, 5), me->GetPositionZ());
}
}
@@ -123,8 +123,8 @@ class boss_altairus : public CreatureScript
{
boss_altairusAI(Creature* creature) : BossAI(creature, DATA_ALTAIRUS)
{
// me->SetHover(true);
// me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->SetHover(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
}
void JustEngagedWith(Unit* /*target*/) override
@@ -104,8 +104,8 @@ Position const ToCCommonLoc[] =
{ 550.955933f, 195.338888f, 395.14f, 0 }, // 4 - Left
{ 563.833008f, 195.244995f, 394.585561f, 0 }, // 5 - Center
{ 573.5f, 180.5f, 395.14f, 0 }, // 6 Move 0 Right
{ 553.5f, 180.5f, 395.14f, 0 }, // 7 Move 0 Left
{ 573.0f, 170.0f, 395.14f, 0 }, // 8 Move 1 Right
{ 553.5f, 180.5f, 400.5521f, 0 }, // 7 Move 0 Left
{ 573.0f, 170.0f, 400.5521f, 0 }, // 8 Move 1 Right
{ 555.5f, 170.0f, 395.14f, 0 }, // 9 Move 1 Left
{ 563.8f, 216.1f, 395.1f, 0 }, // 10 Behind the door
@@ -381,7 +381,7 @@ class npc_coldflame : public CreatureScript
{
float ang = Position::NormalizeOrientation(pos.GetAngle(me));
me->SetOrientation(ang);
owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang);
owner->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang);
}
else
{
@@ -394,7 +394,7 @@ class npc_coldflame : public CreatureScript
float ang = Position::NormalizeOrientation(pos.GetAngle(target));
me->SetOrientation(ang);
owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang);
owner->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang);
}
me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation());
@@ -464,7 +464,7 @@ public:
{
Position pos;
pos.m_positionZ = alexstraszaBunny->GetPositionZ();
alexstraszaBunny->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAngle(me));
alexstraszaBunny->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAngle(me));
me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_AGGRESSIVE);
@@ -849,7 +849,7 @@ public:
Position randomPosOnRadius;
// Hardcodded retail value, reason is Z getters can fail... (TO DO: Change to getter when height calculation works on 100%!)
randomPosOnRadius.m_positionZ = 283.0521f;
alexstraszaBunny->GetNearPoint2D(randomPosOnRadius.m_positionX, randomPosOnRadius.m_positionY, 120.0f, alexstraszaBunny->GetAngle(me));
alexstraszaBunny->GetNearPoint2D(nullptr, randomPosOnRadius.m_positionX, randomPosOnRadius.m_positionY, 120.0f, alexstraszaBunny->GetAngle(me));
me->GetMotionMaster()->MovePoint(POINT_FLY_OUT_OF_PLATFORM_P_TWO, randomPosOnRadius);
_flyingOutOfPlatform = true;
}
@@ -1675,7 +1675,7 @@ class spell_malygos_random_portal : public SpellScriptLoader
{
Position pos;
pos.m_positionZ = target->GetPositionZ();
target->GetNearPoint2D(pos.m_positionX, pos.m_positionY, frand(29.1f, 30.0f), target->GetAngle(malygos));
target->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, frand(29.1f, 30.0f), target->GetAngle(malygos));
malygos->GetMotionMaster()->MovePoint(POINT_NEAR_RANDOM_PORTAL_P_NONE, pos);
}
}
@@ -133,9 +133,6 @@ enum Misc
DATA_PHASE_3 = 1
};
#define FLOOR_Z 427.28f
#define FINAL_FLIGHT_Z 435.0f
class boss_steelbreaker : public CreatureScript
{
public:
@@ -476,7 +473,7 @@ class boss_stormcaller_brundir : public CreatureScript
_Reset();
Initialize();
me->RemoveAllAuras();
me->SetDisableGravity(false);
me->SetHover(false);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, false); // Should be interruptable unless overridden by spell (Overload)
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, false); // Reset immumity, Brundir should be stunnable by default
}
@@ -547,10 +544,6 @@ class boss_stormcaller_brundir : public CreatureScript
if (Steelbreaker->IsAlive())
Steelbreaker->AI()->DoAction(ACTION_SUPERCHARGE);
}
// Prevent to have Brundir somewhere in the air when he die in Air phase
if (me->GetPositionZ() > FLOOR_Z)
me->GetMotionMaster()->MoveFall();
}
void KilledUnit(Unit* who) override
@@ -598,9 +591,7 @@ class boss_stormcaller_brundir : public CreatureScript
DoCast(me, SPELL_LIGHTNING_TENDRILS);
DoCast(me, SPELL_LIGHTNING_TENDRILS_VISUAL);
me->AttackStop();
//me->SetLevitate(true);
me->GetMotionMaster()->Initialize();
me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), FINAL_FLIGHT_Z);
me->SetHover(true);
events.DelayEvents(35000);
events.ScheduleEvent(EVENT_FLIGHT, 2500);
events.ScheduleEvent(EVENT_ENDFLIGHT, 32500);
@@ -608,24 +599,22 @@ class boss_stormcaller_brundir : public CreatureScript
break;
case EVENT_FLIGHT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
me->GetMotionMaster()->MovePoint(0, target->GetPositionX(), target->GetPositionY(), FINAL_FLIGHT_Z);
me->GetMotionMaster()->MovePoint(0, *target);
events.ScheduleEvent(EVENT_FLIGHT, 6000);
break;
case EVENT_ENDFLIGHT:
me->GetMotionMaster()->Initialize();
me->GetMotionMaster()->MovePoint(0, 1586.920166f, 119.848984f, FINAL_FLIGHT_Z);
me->GetMotionMaster()->MovePoint(0, 1586.920166f, 119.848984f, me->GetPositionZ());
events.CancelEvent(EVENT_FLIGHT);
events.CancelEvent(EVENT_ENDFLIGHT);
events.ScheduleEvent(EVENT_LAND, 4000);
break;
case EVENT_LAND:
me->GetMotionMaster()->Initialize();
me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), FLOOR_Z);
me->SetHover(false);
events.CancelEvent(EVENT_LAND);
events.ScheduleEvent(EVENT_GROUND, 2500);
break;
case EVENT_GROUND:
//me->SetLevitate(false);
me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_LIGHTNING_TENDRILS, me));
me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_VISUAL);
DoStartMovement(me->GetVictim());
@@ -637,11 +626,11 @@ class boss_stormcaller_brundir : public CreatureScript
{
float x = float(irand(-25, 25));
float y = float(irand(-25, 25));
me->GetMotionMaster()->MovePoint(0, me->GetPositionX() + x, me->GetPositionY() + y, FLOOR_Z);
me->GetMotionMaster()->MovePoint(0, me->GetPositionX() + x, me->GetPositionY() + y, me->GetPositionZ());
// Prevention to go outside the room or into the walls
if (Creature* trigger = me->FindNearestCreature(NPC_WORLD_TRIGGER, 100.0f, true))
if (me->GetDistance(trigger) >= 50.0f)
me->GetMotionMaster()->MovePoint(0, trigger->GetPositionX(), trigger->GetPositionY(), FLOOR_Z);
me->GetMotionMaster()->MovePoint(0, *trigger);
}
events.ScheduleEvent(EVENT_MOVE_POSITION, urand(7500, 10000));
break;
@@ -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->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, 0);
aerial->CastSpell(vx001, SPELL_MOUNT_VX_001);
aerial->CastSpell(aerial, SPELL_HALF_HEAL);
@@ -1159,6 +1159,8 @@ class boss_aerial_command_unit : public CreatureScript
case DO_START_AERIAL:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC);
me->SetReactState(REACT_AGGRESSIVE);
me->SetHover(true);
me->SetDisableGravity(false);
events.SetPhase(PHASE_AERIAL_COMMAND_UNIT);
events.ScheduleEvent(EVENT_SUMMON_JUNK_BOT, 5000, 0, PHASE_AERIAL_COMMAND_UNIT);
@@ -276,7 +276,7 @@ class npc_frozen_orb_stalker : public CreatureScript
for (uint8 i = 0; i < num_orbs; ++i)
{
Position pos;
me->GetNearPoint(toravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f);
me->GetNearPoint(toravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 10.0f, 0.0f);
me->SetPosition(pos);
DoCast(me, SPELL_FROZEN_ORB_SUMMON);
}
@@ -752,7 +752,7 @@ class npc_frostbrood_skytalon : public CreatureScript
{
Position randomPosOnRadius;
randomPosOnRadius.m_positionZ = (me->GetPositionZ() + 40.0f);
me->GetNearPoint2D(randomPosOnRadius.m_positionX, randomPosOnRadius.m_positionY, 40.0f, me->GetAngle(me));
me->GetNearPoint2D(nullptr, randomPosOnRadius.m_positionX, randomPosOnRadius.m_positionY, 40.0f, me->GetAngle(me));
me->GetMotionMaster()->MovePoint(POINT_FLY_AWAY, randomPosOnRadius);
}
}
@@ -202,7 +202,7 @@ public:
void InitializeAI() override
{
float x, y, z;
me->GetNearPoint(me, x, y, z, 1, 100.0f, frand(0.f, 2.f * float(M_PI)));
me->GetNearPoint(me, x, y, z, 100.0f, frand(0.f, 2.f * float(M_PI)));
me->GetMotionMaster()->MovePoint(0, x, y, z);
DoCastSelf(SPELL_MOLTEN_FLAME, true);
}
@@ -79,7 +79,7 @@ public:
void Reset() override
{
ground = me->GetMap()->GetHeight(me->GetPhaseShift(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZMinusOffset());
ground = me->GetMap()->GetHeight(me->GetPhaseShift(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
SummonInfernal();
events.ScheduleEvent(EVENT_CAST_SUMMON_INFERNAL, urand(1000, 3000));
}