Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
MoveSpline.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Creature.h"
7#include "Log.h"
8#include "MoveSpline.h"
9#include <sstream>
10
11namespace Movement {
12
14 {
16
17 float u = 1.f;
18 int32 seg_time = spline.length(point_Idx, point_Idx + 1);
19 if (seg_time > 0)
20 u = (time_passed - spline.length(point_Idx)) / (float)seg_time;
21 Location c;
23 spline.evaluate_percent(point_Idx, u, c);
24
25 if (splineflags.animation); // MoveSplineFlag::Animation disables falling or parabolic movement
26 else if (splineflags.parabolic)
28 else if (splineflags.falling)
30
31 if (splineflags.done && splineflags.isFacing())
32 {
33 if (splineflags.final_angle)
34 c.orientation = facing.angle;
35 else if (splineflags.final_point)
36 c.orientation = atan2(facing.f.y - c.y, facing.f.x - c.x);
37 //nothing to do for MoveSplineFlag::Final_Target flag
38 }
39 else
40 {
42 {
43 Vector3 hermite;
44 spline.evaluate_derivative(point_Idx, u, hermite);
45 c.orientation = atan2(hermite.y, hermite.x);
46 }
47
48 if (splineflags.orientationInversed)
50 }
51 return c;
52 }
53
55 {
57 {
58 float t_passedf = MSToSec(time_passed - effect_start_time);
59 float t_durationf = MSToSec(Duration() - effect_start_time); //client use not modified duration here
60
61 // -a*x*x + bx + c:
62 //(dur * v3->z_acceleration * dt)/2 - (v3->z_acceleration * dt * dt)/2 + Z;
63 el += (t_durationf - t_passedf) * 0.5f * vertical_acceleration * t_passedf;
64 }
65 }
66
68 {
69 float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed), false);
70 float final_z = FinalDestination().z;
71 el = std::max(z_now, final_z);
72 }
73
74 inline uint32 computeDuration(float length, float velocity)
75 {
76 return SecToMS(length / velocity);
77 }
78
80 {
81 explicit FallInitializer(float _start_elevation) : start_elevation(_start_elevation) { }
84 {
85 return Movement::computeFallTime(start_elevation - s.getPoint(i + 1).z, false) * 1000.f;
86 }
87 };
88
89 enum {
91 };
92
94 {
95 explicit CommonInitializer(float _velocity) : velocityInv(1000.f / _velocity), time(minimal_duration) { }
99 {
100 time += (s.SegLength(i) * velocityInv);
101 return time;
102 }
103 };
104
106 {
108 if (args.flags.cyclic)
109 {
110 uint32 cyclic_point = 0;
111 // MoveSplineFlag::Enter_Cycle support dropped
112 //if (splineflags & SPLINEFLAG_ENTER_CYCLE)
113 //cyclic_point = 1; // shouldn't be modified, came from client
114 spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point);
115 }
116 else
117 {
118 spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]);
119 }
120
121 // init spline timestamps
122 if (splineflags.falling)
123 {
124 FallInitializer init(spline.getPoint(spline.first()).z);
125 spline.initLengths(init);
126 }
127 else
128 {
129 CommonInitializer init(args.velocity);
130 spline.initLengths(init);
131 }
132
134 if (spline.length() < minimal_duration)
135 {
136 SF_LOG_ERROR("misc", "MoveSpline::init_spline: zero length spline, wrong input data?");
137 spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
138 }
139 point_Idx = spline.first();
140 }
141
143 {
144 splineflags = args.flags;
145 facing = args.facing;
146 m_Id = args.splineId;
149
150 time_passed = 0;
153
154 // Check if its a stop spline
155 if (args.flags.done)
156 {
157 spline.clear();
158 return;
159 }
160
161 init_spline(args);
162
163 // init parabolic / animation
164 // spline initialized, duration known and i able to compute parabolic acceleration
166 {
169 {
170 float f_duration = MSToSec(Duration() - effect_start_time);
171 vertical_acceleration = args.parabolic_amplitude * 8.f / (f_duration * f_duration);
172 }
173 }
174 }
175
182
184
186 {
187#define CHECK(exp) \
188 if (!(exp))\
189 {\
190 SF_LOG_ERROR("misc", "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u Entry: %u", #exp, unit->GetTypeId() == TypeID::TYPEID_PLAYER ? unit->GetGUIDLow() : unit->ToCreature()->GetDBTableGUIDLow(), unit->GetEntry());\
191 return false;\
192 }
193 CHECK(path.size() > 1);
194 CHECK(velocity > 0.1f);
195 CHECK(time_perc >= 0.f && time_perc <= 1.f);
196 //CHECK(_checkPathBounds());
197 return true;
198#undef CHECK
199 }
200
201 // MONSTER_MOVE packet format limitation for not CatmullRom movement:
202 // each vertex offset packed into 11 bytes
204 {
205 if (!(flags & MoveSplineFlag::Catmullrom) && path.size() > 2)
206 {
207 enum {
208 MAX_OFFSET = (1 << 11) / 2
209 };
210 Vector3 middle = (path.front() + path.back()) / 2;
211 Vector3 offset;
212 for (uint32 i = 1; i < path.size() - 1; ++i)
213 {
214 offset = path[i] - middle;
215 if (fabs(offset.x) >= float(MAX_OFFSET) || fabs(offset.y) >= float(MAX_OFFSET) || fabs(offset.z) >= float(MAX_OFFSET))
216 {
217 SF_LOG_ERROR("misc", "MoveSplineInitArgs::_checkPathBounds check failed");
218 return false;
219 }
220 }
221 }
222 return true;
223 }
224
226
228 {
229 if (Finalized())
230 {
231 ms_time_diff = 0;
232 return Result_Arrived;
233 }
234
235 UpdateResult result = Result_None;
236
237 int32 minimal_diff = std::min(ms_time_diff, segment_time_elapsed());
238 ASSERT(minimal_diff >= 0);
239 time_passed += minimal_diff;
240 ms_time_diff -= minimal_diff;
241
243 {
244 ++point_Idx;
245 if (point_Idx < spline.last())
246 {
247 result = Result_NextSegment;
248 }
249 else
250 {
251 if (spline.isCyclic())
252 {
253 point_Idx = spline.first();
255 result = Result_NextCycle;
256 }
257 else
258 {
259 _Finalize();
260 ms_time_diff = 0;
261 result = Result_Arrived;
262 }
263 }
264 }
265
266 return result;
267 }
268
269 std::string MoveSpline::ToString() const
270 {
271 std::stringstream str;
272 str << "MoveSpline" << std::endl;
273 str << "spline Id: " << GetId() << std::endl;
274 str << "flags: " << splineflags.ToString() << std::endl;
275 if (splineflags.final_angle)
276 str << "facing angle: " << facing.angle;
277 else if (splineflags.final_target)
278 str << "facing target: " << facing.target;
279 else if (splineflags.final_point)
280 str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z;
281 str << std::endl;
282 str << "time passed: " << time_passed << std::endl;
283 str << "total time: " << Duration() << std::endl;
284 str << "spline point Id: " << point_Idx << std::endl;
285 str << "path point Id: " << currentPathIdx() << std::endl;
286 str << spline.ToString();
287 return str.str();
288 }
289
291 {
292 splineflags.done = true;
293 point_Idx = spline.last() - 1;
295 }
296
298 {
299 int32 point = point_Idx_offset + point_Idx - spline.first() + (int)Finalized();
300 if (isCyclic())
301 point = point % (spline.last() - spline.first());
302 return point;
303 }
304}
std::int32_t int32
Definition Define.h:73
std::uint32_t uint32
Definition Define.h:77
#define ASSERT
Definition Errors.h:29
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define CHECK(exp)
int32 next_timestamp() const
Definition MoveSpline.h:67
bool isCyclic() const
Definition MoveSpline.h:105
std::string ToString() const
UpdateResult _updateState(int32 &ms_time_diff)
============================================================================================
void Initialize(const MoveSplineInitArgs &)
Location ComputePosition() const
uint32 GetId() const
Definition MoveSpline.h:103
void computeFallElevation(float &el) const
bool Finalized() const
Definition MoveSpline.h:104
Vector3 FinalDestination() const
Definition MoveSpline.h:107
int32 currentPathIdx() const
int32 Duration() const
Definition MoveSpline.h:73
bool Initialized() const
Definition MoveSpline.h:81
int32 segment_time_elapsed() const
Definition MoveSpline.h:68
void init_spline(const MoveSplineInitArgs &args)
void computeParabolicElevation(float &el) const
MoveSplineFlag splineflags
Definition MoveSpline.h:47
const Vector3 & getPoint(index_type i) const
Definition Spline.h:99
float SegLength(index_type i) const
Definition Spline.h:115
Definition Unit.h:1367
uint32 computeDuration(float length, float velocity)
@ minimal_duration
float computeFallTime(float path_length, bool isSafeFall)
uint32 SecToMS(float sec)
float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity=0.0f)
float MSToSec(uint32 ms)
CommonInitializer(float _velocity)
int32 operator()(Spline< int32 > &s, int32 i)
FallInitializer(float _start_elevation)
int32 operator()(Spline< int32 > &s, int32 i)
bool Validate(Unit *unit) const
============================================================================================