ScummVM API documentation
objects.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_OBJECTS_H
27 #define SAGA2_OBJECTS_H
28 
29 #include "saga2/objproto.h"
30 #include "saga2/property.h"
31 
32 namespace Saga2 {
33 
34 /* ======================================================================= *
35  GameObject: Describes an instance of an object
36  * ======================================================================= */
37 
38 class GameWorld;
39 
40 const uint16 unlimitedCapacity = maxuint16;
41 
42 enum ActorManaID {
43  kManaIDRed = 0,
44  kManaIDOrange,
45  kManaIDYellow,
46  kManaIDGreen,
47  kManaIDBlue,
48  kManaIDViolet,
49 
50  kNumManas
51 };
52 
53 // Used to indicate if objects can be stacked or merged
54 enum {
55  kCannotStackOrMerge = 0,
56  kCanStack,
57  kCanMerge
58 };
59 
60 // The ResourceGameObject structure represents the game object data as
61 // it is structured in the resource file.
62 
64  int16 protoIndex;
65  TilePoint location;
66  uint16 nameIndex;
67  ObjectID parentID;
68  uint16 script;
69  uint16 objectFlags;
70  uint8 hitPoints;
71  uint16 misc;
72 
74 };
75 
76 // Base class of all objects
77 //
78 // Unlike the object prototypes, the only subclass of GameObject is
79 // the actor subclass, which is kept in an entirely separate table.
80 // This allows all objects to be kept in an array (indexed by ID number)
81 
82 #include "common/pack-start.h"
83 
84 struct ObjectData {
85  uint32 projectDummy;
86  TilePoint location; // where object is located.
87  uint16 nameIndex; // object's proper name, if any
88  ObjectID parentID, // ID of parent object
89  siblingID, // ID of next in chain
90  childID; // ID of 1st child
91  uint16 script; // script attached to this object
92  uint16 objectFlags; // various flags
93  uint8 hitPoints; // object hit points
94  uint8 bParam; // number of spell charges an object has
95  // (also generator radius in metatiles)
96  union {
97  uint16 massCount; // for mergeables, object count
98  uint16 textStringID; // inscription for documents
99  uint16 enchantmentType; // for enchantments
100  uint16 generatorFrequency; // for encounter and mission generators
101  };
102 
103  uint8 missileFacing;
104  ActiveItemID currentTAG; // ActiveItem object is on
105  uint8 sightCtr; // Line of sight counter
106 
107  uint8 reserved[2];
108 
109  GameObject *obj;
110 } PACKED_STRUCT;
111 
112 #include "common/pack-end.h"
113 
114 void initActors();
115 void saveActors(Common::OutSaveFile *outS);
116 void loadActors(Common::InSaveFile *in);
117 void cleanupActors();
118 class GameObject {
119 
120  friend void initWorlds();
121  friend void cleanupWorlds();
122 
123  friend void initObjects();
124  friend void saveObjects(Common::OutSaveFile *out);
125  friend void loadObjects(Common::InSaveFile *in);
126  friend void cleanupObjects();
127 
128  friend void buildDisplayList();
129  friend void drawDisplayList();
130  friend void setMindContainer(int NewContainerClass, IntangibleContainerWindow &cw);
131  friend class EnchantmentContainerWindow;
132  friend bool Enchantment(ObjectID, ObjectID);
133  friend class ProtoObj;
134  friend class PhysicalContainerProto;
135  friend class IntangibleContainerProto;
136  friend class KeyProto;
137  friend class BottleProto;
138  friend class SkillProto;
139  friend class ActorProto;
140  friend class MotionTask;
141  friend class MotionTaskList;
142  friend class ObjectIterator;
143  friend class ContainerIterator;
144  friend class RecursiveContainerIterator;
145  friend class ShopMode;
146 
147 
148 
149 private:
150 
151  // container info
152  enum {
153  kMaxRow = 20,
154  kMaxCol = 4
155  };
156 
157 public:
158 
159  ObjectID thisID(); // calculate our own ID value
160 
161  static const char *nameText(uint16 index);
162 
163 protected:
164  // get address of head-of-chain id.
165  static ObjectID *getHeadPtr(ObjectID parentID, TilePoint &l);
166 
167  // Object list management functions
168  void remove(); // removes from old list
169  void append(ObjectID newParent); // adds to new list (no remove)
170  void insert(ObjectID newPrev); // inserts after this item (no remove)
171 
172  ProtoObj *_prototype; // object that defines our behavior
173 public:
174  ObjectData _data;
175  uint _index;
176  bool _godmode;
177  // Default constructor
178  GameObject();
179 
180  // Constructor -- initial construction
181  GameObject(const ResourceGameObject &res);
182 
184 
185  void read(Common::InSaveFile *in, bool expandProto);
186 
187  // Return the number of bytes needed to archive this object in
188  // a buffer
189  int32 archiveSize();
190 
191  void write(Common::MemoryWriteStreamDynamic *out, bool expandProto);
192 
193  // returns the address of the object based on the ID, and this
194  // includes accounting for actors.
195  static GameObject *objectAddress(ObjectID id);
196 
197  // Converts object ID into prototype address...
198  static ProtoObj *protoAddress(ObjectID id);
199 
200  // Returns first object id found associate with the given name index
201  static int32 nameIndexToID(uint16 ind);
202 
203  // Returns first object id found assciated with the given name
204  static Common::Array<ObjectID> nameToID(Common::String name);
205 
206  // object creation and deletion
207  static GameObject *newObject(); // get a newly created object
208  void deleteObject(); // delete this object and remove
209  void deleteObjectRecursive(); // delete this object and every
210  // object it contains
211 
212  // Return pointer to parent/child/next sibling object, if any
213  GameObject *parent() {
214  return _data.parentID == Nothing ? NULL : objectAddress(_data.parentID);
215  }
216  GameObject *next() {
217  return _data.siblingID == Nothing ? NULL : objectAddress(_data.siblingID);
218  }
219  GameObject *child() {
220  return _data.childID == Nothing ? NULL : objectAddress(_data.childID);
221  }
222 
223  // Return ID of parent/child/next sibling object, if any
224  ObjectID IDParent() {
225  return _data.parentID ;
226  }
227  ObjectID IDNext() {
228  return _data.siblingID;
229  }
230  ObjectID IDChild() {
231  return _data.childID ;
232  }
233 
234  // Return a pointer to the world on which this object resides
235  GameWorld *world();
236 
237  // Return the number of the map of the world on which this object
238  // resides
239  int16 getMapNum();
240 
241  // graphics functions
242  int16 sprNum(int16 state); // returns current sprite number
243 
244  // gets the offset to the spr image according to masscount for mergeables
245  int32 getSprOffset(int16 num = -1);
246 
247  // completely restore the magical energy of a magical object
248  void recharge();
249 
250  // returns the type of charge an object has
251  // be it none, red, violet, etc...
252  int16 getChargeType();
253 
254  // use charge of this object
255  bool deductCharge(ActorManaID manaID, uint16 manaCost);
256 
257  // check charge of this object
258  bool hasCharge(ActorManaID manaID, uint16 manaCost);
259 
260  // context-changing functions
261  void setLocation(const Location &loc); // move to new location in world
262  void setLocation(const TilePoint &tp); // move to new location in world
263  void move(const Location &loc); // move to new location in world
264  void move(const Location &loc, int16 num); // move to new location in world
265  void move(const TilePoint &tp); // move to new location in world
266  void updateImage(ObjectID); // move to new location in world,
267  // (assumes setLocation has been called)
268 
269  // Remove an object from a stack of objects. Returns true if it was in a stack.
270  bool unstack();
271 
272  // this correctly moves merged or stacked objects
273  bool moveMerged(const Location &loc);
274  bool moveMerged(const Location &loc, int16 num = 1);
275  bool moveMerged(const TilePoint &tp);
276 
277  // Extract a merged object with specified merge number from another
278  // merged object and return its ID
279  ObjectID extractMerged(const Location &loc, int16 num);
280  GameObject *extractMerged(int16 num);
281 
282  void moveRandom(const TilePoint &minLoc, const TilePoint &maxLoc); //move to random location Between Two Points
283 
284  ObjectID copy(const Location &loc); // copy item to new context
285  ObjectID copy(const Location &loc, int16 num); // copy item to new context
286 
287  // Create an alias of this object
288  ObjectID makeAlias(const Location &loc);
289 
290  // move the item with a given context
291  void move(int16 slot); // move to new slot in container
292 
293  // Activate the object
294  void activate();
295 
296  // Deactivate this object
297  void deactivate();
298 
299  // Determine if this object is an alias for another object
300  bool isAlias() {
301  return (_data.objectFlags & kObjectAlias) != 0;
302  }
303 
304  // check to see if item can be contained by this object
305  bool canContain(ObjectID item) {
306  return _prototype->canContain(thisID(), item);
307  }
308 
309  // check to see if item is contained by the object
310  bool isContaining(GameObject *item);
311 
312  // check if an instance of the specified target is contained in
313  // this object
314  bool isContaining(ObjectTarget *objTarget);
315 
316  // determine whether this object has a specified property
317  bool hasProperty(const ObjectProperty &objProp) {
318  return objProp.operator()(this);
319  }
320 
321  // Return the location of the first empty slot
322  TilePoint getFirstEmptySlot(GameObject *obj);
323 
324  // Return the location of the first available slot within this object
325  // in which to place the specified object
326  bool getAvailableSlot(
327  GameObject *obj,
328  TilePoint *slot,
329  bool canMerge = false,
330  GameObject **mergeObj = NULL);
331 
332  // Find a slot to place the specified object within this object and
333  // drop it in that slot
334  // If merge count == 0, then no auto-merging allowed
335  bool placeObject(
336  ObjectID enactor,
337  ObjectID objID,
338  bool canMerge = false,
339  int16 num = 1);
340 
341  // Drop the specified object on the ground in a semi-random location
342  void dropInventoryObject(GameObject *obj, int16 count = 1);
343 
344  //Get Specific Container From Object
345  GameObject *getIntangibleContainer(int containerType);
346 
347  // generic actions
348  bool use(ObjectID enactor) {
349  return _prototype->use(thisID(), enactor);
350  }
351  bool useOn(ObjectID enactor, ObjectID item) {
352  return _prototype->useOn(thisID(), enactor, item);
353  }
354 
355  bool useOn(ObjectID enactor, ActiveItem *item) {
356  return _prototype->useOn(thisID(), enactor, item);
357  }
358 
359  bool useOn(ObjectID enactor, Location &loc) {
360  return _prototype->useOn(thisID(), enactor, loc);
361  }
362 
363  // various verb actions that can take place
364  bool take(ObjectID enactor, int16 num = 1) {
365  return _prototype->take(thisID(), enactor, num);
366  }
367  bool drop(ObjectID enactor, const Location &l, int16 num = 1) {
368  return _prototype->drop(thisID(), enactor, l, num);
369  }
370  // drop an object onto another object and handle the result.
371  bool dropOn(ObjectID enactor, ObjectID target, int16 num = 1) {
372  return _prototype->dropOn(thisID(), enactor, target, num);
373  }
374  // drop this object on a TAG
375  bool dropOn(ObjectID enactor, ActiveItem *target, const Location &loc, int16 num = 1) {
376  return _prototype->dropOn(thisID(), enactor, target, loc, num);
377  }
378  bool open(ObjectID enactor) {
379  return _prototype->open(thisID(), enactor);
380  }
381  bool close(ObjectID enactor) {
382  return _prototype->close(thisID(), enactor);
383  }
384  bool strike(ObjectID enactor, ObjectID item) {
385  return _prototype->strike(thisID(), enactor, item);
386  }
387  bool damage(ObjectID enactor, ObjectID target) {
388  return _prototype->damage(thisID(), enactor, target);
389  }
390  bool eat(ObjectID enactor) {
391  return _prototype->eat(thisID(), enactor);
392  }
393  bool insert(ObjectID enactor, ObjectID item) {
394  return _prototype->insert(thisID(), enactor, item);
395  }
396  bool remove(ObjectID enactor) {
397  return _prototype->remove(thisID(), enactor);
398  }
399  bool acceptDrop(ObjectID enactor, ObjectID droppedObj, int count) {
400  return _prototype->acceptDrop(thisID(), enactor, droppedObj, count);
401  }
402  bool acceptDamage(
403  ObjectID enactor,
404  int8 absDamage,
405  effectDamageTypes dType = kDamageOther,
406  int8 dice = 0,
407  uint8 sides = 1,
408  int8 perDieMod = 0) {
409  if (_godmode)
410  return false;
411 
412  return _prototype->acceptDamage(
413  thisID(),
414  enactor,
415  absDamage,
416  dType,
417  dice,
418  sides,
419  perDieMod);
420  }
421  bool acceptHealing(ObjectID enactor, int8 absDamage, int8 dice = 0, uint8 sides = 1, int8 perDieMod = 0) {
422  return _prototype->acceptHealing(thisID(), enactor, absDamage, dice, sides, perDieMod);
423  }
424  bool acceptStrike(
425  ObjectID enactor,
426  ObjectID strikingObj,
427  uint8 skillIndex) {
428  return _prototype->acceptStrike(
429  thisID(),
430  enactor,
431  strikingObj,
432  skillIndex);
433  }
434  bool acceptLockToggle(ObjectID enactor, uint8 keyCode) {
435  return _prototype->acceptLockToggle(thisID(), enactor, keyCode);
436  }
437  bool acceptMix(ObjectID enactor, ObjectID mixObj) {
438  return _prototype->acceptMix(thisID(), enactor, mixObj);
439  }
440  bool acceptInsertion(ObjectID enactor, ObjectID item, int16 count) {
441  return _prototype->acceptInsertion(thisID(), enactor, item, count);
442  }
443  bool acceptInsertionAt(ObjectID enactor, ObjectID item, const TilePoint &where, int16 num = 1) {
444  return _prototype->acceptInsertionAt(thisID(), enactor, item, where, num);
445  }
446 
447  // query functions:
448  ObjectID possessor(); // return actor possessing this object
449 
450  // Access functions
451  ProtoObj *proto() {
452  return _prototype;
453  }
454  TilePoint getLocation() const {
455  return _data.location;
456  }
457  TilePoint getWorldLocation();
458  bool getWorldLocation(Location &loc);
459  Location notGetLocation();
460  Location notGetWorldLocation();
461 
462  // Return the name of this object (proper noun if it has one)
463  const char *objName() {
464  if (_data.nameIndex > 0)
465  return nameText((int16)_data.nameIndex);
466  else if (_prototype)
467  return nameText((int16)_prototype->nameIndex);
468 
469  return nameText(0);
470  }
471 
472  // return name of object, and it's quantity if merged
473  void objCursorText(char nameBuf[], const int8 size, int16 count = -1);
474 
475  // find out if this is a trueskill
476  bool isTrueSkill();
477 
478  // Access functions for name index
479  uint16 getNameIndex() {
480  return _data.nameIndex;
481  }
482  void setNameIndex(uint16 n) {
483  _data.nameIndex = n;
484  }
485 
486  // Return the name of this type of object
487  const char *protoName() {
488  return nameText(_prototype->nameIndex);
489  }
490 
491  // Update the state of this object. This function is called every
492  // frame for every active object.
493  void updateState();
494 
495  // Flag test functions
496  bool isOpen() {
497  return (int16)(_data.objectFlags & kObjectOpen);
498  }
499  bool isLocked() {
500  return (int16)(_data.objectFlags & kObjectLocked);
501  }
502  bool isImportant() {
503  return (int16)(_data.objectFlags & kObjectImportant);
504  }
505  bool isGhosted() {
506  return (_data.objectFlags & kObjectGhosted)
507  || (_prototype->flags & ResourceObjectPrototype::kObjPropGhosted);
508  }
509  bool isInvisible() {
510  return (_data.objectFlags & kObjectInvisible)
511  || (_prototype->flags & ResourceObjectPrototype::kObjPropHidden);
512  }
513  bool isMoving() {
514  return (int16)(_data.objectFlags & kObjectMoving);
515  }
516  bool isActivated() {
517  return (int16)(_data.objectFlags & kObjectActivated);
518  }
519 
520  void setScavengable(bool val) {
521  if (val)
522  _data.objectFlags |= kObjectScavengable;
523  else
524  _data.objectFlags &= ~kObjectScavengable;
525  }
526  bool isScavengable() {
527  return (_data.objectFlags & kObjectScavengable) != 0;
528  }
529 
530  void setObscured(bool val) {
531  if (val)
532  _data.objectFlags |= kObjectObscured;
533  else
534  _data.objectFlags &= ~kObjectObscured;
535  }
536  bool isObscured() {
537  return (_data.objectFlags & kObjectObscured) != 0;
538  }
539 
540  void setTriggeringTAG(bool val) {
541  if (val)
542  _data.objectFlags |= kObjectTriggeringTAG;
543  else
544  _data.objectFlags &= ~kObjectTriggeringTAG;
545  }
546  bool isTriggeringTAG() {
547  return (_data.objectFlags & kObjectTriggeringTAG) != 0;
548  }
549 
550  void setOnScreen(bool val) {
551  if (val)
552  _data.objectFlags |= kObjectOnScreen;
553  else
554  _data.objectFlags &= ~kObjectOnScreen;
555  }
556  bool isOnScreen() {
557  return (_data.objectFlags & kObjectOnScreen) != 0;
558  }
559 
560  void setSightedByCenter(bool val) {
561  if (val)
562  _data.objectFlags |= kObjectSightedByCenter;
563  else
564  _data.objectFlags &= ~kObjectSightedByCenter;
565  }
566  bool isSightedByCenter() {
567  return (_data.objectFlags & kObjectSightedByCenter) != 0;
568  }
569 
570  bool isMissile() {
571  return _prototype->isMissile();
572  }
573 
574  // image data
575  Sprite *getIconSprite(); // sprite when in inventory + cursor
576  Sprite *getGroundSprite(); // sprite when on ground
577 
578  // world interaction type flags
579  uint16 containmentSet();
580 
581  uint16 scriptClass() {
582  if (_data.script)
583  return _data.script;
584  if (_prototype)
585  return _prototype->script;
586  return 0;
587  }
588 
589  // General access functions
590 
591  // Script access functions
592  uint16 getScript() {
593  return _data.script;
594  }
595  void setScript(uint16 scr) {
596  _data.script = scr;
597  }
598 
599  // access function to set object flags
600  void setFlags(uint8 newval, uint8 changeMask) {
601  // Only change the flags spec'd by changeFlags
602  _data.objectFlags = (newval & changeMask)
603  | (_data.objectFlags & ~changeMask);
604  }
605 
606  // Access functions for hit points
607  uint8 getHitPoints() {
608  return _data.hitPoints;
609  }
610  void setHitPoints(uint8 hp) {
611  _data.hitPoints = hp;
612  }
613 
614  // Builds the color remapping for this object based on the
615  // prototype's color map
616  void getColorTranslation(ColorTable map) {
617  _prototype->getColorTranslation(map);
618  }
619 
620  // Functions to get and set prototype (used by scripts)
621  int32 getProtoNum();
622  void setProtoNum(int32 nProto);
623 
624  // Acess functions for extra data
625  uint16 getExtra() {
626  return _data.massCount;
627  }
628  void setExtra(uint16 x) {
629  _data.massCount = x;
630  }
631 
632  // Function to evaluate the effects of all enchantments
633  void evalEnchantments();
634 
635  bool makeSavingThrow() {
636  return _prototype->makeSavingThrow();
637  }
638 
639  // Generic range checking function
640  bool inRange(const TilePoint &tp, uint16 range);
641 
642  // Generic function to test if object can be picked up
643  bool isCarryable() {
644  return _prototype->mass <= 200 && _prototype->bulk <= 200;
645  }
646 
647  bool isMergeable() {
648  return (_prototype->flags & ResourceObjectPrototype::kObjPropMergeable) != 0;
649  }
650 
651  // A timer for this object has ticked
652  void timerTick(TimerID timer);
653 
654  // A sensor for this object has sensed an object
655  void senseObject(SensorID sensor, ObjectID sensedObj);
656 
657  // A sensor for this object has sensed an event
658  void senseEvent(
659  SensorID sensor,
660  int16 type,
661  ObjectID directObject,
662  ObjectID indirectObject);
663 
664  // Timer related member functions
665  bool addTimer(TimerID id);
666  bool addTimer(TimerID id, int16 frameInterval);
667  void removeTimer(TimerID id);
668  void removeAllTimers();
669 
670  // Sensor related member functions
671 private:
672  bool addSensor(Sensor *newSensor);
673 public:
674  bool addProtaganistSensor(SensorID id, int16 range);
675  bool addSpecificActorSensor(SensorID id, int16 range, Actor *a);
676  bool addSpecificObjectSensor(SensorID id, int16 range, ObjectID obj);
677  bool addActorPropertySensor(
678  SensorID id,
679  int16 range,
680  ActorPropertyID prop);
681  bool addObjectPropertySensor(
682  SensorID id,
683  int16 range,
684  ObjectPropertyID prop);
685  bool addEventSensor(SensorID id, int16 range, int16 eventType);
686  void removeSensor(SensorID id);
687  void removeAllSensors();
688 
689  bool canSenseProtaganist(SenseInfo &info, int16 range);
690  bool canSenseSpecificActor(SenseInfo &info, int16 range, Actor *a);
691  bool canSenseSpecificObject(SenseInfo &info, int16 range, ObjectID obj);
692  bool canSenseActorProperty(
693  SenseInfo &info,
694  int16 range,
695  ActorPropertyID prop);
696  bool canSenseObjectProperty(
697  SenseInfo &info,
698  int16 range,
699  ObjectPropertyID prop);
700 
701  static int32 canStackOrMerge(GameObject *dropObj, GameObject *target);
702  static void mergeWith(GameObject *dropObj, GameObject *target, int16 count);
703 
704  bool merge(ObjectID enactor, ObjectID objToMergeID, int16 count);
705  bool stack(ObjectID enactor, ObjectID objToStackID);
706 
707  bool canFitBulkwise(GameObject *obj) {
708  return _prototype->canFitBulkwise(this, obj);
709  }
710  bool canFitMasswise(GameObject *obj) {
711  return _prototype->canFitMasswise(this, obj);
712  }
713 
714  uint16 totalContainedMass();
715  uint16 totalContainedBulk();
716 
717  uint16 totalMass() {
718  return _prototype->mass * (isMergeable() ? getExtra() : 1)
719  + totalContainedMass();
720  }
721  uint16 totalBulk() {
722  return _prototype->bulk * (isMergeable() ? getExtra() : 1);
723  }
724 
725  uint16 massCapacity() {
726  return _prototype->massCapacity(this);
727  }
728  uint16 bulkCapacity() {
729  return _prototype->bulkCapacity(this);
730  }
731 };
732 
733 /* ===================================================================== *
734  Sector struct
735  * ===================================================================== */
736 
737 class Sector {
738 public:
739  uint16 _activationCount;
740  ObjectID _childID;
741 
742  Sector() :
743  _activationCount(0),
744  _childID(Nothing) {
745  }
746 
747  bool isActivated() {
748  return _activationCount != 0;
749  }
750 
751  void activate();
752  void deactivate();
753 
754  void write(Common::MemoryWriteStreamDynamic *out);
755  void read(Common::InSaveFile *in);
756 };
757 
758 /* ======================================================================= *
759  GameWorld: Describes a world within the game
760  * ======================================================================= */
761 
762 // Terminology note: A "sector" is a small portion of a map.
763 // All objects within a sector are stored on a single list.
764 
765 // The size of a sector (length of side) in UV coodinates.
766 // A sector is an area of about 4x4 metatiles.
767 
768 class GameWorld : public GameObject {
769 
770  friend void initWorlds();
771  friend void cleanupWorlds();
772  friend void buildDisplayList();
773 
774  friend class ProtoObj;
775  friend class GameObject;
776  friend class ObjectIterator;
777 
778 public:
779  TilePoint _size; // size of world in U/V coords
780  int16 _sectorArraySize; // size of sector array
781  Sector *_sectorArray; // array of sectors
782  int16 _mapNum; // map number for this world.
783 
784  // Default constructor
785  GameWorld() : _sectorArraySize(0), _sectorArray(nullptr), _mapNum(0) {}
786 
787  // Initial constructor
788  GameWorld(int16 map);
789 
791 
792  ~GameWorld();
793 
794  int32 archiveSize();
795 
796  void cleanup();
797 
798  Sector *getSector(int16 u, int16 v) {
799  if (u == -1 && v == -1)
800  return nullptr;
801 
802  if (v * _sectorArraySize + u >= _sectorArraySize * _sectorArraySize ||
803  v * _sectorArraySize + u < 0) {
804  warning("Sector::getSector: Invalid sector: (%d, %d) (sectorArraySize = %d)", u, v, _sectorArraySize);
805  return nullptr;
806  }
807 
808  return &(_sectorArray)[v * _sectorArraySize + u];
809  }
810 
811  TilePoint sectorSize() { // size of map in sectors
812  return TilePoint(_sectorArraySize, _sectorArraySize, 0);
813  }
814 
815  static uint32 IDtoMapNum(ObjectID id) {
816  assert(isWorld(id));
817  return ((GameWorld *)GameObject::objectAddress(id))->_mapNum;
818  }
819 };
820 
821 void setCurrentWorld(ObjectID worldID);
822 
823 extern GameWorld *currentWorld;
824 
825 /* ======================================================================= *
826  GameObject inline member function
827  * ======================================================================= */
828 
829 //------------------------------------------------------------------------
830 // Return the number of the map of the world on which this object resides.
831 
832 inline int16 GameObject::getMapNum() {
833  if (world())
834  return world()->_mapNum;
835  else if (_data.siblingID) {
836  GameObject *sibling = GameObject::objectAddress(_data.siblingID);
837  return sibling->getMapNum();
838  } else
839  return currentWorld->_mapNum;
840 }
841 
842 /* ======================================================================= *
843  Enchantment Class
844  * ======================================================================= */
845 //class Enchantment {
846 //
847 //public:
848 // Enchantment(ObjectID Skill,ObjectID Obj);
849 // ~Enchantment();
850 //
851 //};
852 
853 /* ===================================================================== *
854  ActiveRegion class
855  * ===================================================================== */
856 
858 
859  friend void initActiveRegions();
860  friend void cleanupActiveRegions();
861 
862  friend class ActiveRegionObjectIterator;
863 
864  ObjectID _anchor; // ID of object this region is attached to
865  TilePoint _anchorLoc; // Location of anchor
866  ObjectID _worldID;
867  TileRegion _region; // Region coords ( in sectors )
868 
869 public:
870 
871  enum {
872  kActiveRegionSize = 22
873  };
874 
875  ActiveRegion() : _anchor(0), _worldID(0) {}
876  void update();
877 
878  void read(Common::InSaveFile *in);
879  void write(Common::MemoryWriteStreamDynamic *out);
880 
881  // Return the current region in tile point coords
882  TileRegion getRegion() {
883  TileRegion tReg;
884 
885  tReg.min.u = _region.min.u << kSectorShift;
886  tReg.min.v = _region.min.v << kSectorShift;
887  tReg.max.u = _region.max.u << kSectorShift;
888  tReg.max.v = _region.max.v << kSectorShift;
889  tReg.min.z = tReg.max.z = 0;
890 
891  return tReg;
892  }
893 
894  // Return the region world
895  GameWorld *getWorld() {
896  return (GameWorld *)GameObject::objectAddress(_worldID);
897  }
898 };
899 
900 void updateActiveRegions();
901 
902 // Return a pointer to an active region given its PlayerActor's ID
903 ActiveRegion *getActiveRegion(PlayerActorID id);
904 
905 void initActiveRegions();
906 void saveActiveRegions(Common::OutSaveFile *outS);
907 void loadActiveRegions(Common::InSaveFile *in);
908 inline void cleanupActiveRegions() {}
909 
910 /* ======================================================================= *
911  ObjectIterator Class
912  * ======================================================================= */
913 
914 // This class simply defines a standard interface for all derived
915 // object iterator classes.
916 
918 public:
919  // Virtual destructor
920  virtual ~ObjectIterator() {}
921 
922  // Iteration functions
923  virtual ObjectID first(GameObject **obj) = 0;
924  virtual ObjectID next(GameObject **obj) = 0;
925 };
926 
927 /* ======================================================================= *
928  SectorRegionObjectIterator Class
929  * ======================================================================= */
930 
931 // This class iterates through every object within a given region of
932 // sectors.
933 
935 
936  TilePoint _minSector,
937  _maxSector,
938  _sectorCoords;
939  GameWorld *_searchWorld;
940  GameObject *_currentObject;
941 
942 public:
943  // Constructor
945 
946  // Constructor
948  GameWorld *world,
949  const TileRegion &sectorRegion) :
950  _searchWorld(world),
951  _minSector(sectorRegion.min),
952  _maxSector(sectorRegion.max),
953  _currentObject(nullptr) {
954  assert(_searchWorld != NULL);
955  assert(isWorld(_searchWorld));
956  }
957 
958 protected:
959  GameWorld *getSearchWorld() {
960  return _searchWorld;
961  }
962 
963 public:
964  // Iteration functions
965  ObjectID first(GameObject **obj);
966  ObjectID next(GameObject **obj);
967 };
968 
969 /* ======================================================================= *
970  RadialObjectIterator Class
971  * ======================================================================= */
972 
973 // This class will iterate through all objects within a given radius of
974 // a given center point.
975 
977 private:
978 
979  TilePoint _center;
980  int16 _radius;
981 
982  // Compute the region of sectors to pass to the ObjectIterator
983  // constructor
984  static TileRegion computeSectorRegion(
985  const TilePoint &sectors,
986  const TilePoint &center,
987  int16 radius);
988 
989  // Compute the distance to the specified point from the search
990  // center
991  virtual int16 computeDist(const TilePoint &tp) = 0;
992 
993 protected:
994 
995  // Simply return the center coordinates
996  TilePoint getCenter() {
997  return _center;
998  }
999 
1000 public:
1001 
1002  // Constructor
1004  GameWorld *world,
1005  const TilePoint &searchCenter,
1006  int16 distance) :
1008  world,
1009  computeSectorRegion(
1010  world->sectorSize(),
1011  searchCenter,
1012  distance)),
1013  _center(searchCenter),
1014  _radius(distance) {
1015  }
1016 
1017  // Return the first object found
1018  ObjectID first(GameObject **obj, int16 *dist);
1019  // Return the next object found
1020  ObjectID next(GameObject **obj, int16 *dist);
1021 
1022  // Return the first object found
1023  ObjectID first(GameObject **obj) {
1024  return first(obj, NULL);
1025  }
1026  // Return the next object found
1027  ObjectID next(GameObject **obj) {
1028  return next(obj, NULL);
1029  }
1030 };
1031 
1032 /* ======================================================================= *
1033  CircularObjectIterator Class
1034  * ======================================================================= */
1035 
1036 // Iterate through all objects within a circular region
1037 
1039 protected:
1040 
1041  // Compute the distance to the specified point from the center
1042  int16 computeDist(const TilePoint &tp);
1043 
1044 public:
1045  // Constructor
1047  GameWorld *world,
1048  const TilePoint &searchCenter,
1049  int16 distance) :
1050  RadialObjectIterator(world, searchCenter, distance) {
1051  }
1052 };
1053 
1054 /* ======================================================================= *
1055  RingObjectIterator Class
1056  * ======================================================================= */
1057 
1058 // Iterate through all objects within a circular region
1059 
1061 private:
1062 
1063  int16 _innerDist;
1064 
1065 public:
1066  // Constructor
1068  GameWorld *world,
1069  const TilePoint &searchCenter,
1070  int16 outerDistance,
1071  int16 innerDistance) :
1072  CircularObjectIterator(world, searchCenter, outerDistance) {
1073  _innerDist = innerDistance;
1074  }
1075 
1076  ObjectID first(GameObject **obj);
1077  ObjectID next(GameObject **obj);
1078 };
1079 
1080 /* ======================================================================= *
1081  DispRegionObjectIterator Class
1082  * ======================================================================= */
1083 
1084 // Iterate through all objects within a region parallel to the display
1085 // area
1086 
1088 private:
1089 
1090  // Compute the distance to the specified point from the center
1091  int16 computeDist(const TilePoint &tp);
1092 
1093 public:
1094  // Constructor
1096  GameWorld *world,
1097  const TilePoint &searchCenter,
1098  int16 distance) :
1099  RadialObjectIterator(world, searchCenter, distance) {
1100  }
1101 };
1102 
1103 /* ======================================================================= *
1104  RegionalObjectIterator Class
1105  * ======================================================================= */
1106 
1107 // Iterate through all objects within a rectangular region
1108 
1110 
1111  TilePoint minCoords,
1112  maxCoords;
1113 
1114  // Calculate the sector region to pass to the ObjectIterator
1115  // constructor
1116  static TileRegion computeSectorRegion(
1117  const TilePoint &sectors,
1118  const TilePoint &min,
1119  const TilePoint &max);
1120 
1121  // Test to see if the specified point is within the region
1122  bool inRegion(const TilePoint &tp);
1123 
1124 public:
1125  // Constructor
1127  GameWorld *world,
1128  const TilePoint &min,
1129  const TilePoint &max) :
1131  world,
1132  computeSectorRegion(world->sectorSize(), min, max)),
1133  minCoords(min),
1134  maxCoords(max) {
1135  }
1136 
1137  // Iteration functions
1138  virtual ObjectID first(GameObject **obj);
1139  virtual ObjectID next(GameObject **obj);
1140 };
1141 
1142 /* ======================================================================= *
1143  RectangularObjectIterator Class
1144  * ======================================================================= */
1145 
1146 // Iterate through all objects within a rectangular region
1147 
1149 
1150  TilePoint center,
1151  coords1,
1152  coords2,
1153  coords3,
1154  coords4;
1155 
1156  // Test to see if the specified point is within the region
1157  bool inRegion(const TilePoint &tp);
1158 
1159 public:
1160  // Constructor
1162  GameWorld *world,
1163  const TilePoint &c,
1164  const TilePoint &cdelta1,
1165  const TilePoint &cdelta2);
1166 
1167  virtual ObjectID first(GameObject **obj);
1168  virtual ObjectID next(GameObject **obj);
1169 
1170 };
1171 
1172 /* ======================================================================= *
1173  TriangularObjectIterator Class
1174  * ======================================================================= */
1175 
1176 // Iterate through all objects within a rectangular region
1177 
1179 
1180  TilePoint coords1,
1181  coords2,
1182  coords3;
1183 
1184  // Test to see if the specified point is within the region
1185  bool inRegion(const TilePoint &tp);
1186 
1187 public:
1188  // Constructor
1190  GameWorld *world,
1191  const TilePoint &c1,
1192  const TilePoint &c2,
1193  const TilePoint &c3);
1194 
1195  // Iteration functions
1196  ObjectID first(GameObject **obj);
1197  ObjectID next(GameObject **obj);
1198 };
1199 
1200 /* ======================================================================= *
1201  CenterRegionObjectIterator Class
1202  * ======================================================================= */
1203 
1205 
1206  static GameWorld *CenterWorld();
1207  static TilePoint MinCenterRegion();
1208  static TilePoint MaxCenterRegion();
1209 
1210 public:
1211  // Constructor
1213  RegionalObjectIterator(CenterWorld(),
1214  MinCenterRegion(),
1215  MaxCenterRegion()) {}
1216 
1217 };
1218 
1219 /* ======================================================================= *
1220  ActiveRegionObjectIterator Class
1221  * ======================================================================= */
1222 
1224 
1225  int16 _activeRegionIndex;
1226  TilePoint _baseSectorCoords,
1227  _size,
1228  _sectorCoords;
1229  uint8 _sectorBitMask;
1230  GameWorld *_currentWorld;
1231  GameObject *_currentObject;
1232 
1233  bool firstActiveRegion();
1234  bool nextActiveRegion();
1235  bool firstSector();
1236  bool nextSector();
1237 
1238 public:
1239  // Constructor
1240  ActiveRegionObjectIterator() : _activeRegionIndex(-1), _sectorBitMask(0), _currentWorld(nullptr), _currentObject(nullptr) {}
1241 
1242  // Iteration functions
1243  ObjectID first(GameObject **obj);
1244  ObjectID next(GameObject **obj);
1245 };
1246 
1247 /* ============================================================================ *
1248  Container Iterator Class
1249  * ============================================================================ */
1250 
1251 // This class iterates through every object within a container
1252 
1254  ObjectID _nextID;
1255 
1256 public:
1257  GameObject *_object;
1258 
1259  // Constructor
1260  ContainerIterator(GameObject *container);
1261 
1262  // Iteration function
1263  ObjectID next(GameObject **obj);
1264 };
1265 
1266 /* ============================================================================ *
1267  Recursive Container iterator Class
1268  * ============================================================================ */
1269 
1270 // This class iterates through every object within a container and
1271 // all of the containers within the container
1272 
1274  ObjectID _id,
1275  _root;
1276 
1277 public:
1278  // Constructor
1280  _root(container->thisID()), _id(0) {}
1281 
1282  // Iteration functions
1283  ObjectID first(GameObject **obj);
1284  ObjectID next(GameObject **obj);
1285 };
1286 
1287 /* ============================================================================ *
1288  Object sound effect struct
1289  * ============================================================================ */
1290 
1292  uint8 soundFXHitFlesh,
1293  soundFXHitHard,
1294  soundFXParried,
1295  soundFXMissed;
1296 };
1297 
1298 /* ======================================================================= *
1299  Misc Prototypes
1300  * ======================================================================= */
1301 
1302 
1303 // Defines values for sixteen missile facings, plus a value for no
1304 // missile facing.
1305 enum MissileFacings {
1306  kMissileUp,
1307  kMissileUpUpLf,
1308  kMissileUpLf,
1309  kMissileUpLfLf,
1310  kMissileLf,
1311  kMissileDnLfLf,
1312  kMissileDnLf,
1313  kMissileDnDnLf,
1314  kMissileDn,
1315  kMissileDnDnRt,
1316  kMissileDnRt,
1317  kMissileDnRtRt,
1318  kMissileRt,
1319  kMissileUpRtRt,
1320  kMissileUpRt,
1321  kMissileUpUpRt,
1322  kMissileNoFacing
1323 };
1324 
1325 enum blockageType {
1326  kBlockageNone = 0,
1327  kBlockageTerrain,
1328  kBlockageObject
1329 };
1330 
1331 uint32 objectTerrain(GameObject *obj);
1332 
1333 // Return an object which is in collision with another object.
1334 GameObject *objectCollision(GameObject *obj, GameWorld *world, const TilePoint &loc);
1335 
1336 // Test for line of sight between two objects
1337 bool lineOfSight(GameObject *obj1, GameObject *obj2, uint32 terrainMask);
1338 bool lineOfSight(GameObject *obj, const TilePoint &loc, uint32 terrainMask);
1339 bool lineOfSight(
1340  GameWorld *world,
1341  const TilePoint &loc1,
1342  const TilePoint &loc2,
1343  uint32 terrainMask);
1344 
1345 // Test if object is obscured by terrain
1346 bool objObscured(GameObject *testObj);
1347 
1348 // Determine which object mouse pointer is picking
1349 ObjectID pickObject(const StaticPoint32 &mouse, StaticTilePoint &objPos);
1350 
1351 // Create enchantment attach it to object
1352 ObjectID EnchantObject(
1353  ObjectID target,
1354  int enchantmentType,
1355  int duration);
1356 
1357 // Find an enchantment of a particular type
1358 ObjectID FindObjectEnchantment(
1359  ObjectID target,
1360  int enchantmentType);
1361 
1362 // Remove an enchantment of a particular type
1363 bool DispelObjectEnchantment(
1364  ObjectID target,
1365  int enchantmentType);
1366 
1367 // Function to eval the enchantments on an actor
1368 void evalActorEnchantments(Actor *a);
1369 
1370 // Function to eval the enchantments on an actor
1371 void evalObjectEnchantments(GameObject *obj);
1372 
1373 // Load prototypes from resource file
1374 void initPrototypes();
1375 
1376 // Cleanup the prototype lists
1377 void cleanupPrototypes();
1378 
1379 // Load the sound effects table
1380 void initObjectSoundFXTable();
1381 
1382 // Cleanup the sound effects table
1383 void cleanupObjectSoundFXTable();
1384 
1385 // Allocate array to hold the counts of the temp actors
1386 void initTempActorCount();
1387 
1388 // Save the array of temp actor counts
1389 void saveTempActorCount(Common::OutSaveFile *outS);
1390 
1391 // Load the array of temp actor counts
1392 void loadTempActorCount(Common::InSaveFile *in, int32 chunkSize);
1393 
1394 // Cleanup the array to temp actor counts
1395 void cleanupTempActorCount();
1396 
1397 // Increment the temporary actor count for the specified prototype
1398 void incTempActorCount(uint16 protoNum);
1399 
1400 // Decrement the temporary actor count for the specified prototype
1401 void decTempActorCount(uint16 protoNum);
1402 
1403 // Return the number of temporary actors for the specified prototype
1404 uint16 getTempActorCount(uint16 protoNum);
1405 
1406 // Init game worlds
1407 void initWorlds();
1408 
1409 // Save worlds to the save file
1410 void saveWorlds(Common::OutSaveFile *outS);
1411 
1412 // Load worlds from the save file
1413 void loadWorlds(Common::InSaveFile *in);
1414 
1415 // Cleanup game worlds
1416 void cleanupWorlds();
1417 
1418 // Initialize object list
1419 void initObjects();
1420 
1421 // Save the objects to the save file
1422 void saveObjects(Common::OutSaveFile *outS);
1423 
1424 // Load the objects from the save file
1425 void loadObjects(Common::InSaveFile *in);
1426 
1427 // Cleanup object list
1428 void cleanupObjects();
1429 
1430 // Do background processing for objects
1431 void doBackgroundSimulation();
1432 
1433 void pauseBackgroundSimulation();
1434 void resumeBackgroundSimulation();
1435 
1436 // This function simply calls the GameObject::updateState() method
1437 // for all active objects directly within a world.
1438 void updateObjectStates();
1439 
1440 void pauseObjectStates();
1441 void resumeObjectStates();
1442 
1443 void readyContainerSetup();
1444 void cleanupReadyContainers();
1445 
1446 } // end of namespace Saga2
1447 
1448 #endif
Definition: motion.h:536
Definition: str.h:59
Definition: actor.h:289
Definition: tile.h:388
Definition: objects.h:63
Definition: objproto.h:371
Definition: objproto.h:105
Definition: objects.h:917
Definition: objects.h:1109
Definition: contain.h:302
Definition: savefile.h:54
void warning(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: target.h:401
Definition: array.h:52
Definition: motion.h:92
Definition: actor.h:32
Definition: idtypes.h:124
Definition: objects.h:1060
Definition: objproto.h:880
Definition: objproto.h:1542
Definition: memstream.h:194
Definition: sprite.h:42
Definition: tcoords.h:127
Definition: stream.h:745
Definition: sensor.h:100
Definition: objects.h:1148
Definition: objects.h:1178
Definition: actor.h:589
Definition: tcoords.h:222
Definition: tcoords.h:48
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
Definition: objects.h:84
Definition: contain.h:313
Definition: objects.h:934
Definition: objects.h:1273
Definition: sensor.h:147
Definition: objproto.h:798
Definition: objects.h:768
Definition: objects.h:118
Out move(In first, In last, Out dst)
Definition: algorithm.h:109
Definition: objects.h:1204
Definition: objects.h:1253
Definition: objects.h:1087
Definition: objects.h:1291
Definition: objects.h:976
Definition: rect.h:140
Definition: objects.h:857
Definition: objects.h:1223
Definition: objproto.h:1493
Definition: property.h:45
Definition: objproto.h:902
Definition: objects.h:1038
Definition: objects.h:737