Skip to content

Commit

Permalink
[11720] Implement spline movement subsystem
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
SilverIce committed Jul 8, 2011
1 parent d28fc6d commit 326ba2c
Show file tree
Hide file tree
Showing 52 changed files with 2,471 additions and 1,203 deletions.
9 changes: 8 additions & 1 deletion src/game/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ source_group("World/Handlers"
)

source_group("Motion generators"
REGULAR_EXPRESSION Movement|Holder|Motion|Traveller
REGULAR_EXPRESSION Generator|MotionMaster
)

source_group("Server"
Expand All @@ -64,6 +64,13 @@ source_group("References"
REGULAR_EXPRESSION Reference|RefManager|ThreatManager
)

source_group("Movement"
REGULAR_EXPRESSION spline|Spline|packet_builder
FILES
movement/typedefs.h
movement/util.cpp
)

if(PCH)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
endif()
Expand Down
42 changes: 15 additions & 27 deletions src/game/ConfusedMovementGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
#include "Creature.h"
#include "MapManager.h"
#include "Opcodes.h"
#include "DestinationHolderImp.h"
#include "movement/MoveSplineInit.h"
#include "movement/MoveSpline.h"

template<class T>
void
Expand Down Expand Up @@ -71,8 +72,6 @@ template<>
void
ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
{
creature.RemoveSplineFlag(SPLINEFLAG_WALKMODE);

is_water_ok = creature.CanSwim();
is_land_ok = creature.CanWalk();
}
Expand All @@ -97,17 +96,13 @@ void ConfusedMovementGenerator<T>::Reset(T &unit)
{
i_nextMove = 1;
i_nextMoveTime.Reset(0);
i_destinationHolder.ResetUpdate();
unit.StopMoving();
unit.addUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
}

template<class T>
bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
if(!&unit)
return true;

// ignore in case other no reaction state
if (unit.hasUnitState(UNIT_STAT_CAN_NOT_REACT & ~UNIT_STAT_CONFUSED))
return true;
Expand All @@ -116,36 +111,30 @@ bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
// currently moving, update location
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
Traveller<T> traveller(unit);
if (i_destinationHolder.UpdateTraveller(traveller, diff, false))
{
if (!IsActive(unit)) // force stop processing (movement can move out active zone with cleanup movegens list)
return true; // not expire now, but already lost

if (i_destinationHolder.HasArrived())
{
// arrived, stop and wait a bit
unit.StopMoving();

i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
}
if (unit.movespline->Finalized())
{
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
}
}
else
{
// waiting for next move
i_nextMoveTime.Update(diff);
if( i_nextMoveTime.Passed() )
if(i_nextMoveTime.Passed() )
{
// start moving
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);

MANGOS_ASSERT( i_nextMove <= MAX_CONF_WAYPOINTS );
const float x = i_waypoints[i_nextMove][0];
const float y = i_waypoints[i_nextMove][1];
const float z = i_waypoints[i_nextMove][2];
Traveller<T> traveller(unit);
i_destinationHolder.SetDestination(traveller, x, y, z);
float x = i_waypoints[i_nextMove][0];
float y = i_waypoints[i_nextMove][1];
float z = i_waypoints[i_nextMove][2];
Movement::MoveSplineInit init(unit);
init.MoveTo(x, y, z);
init.SetWalk(true);
init.Launch();
}
}
return true;
Expand All @@ -161,7 +150,6 @@ template<>
void ConfusedMovementGenerator<Creature>::Finalize(Creature &unit)
{
unit.clearUnitState(UNIT_STAT_CONFUSED|UNIT_STAT_CONFUSED_MOVE);
unit.AddSplineFlag(SPLINEFLAG_WALKMODE);
}

template void ConfusedMovementGenerator<Player>::Initialize(Player &player);
Expand Down
3 changes: 0 additions & 3 deletions src/game/ConfusedMovementGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
#define MANGOS_CONFUSEDMOVEMENTGENERATOR_H

#include "MovementGenerator.h"
#include "DestinationHolder.h"
#include "Traveller.h"

#define MAX_CONF_WAYPOINTS 24

Expand All @@ -43,7 +41,6 @@ class MANGOS_DLL_SPEC ConfusedMovementGenerator
void _InitSpecific(T &, bool &, bool &);
TimeTracker i_nextMoveTime;
float i_waypoints[MAX_CONF_WAYPOINTS+1][3];
DestinationHolder< Traveller<T> > i_destinationHolder;
uint32 i_nextMove;
};
#endif
64 changes: 37 additions & 27 deletions src/game/Creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand All @@ -173,8 +175,6 @@ m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)

m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();

m_splineFlags = SPLINEFLAG_WALKMODE;
}

Creature::~Creature()
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -1484,8 +1486,6 @@ void Creature::SetDeathState(DeathState s)
SetHealth(GetMaxHealth());
SetLootRecipient(NULL);

AddSplineFlag(SPLINEFLAG_WALKMODE);

if (GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_RESPAWN)
ClearTemporaryFaction();

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
30 changes: 4 additions & 26 deletions src/game/Creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,31 +516,10 @@ class MANGOS_DLL_SPEC Creature : public Unit

CreatureAI* AI() { return i_AI; }

