[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

208
src/game/movement/util.cpp Normal file
View file

@ -0,0 +1,208 @@
/*
* Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "MoveSplineFlag.h"
#include <math.h>
#include <string>
namespace Movement
{
double gravity = 19.29110527038574;
/// Velocity bounds that makes fall speed limited
float terminalVelocity = 60.148003f;
float terminalSavefallVelocity = 7.f;
const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.f * gravity);
const float terminal_savefall_length = (terminalSavefallVelocity * terminalSavefallVelocity) / (2.f * gravity);
const float terminalFallTime = float(terminalVelocity/gravity); // the time that needed to reach terminalVelocity
float computeFallTime(float path_length, bool isSafeFall)
{
if (path_length < 0.f)
return 0.f;
float time;
if ( isSafeFall )
{
if (path_length >= terminal_savefall_length)
time = (path_length - terminal_savefall_length)/terminalSavefallVelocity + terminalSavefallVelocity/gravity;
else
time = sqrtf(2.f * path_length/gravity);
}
else
{
if (path_length >= terminal_length)
time = (path_length - terminal_length)/terminalVelocity + terminalFallTime;
else
time = sqrtf(2.f * path_length/gravity);
}
return time;
}
float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity)
{
float termVel;
float result;
if ( isSafeFall )
termVel = terminalSavefallVelocity;
else
termVel = terminalVelocity;
if ( start_velocity > termVel )
start_velocity = termVel;
float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity
if ( t_passed > terminal_time )
{
result = terminalVelocity*(t_passed - terminal_time) +
start_velocity*terminal_time + gravity*terminal_time*terminal_time*0.5f;
}
else
result = t_passed * (start_velocity + t_passed * gravity * 0.5f);
return result;
}
float computeFallElevation(float t_passed)
{
float result;
if (t_passed > terminalFallTime)
{
//result = terminalVelocity * (t_passed - terminal_time) + gravity*terminal_time*terminal_time*0.5f;
// simplified view:
result = terminalVelocity * (t_passed - terminalFallTime) + terminal_length;
}
else
result = t_passed * t_passed * gravity * 0.5f;
return result;
}
#define STR(x) #x
const char * g_MovementFlag_names[]=
{
STR(Forward ),// 0x00000001,
STR(Backward ),// 0x00000002,
STR(Strafe_Left ),// 0x00000004,
STR(Strafe_Right ),// 0x00000008,
STR(Turn_Left ),// 0x00000010,
STR(Turn_Right ),// 0x00000020,
STR(Pitch_Up ),// 0x00000040,
STR(Pitch_Down ),// 0x00000080,
STR(Walk ),// 0x00000100, // Walking
STR(Ontransport ),// 0x00000200,
STR(Levitation ),// 0x00000400,
STR(Root ),// 0x00000800,
STR(Falling ),// 0x00001000,
STR(Fallingfar ),// 0x00002000,
STR(Pendingstop ),// 0x00004000,
STR(PendingSTRafestop ),// 0x00008000,
STR(Pendingforward ),// 0x00010000,
STR(Pendingbackward ),// 0x00020000,
STR(PendingSTRafeleft ),// 0x00040000,
STR(PendingSTRaferight ),// 0x00080000,
STR(Pendingroot ),// 0x00100000,
STR(Swimming ),// 0x00200000, // Appears With Fly Flag Also
STR(Ascending ),// 0x00400000, // Swim Up Also
STR(Descending ),// 0x00800000, // Swim Down Also
STR(Can_Fly ),// 0x01000000, // Can Fly In 3.3?
STR(Flying ),// 0x02000000, // Actual Flying Mode
STR(Spline_Elevation ),// 0x04000000, // Used For Flight Paths
STR(Spline_Enabled ),// 0x08000000, // Used For Flight Paths
STR(Waterwalking ),// 0x10000000, // Prevent Unit From Falling Through Water
STR(Safe_Fall ),// 0x20000000, // Active Rogue Safe Fall Spell (Passive)
STR(Hover ),// 0x40000000
STR(Unknown13 ),// 0x80000000
STR(Unk1 ),
STR(Unk2 ),
STR(Unk3 ),
STR(Fullspeedturning ),
STR(Fullspeedpitching ),
STR(Allow_Pitching ),
STR(Unk4 ),
STR(Unk5 ),
STR(Unk6 ),
STR(Unk7 ),
STR(Interp_Move ),
STR(Interp_Turning ),
STR(Interp_Pitching ),
STR(Unk8 ),
STR(Unk9 ),
STR(Unk10 ),
};
const char * g_SplineFlag_names[32]=
{
STR(Forward ),// 0x00000001,
STR(Backward ),// 0x00000002,
STR(Strafe_Left ),// 0x00000004,
STR(Strafe_Right ),// 0x00000008,
STR(Left ),// 0x00000010,
STR(Right ),// 0x00000020,
STR(Pitch_Up ),// 0x00000040,
STR(Pitch_Down ),// 0x00000080,
STR(Done ),// 0x00000100,
STR(Falling ),// 0x00000200, // Not Compartible With Trajectory Movement
STR(No_Spline ),// 0x00000400,
STR(Trajectory ),// 0x00000800, // Not Compartible With Fall Movement
STR(Walkmode ),// 0x00001000,
STR(Flying ),// 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
STR(Knockback ),// 0x00004000, // Model Orientation Fixed
STR(Final_Point ),// 0x00008000,
STR(Final_Target ),// 0x00010000,
STR(Final_Angle ),// 0x00020000,
STR(Catmullrom ),// 0x00040000, // Used Catmullrom Interpolation Mode
STR(Cyclic ),// 0x00080000, // Movement By Cycled Spline
STR(Enter_Cycle ),// 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet
STR(Animation ),// 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
STR(Unknown4 ),// 0x00400000, // Disables Movement By Path
STR(Unknown5 ),// 0x00800000,
STR(Unknown6 ),// 0x01000000,
STR(Unknown7 ),// 0x02000000,
STR(Unknown8 ),// 0x04000000,
STR(Backward ),// 0x08000000, // Appears With Walkmode Flag, Nodes ),// 1, Handles Orientation
STR(Unknown10 ),// 0x10000000,
STR(Unknown11 ),// 0x20000000,
STR(Unknown12 ),// 0x40000000,
STR(Unknown13 ),// 0x80000000,
};
template<class Flags, int N>
void print_flags(Flags t, const char* (&names)[N], std::string& str)
{
for (int i = 0; i < N; ++i)
{
if ((t & (Flags)(1 << i)) && names[i] != NULL)
str.append(" ").append(names[i]);
}
}
std::string MoveSplineFlag::ToString() const
{
std::string str;
print_flags(raw(),g_SplineFlag_names,str);
return str;
}
}