[11720] Implement spline movement subsystem

Spline movement controls movements of server-side controlled units (monster movement, taxi movement, etc).
Proper implementation of effects such as charge, jump, cyclic movement will rely on it.
However, need improve our states system before.

Technical changes:

 1. Added linear, catmullrom and bezier3 splines which based on client's algorthims. They can be reused for proper transport position interpolation.
 2. Precission increased. There are no more position desync issues since client's position calculation formulas used.
 3. Now possible to move by paths with multiple points, send whole path to client.
This commit is contained in:
SilverIce 2011-07-08 17:25:13 +03:00
parent e302fce513
commit 9d566398ad
52 changed files with 2471 additions and 1203 deletions

View file

@ -45,6 +45,8 @@
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "movement/MoveSplineInit.h"
#include "movement/MoveSpline.h"
// apply implementation of the singletons
#include "Policies/SingletonImp.h"
@ -163,7 +165,7 @@ m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_temporaryFactionFlags(TEMPFACTION_NONE),
m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)
m_creatureInfo(NULL)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
@ -173,8 +175,6 @@ m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
m_splineFlags = SPLINEFLAG_WALKMODE;
}
Creature::~Creature()
@ -322,6 +322,8 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
UpdateSpeed(MOVE_WALK, false);
UpdateSpeed(MOVE_RUN, false);
SetLevitate(CanFly());
// checked at loading
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
@ -1484,8 +1486,6 @@ void Creature::SetDeathState(DeathState s)
SetHealth(GetMaxHealth());
SetLootRecipient(NULL);
AddSplineFlag(SPLINEFLAG_WALKMODE);
if (GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_RESPAWN)
ClearTemporaryFaction();
@ -1530,25 +1530,19 @@ bool Creature::FallGround()
Unit::SetDeathState(CORPSE_FALLING);
float dz = tz - GetPositionZ();
float distance = sqrt(dz*dz);
// default run speed * 2 explicit, not verified though but result looks proper
double speed = baseMoveSpeed[MOVE_RUN] * 2;
speed *= 0.001; // to milliseconds
uint32 travelTime = uint32(distance/speed);
DEBUG_LOG("FallGround: traveltime: %u, distance: %f, speed: %f, from %f to %f", travelTime, distance, speed, GetPositionZ(), tz);
// For creatures that are moving towards target and dies, the visual effect is not nice.
// It is possibly caused by a xyz mismatch in DestinationHolder's GetLocationNow and the location
// of the mob in client. For mob that are already reached target or dies while not moving
// the visual appear to be fairly close to the expected.
Movement::MoveSplineInit init(*this);
init.MoveTo(GetPositionX(),GetPositionY(),tz);
init.SetFall();
init.Launch();
// hacky solution: by some reason died creatures not updated, that's why need finalize movement state
GetMap()->CreatureRelocation(this, GetPositionX(), GetPositionY(), tz, GetOrientation());
SendMonsterMove(GetPositionX(), GetPositionY(), tz, SPLINETYPE_NORMAL, SPLINEFLAG_FALLING, travelTime);
movespline->_Finalize();
return true;
}
@ -1955,8 +1949,8 @@ bool Creature::LoadCreatureAddon(bool reload)
if (cainfo->emote != 0)
SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote);
if (cainfo->splineFlags != 0)
SetSplineFlags(SplineFlags(cainfo->splineFlags));
if (cainfo->splineFlags & SPLINEFLAG_FLYING)
SetLevitate(true);
if(cainfo->auras)
{
@ -2387,13 +2381,6 @@ void Creature::SetActiveObjectState( bool on )
map->Add(this);
}
void Creature::SendMonsterMoveWithSpeedToCurrentDestination(Player* player)
{
float x, y, z;
if (!IsStopped() && GetMotionMaster()->GetDestination(x, y, z))
SendMonsterMoveWithSpeed(x, y, z, 0, player);
}
void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl)
{
uint32 next_resurrect = 0;
@ -2490,3 +2477,26 @@ bool Creature::HasStaticDBSpawnData() const
{
return sObjectMgr.GetCreatureData(GetGUIDLow()) != NULL;
}
void Creature::SetWalk(bool enable)
{
if (enable)
m_movementInfo.AddMovementFlag(MOVEFLAG_WALK_MODE);
else
m_movementInfo.RemoveMovementFlag(MOVEFLAG_WALK_MODE);
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
data << GetPackGUID();
SendMessageToSet(&data, true);
UpdateWalkMode(this, false);
}
void Creature::SetLevitate(bool enable)
{
if (enable)
m_movementInfo.AddMovementFlag(MOVEFLAG_LEVITATING);
else
m_movementInfo.RemoveMovementFlag(MOVEFLAG_LEVITATING);
WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
data << GetPackGUID();
SendMessageToSet(&data, true);
}