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