ScummVM API documentation
motion.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *
21 * Based on the original sources
22 * Faery Tale II -- The Halls of the Dead
23 * (c) 1993-1996 The Wyrmkeep Entertainment Co.
24 */
25
26#ifndef SAGA2_MOTION_H
27#define SAGA2_MOTION_H
28
29#include "saga2/actor.h"
30
31namespace Saga2 {
32
33class PathRequest;
34struct StandingTileInfo;
35
36extern const StaticTilePoint dirTable[];
37extern const StaticTilePoint incDirTable[];
38
39
40const int kGravity = 2;
41const int kWalkSpeed = 4;
42const int kSlowWalkSpeed = 2;
43const int kRunSpeed = 8;
44const int kWalkSpeedDiag = 3;
45const int kRunSpeedDiag = 6;
46const int kAngleThresh = 24;
47
48enum MotionThreadReturnValues {
49 kMotionInterrupted, // MotionTask has been rudely
50 // interrupted and recycled for a new
51 // motion.
52
53 kMotionStarted, // The actor started moving.
54 kMotionCompleted, // The actor motion completed
55 // successfully.
56 kMotionWalkBlocked // The walk motion failed.
57};
58
59enum {
60 kMoveWait = (1 << 0),
61 kMoveRun = (1 << 1)
62};
63
64/* ===================================================================== *
65 Utility Motion Functions
66 * ===================================================================== */
67
68void setObjectSurface(GameObject *obj, StandingTileInfo &sti);
69
70/* ===================================================================== *
71 Motion Task Class
72 * ===================================================================== */
73
74// This class handles the movement of objects. It includes things like
75// thrown rocks, cast spells, and actors walking.
76//
77// Since most things in the game aren't moving at a given point, the
78// variables for simulating motion don't need to always be present.
79
80// Also need to handle explosion on impact for projectiles
81// Or other special action.
82// an object can hit a regular surface
83// can hit a trip plate
84// can hit another object
85// can hit an actor
86//
87// can damage actor
88// can break
89// can set off trap
90// can explode
91
93 friend class MotionTaskList;
94 friend class PathRequest;
95 friend class DestinationPathRequest;
96 friend class WanderPathRequest;
97 friend class Actor;
98 friend void RequestPath(MotionTask *mTask, int16 smartness);
99 friend void RequestWanderPath(MotionTask *mTask, int16 smartness);
100 friend void abortPathFind(MotionTask *mTask);
101
102 GameObject *_object; // the object to move
103 TilePoint _velocity; // object velocity for ballistic flight
104 TilePoint _immediateLocation, // where we are trying to get to
105 _finalTarget; // where we eventually want to get to
106 int16 _tetherMinU,
107 _tetherMinV,
108 _tetherMaxU,
109 _tetherMaxV;
110 uint8 _motionType, // thrown or shot.
111 _prevMotionType; // motion type before interruption
112
113 ThreadID _thread; // SAGA thread to wake up when
114 // motion is done
115
116 uint16 _flags; // various flags
117
118 enum motionFlags {
119 kMfPathFind = (1 << 0), // walk is using path finding
120 kMfFinalPath = (1 << 1), // current path is final
121 kMfInWater = (1 << 2), // handle motion as in water
122 kMfReset = (1 << 3), // target has been reset
123 kMfBlocked = (1 << 4), // target was blocked
124 kMfRequestRun = (1 << 5), // caller has requested running
125 kMfWandering = (1 << 6), // wander
126 kMfTethered = (1 << 7), // stay within tether
127 kMfNextAnim = (1 << 8), // update animation for this frame
128 kMfTurnDelay = (1 << 9), // Delay While Turning
129 kMfTAGTarg = (1 << 10), // The target is not an object but a TAG
130 kMfLocTarg = (1 << 11), // The target is not an object but a TAG
131 kMfAgitated = (1 << 12), // Walking around blockage
132 kMfAgitatable = (1 << 13), // Will agitate when blocked
133 kMfOnStairs = (1 << 14), // actor is climbing stairs
134 kMfPrivledged = (1 << 15) // don't let AI interrupt this
135 };
136
137 Direction _direction; // direction of movement
138 TilePoint _pathList[16]; // intermediate motion targets
139 int16 _pathCount, // number of points in path
140 _pathIndex, // number of points so far
141 _runCount; // used for run requests.
142 PathRequest *_pathFindTask; // request to find the path
143 int16 _steps, // number of steps in ballistic motion
144 _uFrac, // remainder in U direction
145 _vFrac, // remainder in V direction
146 _uErrorTerm, // used to adjust for rounding errors
147 _vErrorTerm; // used to adjust for rounding errors
148
149 // Data used in combat motion
150 uint8 _combatMotionType; // combat sub motion type
151
152 // Spell casting stuff
153 GameObject *_targetObj; // target of attack or defense (object)
154 ActiveItem *_targetTAG; // target of attack or defense (TAG)
155 Location _targetLoc; // target of attack or defense (Location)
156 SkillProto *_spellObj; // spell being cast
157
158 union {
159 int16 actionCounter; // counter used in some motion
160 int16 moveCount; // counter used when moving mergeable objects around
161 };
162
163 enum defenseMotionFlags {
164 kDfBlocking = (1 << 0) // actor is blocking an attack
165 };
166
167 union {
168 // Object interaction stuff
169 struct {
170 GameObject *directObject, // object directly being acted
171 // upon.
172 *indirectObject; // object idirectly being acted
173 // upon.
174 Actor *enactor;
175 ActiveItem *TAI; // TAI involved in interation
176 } _o;
177
178 // Defensive motion stuff
179 struct {
180 Actor *attacker; // attacking actor
181 GameObject *defensiveObj; // shield or parrying weapon
182 uint8 defenseFlags; // various combat flags
183 } _d;
184 };
185
186public:
187 // Combat specific motion sub-types
188 enum TwoHandedSwingTypes {
189 kTwoHandedSwingHigh,
190 kTwoHandedSwingLow,
191 kTwoHandedSwingLeftHigh,
192 kTwoHandedSwingLeftLow,
193 kTwoHandedSwingRightHigh,
194 kTwoHandedSwingRightLow
195 };
196
197 enum OneHandedSwingTypes {
198 kOneHandedSwingHigh,
199 kOneHandedSwingLow,
200 kOneHandedThrust
201 };
202
203 enum OneHandedParryTypes {
204 kOneHandedParryHigh,
205 kOneHandedParryLow
206 };
207
208private:
209
210 enum motionTypes {
211 kMotionTypeNone, // no motion
212
213 kMotionTypeThrown, // thrown in an arc
214 kMotionTypeShot, // shot in very shallow arc w/ cheat
215 kMotionTypeFall, // fall from a height
216 kMotionTypeWalk, // walk to a point
217 kMotionTypeStagger, // stagger to a point
218 kMotionTypeClimbUp, // climb up ladder to a point
219 kMotionTypeClimbDown, // climb dowb ladder
220 kMotionTypeTalk, // talk and gesture
221 kMotionTypeLand, // land after falling
222 kMotionTypeLandBadly, // land badly after falling
223 kMotionTypeJump, // get ready for jump
224 kMotionTypeTurn, // Turn Object
225 kMotionTypeGive, // Extend arm to give object
226 kMotionTypeRise, // Rise slowly in water
227 kMotionTypeHit, // For simple animations
228
229 // Immobile motions
230 kMotionTypeWait, // Don't move, simply eat some time
231 kMotionTypeUseObject, // Use an object
232 kMotionTypeUseObjectOnObject, // Use one object on another
233 kMotionTypeUseObjectOnTAI, // Use an object on a TAI
234 kMotionTypeUseObjectOnLocation, // Use an object on a TilePoint
235 kMotionTypeUseTAI, // Use a TAI
236 kMotionTypeDropObject, // Drop an object at a location
237 kMotionTypeDropObjectOnObject, // Drop one object on another
238 kMotionTypeDropObjectOnTAI, // Drop an object on a TAI
239
240 // Offensive combat actions
241 kMotionTypeTwoHandedSwing, // swing two-handed weapon
242 kMotionTypeOneHandedSwing, // swing one-handed weapon
243 kMotionTypeFireBow, // fire bow
244 kMotionTypeCastSpell, // cast spell
245 kMotionTypeUseWand, // cast spell with wand
246
247 // Defensive combat actions
248 kMotionTypeTwoHandedParry, // parry with two-handed weapon
249 kMotionTypeOneHandedParry, // parry with one-handed weapon
250 kMotionTypeShieldParry, // parry with shield
251 kMotionTypeDodge, // dodge blow
252
253 // Other combat actions
254 kMotionTypeAcceptHit, // show effect of hit
255 kMotionTypeFallDown, // be knocked off feet
256 kMotionTypeDie // self-explanatory
257
258 };
259
260 void read(Common::InSaveFile *in);
261
262 // Return the number of bytes needed to archive this MotionTask
263 int32 archiveSize();
264
265 void write(Common::MemoryWriteStreamDynamic *out);
266
267 // motion task is finished.
268 void remove(int16 returnVal = kMotionInterrupted);
269
270 TilePoint getImmediateTarget(); // determine immediate target
271 // location
272
273 // Routines to handle updating of specific motion types
274 void turnAction() {
275 Actor *a = (Actor *)_object;
276
277 if (_flags & kMfReset) {
278 a->setAction(kActionStand, 0);
279 _flags &= ~kMfReset;
280 }
281
282 if (a->_currentFacing != _direction)
283 a->turn(_direction);
284 else
285 remove(kMotionCompleted);
286 }
287
288 void ballisticAction();
289 void walkAction();
290 void giveAction();
291
292 void upLadderAction();
293 void downLadderAction();
294
295 // Set up specified animation and run through the frames
296 void genericAnimationAction(uint8 actionType);
297
298 // Offensive combat actions
299 void twoHandedSwingAction();
300 void oneHandedSwingAction();
301 void fireBowAction();
302 void castSpellAction();
303 void useWandAction();
304
305 // Defensive combat actions
306 void twoHandedParryAction();
307 void oneHandedParryAction();
308 void shieldParryAction();
309 void dodgeAction();
310
311 // Other combat actions
312 void acceptHitAction();
313 void fallDownAction();
314
315 // Generic offensive melee code. Called by twoHandedSwingAction()
316 // and oneHandedSwingAction
317 void offensiveMeleeAction();
318
319 // Generic magic weapon code. Called by useWandAction() and
320 // useStaffAction()
321 void useMagicWeaponAction();
322
323 // Generic defensive melee code. Called by twoHandedParryAction(),
324 // oneHandedParryAction() and shieldParryAction().
325 void defensiveMeleeAction();
326
327 // Retrieve the next waypoint from the path list.
328 bool nextWayPoint();
329 bool checkWalk(int16, int16, int16, TilePoint &);
330
331 // Determine the velocity for a ballistic motion
332 void calcVelocity(const TilePoint &vector, int16 turns);
333
334public:
335
336 // Functions to create a new motion task. If the game object is
337 // an actor, then it will cancel any existing motion task
338 static void throwObject(GameObject &obj, const TilePoint &velocity);
339 static void throwObjectTo(GameObject &obj, const TilePoint &where);
340 static void shootObject(
341 GameObject &obj,
342 Actor &doer,
343 GameObject &target,
344 int16 speed);
345 static void walkTo(
346 Actor &obj,
347 const TilePoint &target,
348 bool run = false,
349 bool canAgitate = true);
350 static void walkTo(
351 ThreadID th,
352 Actor &obj,
353 const TilePoint &target,
354 bool run = false,
355 bool canAgitate = true);
356 static void walkToDirect(
357 Actor &obj,
358 const TilePoint &target,
359 bool run = false,
360 bool canAgitate = true);
361 static void walkToDirect(
362 ThreadID th,
363 Actor &obj,
364 const TilePoint &target,
365 bool run = false,
366 bool canAgitate = true);
367 static void wander(Actor &obj, bool run = false);
368 static void tetheredWander(Actor &obj, const TileRegion &tether, bool run = false);
369// static void runTo( GameObject &obj, const TilePoint &target );
370 static void staggerTo(Actor &obj, const TilePoint &target);
371 static void upLadder(Actor &obj);
372 static void downLadder(Actor &obj);
373 static void talk(Actor &obj);
374 static void jump(Actor &obj);
375 static void turn(Actor &obj, Direction dir);
376 static void turn(ThreadID th, Actor &obj, Direction dir);
377 static void turnTowards(Actor &obj, const TilePoint &where);
378 static void turnTowards(ThreadID th, Actor &obj, const TilePoint &where);
379 static void give(Actor &obj, Actor &givee);
380 static void give(ThreadID th, Actor &obj, Actor &givee);
381
382 // Imobile motions
383 static void wait(Actor &a);
384 static void useObject(Actor &a, GameObject &dObj);
385 static void useObjectOnObject(
386 Actor &a,
387 GameObject &dObj,
388 GameObject &target);
389 static void useObjectOnTAI(
390 Actor &a,
391 GameObject &dObj,
392 ActiveItem &target);
393 static void useObjectOnLocation(
394 Actor &a,
395 GameObject &dObj,
396 const Location &target);
397 static void useTAI(Actor &a, ActiveItem &dTAI);
398 static void dropObject(
399 Actor &a,
400 GameObject &dObj,
401 const Location &loc,
402 int16 num = 1);
403
404 static void dropObjectOnObject(
405 Actor &a,
406 GameObject &dObj,
407 GameObject &target,
408 int16 num = 1);
409
410 static void dropObjectOnTAI(
411 Actor &a,
412 GameObject &dObj,
413 ActiveItem &target,
414 const Location &loc);
415
416 // Offensive combat actions
417 static void twoHandedSwing(Actor &obj, GameObject &target);
418 static void oneHandedSwing(Actor &obj, GameObject &target);
419 static void fireBow(Actor &obj, GameObject &target);
420 static void castSpell(Actor &obj, SkillProto &spell, GameObject &target);
421 static void castSpell(Actor &obj, SkillProto &spell, Location &target);
422 static void castSpell(Actor &obj, SkillProto &spell, ActiveItem &target);
423 static void useWand(Actor &obj, GameObject &target);
424
425 // Defensive combat actions
426 static void twoHandedParry(
427 Actor &obj,
428 GameObject &weapon,
429 Actor &opponent);
430 static void oneHandedParry(
431 Actor &obj,
432 GameObject &weapon,
433 Actor &opponent);
434 static void shieldParry(
435 Actor &obj,
436 GameObject &shield,
437 Actor &opponent);
438 static void dodge(Actor &obj, Actor &opponent);
439
440 // Other combat actions
441 static void acceptHit(Actor &obj, Actor &opponent);
442 static void fallDown(Actor &obj, Actor &opponent);
443 static void die(Actor &obj);
444
445 static void updatePositions();
446
447 int16 testCollision(GameObject &obstacle);
448
449 bool freeFall(TilePoint &newPos, StandingTileInfo &sti);
450
451 // Determine if the motion task is a walk motion
452 bool isWalk();
453
454 // Determine if the motion task is walking to a destination
455 bool isWalkToDest() {
456 return isWalk() && !(_flags & kMfWandering);
457 }
458
459 // Determine if the motion task is a wandering motion
460 bool isWander() {
461 return isWalk() && (_flags & kMfWandering);
462 }
463
464 // Determine if the motion task is tethered
465 bool isTethered() {
466 return isWander() && (_flags & kMfTethered);
467 }
468
469 bool isRunning() {
470 return (_flags & kMfRequestRun) && _runCount == 0;
471 }
472
473 bool isTurn() {
474 return _motionType == kMotionTypeTurn;
475 }
476
477 // Return the wandering tether region
478 TileRegion getTether();
479
480 // Return the final target location
481 TilePoint getTarget() {
482 return _finalTarget;
483 }
484
485 // Update to a new final target
486 void changeTarget(const TilePoint &newPos, bool run = false);
487 void changeDirectTarget(const TilePoint &newPos, bool run = false);
488 void finishWalk(); // stop walking
489 void finishTurn() {
490 if (isTurn()) remove();
491 }
492 void finishTalking(); // stop talking motion
493
494 // Determine if this MotionTask is a reflexive motion
495 bool isReflex();
496
497 // Determine if this MotionTask is a defensive motion
498 bool isDefense();
499
500 // End the defensive motion task
501 void finishDefense() {
502 if (isDefense()) remove();
503 }
504
505 // Determine if this MotionTask is an offensive motion
506 bool isAttack();
507
508 // Determine if this MotionTask is an offensive melee motion
509 bool isMeleeAttack();
510
511 // Compute the number of frames before the actual strike in an
512 // offensive melee motion
513 uint16 framesUntilStrike();
514
515 // End the offensive motion
516 void finishAttack() {
517 if (isAttack()) remove();
518 }
519
520 // Returns a pointer to the blocking object if it applicable to
521 // this motion task
522 GameObject *blockingObject(Actor *thisAttacker);
523
524 // Determine if this motion is a dodge motion
525 bool isDodging(Actor *thisAttacker) {
526 return _motionType == kMotionTypeDodge && thisAttacker == _d.attacker;
527 }
528
529 static void initMotionTasks();
530
531 bool isPrivledged() {
532 return _flags & kMfPrivledged;
533 }
534};
535
537 friend class MotionTask;
538
541
542public:
543 // Default constructor
545
547
548 void read(Common::InSaveFile *in);
549
550 // Return the number of bytes needed to archive the motion tasks
551 // in a buffer
552 int32 archiveSize();
553
554 void write(Common::MemoryWriteStreamDynamic *out);
555
556 // Cleanup the motion tasks
557 void cleanup();
558
559 MotionTask *newTask(GameObject *obj); // get new motion task
560};
561
562/* ===================================================================== *
563 MotionTask inline member functions
564 * ===================================================================== */
565
566inline void MotionTask::walkTo(
567 ThreadID th,
568 Actor &actor,
569 const TilePoint &target,
570 bool run,
571 bool canAgitate) {
572 walkTo(actor, target, run, canAgitate);
573 if (actor._moveTask != NULL)
574 actor._moveTask->_thread = th;
575}
576
577inline void MotionTask::walkToDirect(
578 ThreadID th,
579 Actor &actor,
580 const TilePoint &target,
581 bool run,
582 bool canAgitate) {
583 walkToDirect(actor, target, run, canAgitate);
584 if (actor._moveTask != NULL)
585 actor._moveTask->_thread = th;
586}
587
588inline void MotionTask::turn(ThreadID th, Actor &actor, Direction dir) {
589 turn(actor, dir);
590 if (actor._moveTask != NULL)
591 actor._moveTask->_thread = th;
592}
593
594inline void MotionTask::turnTowards(
595 ThreadID th,
596 Actor &actor,
597 const TilePoint &where) {
598 turnTowards(actor, where);
599 if (actor._moveTask != NULL)
600 actor._moveTask->_thread = th;
601}
602
603inline void MotionTask::give(ThreadID th, Actor &actor, Actor &givee) {
604 give(actor, givee);
605 if (actor._moveTask != NULL)
606 actor._moveTask->_thread = th;
607}
608
609/* ===================================================================== *
610 Utility functions
611 * ===================================================================== */
612
613// Initiate ladder climbing
614bool checkLadder(Actor *a, const TilePoint &tp);
615
616void pauseInterruptableMotions();
617void resumeInterruptableMotions();
618
619/* ===================================================================== *
620 MotionTask list management functions
621 * ===================================================================== */
622
623// Initialize the motion task list
624void initMotionTasks();
625
626void saveMotionTasks(Common::OutSaveFile *out);
627void loadMotionTasks(Common::InSaveFile *in, int32 chunkSize);
628
629// Cleanup the motion task list
630void cleanupMotionTasks();
631
632} // end of namespace Saga2
633
634#endif
Definition: list.h:44
Definition: memstream.h:194
Definition: savefile.h:54
Definition: stream.h:745
Definition: tile.h:388
Definition: actor.h:584
Definition: objects.h:118
Definition: objproto.h:105
Definition: motion.h:92
Definition: motion.h:536
Definition: objproto.h:1493
Definition: list_intern.h:54
Definition: tile.h:634
Definition: tcoords.h:127
Definition: tcoords.h:222