void AddSplineFlag(SplineFlags f)
{
bool need_walk_sync = (f & SPLINEFLAG_WALKMODE) != (m_splineFlags & SPLINEFLAG_WALKMODE);
m_splineFlags = SplineFlags(m_splineFlags | f);
if (need_walk_sync)
UpdateWalkMode(this, false);
}
void RemoveSplineFlag(SplineFlags f)
{
bool need_walk_sync = (f & SPLINEFLAG_WALKMODE) != (m_splineFlags & SPLINEFLAG_WALKMODE);
m_splineFlags = SplineFlags(m_splineFlags & ~f);
if (need_walk_sync)
UpdateWalkMode(this, false);
}
bool HasSplineFlag(SplineFlags f) const { return m_splineFlags & f; }
SplineFlags GetSplineFlags() const { return m_splineFlags; }
void SetSplineFlags(SplineFlags f)
{
bool need_walk_sync = (f & SPLINEFLAG_WALKMODE) != (m_splineFlags & SPLINEFLAG_WALKMODE);
m_splineFlags = f; // need set before
if (need_walk_sync)
UpdateWalkMode(this, false);
}

void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
void SetWalk(bool enable);
void SetLevitate(bool enable);
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING);}
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);}

uint32 GetShieldBlockValue() const // dunno mob block value
{
Expand Down Expand Up @@ -762,7 +741,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
private:
GridReference<Creature> m_gridRef;
CreatureInfo const* m_creatureInfo; // in difficulty mode > 0 can different from ObjMgr::GetCreatureTemplate(GetEntry())
SplineFlags m_splineFlags;
};

class AssistDelayEvent : public BasicEvent
Expand Down
63 changes: 0 additions & 63 deletions src/game/DestinationHolder.h

This file was deleted.

Loading

6 comments on commit 326ba2c

@Zakamurite
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome...

@rsa
Copy link
Contributor

@rsa rsa commented on 326ba2c Jul 8, 2011

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mamma mia... gigantic work..

@SkirnirMaNGOS
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who's da man! SilverIce :)

@MaxXx2021
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooo... My God! Great job!

@Tasssadar
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is just amazing. Thank you.

@sixsixnine
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Little something for VC9 compilation ...

diff --git a/src/game/ConfusedMovementGenerator.cpp b/src/game/ConfusedMovementGenerator.cpp
index 169d4fc..b447fbc 100644
--- a/src/game/ConfusedMovementGenerator.cpp
+++ b/src/game/ConfusedMovementGenerator.cpp
@@ -18,6 +18,7 @@

#include "ConfusedMovementGenerator.h"
#include "Creature.h"
+#include "Player.h"
#include "MapManager.h"
#include "Opcodes.h"
#include "movement/MoveSplineInit.h"
diff --git a/src/game/ConfusedMovementGenerator.h b/src/game/ConfusedMovementGenerator.h
index b62ca1a..08995fa 100644
--- a/src/game/ConfusedMovementGenerator.h
+++ b/src/game/ConfusedMovementGenerator.h
@@ -20,6 +20,7 @@
#define MANGOS_CONFUSEDMOVEMENTGENERATOR_H

#include "MovementGenerator.h"
+#include "Timer.h"

#define MAX_CONF_WAYPOINTS 24

diff --git a/src/game/PointMovementGenerator.h b/src/game/PointMovementGenerator.h
index 5a5c7fa..dd6e4bd 100644
--- a/src/game/PointMovementGenerator.h
+++ b/src/game/PointMovementGenerator.h
@@ -21,6 +21,8 @@

#include "MovementGenerator.h"
#include "FollowerReference.h"
+#include "Creature.h"
+#include "Timer.h"

template
class MANGOS_DLL_SPEC PointMovementGenerator
diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp
index f6a0cd3..029fe94 100644
--- a/src/game/TargetedMovementGenerator.cpp
+++ b/src/game/TargetedMovementGenerator.cpp
@@ -20,13 +20,11 @@
#include "TargetedMovementGenerator.h"
#include "Errors.h"
#include "Creature.h"
+#include "Player.h"
#include "World.h"
#include "movement/MoveSplineInit.h"
#include "movement/MoveSpline.h"

-#define SMALL_ALPHA 0.05f

-#include

//-----------------------------------------------//
template<class T, typename D>
diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h
index ff4d4ad..c38797f 100644
--- a/src/game/TargetedMovementGenerator.h
+++ b/src/game/TargetedMovementGenerator.h
@@ -21,6 +21,7 @@

#include "MovementGenerator.h"
#include "FollowerReference.h"
+struct ShortTimeTracker;

class MANGOS_DLL_SPEC TargetedMovementGeneratorBase
{
diff --git a/src/game/movement/packet_builder.cpp b/src/game/movement/packet_builder.cpp
index 022a59b..282500d 100644
--- a/src/game/movement/packet_builder.cpp
+++ b/src/game/movement/packet_builder.cpp
@@ -17,8 +17,6 @@
*/

#include "packet_builder.h"
-#include "MoveSpline.h"
-#include "WorldPacket.h"

namespace Movement
{
diff --git a/src/game/movement/packet_builder.h b/src/game/movement/packet_builder.h
index 48043d9..6377b80 100644
--- a/src/game/movement/packet_builder.h
+++ b/src/game/movement/packet_builder.h
@@ -19,8 +19,9 @@
#ifndef MANGOSSERVER_PACKET_BUILDER_H
#define MANGOSSERVER_PACKET_BUILDER_H

-class ByteBuffer;
-class WorldPacket;
+#include "MoveSpline.h"
+#include "WorldPacket.h"
+#include "ByteBuffer.h"

namespace Movement
{

Please sign in to comment.