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 
31 namespace Saga2 {
32 
33 class PathRequest;
34 struct StandingTileInfo;
35 
36 extern const StaticTilePoint dirTable[];
37 extern const StaticTilePoint incDirTable[];
38 
39 
40 const int kGravity = 2;
41 const int kWalkSpeed = 4;
42 const int kSlowWalkSpeed = 2;
43 const int kRunSpeed = 8;
44 const int kWalkSpeedDiag = 3;
45 const int kRunSpeedDiag = 6;
46 const int kAngleThresh = 24;
47 
48 enum 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 
59 enum {
60  kMoveWait = (1 << 0),
61  kMoveRun = (1 << 1)
62 };
63 
64 /* ===================================================================== *
65  Utility Motion Functions
66  * ===================================================================== */
67 
68 void 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 
92 class MotionTask {
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 
186 public:
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 
208 private:
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 
334 public:
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 
542 public:
543  // Default constructor
544  MotionTaskList();
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 
566 inline 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 
577 inline 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 
588 inline 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 
594 inline 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 
603 inline 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
614 bool checkLadder(Actor *a, const TilePoint &tp);
615 
616 void pauseInterruptableMotions();
617 void resumeInterruptableMotions();
618 
619 /* ===================================================================== *
620  MotionTask list management functions
621  * ===================================================================== */
622 
623 // Initialize the motion task list
624 void initMotionTasks();
625 
626 void saveMotionTasks(Common::OutSaveFile *out);
627 void loadMotionTasks(Common::InSaveFile *in, int32 chunkSize);
628 
629 // Cleanup the motion task list
630 void cleanupMotionTasks();
631 
632 } // end of namespace Saga2
633 
634 #endif
Definition: motion.h:536
Definition: tile.h:388
Definition: objproto.h:105
Definition: savefile.h:54
Definition: motion.h:92
Definition: actor.h:32
Definition: list.h:44
Definition: memstream.h:194
Definition: tcoords.h:127
Definition: stream.h:745
Definition: actor.h:589
Definition: tcoords.h:222
Definition: tile.h:634
Definition: objects.h:118
Definition: list_intern.h:51
Definition: objproto.h:1493