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