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
32namespace Saga2 {
33
34/* ======================================================================= *
35 GameObject: Describes an instance of an object
36 * ======================================================================= */
37
38class GameWorld;
39
40const uint16 unlimitedCapacity = maxuint16;
41
42enum 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
54enum {
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
84struct 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
114void initActors();
115void saveActors(Common::OutSaveFile *outS);
116void loadActors(Common::InSaveFile *in);
117void cleanupActors();
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
149private:
150
151 // container info
152 enum {
153 kMaxRow = 20,
154 kMaxCol = 4
155 };
156
157public:
158
159 ObjectID thisID(); // calculate our own ID value
160
161 static const char *nameText(uint16 index);
162
163protected:
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
173public:
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
671private:
672 bool addSensor(Sensor *newSensor);
673public:
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
737class Sector {
738public:
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
768class 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
778public:
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
821void setCurrentWorld(ObjectID worldID);
822
823extern 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
832inline 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
869public:
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
900void updateActiveRegions();
901
902// Return a pointer to an active region given its PlayerActor's ID
903ActiveRegion *getActiveRegion(PlayerActorID id);
904
905void initActiveRegions();
906void saveActiveRegions(Common::OutSaveFile *outS);
907void loadActiveRegions(Common::InSaveFile *in);
908inline 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
918public:
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
942public:
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
958protected:
959 GameWorld *getSearchWorld() {
960 return _searchWorld;
961 }
962
963public:
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
977private:
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
993protected:
994
995 // Simply return the center coordinates
996 TilePoint getCenter() {
997 return _center;
998 }
999
1000public:
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
1039protected:
1040
1041 // Compute the distance to the specified point from the center
1042 int16 computeDist(const TilePoint &tp);
1043
1044public:
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
1061private:
1062
1063 int16 _innerDist;
1064
1065public:
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
1088private:
1089
1090 // Compute the distance to the specified point from the center
1091 int16 computeDist(const TilePoint &tp);
1092
1093public:
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
1124public:
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
1159public:
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
1187public:
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
1210public:
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
1238public:
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
1256public:
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
1277public:
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.
1305enum 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
1325enum blockageType {
1326 kBlockageNone = 0,
1327 kBlockageTerrain,
1328 kBlockageObject
1329};
1330
1331uint32 objectTerrain(GameObject *obj);
1332
1333// Return an object which is in collision with another object.
1334GameObject *objectCollision(GameObject *obj, GameWorld *world, const TilePoint &loc);
1335
1336// Test for line of sight between two objects
1337bool lineOfSight(GameObject *obj1, GameObject *obj2, uint32 terrainMask);
1338bool lineOfSight(GameObject *obj, const TilePoint &loc, uint32 terrainMask);
1339bool lineOfSight(
1340 GameWorld *world,
1341 const TilePoint &loc1,
1342 const TilePoint &loc2,
1343 uint32 terrainMask);
1344
1345// Test if object is obscured by terrain
1346bool objObscured(GameObject *testObj);
1347
1348// Determine which object mouse pointer is picking
1349ObjectID pickObject(const StaticPoint32 &mouse, StaticTilePoint &objPos);
1350
1351// Create enchantment attach it to object
1352ObjectID EnchantObject(
1353 ObjectID target,
1354 int enchantmentType,
1355 int duration);
1356
1357// Find an enchantment of a particular type
1358ObjectID FindObjectEnchantment(
1359 ObjectID target,
1360 int enchantmentType);
1361
1362// Remove an enchantment of a particular type
1363bool DispelObjectEnchantment(
1364 ObjectID target,
1365 int enchantmentType);
1366
1367// Function to eval the enchantments on an actor
1368void evalActorEnchantments(Actor *a);
1369
1370// Function to eval the enchantments on an actor
1371void evalObjectEnchantments(GameObject *obj);
1372
1373// Load prototypes from resource file
1374void initPrototypes();
1375
1376// Cleanup the prototype lists
1377void cleanupPrototypes();
1378
1379// Load the sound effects table
1380void initObjectSoundFXTable();
1381
1382// Cleanup the sound effects table
1383void cleanupObjectSoundFXTable();
1384
1385// Allocate array to hold the counts of the temp actors
1386void initTempActorCount();
1387
1388// Save the array of temp actor counts
1389void saveTempActorCount(Common::OutSaveFile *outS);
1390
1391// Load the array of temp actor counts
1392void loadTempActorCount(Common::InSaveFile *in, int32 chunkSize);
1393
1394// Cleanup the array to temp actor counts
1395void cleanupTempActorCount();
1396
1397// Increment the temporary actor count for the specified prototype
1398void incTempActorCount(uint16 protoNum);
1399
1400// Decrement the temporary actor count for the specified prototype
1401void decTempActorCount(uint16 protoNum);
1402
1403// Return the number of temporary actors for the specified prototype
1404uint16 getTempActorCount(uint16 protoNum);
1405
1406// Init game worlds
1407void initWorlds();
1408
1409// Save worlds to the save file
1410void saveWorlds(Common::OutSaveFile *outS);
1411
1412// Load worlds from the save file
1413void loadWorlds(Common::InSaveFile *in);
1414
1415// Cleanup game worlds
1416void cleanupWorlds();
1417
1418// Initialize object list
1419void initObjects();
1420
1421// Save the objects to the save file
1422void saveObjects(Common::OutSaveFile *outS);
1423
1424// Load the objects from the save file
1425void loadObjects(Common::InSaveFile *in);
1426
1427// Cleanup object list
1428void cleanupObjects();
1429
1430// Do background processing for objects
1431void doBackgroundSimulation();
1432
1433void pauseBackgroundSimulation();
1434void resumeBackgroundSimulation();
1435
1436// This function simply calls the GameObject::updateState() method
1437// for all active objects directly within a world.
1438void updateObjectStates();
1439
1440void pauseObjectStates();
1441void resumeObjectStates();
1442
1443void readyContainerSetup();
1444void cleanupReadyContainers();
1445
1446} // end of namespace Saga2
1447
1448#endif
Definition: array.h:52
Definition: memstream.h:194
Definition: savefile.h:54
Definition: stream.h:745
Definition: str.h:59
Definition: tile.h:388
Definition: objects.h:857
Definition: objects.h:1223
Definition: actor.h:584
Definition: actor.h:284
Definition: objproto.h:902
Definition: objects.h:1204
Definition: objects.h:1038
Definition: objects.h:1253
Definition: objects.h:1087
Definition: contain.h:313
Definition: objects.h:118
Definition: objects.h:768
Definition: objproto.h:1542
Definition: contain.h:302
Definition: objproto.h:880
Definition: objproto.h:105
Definition: motion.h:92
Definition: motion.h:536
Definition: objects.h:917
Definition: target.h:401
Definition: objproto.h:798
Definition: property.h:45
Definition: objproto.h:371
Definition: objects.h:976
Definition: objects.h:1148
Definition: objects.h:1273
Definition: objects.h:1109
Definition: objects.h:1060
Definition: objects.h:737
Definition: objects.h:934
Definition: sensor.h:147
Definition: objproto.h:1493
Definition: objects.h:1178
Out move(In first, In last, Out dst)
Definition: algorithm.h:109
It remove(It first, It last, const T &val)
Definition: algorithm.h:466
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
void warning(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: idtypes.h:124
Definition: objects.h:84
Definition: objects.h:1291
Definition: objects.h:63
Definition: sensor.h:100
Definition: sprite.h:42
Definition: tcoords.h:127
Definition: tcoords.h:222