Core/Movement

* Implemented creature movement on transports
* Set minimum speed for creature allowed to start movement (too low speed leads to overflows in movement time calculations which in turn leads to crashes)
This commit is contained in:
Shauren
2012-05-31 19:45:11 +02:00
parent 851f43b0a6
commit 425eeb8280
14 changed files with 146 additions and 58 deletions
@@ -677,6 +677,11 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
void GetHomePosition(float &x, float &y, float &z, float &ori) { m_homePosition.GetPosition(x, y, z, ori); }
Position GetHomePosition() { return m_homePosition; }
void SetTransportHomePosition(float x, float y, float z, float o) { m_transportHomePosition.Relocate(x, y, z, o); }
void SetTransportHomePosition(const Position &pos) { m_transportHomePosition.Relocate(pos); }
void GetTransportHomePosition(float &x, float &y, float &z, float &ori) { m_transportHomePosition.GetPosition(x, y, z, ori); }
Position GetTransportHomePosition() { return m_transportHomePosition; }
uint32 GetWaypointPath(){return m_path_id;}
void LoadPath(uint32 pathid) { m_path_id = pathid; }
@@ -750,6 +755,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
uint32 m_originalEntry;
Position m_homePosition;
Position m_transportHomePosition;
bool DisableReputationGain;
@@ -656,6 +656,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y,
o + GetOrientation());
creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
creature->SetTransportHomePosition(creature->m_movementInfo.t_pos);
if (!creature->IsPositionValid())
{
@@ -698,11 +699,33 @@ void Transport::UpdateNPCPositions()
Creature* npc = *itr;
float x, y, z, o;
o = GetOrientation() + npc->m_movementInfo.t_pos.m_orientation;
x = GetPositionX() + (npc->m_movementInfo.t_pos.m_positionX * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionY * sin(GetOrientation() + M_PI));
y = GetPositionY() + (npc->m_movementInfo.t_pos.m_positionY * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionX * sin(GetOrientation()));
z = GetPositionZ() + npc->m_movementInfo.t_pos.m_positionZ;
npc->SetHomePosition(x, y, z, o);
npc->m_movementInfo.t_pos.GetPosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, o);
GetMap()->CreatureRelocation(npc, x, y, z, o, false);
npc->GetTransportHomePosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, o);
npc->SetHomePosition(x, y, z, o);
}
}
//! This method transforms supplied transport offsets into global coordinates
void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float& o)
{
float inx = x, iny = y, inz = z, ino = o;
o = GetOrientation() + ino;
x = GetPositionX() + (inx * cos(GetOrientation()) + iny * sin(GetOrientation() + M_PI));
y = GetPositionY() + (iny * cos(GetOrientation()) + inx * sin(GetOrientation()));
z = GetPositionZ() + inz;
}
//! This method transforms supplied global coordinates into local offsets
void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float& o)
{
o -= GetOrientation();
z -= GetPositionZ();
y -= GetPositionY(); // y = searchedY * cos(o) + searchedX * sin(o)
x -= GetPositionX(); // x = searchedX * cos(o) + searchedY * sin(o + pi)
float inx = x, iny = y;
y = (iny - inx * tan(GetOrientation())) / (cos(GetOrientation()) - sin(GetOrientation() + M_PI) * tan(GetOrientation()));
x = (inx - iny * sin(GetOrientation() + M_PI) / cos(GetOrientation())) / (cos(GetOrientation()) - tan(GetOrientation()) * sin(GetOrientation() + M_PI));
}
@@ -47,6 +47,8 @@ class Transport : public GameObject
uint32 AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim=0);
void UpdatePosition(MovementInfo* mi);
void UpdateNPCPositions();
void CalculatePassengerPosition(float& x, float& y, float& z, float& o);
void CalculatePassengerOffset(float& x, float& y, float& z, float& o);
void BuildStartMovePacket(Map const* targetMap);
void BuildStopMovePacket(Map const* targetMap);
uint32 GetScriptId() const { return ScriptId; }
+23 -9
View File
@@ -396,10 +396,25 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
m_movesplineTimer.Reset(POSITION_UPDATE_DELAY);
Movement::Location loc = movespline->ComputePosition();
if (GetTypeId() == TYPEID_PLAYER)
((Player*)this)->UpdatePosition(loc.x,loc.y,loc.z,loc.orientation);
else
GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation);
if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
{
Position& pos = m_movementInfo.t_pos;
pos.m_positionX = loc.x;
pos.m_positionY = loc.y;
pos.m_positionZ = loc.z;
pos.m_orientation = loc.orientation;
if (Unit* vehicle = GetVehicleBase())
{
loc.x += vehicle->GetPositionX();
loc.y += vehicle->GetPositionY();
loc.z += vehicle->GetPositionZMinusOffset();
loc.orientation = vehicle->GetOrientation();
}
else if (Transport* trans = GetTransport())
trans->CalculatePassengerPosition(loc.x, loc.y, loc.z, loc.orientation);
}
UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
}
}
@@ -414,7 +429,7 @@ void Unit::SendMonsterMoveExitVehicle(Position const* newPos)
WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size());
data.append(GetPackGUID());
data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // new in 3.1, bool
data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40)
data << GetPositionX() << GetPositionY() << GetPositionZ();
data << getMSTime();
@@ -437,7 +452,7 @@ void Unit::SendMonsterMoveTransport(Unit* vehicleOwner)
data.append(GetPackGUID());
data.append(vehicleOwner->GetPackGUID());
data << int8(GetTransSeat());
data << uint8(0);
data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40)
data << GetPositionX() - vehicleOwner->GetPositionX();
data << GetPositionY() - vehicleOwner->GetPositionY();
data << GetPositionZ() - vehicleOwner->GetPositionZ();
@@ -12662,7 +12677,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
{
// Set creature speed rate from CreatureInfo
if (GetTypeId() == TYPEID_UNIT)
speed *= ToCreature()->GetCreatureTemplate()->speed_walk;
speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached
// Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need
// TODO: possible affect only on MOVE_RUN
@@ -12982,8 +12997,7 @@ void Unit::TauntFadeOut(Unit* taunter)
return;
}
//m_ThreatManager.tauntFadeOut(taunter);
target = m_ThreatManager.getHostilTarget();
target = creature->SelectVictim(); // might have more taunt auras remaining
if (target && target != taunter)
{
+2 -4
View File
@@ -298,7 +298,7 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z)
}
}
void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed)
void MotionMaster::MoveLand(uint32 id, Position const& pos)
{
float x, y, z;
pos.GetPosition(x, y, z);
@@ -307,13 +307,12 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed)
Movement::MoveSplineInit init(*_owner);
init.MoveTo(x,y,z);
init.SetVelocity(speed);
init.SetAnimation(Movement::ToGround);
init.Launch();
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
}
void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed)
void MotionMaster::MoveTakeoff(uint32 id, Position const& pos)
{
float x, y, z;
pos.GetPosition(x, y, z);
@@ -322,7 +321,6 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed)
Movement::MoveSplineInit init(*_owner);
init.MoveTo(x,y,z);
init.SetVelocity(speed);
init.SetAnimation(Movement::ToFly);
init.Launch();
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
+2 -2
View File
@@ -157,8 +157,8 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void MovePoint(uint32 id, float x, float y, float z);
// These two movement types should only be used with creatures having landing/takeoff animations
void MoveLand(uint32 id, Position const& pos, float speed);
void MoveTakeoff(uint32 id, Position const& pos, float speed);
void MoveLand(uint32 id, Position const& pos);
void MoveTakeoff(uint32 id, Position const& pos);
void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE);
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
@@ -203,7 +203,7 @@ bool MoveSplineInitArgs::Validate() const
return false;\
}
CHECK(path.size() > 1);
CHECK(velocity > 0.f);
CHECK(velocity > 0.1f);
CHECK(time_perc >= 0.f && time_perc <= 1.f);
//CHECK(_checkPathBounds());
return true;
@@ -20,6 +20,8 @@
#include "MoveSpline.h"
#include "MovementPacketBuilder.h"
#include "Unit.h"
#include "Transport.h"
#include "Vehicle.h"
namespace Movement
{
@@ -58,17 +60,25 @@ namespace Movement
{
MoveSpline& move_spline = *unit.movespline;
Location real_position(unit.GetPositionX(),unit.GetPositionY(),unit.GetPositionZMinusOffset(),unit.GetOrientation());
// there is a big chane that current position is unknown if current state is not finalized, need compute it
bool transport = false;
Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZMinusOffset(), unit.GetOrientation());
if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
{
transport = true;
real_position.x = unit.GetTransOffsetX();
real_position.y = unit.GetTransOffsetY();
real_position.z = unit.GetTransOffsetZ();
real_position.orientation = unit.GetTransOffsetO();
}
// there is a big chance that current position is unknown if current state is not finalized, need compute it
// this also allows calculate spline position and update map position in much greater intervals
if (!move_spline.Finalized())
real_position = move_spline.ComputePosition();
// should i do the things that user should do? - no.
if (args.path.empty())
{
// should i do the things that user should do?
MoveTo(real_position);
}
return;
// corrent first vertex
args.path[0] = real_position;
@@ -82,7 +92,7 @@ namespace Movement
moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD);
if (args.velocity == 0.f)
if (!args.HasVelocity)
args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags));
if (!args.Validate())
@@ -94,8 +104,20 @@ namespace Movement
unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags);
move_spline.Initialize(args);
WorldPacket data(SMSG_MONSTER_MOVE, 64);
WorldPacket data(!transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT, 64);
data.append(unit.GetPackGUID());
if (transport)
{
if (unit.GetVehicle())
data.appendPackGUID(unit.GetVehicleBase()->GetGUID());
else if (unit.GetTransport())
data.appendPackGUID(unit.GetTransGUID());
else
data << uint8(0);
data << int8(unit.GetTransSeat());
}
PacketBuilder::WriteMonsterMove(move_spline, data);
unit.SendMessageToSet(&data,true);
}
@@ -119,4 +141,33 @@ namespace Movement
args.facing.angle = G3D::wrap(angle, 0.f, (float)G3D::twoPi());
args.flags.EnableFacingAngle();
}
void MoveSplineInit::MoveTo(Vector3 const& dest)
{
args.path_Idx_offset = 0;
args.path.resize(2);
TransportPathTransform transform(unit);
args.path[1] = transform(dest);
}
Vector3 TransportPathTransform::operator()(Vector3 input)
{
if (_owner.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
{
if (Unit* vehicle = _owner.GetVehicleBase())
{
input.x -= vehicle->GetPositionX();
input.y -= vehicle->GetPositionY();
input.z -= vehicle->GetPositionZMinusOffset();
}
else if (Transport* transport = _owner.GetTransport())
{
float unused = 0.0f;
transport->CalculatePassengerOffset(input.x, input.y, input.z, unused);
}
}
return input;
}
}
@@ -33,6 +33,17 @@ namespace Movement
FlyToGround = 3, // 463 = FlyToGround
};
// Transforms coordinates from global to transport offsets
class TransportPathTransform
{
public:
TransportPathTransform(Unit& owner) : _owner(owner) { }
Vector3 operator()(Vector3 input);
private:
Unit& _owner;
};
/* Initializes and launches spline movement
*/
class MoveSplineInit
@@ -123,14 +134,15 @@ namespace Movement
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();}
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;}
inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();}
inline void MoveSplineInit::SetVelocity(float vel){ args.velocity = vel;}
inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; }
inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;}
inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;}
inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset)
{
args.path_Idx_offset = path_offset;
args.path.assign(controls.begin(),controls.end());
args.path.resize(controls.size());
std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit));
}
inline void MoveSplineInit::MoveTo(float x, float y, float z)
@@ -139,13 +151,6 @@ namespace Movement
MoveTo(v);
}
inline void MoveSplineInit::MoveTo(const Vector3& dest)
{
args.path_Idx_offset = 0;
args.path.resize(2);
args.path[1] = dest;
}
inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift)
{
args.time_perc = time_shift;
@@ -42,7 +42,7 @@ namespace Movement
struct MoveSplineInitArgs
{
MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0),
velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f)
velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), HasVelocity(false)
{
path.reserve(path_capacity);
}
@@ -56,6 +56,7 @@ namespace Movement
float time_perc;
uint32 splineId;
float initialOrientation;
bool HasVelocity;
/** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
bool Validate() const;
@@ -44,20 +44,8 @@ namespace Movement
void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data)
{
MoveSplineFlag splineflags = move_spline.splineflags;
/*if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
{
data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
if (unit->GetVehicle())
data << unit->GetVehicle()->GetBase()->GetPackGUID();
else if (unit->GetTransport())
data << unit->GetTransport()->GetPackGUID();
else
data << uint64(0);
data << int8(unit->GetTransSeat());
}*/
data << uint8(0);
data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40)
data << move_spline.spline.getPoint(move_spline.spline.first());
data << move_spline.GetId();
@@ -167,7 +167,7 @@ class FrostwyrmLandEvent : public BasicEvent
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
{
_owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest, 8.247422f);
_owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest);
return true;
}
@@ -481,7 +481,7 @@ class boss_sindragosa : public CreatureScript
Position pos;
pos.Relocate(me);
pos.m_positionZ += 17.0f;
me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos, 8.30078125f);
me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos);
events.CancelEventGroup(EVENT_GROUP_LAND_PHASE);
events.ScheduleEvent(EVENT_AIR_PHASE, 110000);
break;
@@ -523,7 +523,7 @@ class boss_sindragosa : public CreatureScript
events.ScheduleEvent(EVENT_FROST_BREATH, urand(10000, 15000), EVENT_GROUP_LAND_PHASE);
events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(12000, 17000), EVENT_GROUP_LAND_PHASE);
events.ScheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000), EVENT_GROUP_LAND_PHASE);
me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos, 0.0f);
me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos);
break;
case EVENT_THIRD_PHASE_CHECK:
{
@@ -1926,7 +1926,7 @@ class spell_svalna_revive_champion : public SpellScriptLoader
//pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), caster->GetPositionZ(), true, 50.0f);
//pos.m_positionZ += 0.05f;
caster->SetHomePosition(pos);
caster->GetMotionMaster()->MoveLand(POINT_LAND, pos, caster->GetSpeed(MOVE_FLIGHT));
caster->GetMotionMaster()->MoveLand(POINT_LAND, pos);
}
void Register()
@@ -276,7 +276,7 @@ public:
arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false);
pos.Relocate(me);
pos.m_positionZ += 8.0f;
me->GetMotionMaster()->MoveTakeoff(0, pos, 3.30078125f);
me->GetMotionMaster()->MoveTakeoff(0, pos);
// spectators flee event
if (instance)
{
@@ -333,7 +333,7 @@ public:
pos.m_positionX = me->GetHomePosition().GetPositionX();
pos.m_positionY = me->GetHomePosition().GetPositionY();
pos.m_positionZ = 90.6065f;
me->GetMotionMaster()->MoveLand(0, pos, 6.247422f);
me->GetMotionMaster()->MoveLand(0, pos);
me->SetDisableGravity(false, true);
me->SetHover(true);
++introPhase;