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
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 *
22 * Based on the original sources
23 * Faery Tale II -- The Halls of the Dead
24 * (c) 1993-1996 The Wyrmkeep Entertainment Co.
25 */
26
27 #ifndef SAGA2_ACTOR_H
28 #define SAGA2_ACTOR_H
29
30 #include "saga2/objects.h"
31 #include "saga2/saveload.h"
32
33 namespace Saga2 {
34
35 class ActorAssignment;
36 class Band;
37 class MotionTask;
38 class TaskStack;
39
40 const int bandingDist = kSectorSize * 2;
41 const int actorScriptVars = 4;
42
43 /* ===================================================================== *
44 Actor character attributes
45 * ===================================================================== */
46
47 // Defines the colors of MANA
48
49 enum ActorSkillID {
50 skillIDArchery = 0,
51 skillIDSwordcraft,
52 skillIDShieldcraft,
53 skillIDBludgeon,
54 skillIDThrowing, // gone
55 skillIDSpellcraft,
56 skillIDStealth, // gone
57 skillIDAgility,
58 skillIDBrawn,
59 skillIDLockpick, // gone
60 skillIDPilfer, // gone
61 skillIDFirstAid, // gone
62 skillIDSpotHidden, // gone
63 numSkills
64 };
65
66 enum ArmorObjectTypes {
67 SHIRT_ARMOR = 0,
68 BOOT_ARMOR,
69 BRACER_ARMOR,
70 HELM_ARMOR,
71 NECKLACE_ARMOR,
72 CLOAK_ARMOR,
73 RING_ARMOR,
74
75 ARMOR_COUNT
76 };
77
78 /* ===================================================================== *
79 ArmorAttributes struct
80 * ===================================================================== */
81
82 struct ArmorAttributes {
83 uint8 damageAbsorbtion,
84 damageDivider,
85 defenseBonus;
86 };
87
88 /* ===================================================================== *
89 ActorAttributes structure
90 * ===================================================================== */
91
92 // this enum acts as a layer of indirection for the unioned allSkills
93 // array.
94
95
96 // This defines the basic skills possessed by an actor
97 struct ActorAttributes {
98 enum skillInfo {
99 skillBasePercent = 100,
100 skillFracPointsPerLevel = 5, // this being twenty and levels at 5
101 skillLevels = 20, // will make the advancement calc quick & easy
102 skillMaxLevel = skillFracPointsPerLevel * skillLevels
103 };
104
105 enum vitalityInfo {
106 vitalityLimit = 256
107 };
108
109 // Automatic skills
110 uint8 archery, // Accuracy of missile weapons
111 swordcraft, // Accuracy of bladed melee weapons
112 shieldcraft, // Actor's ability to use a shield
113 bludgeon, // Accuracy of non-bladed melee weapons
114 throwing, // Ability to throw objects accurately
115 spellcraft, // Accuracy of spell combat
116 stealth, // Ability to remain unnoticed
117 agility, // Ability to dodge
118 brawn, // Ability to lift, and damage of weapons
119 lockpick; // Ability to pick locks
120
121 // Manual skills
122 uint8 pilfer, // Ability to "lift" an item
123 firstAid, // Ability to heal recent injuries
124 spotHidden; // Ability to spot hidden objects
125
126 // Pad byte for alignment
127 int8 pad;
128
129 // Hit-points
130 int16 vitality;
131
132 // Magic energy
133 int16 redMana,
134 orangeMana,
135 yellowMana,
136 greenMana,
137 blueMana,
138 violetMana;
139
skillActorAttributes140 uint8 &skill(int16 id) {
141 switch (id) {
142 case skillIDArchery: return archery;
143 case skillIDSwordcraft: return swordcraft;
144 case skillIDShieldcraft: return shieldcraft;
145 case skillIDBludgeon: return bludgeon;
146 case skillIDThrowing: return throwing;
147 case skillIDSpellcraft: return spellcraft;
148 case skillIDStealth: return stealth;
149 case skillIDAgility: return agility;
150 case skillIDBrawn: return brawn;
151 case skillIDLockpick: return lockpick;
152 case skillIDPilfer: return pilfer;
153 case skillIDFirstAid: return firstAid;
154 case skillIDSpotHidden: return spotHidden;
155 }
156 error("Incorrect skill id: %d", id);
157 }
manaActorAttributes158 int16 &mana(int16 id) {
159 switch (id) {
160 case manaIDRed: return redMana;
161 case manaIDOrange: return orangeMana;
162 case manaIDYellow: return yellowMana;
163 case manaIDGreen: return greenMana;
164 case manaIDBlue: return blueMana;
165 case manaIDViolet: return violetMana;
166 }
167 error("Incorrect mana id: %d", id);
168 }
169
getSkillLevelActorAttributes170 uint8 getSkillLevel(int16 id) {
171 return skill(id) / skillFracPointsPerLevel + 1;
172 }
173
readActorAttributes174 void read(Common::InSaveFile *in) {
175 archery = in->readByte();
176 swordcraft = in->readByte();
177 shieldcraft = in->readByte();
178 bludgeon = in->readByte();
179 throwing = in->readByte();
180 spellcraft = in->readByte();
181 stealth = in->readByte();
182 agility = in->readByte();
183 brawn = in->readByte();
184 lockpick = in->readByte();
185 pilfer = in->readByte();
186 firstAid = in->readByte();
187 spotHidden = in->readByte();
188 pad = in->readSByte();
189 vitality = in->readSint16LE();
190 redMana = in->readSint16LE();
191 orangeMana = in->readSint16LE();
192 yellowMana = in->readSint16LE();
193 greenMana = in->readSint16LE();
194 blueMana = in->readSint16LE();
195 violetMana = in->readSint16LE();
196 }
197
writeActorAttributes198 void write(Common::MemoryWriteStreamDynamic *out) {
199 out->writeByte(archery);
200 out->writeByte(swordcraft);
201 out->writeByte(shieldcraft);
202 out->writeByte(bludgeon);
203 out->writeByte(throwing);
204 out->writeByte(spellcraft);
205 out->writeByte(stealth);
206 out->writeByte(agility);
207 out->writeByte(brawn);
208 out->writeByte(lockpick);
209 out->writeByte(pilfer);
210 out->writeByte(firstAid);
211 out->writeByte(spotHidden);
212 out->writeSByte(pad);
213 out->writeSint16LE(vitality);
214 out->writeSint16LE(redMana);
215 out->writeSint16LE(orangeMana);
216 out->writeSint16LE(yellowMana);
217 out->writeSint16LE(greenMana);
218 out->writeSint16LE(blueMana);
219 out->writeSint16LE(violetMana);
220 }
221 }; // 28 bytes
222
223
224 const int baseCarryingCapacity = 100;
225 const int carryingCapacityBonusPerBrawn = 200 / ActorAttributes::skillLevels;
226
227 /* ===================================================================== *
228 ResourceActorProtoExtension structure
229 * ===================================================================== */
230
231 enum combatBehaviorTypes {
232 behaviorHungry,
233 behaviorCowardly,
234 behaviorBerserk,
235 behaviorSmart
236 };
237
238 // This defines the additional data fields needed for actor prototypes
239 struct ResourceActorProtoExtension {
240
241 ActorAttributes baseStats; // Base stats for non-player actors
242
243 // Defines behavior for combat tactics.
244 uint8 combatBehavior;
245 uint8 gruntStyle;
246
247 uint32 baseEffectFlags; // special effects, see EFFECTS.H
248
249 // Default constructor -- do nothing
ResourceActorProtoExtensionResourceActorProtoExtension250 ResourceActorProtoExtension(void) {
251 memset(&baseStats, 0, sizeof(baseStats));
252
253 combatBehavior = 0;
254 gruntStyle = 0;
255 baseEffectFlags = 0;
256 }
257
258 // Copy constructor
ResourceActorProtoExtensionResourceActorProtoExtension259 ResourceActorProtoExtension(ResourceActorProtoExtension &ext) {
260 memcpy(this, &ext, sizeof(ResourceActorProtoExtension));
261 }
262
loadResourceActorProtoExtension263 void load(Common::SeekableReadStream *stream) {
264 baseStats.read(stream);
265 combatBehavior = stream->readByte();
266 gruntStyle = stream->readByte();
267 baseEffectFlags = stream->readUint32LE();
268 }
269 }; // 28 bytes
270
271 /* ===================================================================== *
272 ResourceActorPrototype structure
273 * ===================================================================== */
274
275 // Defines the actor prototype data as read from the resource file
276 struct ResourceActorPrototype {
277 ResourceObjectPrototype proto; // Standard prototype data
278 ResourceActorProtoExtension ext; // Extended actor data
279
loadResourceActorPrototype280 void load(Common::SeekableReadStream *stream) {
281 proto.load(stream);
282 ext.load(stream);
283 }
284 };
285
286 /* ===================================================================== *
287 ActorProto prototype behavior for Actors
288 * ===================================================================== */
289
290 class ActorProto : public ProtoObj, public ResourceActorProtoExtension {
291
292 private:
293 enum {
294 ViewableRows = 3,
295 ViewableCols = 3,
296 maxRows = 3,
297 maxCols = 3
298 };
299
300 public:
ActorProto(ResourceActorPrototype & a)301 ActorProto(ResourceActorPrototype &a) :
302 ProtoObj(a.proto),
303 ResourceActorProtoExtension(a.ext) {
304 }
305
306 // returns the containment type flags for this object
307 virtual uint16 containmentSet(void);
308
309 // returns true if this object can contain another object
310 virtual bool canContain(ObjectID dObj, ObjectID item);
311
312 // Determine if this object can contain another object at a
313 // specified slot
314 virtual bool canContainAt(
315 ObjectID dObj,
316 ObjectID item,
317 const TilePoint &where);
318
319 weaponID getWeaponID(void);
320
321 // use this actor
322 bool useAction(ObjectID dObj, ObjectID enactor);
323
324 // open this actor
325 bool canOpen(ObjectID dObj, ObjectID enactor);
326 bool openAction(ObjectID dObj, ObjectID enactor);
327
328 // close this actor
329 bool closeAction(ObjectID dObj, ObjectID enactor);
330
331 bool strikeAction(
332 ObjectID dObj,
333 ObjectID enactor,
334 ObjectID item);
335
336 bool damageAction(
337 ObjectID dObj,
338 ObjectID enactor,
339 ObjectID target);
340
341 // drop another object onto this actor.
342 bool acceptDropAction(
343 ObjectID dObj,
344 ObjectID enactor,
345 ObjectID droppedObj,
346 int count);
347
348 // cause damage directly
349 bool acceptDamageAction(
350 ObjectID dObj,
351 ObjectID enactor,
352 int8 absDamage,
353 effectDamageTypes dType,
354 int8 dice,
355 uint8 sides,
356 int8 perDieMod);
357
358 // cause healing directly
359 bool acceptHealingAction(ObjectID dObj, ObjectID enactor, int8 healing);
360
361 // Accept strike from an object (allows this actor to cause
362 // damage to the striking object).
363 bool acceptStrikeAction(
364 ObjectID dObj,
365 ObjectID enactor,
366 ObjectID strikingObj,
367 uint8 skillIndex);
368
369 // Handle the results of an object being inserted into this object
370 // at the specified slot
371 bool acceptInsertionAtAction(
372 ObjectID dObj,
373 ObjectID enactor,
374 ObjectID item,
375 const TilePoint &where,
376 int16 num = 1);
377
378 // Initiate an attack using this type of object
379 virtual void initiateAttack(ObjectID attacker, ObjectID target);
380
381 // Given an object sound effect record, which sound should be made
382 // when this object is damaged
383 virtual uint8 getDamageSound(const ObjectSoundFXs &soundFXs);
384
385 // Do the background processing, if needed, for this object.
386 void doBackgroundUpdate(GameObject *obj);
387
388 // Cause the user's associated skill to grow
389 void applySkillGrowth(ObjectID enactor, uint8 points = 1);
390
391 bool greetActor(
392 ObjectID dObj, // object dropped on
393 ObjectID enactor); // person doing dropping
394
395 public:
getViewableRows(void)396 virtual uint16 getViewableRows(void) {
397 return ViewableRows;
398 }
getViewableCols(void)399 virtual uint16 getViewableCols(void) {
400 return ViewableCols;
401 }
getMaxRows(void)402 virtual uint16 getMaxRows(void) {
403 return maxRows;
404 }
getMaxCols(void)405 virtual uint16 getMaxCols(void) {
406 return maxCols;
407 }
408
409 virtual bool canFitBulkwise(GameObject *container, GameObject *obj);
410 virtual bool canFitMasswise(GameObject *container, GameObject *obj);
411
412 virtual uint16 massCapacity(GameObject *container);
413 virtual uint16 bulkCapacity(GameObject *container);
414 };
415
416 /* ============================================================================ *
417 Actor: Describes an instance of a character
418 * ============================================================================ */
419
420 enum actorCreationFlags {
421 actorPermanent = (1 << 0)
422 };
423
424 enum DispositionType {
425 dispositionFriendly,
426 dispositionEnemy,
427
428 dispositionPlayer
429 };
430
431 enum actionSequenceOptions {
432
433 // Flags set by call to setAction
434 animateRepeat = (1 << 0), // repeat animation when done
435 animateReverse = (1 << 1), // animate in reverse direction
436 animateAlternate = (1 << 2), // both directions, back & forth
437 animateRandom = (1 << 3), // pick a random frame
438 animateNoRestart = (1 << 4), // don't reset from start
439
440 // This flag is set if the animation has been put on hold until
441 // the actor's appearance is reloaded.
442 animateOnHold = (1 << 5),
443
444 // This flag is set if the final frame of the animation has
445 // been reached.
446 animateFinished = (1 << 6),
447
448 // This flag gets set if the sprite could not be displayed
449 // because it's bank hasn't been loaded yet.
450 animateNotLoaded = (1 << 7)
451 };
452
453 // Various types of action sequences
454
455
456 enum ActorAnimationTypes {
457
458 // Various types of stands
459 actionStand = 0, // standing still
460 actionWaitAgressive, // an agressive wait cycle
461 actionWaitImpatient, // an impatient wait cycle
462 actionWaitFriendly, // a a friendly wait cycle
463
464 // Walking and running
465 actionWalk, // walking motion
466 actionRun, // running motion
467
468 // Squatting
469 actionDuck, // stoop to dodge sword
470 actionStoop, // stoop to pick up object
471
472 // Jumping
473 actionFreeFall, // how he looks in ballistic
474 actionFreeFallRunning, // a running leap (free fall)
475 actionJumpUp, // begin jump straight up
476 actionJumpFwd, // begin jump forward
477 actionJumpBack, // begin jump back in surprise
478 actionLand, // land after jump
479 actionFallBadly, // after a very long fall
480
481 // Climbing
482 actionClimbLadder, // climb a ladder (2 directions)
483
484 // Talking & interacting
485 actionTalk, // talking
486 actionGesture, // gesture with hands or body
487 actionGiveItem, // give or take item
488
489 // Two-handed weapon use
490 actionTwoHandSwingHigh, // full overhead swing aim high
491 actionTwoHandSwingLow, // full overhead swing aim low
492 actionTwoHandSwingLeftHigh, // partial swing on left (high)
493 actionTwoHandSwingLeftLow, // partial swing on left (low)
494 actionTwoHandSwingRightHigh, // partial swing on rgt (high)
495 actionTwoHandSwingRightLow, // partial swing on rgt (low)
496 actionTwoHandParry, // hold sword up to parry
497
498 // One-handed weapon use
499 actionSwingHigh, // one-handed swing (high)
500 actionSwingLow, // one-handed swing (low)
501 actionParryHigh, // one-handed parry (high)
502 actionParryLow, // one-handed parry (low)
503 actionShieldParry, // parry with shield
504
505 actionThrowObject, // throw
506
507 // Other combat actions
508 actionFireBow, // fire an arrow
509 actionCastSpell, // cast a magic spell
510 actionUseWand, // cast a magic spell w/wand
511 actionUseStaff, // cast a magic spell w/staff
512 actionHit, // show impact of blow
513 actionKnockedDown, // knocked down by opponent
514 actionDie, // death agony
515
516 // Passive actions
517 actionSleep, // sleeping
518 actionDead, // dead body on ground
519 actionSit, // sitting at table
520
521 // Misc actions built from other frames
522 actionListenAtDoor, // listening at doors
523 actionShoveDoor, // try to force a door open
524 actionSpecial1, // special Action
525 actionSpecial2, // special Action
526 actionSpecial3, // special Action
527 actionSpecial4, // special Action
528 actionSpecial5, // special Action
529 actionSpecial6, // special Action
530 actionSpecial7, // special Action
531 actionSpecial8 // special Action
532 };
533
534 enum ActorGoalTypes {
535 actorGoalFollowAssignment,
536 actorGoalPreserveSelf,
537 actorGoalAttackEnemy,
538 actorGoalFollowLeader,
539 actorGoalAvoidEnemies
540 };
541
542 // The actor structure will be divided into two parts. The
543 // ResourceActor structure defines the data as it is stored in the
544 // resource file. The Actor structure has a copy of all of the
545 // ResourceActor data members, plus data members which will be
546 // initialized and used during run time.
547
548 struct ResourceActor : public ResourceGameObject {
549
550 // Social loyalty
551 uint8 faction; // actor's faction
552
553 // Appearance attribute
554 uint8 colorScheme; // indirect color map
555
556 int32 appearanceID; // appearnce of this actor
557
558 // Personality attributes
559 int8 attitude, // cooperativeness
560 mood; // happiness
561 uint8 disposition; // actor disposition
562 // 0 = friendly, 1 = enemy,
563 // 2 = Julian, 3 = Philip,
564 // 4 = Kevin
565
566 // Character orientation
567 Direction currentFacing; // current facing direction
568
569 // Tether info
570 int16 tetherLocU; // tether U coordinate
571 int16 tetherLocV; // tether V coordinate
572 int16 tetherDist; // length of tether
573
574 // Held objects
575 ObjectID leftHandObject, // object held in left hand.
576 rightHandObject; // object held in right hand.
577
578 // Knowledge packets
579 uint16 knowledge[16];
580
581 // Schedule script ID
582 uint16 schedule;
583
584 // Pad bytes
585 uint8 reserved[18];
586
587 ResourceActor(Common::SeekableReadStream *stream);
588 };
589
590 class Actor : public GameObject {
591 friend class ActorProto;
592 friend class MotionTask;
593 friend class Task;
594 friend class TaskStack;
595
596 public:
597
598 // Resource fields
599
600 // Social loyalty
601 uint8 _faction; // actor's faction
602
603 // Appearance attribute
604 uint8 _colorScheme; // indirect color map
605
606 int32 _appearanceID; // appearnce of this actor
607
608 // Personality attributes
609 int8 _attitude, // cooperativeness
610 _mood; // happiness
611 uint8 _disposition; // actor disposition
612 // 0 = friendly, 1 = enemy,
613 // 2 = Julian, 3 = Philip,
614 // 4 = Kevin
615
616 // Character orientation
617 Direction _currentFacing; // current facing direction
618
619 // Tether info
620 int16 _tetherLocU; // tether U coordinate
621 int16 _tetherLocV; // tether V coordinate
622 int16 _tetherDist; // length of tether
623
624 // Held objects
625 ObjectID _leftHandObject, // object held in left hand.
626 _rightHandObject; // object held in right hand.
627
628 // Knowledge packets
629 uint16 _knowledge[16];
630
631 // Schedule script ID
632 uint16 _schedule;
633
634 // Run-time fields
635
636 uint8 _conversationMemory[4];// last things talked about
637
638 // Sprite animation variables
639 uint8 _currentAnimation, // current action sequence
640 _currentPose, // current pose in sequence
641 _animationFlags; // current posing flags
642
643 // Various actor flags
644 enum {
645 lobotomized = (1 << 0),
646 temporary = (1 << 1),
647 afraid = (1 << 2),
648 hasAssignment = (1 << 3),
649 specialAttack = (1 << 4),
650 fightStance = (1 << 5)
651 };
652
653 uint8 _flags;
654
655 // Contains sprite index and positioning info for the current
656 // actor state.
657 ActorPose _poseInfo; // current animation state
658
659 // Pointer to the appearance record (sprite array) for this actor.
660 ActorAppearance *_appearance; // appearance structs
661
662 int16 _cycleCount; // misc counter for actions
663 int16 _kludgeCount; // another misc counter
664
665 uint32 _enchantmentFlags; // flags indicating racial
666 // abilities and enchantments
667
668 // Movement attributes
669 MotionTask *_moveTask;
670
671 // Current task
672 TaskStack *_curTask;
673
674 // Current goal type
675 uint8 _currentGoal;
676
677 // Used for deltayed deactivation (and also to word-align struct)
678 uint8 _deactivationCounter;
679
680 // Assignment
681 ActorAssignment *_assignment;
682 // assignments
683
684 // Current effective stats
685 ActorAttributes _effectiveStats;
686
687 uint8 _actionCounter; // coordinate moves in combat
688
689 uint16 _effectiveResistance; // resistances (see EFFECTS.H)
690 uint16 _effectiveImmunity; // immunities (see EFFECTS.H)
691
692 int16 _recPointsPerUpdate; // fractional vitality recovery
693
694 int16 _currentRecoveryPoints; // fraction left from last recovery
695
696 enum vitalityRecovery {
697 recPointsPerVitality = 10
698 };
699
700
701 Actor *_leader; // This actor's leader
702 ObjectID _leaderID;
703 Band *_followers; // This actor's band of followers
704 BandID _followersID;
705
706 ObjectID _armorObjects[ARMOR_COUNT]; // armor objects being worn
707
708 GameObject *_currentTarget;
709 ObjectID _currentTargetID;
710
711 int16 _scriptVar[actorScriptVars]; // scratch variables for scripter use
712
713 // Member functions
714
715 private:
716 // Initialize actor record
717 void init(
718 int16 protoIndex,
719 uint16 nameIndex,
720 uint16 scriptIndex,
721 int32 appearanceNum,
722 uint8 colorSchemeIndex,
723 uint8 factionNum,
724 uint8 initFlags);
725
726 public:
727 // Default constructor
728 Actor(void);
729
730 // Constructor - initial actor construction
731 Actor(const ResourceActor &res);
732
733 Actor(Common::InSaveFile *in);
734
735 // Destructor
736 ~Actor(void);
737
738 // Return the number of bytes needed to archive this actor
739 int32 archiveSize(void);
740
741 void write(Common::MemoryWriteStreamDynamic *out);
742
743 static Actor *newActor(
744 int16 protoNum,
745 uint16 nameIndex,
746 uint16 scriptIndex,
747 int32 appearanceNum,
748 uint8 colorSchemeIndex,
749 uint8 factionNum,
750 uint8 initFlags);
751
752 // Delete this actor
753 void deleteActor(void);
754
755 private:
756 // Turn incrementally
turn(Direction targetDir)757 void turn(Direction targetDir) {
758 Direction relativeDir = (targetDir - _currentFacing) & 0x7;
759
760 _currentFacing =
761 (relativeDir < 4
762 ? _currentFacing + 1
763 : _currentFacing - 1)
764 & 0x7;
765 }
766 public:
767
768 // Cause the actor to stop his current motion task is he is
769 // interruptable
770 void stopMoving(void);
771
772 // Cause this actor to die
773 void die(void);
774
775 // Cause this actor to return from the dead
776 void imNotQuiteDead(void);
777
778 // makes the actor do a vitality change test
779 void vitalityUpdate(void);
780
781 // Perform actor specific activation tasks
782 void activateActor(void);
783
784 // Perform actor specific deactivation tasks
785 void deactivateActor(void);
786
787 // De-lobotomize this actor
788 void delobotomize(void);
789
790 // Lobotomize this actor
791 void lobotomize(void);
792
793 // Return a pointer to the actor's current assignment
getAssignment(void)794 ActorAssignment *getAssignment(void) {
795 return _flags & hasAssignment
796 ? _assignment
797 : nullptr;
798 }
799
800 // determine wether this actor has a specified property
hasProperty(const ActorProperty & actorProp)801 bool hasProperty(const ActorProperty &actorProp) {
802 // The function call operator is used explicitly because
803 // Visual C++ 4.0 doesn't like it otherwise.
804 return actorProp.operator()(this);
805 }
806
807 // Determine if specified point is within actor's arms' reach
808 bool inReach(const TilePoint &tp);
809
810 // Determine if specified point is within an objects use range
811 bool inUseRange(const TilePoint &tp, GameObject *obj);
812
813 // Determine if actor is dead
isDead(void)814 bool isDead(void) {
815 return _effectiveStats.vitality <= 0;
816 }
817
818 // Determine if actor is immobile (i.e. can't walk)
819 bool isImmobile(void);
820
821 // Return a pointer to this actor's currently readied offensive
822 // object
823 GameObject *offensiveObject(void);
824
825 // Returns pointers to this actor's readied primary defensive object
826 // and optionally their scondary defensive object
827 void defensiveObject(GameObject **priPtr, GameObject **secPtr = NULL);
828
829 // Returns a pointer to the object with which this actor is
830 // currently blocking, if any
831 GameObject *blockingObject(Actor *attacker);
832
833 // Return the total used armor attributes
834 void totalArmorAttributes(ArmorAttributes &armorAttribs);
835
836 // Determine if specified point is within actor's attack range
837 bool inAttackRange(const TilePoint &tp);
838
839 // Attack the specified object with the currently selected weapon
840 void attack(GameObject *obj);
841
842 // Stop any attack on the specified object
843 void stopAttack(GameObject *obj);
844
845 // Determine if this actor can block an attack with objects
846 // currently being held
847 bool canDefend(void);
848
849 // Return a numeric value which roughly estimates this actor's
850 // offensive strength
851 int16 offenseScore(void);
852
853 // Return a numeric value which roughly estimates this actor's
854 // defensive strenght
855 int16 defenseScore(void);
856
857 // Handle the effect of a successful hit on an opponent in combat
handleSuccessfulStrike(GameObject * weapon)858 void handleSuccessfulStrike(GameObject *weapon) {
859 weapon->proto()->applySkillGrowth(thisID());
860 }
861
862 // Return the value of this actor's disposition
getDisposition(void)863 int16 getDisposition(void) {
864 return _disposition;
865 }
866
867 // Give the actor a new disposition
setDisposition(int16 newDisp)868 int16 setDisposition(int16 newDisp) {
869 int16 oldDisp = _disposition;
870 if (newDisp < dispositionPlayer)
871 _disposition = newDisp;
872 return oldDisp;
873 }
874
875 // Return a pointer to the effective stats
getStats(void)876 ActorAttributes *getStats(void) {
877 return &_effectiveStats;
878 }
879
880 // Return a pointer to this actor's base stats
881 ActorAttributes *getBaseStats(void);
882
883 // Return the color remapping table
884 void getColorTranslation(ColorTable map);
885
886 // Determine if this actor is interruptable
isInterruptable(void)887 bool isInterruptable(void) {
888 return _actionCounter == 0;
889 }
890
891 // Determine if this actor is permanently uninterruptable
isPermanentlyUninterruptable(void)892 bool isPermanentlyUninterruptable(void) {
893 return _actionCounter == maxuint8;
894 }
895
896 // Set the inturruptability for this actor
setInterruptablity(bool val)897 void setInterruptablity(bool val) {
898 _actionCounter = val ? 0 : maxuint8;
899 }
900
901 // Set action time counter for this actor
902 // REM: the action points will eventually need to be scaled based
903 // upon enchantments and abilities
setActionPoints(uint8 points)904 void setActionPoints(uint8 points) {
905 _actionCounter = points;
906 }
907
908 // Drop the all of the actor's inventory
909 void dropInventory(void);
910
911 // Place an object into this actor's right or left hand
912 void holdInRightHand(ObjectID objID);
913 void holdInLeftHand(ObjectID objID);
914
915 // Wear a piece of armor
916 void wear(ObjectID objID, uint8 where);
917
918 // Update the appearance of an actor with no motion task.
919 void updateAppearance(int32 deltaTime);
920
921 // Used To Find Wait State When Preffered Not Available
922 bool setAvailableAction(int16 action1, int16 action2, int16 action3, int16 actiondefault);
923
924 // Set the current animation sequence that the actor is doing.
925 // Returns the number of poses in the sequence, or 0 if there
926 // are no poses in the sequence.
927 int16 setAction(int16 newState, int16 flags);
928
929 // returns true if the action is available in the current
930 // direction.
931 bool isActionAvailable(int16 newState, bool anyDir = false);
932
933 // Return the number of animation frames in the specified action
934 // for the specified direction
935 int16 animationFrames(int16 actionType, Direction dir);
936
937 // Update the current animation sequence to the next frame
938 bool nextAnimationFrame(void);
939
940 // calculate which sprite frames to show. Return false if
941 // sprite frames are not loaded.
942 bool calcSpriteFrames(void);
943
944 // Calculate the frame list entry, given the current actor's
945 // body state, and facing direction.
946 // FrameListEntry *calcFrameState( int16 bodyState );
947
948 // Returns 0 if not moving, 1 if path being calculated,
949 // 2 if path being followed.
950 bool pathFindState(void);
951
952 // High level actor behavior functions
953 private:
954 void setGoal(uint8 newGoal);
955
956 public:
957 void evaluateNeeds(void);
958
959 // Called every frame to update the state of this actor
960 void updateState(void);
961
962 void handleTaskCompletion(TaskResult result);
963 void handleOffensiveAct(Actor *attacker);
964 void handleDamageTaken(uint8 damage);
965 void handleSuccessfulStrike(Actor *target, int8 damage);
966 void handleSuccessfulKill(Actor *target);
967
968 private:
969 static bool canBlockWith(GameObject *defenseObj, Direction relativeDir);
970 public:
971 void evaluateMeleeAttack(Actor *attacker);
972
973 // Banding related functions
974 void bandWith(Actor *newLeader);
975 void disband(void);
976
inBandingRange(void)977 bool inBandingRange(void) {
978 assert(_leader != NULL);
979
980 return _leader->IDParent() == IDParent()
981 && (_leader->getLocation() - getLocation()).quickHDistance()
982 <= bandingDist;
983 }
984
985 private:
986 bool addFollower(Actor *newBandMember);
987 void removeFollower(Actor *bandMember);
988
989 TaskStack *createFollowerTask(Actor *bandMember);
990 uint8 evaluateFollowerNeeds(Actor *follower);
991
992 public:
993 // Knowledge-related member functions
994 bool addKnowledge(uint16 kID);
995 bool removeKnowledge(uint16 kID);
996 void clearKnowledge(void);
997 void useKnowledge(scriptCallFrame &scf);
998
999 bool canSenseProtaganistIndirectly(SenseInfo &info, int16 range);
1000 bool canSenseSpecificActorIndirectly(
1001 SenseInfo &info,
1002 int16 range,
1003 Actor *a);
1004 bool canSenseSpecificObjectIndirectly(
1005 SenseInfo &info,
1006 int16 range,
1007 ObjectID obj);
1008 bool canSenseActorPropertyIndirectly(
1009 SenseInfo &info,
1010 int16 range,
1011 ActorPropertyID prop);
1012 bool canSenseObjectPropertyIndirectly(
1013 SenseInfo &info,
1014 int16 range,
1015 ObjectPropertyID prop);
1016
1017 // Take mana from actor's mana pool (if possible)
1018 bool takeMana(ActorManaID i, int8 dMana);
1019
1020 bool hasMana(ActorManaID i, int8 dMana);
1021
1022 uint32 getBaseEnchantmentEffects(void);
1023 uint16 getBaseResistance(void);
1024 uint16 getBaseImmunity(void);
1025 uint16 getBaseRecovery(void);
1026
resists(effectResistTypes r)1027 bool resists(effectResistTypes r) {
1028 return _effectiveResistance & (1 << r);
1029 }
isImmuneTo(effectImmuneTypes r)1030 bool isImmuneTo(effectImmuneTypes r) {
1031 return _effectiveImmunity & (1 << r);
1032 }
hasEffect(effectOthersTypes e)1033 bool hasEffect(effectOthersTypes e) {
1034 return (_enchantmentFlags & (1 << e)) != 0;
1035 }
1036
setResist(effectResistTypes r,bool on)1037 void setResist(effectResistTypes r, bool on) {
1038 _effectiveResistance = on ?
1039 _effectiveResistance | (1 << r) :
1040 _effectiveResistance & ~(1 << r);
1041 }
1042
setImmune(effectImmuneTypes r,bool on)1043 void setImmune(effectImmuneTypes r, bool on) {
1044 _effectiveImmunity = on ?
1045 _effectiveImmunity | (1 << r) :
1046 _effectiveImmunity & ~(1 << r);
1047 }
1048
setEffect(effectOthersTypes e,bool on)1049 void setEffect(effectOthersTypes e, bool on) {
1050 _enchantmentFlags = on ?
1051 _enchantmentFlags | (1 << e) :
1052 _enchantmentFlags & ~(1 << e);
1053 }
1054
1055 bool makeSavingThrow(void);
1056
setFightStance(bool val)1057 void setFightStance(bool val) {
1058 if (val)
1059 _flags |= fightStance;
1060 else
1061 _flags &= ~fightStance;
1062 }
1063 };
1064
isPlayerActor(Actor * a)1065 inline bool isPlayerActor(Actor *a) {
1066 return a->_disposition >= dispositionPlayer;
1067 }
1068
isPlayerActor(ObjectID obj)1069 inline bool isPlayerActor(ObjectID obj) {
1070 return isActor(obj)
1071 && isPlayerActor((Actor *)GameObject::objectAddress(obj));
1072 }
1073
isEnemy(Actor * a)1074 inline bool isEnemy(Actor *a) {
1075 return !a->isDead() && a->_disposition == dispositionEnemy;
1076 }
1077
isEnemy(ObjectID obj)1078 inline bool isEnemy(ObjectID obj) {
1079 return isActor(obj)
1080 && isEnemy((Actor *)GameObject::objectAddress(obj));
1081 }
1082
1083 void updateActorStates(void);
1084
1085 void pauseActorStates(void);
1086 void resumeActorStates(void);
1087
1088 void setCombatBehavior(bool enabled);
1089
1090 // Determine if the actors are currently initialized
1091 bool areActorsInitialized(void);
1092
1093 void clearEnchantments(Actor *a);
1094 void addEnchantment(Actor *a, uint16 enchantmentID);
1095
1096 /* ============================================================================ *
1097 Actor factions table
1098 * ============================================================================ */
1099
1100 enum factionTallyTypes {
1101 factionNumKills = 0, // # of times faction member killed by PC
1102 factionNumThefts, // # of times PC steals from faction member
1103 factionNumFavors, // accumulated by SAGA script.
1104
1105 factionNumColumns
1106 };
1107
1108 // Get the attitude a particular faction has for a char.
1109 int16 GetFactionTally(int faction, enum factionTallyTypes act);
1110
1111 // Increment / Decrement faction attitude
1112 // Whenever an actor is killed, call:
1113 // AddFactionAttitude( actor.faction, factionNumKills, 1 );
1114 // Whenever an actor is robbed, call:
1115 // AddFactionAttitude( actor.faction, factionNumThefts, 1 );
1116 int16 AddFactionTally(int faction, enum factionTallyTypes act, int amt);
1117
1118 // Initialize the faction tally table
1119 void initFactionTallies(void);
1120
1121 // Save the faction tallies to a save file
1122 void saveFactionTallies(Common::OutSaveFile *outS);
1123
1124 // Load the faction tallies from a save file
1125 void loadFactionTallies(Common::InSaveFile *in);
1126
1127 // Cleanup the faction tally table
cleanupFactionTallies(void)1128 inline void cleanupFactionTallies(void) { /* Nothing to do */ }
1129
1130 class ActorManager {
1131 public:
1132
1133 enum {
1134 kEvalRate = 8,
1135 kEvalRateMask = kEvalRate - 1
1136 };
1137
1138 Common::Array<Actor *> _actorList;
1139
1140 int32 _updatesViaScript;
1141 int32 _baseActorIndex;
1142 int16 _factionTable[kMaxFactions][factionNumColumns];
1143 bool _actorStatesPaused;
1144 bool _combatBehaviorEnabled;
1145
ActorManager()1146 ActorManager() {
1147 _updatesViaScript = 0;
1148 _baseActorIndex = kEvalRateMask;
1149
1150 memset(_factionTable, 0, sizeof(_factionTable));
1151
1152 _actorStatesPaused = false;
1153 _combatBehaviorEnabled = false;
1154 }
1155 };
1156
1157 } // end of namespace Saga2
1158
1159 #endif
1160