scummvm/engines/saga2/actor.h
2021-07-01 01:37:30 +02:00

1103 lines
32 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* Based on the original sources
* Faery Tale II -- The Halls of the Dead
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
*/
#ifndef SAGA2_ACTOR_H
#define SAGA2_ACTOR_H
#include "saga2/objects.h"
namespace Saga2 {
class ActorAssignment;
class Band;
class MotionTask;
class TaskStack;
const int bandingDist = kSectorSize * 2;
const int actorScriptVars = 4;
/* ===================================================================== *
Actor character attributes
* ===================================================================== */
// Defines the colors of MANA
enum ActorSkillID {
skillIDArchery = 0,
skillIDSwordcraft,
skillIDShieldcraft,
skillIDBludgeon,
skillIDThrowing, // gone
skillIDSpellcraft,
skillIDStealth, // gone
skillIDAgility,
skillIDBrawn,
skillIDLockpick, // gone
skillIDPilfer, // gone
skillIDFirstAid, // gone
skillIDSpotHidden, // gone
numSkills,
};
enum ArmorObjectTypes {
SHIRT_ARMOR = 0,
BOOT_ARMOR,
BRACER_ARMOR,
HELM_ARMOR,
NECKLACE_ARMOR,
CLOAK_ARMOR,
RING_ARMOR,
ARMOR_COUNT
};
/* ===================================================================== *
ArmorAttributes struct
* ===================================================================== */
struct ArmorAttributes {
uint8 damageAbsorbtion,
damageDivider,
defenseBonus;
};
/* ===================================================================== *
ActorAttributes structure
* ===================================================================== */
// this enum acts as a layer of indirection for the unioned allSkills
// array.
// This defines the basic skills possessed by an actor
struct ActorAttributes {
enum skillInfo {
skillBasePercent = 100,
skillFracPointsPerLevel = 5, // this being twenty and levels at 5
skillLevels = 20, // will make the advancement calc quick & easy
skillMaxLevel = skillFracPointsPerLevel * skillLevels,
};
enum vitalityInfo {
vitalityLimit = 256,
};
// Automatic skills
uint8 archery, // Accuracy of missile weapons
swordcraft, // Accuracy of bladed melee weapons
shieldcraft, // Actor's ability to use a shield
bludgeon, // Accuracy of non-bladed melee weapons
throwing, // Ability to throw objects accurately
spellcraft, // Accuracy of spell combat
stealth, // Ability to remain unnoticed
agility, // Ability to dodge
brawn, // Ability to lift, and damage of weapons
lockpick; // Ability to pick locks
// Manual skills
uint8 pilfer, // Ability to "lift" an item
firstAid, // Ability to heal recent injuries
spotHidden; // Ability to spot hidden objects
// Pad byte for alignment
int8 pad;
// Hit-points
int16 vitality;
// Magic energy
int16 redMana,
orangeMana,
yellowMana,
greenMana,
blueMana,
violetMana;
uint8 &skill(int16 id) {
switch (id) {
case skillIDArchery: return archery;
case skillIDSwordcraft: return swordcraft;
case skillIDShieldcraft: return shieldcraft;
case skillIDBludgeon: return bludgeon;
case skillIDThrowing: return throwing;
case skillIDSpellcraft: return spellcraft;
case skillIDStealth: return stealth;
case skillIDAgility: return agility;
case skillIDBrawn: return brawn;
case skillIDLockpick: return lockpick;
case skillIDPilfer: return pilfer;
case skillIDFirstAid: return firstAid;
case skillIDSpotHidden: return spotHidden;
}
error("Incorrect skill id: %d", id);
}
int16 &mana(int16 id) {
switch (id) {
case manaIDRed: return redMana;
case manaIDOrange: return orangeMana;
case manaIDYellow: return yellowMana;
case manaIDGreen: return greenMana;
case manaIDBlue: return blueMana;
case manaIDViolet: return violetMana;
}
error("Incorrect mana id: %d", id);
}
uint8 getSkillLevel(int16 id) {
return skill(id) / skillFracPointsPerLevel + 1;
}
void load(Common::SeekableReadStream *stream) {
archery = stream->readByte();
swordcraft = stream->readByte();
shieldcraft = stream->readByte();
bludgeon = stream->readByte();
throwing = stream->readByte();
spellcraft = stream->readByte();
stealth = stream->readByte();
agility = stream->readByte();
brawn = stream->readByte();
lockpick = stream->readByte();
pilfer = stream->readByte();
firstAid = stream->readByte();
spotHidden = stream->readByte();
pad = stream->readSByte();
vitality = stream->readSint16LE();
redMana = stream->readSint16LE();
orangeMana = stream->readSint16LE();
yellowMana = stream->readSint16LE();
greenMana = stream->readSint16LE();
blueMana = stream->readSint16LE();
violetMana = stream->readSint16LE();
}
}; // 28 bytes
const int baseCarryingCapacity = 100;
const int carryingCapacityBonusPerBrawn = 200 / ActorAttributes::skillLevels;
/* ===================================================================== *
ResourceActorProtoExtension structure
* ===================================================================== */
enum combatBehaviorTypes {
behaviorHungry,
behaviorCowardly,
behaviorBerserk,
behaviorSmart,
};
// This defines the additional data fields needed for actor prototypes
struct ResourceActorProtoExtension {
ActorAttributes baseStats; // Base stats for non-player actors
// Defines behavior for combat tactics.
uint8 combatBehavior;
uint8 gruntStyle;
uint32 baseEffectFlags; // special effects, see EFFECTS.H
// Default constructor -- do nothing
ResourceActorProtoExtension(void) {}
// Copy constructor
ResourceActorProtoExtension(ResourceActorProtoExtension &ext) {
memcpy(this, &ext, sizeof(ResourceActorProtoExtension));
}
void load(Common::SeekableReadStream *stream) {
baseStats.load(stream);
combatBehavior = stream->readByte();
gruntStyle = stream->readByte();
baseEffectFlags = stream->readUint32LE();
}
}; // 28 bytes
/* ===================================================================== *
ResourceActorPrototype structure
* ===================================================================== */
// Defines the actor prototype data as read from the resource file
struct ResourceActorPrototype {
ResourceObjectPrototype proto; // Standard prototype data
ResourceActorProtoExtension ext; // Extended actor data
void load(Common::SeekableReadStream *stream) {
proto.load(stream);
ext.load(stream);
}
};
/* ===================================================================== *
ActorProto prototype behavior for Actors
* ===================================================================== */
class ActorProto : public ProtoObj, public ResourceActorProtoExtension {
private:
enum {
ViewableRows = 3,
ViewableCols = 3,
maxRows = 3,
maxCols = 3,
};
public:
ActorProto(ResourceActorPrototype &a) :
ProtoObj(a.proto),
ResourceActorProtoExtension(a.ext) {
}
// returns the containment type flags for this object
virtual uint16 containmentSet(void);
// returns true if this object can contain another object
virtual bool canContain(ObjectID dObj, ObjectID item);
// Determine if this object can contain another object at a
// specified slot
virtual bool canContainAt(
ObjectID dObj,
ObjectID item,
const TilePoint &where);
weaponID getWeaponID(void);
// use this actor
bool useAction(ObjectID dObj, ObjectID enactor);
// open this actor
bool canOpen(ObjectID dObj, ObjectID enactor);
bool openAction(ObjectID dObj, ObjectID enactor);
// close this actor
bool closeAction(ObjectID dObj, ObjectID enactor);
bool strikeAction(
ObjectID dObj,
ObjectID enactor,
ObjectID item);
bool damageAction(
ObjectID dObj,
ObjectID enactor,
ObjectID target);
// drop another object onto this actor.
bool acceptDropAction(
ObjectID dObj,
ObjectID enactor,
ObjectID droppedObj,
int count);
// cause damage directly
bool acceptDamageAction(
ObjectID dObj,
ObjectID enactor,
int8 absDamage,
effectDamageTypes dType,
int8 dice,
uint8 sides,
int8 perDieMod);
// cause healing directly
bool acceptHealingAction(ObjectID dObj, ObjectID enactor, int8 healing);
// Accept strike from an object (allows this actor to cause
// damage to the striking object).
bool acceptStrikeAction(
ObjectID dObj,
ObjectID enactor,
ObjectID strikingObj,
uint8 skillIndex);
// Handle the results of an object being inserted into this object
// at the specified slot
bool acceptInsertionAtAction(
ObjectID dObj,
ObjectID enactor,
ObjectID item,
const TilePoint &where,
int16 num = 1);
// Initiate an attack using this type of object
virtual void initiateAttack(ObjectID attacker, ObjectID target);
// Given an object sound effect record, which sound should be made
// when this object is damaged
virtual uint8 getDamageSound(const ObjectSoundFXs &soundFXs);
// Do the background processing, if needed, for this object.
void doBackgroundUpdate(GameObject *obj);
// Cause the user's associated skill to grow
void applySkillGrowth(ObjectID enactor, uint8 points = 1);
bool greetActor(
ObjectID dObj, // object dropped on
ObjectID enactor); // person doing dropping
public:
virtual uint16 getViewableRows(void) {
return ViewableRows;
}
virtual uint16 getViewableCols(void) {
return ViewableCols;
}
virtual uint16 getMaxRows(void) {
return maxRows;
}
virtual uint16 getMaxCols(void) {
return maxCols;
}
virtual bool canFitBulkwise(GameObject *container, GameObject *obj);
virtual bool canFitMasswise(GameObject *container, GameObject *obj);
virtual uint16 massCapacity(GameObject *container);
virtual uint16 bulkCapacity(GameObject *container);
};
/* ============================================================================ *
Actor: Describes an instance of a character
* ============================================================================ */
enum actorCreationFlags {
actorPermanent = (1 << 0),
};
enum DispositionType {
dispositionFriendly,
dispositionEnemy,
dispositionPlayer
};
enum actionSequenceOptions {
// Flags set by call to setAction
animateRepeat = (1 << 0), // repeat animation when done
animateReverse = (1 << 1), // animate in reverse direction
animateAlternate = (1 << 2), // both directions, back & forth
animateRandom = (1 << 3), // pick a random frame
animateNoRestart = (1 << 4), // don't reset from start
// This flag is set if the animation has been put on hold until
// the actor's appearance is reloaded.
animateOnHold = (1 << 5),
// This flag is set if the final frame of the animation has
// been reached.
animateFinished = (1 << 6),
// This flag gets set if the sprite could not be displayed
// because it's bank hasn't been loaded yet.
animateNotLoaded = (1 << 7),
};
// Various types of action sequences
enum ActorAnimationTypes {
// Various types of stands
actionStand = 0, // standing still
actionWaitAgressive, // an agressive wait cycle
actionWaitImpatient, // an impatient wait cycle
actionWaitFriendly, // a a friendly wait cycle
// Walking and running
actionWalk, // walking motion
actionRun, // running motion
// Squatting
actionDuck, // stoop to dodge sword
actionStoop, // stoop to pick up object
// Jumping
actionFreeFall, // how he looks in ballistic
actionFreeFallRunning, // a running leap (free fall)
actionJumpUp, // begin jump straight up
actionJumpFwd, // begin jump forward
actionJumpBack, // begin jump back in surprise
actionLand, // land after jump
actionFallBadly, // after a very long fall
// Climbing
actionClimbLadder, // climb a ladder (2 directions)
// Talking & interacting
actionTalk, // talking
actionGesture, // gesture with hands or body
actionGiveItem, // give or take item
// Two-handed weapon use
actionTwoHandSwingHigh, // full overhead swing aim high
actionTwoHandSwingLow, // full overhead swing aim low
actionTwoHandSwingLeftHigh, // partial swing on left (high)
actionTwoHandSwingLeftLow, // partial swing on left (low)
actionTwoHandSwingRightHigh, // partial swing on rgt (high)
actionTwoHandSwingRightLow, // partial swing on rgt (low)
actionTwoHandParry, // hold sword up to parry
// One-handed weapon use
actionSwingHigh, // one-handed swing (high)
actionSwingLow, // one-handed swing (low)
actionParryHigh, // one-handed parry (high)
actionParryLow, // one-handed parry (low)
actionShieldParry, // parry with shield
actionThrowObject, // throw
// Other combat actions
actionFireBow, // fire an arrow
actionCastSpell, // cast a magic spell
actionUseWand, // cast a magic spell w/wand
actionUseStaff, // cast a magic spell w/staff
actionHit, // show impact of blow
actionKnockedDown, // knocked down by opponent
actionDie, // death agony
// Passive actions
actionSleep, // sleeping
actionDead, // dead body on ground
actionSit, // sitting at table
// Misc actions built from other frames
actionListenAtDoor, // listening at doors
actionShoveDoor, // try to force a door open
actionSpecial1, // special Action
actionSpecial2, // special Action
actionSpecial3, // special Action
actionSpecial4, // special Action
actionSpecial5, // special Action
actionSpecial6, // special Action
actionSpecial7, // special Action
actionSpecial8, // special Action
};
enum ActorGoalTypes {
actorGoalFollowAssignment,
actorGoalPreserveSelf,
actorGoalAttackEnemy,
actorGoalFollowLeader,
actorGoalAvoidEnemies,
};
// The actor structure will be divided into two parts. The
// ResourceActor structure defines the data as it is stored in the
// resource file. The Actor structure has a copy of all of the
// ResourceActor data members, plus data members which will be
// initialized and used during run time.
struct ResourceActor : public ResourceGameObject {
// Social loyalty
uint8 faction; // actor's faction
// Appearance attribute
uint8 colorScheme; // indirect color map
int32 appearanceID; // appearnce of this actor
// Personality attributes
int8 attitude, // cooperativeness
mood; // happiness
uint8 disposition; // actor disposition
// 0 = friendly, 1 = enemy,
// 2 = Julian, 3 = Philip,
// 4 = Kevin
// Character orientation
Direction currentFacing; // current facing direction
// Tether info
int16 tetherLocU; // tether U coordinate
int16 tetherLocV; // tether V coordinate
int16 tetherDist; // length of tether
// Held objects
ObjectID leftHandObject, // object held in left hand.
rightHandObject; // object held in right hand.
// Knowledge packets
uint16 knowledge[16];
// Schedule script ID
uint16 schedule;
// Pad bytes
uint8 reserved[18];
ResourceActor(Common::SeekableReadStream *stream);
};
class Actor : public GameObject {
friend class ActorProto;
friend class MotionTask;
friend class Task;
friend class TaskStack;
public:
// Resource fields
// Social loyalty
uint8 faction; // actor's faction
// Appearance attribute
uint8 colorScheme; // indirect color map
int32 appearanceID; // appearnce of this actor
// Personality attributes
int8 attitude, // cooperativeness
mood; // happiness
uint8 disposition; // actor disposition
// 0 = friendly, 1 = enemy,
// 2 = Julian, 3 = Philip,
// 4 = Kevin
// Character orientation
Direction currentFacing; // current facing direction
// Tether info
int16 tetherLocU; // tether U coordinate
int16 tetherLocV; // tether V coordinate
int16 tetherDist; // length of tether
// Held objects
ObjectID leftHandObject, // object held in left hand.
rightHandObject; // object held in right hand.
// Knowledge packets
uint16 knowledge[16];
// Schedule script ID
uint16 schedule;
// Run-time fields
uint8 conversationMemory[4];// last things talked about
// Sprite animation variables
uint8 currentAnimation, // current action sequence
currentPose, // current pose in sequence
animationFlags; // current posing flags
// Various actor flags
enum {
lobotomized = (1 << 0),
temporary = (1 << 1),
afraid = (1 << 2),
hasAssignment = (1 << 3),
specialAttack = (1 << 4),
fightStance = (1 << 5),
};
uint8 flags;
// Contains sprite index and positioning info for the current
// actor state.
ActorPose poseInfo; // current animation state
// Pointer to the appearance record (sprite array) for this actor.
ActorAppearance *appearance; // appearance structs
int16 cycleCount; // misc counter for actions
int16 kludgeCount; // another misc counter
uint32 enchantmentFlags; // flags indicating racial
// abilities and enchantments
// Movement attributes
MotionTask *moveTask;
// Current task
TaskStack *curTask;
// Current goal type
uint8 currentGoal;
// Used for deltayed deactivation (and also to word-align struct)
uint8 deactivationCounter;
// Assignment
ActorAssignment *_assignment;
// assignments
// Current effective stats
ActorAttributes effectiveStats;
uint8 actionCounter; // coordinate moves in combat
uint16 effectiveResistance; // resistances (see EFFECTS.H)
uint16 effectiveImmunity; // immunities (see EFFECTS.H)
int16 recPointsPerUpdate; // fractional vitality recovery
int16 currentRecoveryPoints; // fraction left from last recovery
enum vitalityRecovery {
recPointsPerVitality = 10,
};
Actor *leader; // This actor's leader
Band *followers; // This actor's band of followers
ObjectID armorObjects[ARMOR_COUNT]; // armor objects being worn
GameObject *currentTarget;
int16 scriptVar[actorScriptVars]; // scratch variables for scripter use
// Member functions
private:
// Initialize actor record
void init(
int16 protoIndex,
uint16 nameIndex,
uint16 scriptIndex,
int32 appearanceNum,
uint8 colorSchemeIndex,
uint8 factionNum,
uint8 initFlags);
public:
// Default constructor
Actor(void);
// Constructor - initial actor construction
Actor(const ResourceActor &res);
// Reconstruct from archive buffer
Actor(void **buf);
// Destructor
~Actor(void);
// Return the number of bytes needed to archive this actor
int32 archiveSize(void);
// Archive this actor in a buffer
void *archive(void *buf);
static Actor *newActor(
int16 protoNum,
uint16 nameIndex,
uint16 scriptIndex,
int32 appearanceNum,
uint8 colorSchemeIndex,
uint8 factionNum,
uint8 initFlags);
// Delete this actor
void deleteActor(void);
private:
// Turn incrementally
void turn(Direction targetDir) {
Direction relativeDir = (targetDir - currentFacing) & 0x7;
currentFacing =
(relativeDir < 4
? currentFacing + 1
: currentFacing - 1)
& 0x7;
}
public:
// Cause the actor to stop his current motion task is he is
// interruptable
void stopMoving(void);
// Cause this actor to die
void die(void);
// Cause this actor to return from the dead
void imNotQuiteDead(void);
// makes the actor do a vitality change test
void vitalityUpdate(void);
// Perform actor specific activation tasks
void activateActor(void);
// Perform actor specific deactivation tasks
void deactivateActor(void);
// De-lobotomize this actor
void delobotomize(void);
// Lobotomize this actor
void lobotomize(void);
// Return a pointer to the actor's current assignment
ActorAssignment *getAssignment(void) {
return flags & hasAssignment
? _assignment
: NULL;
}
// determine wether this actor has a specified property
bool hasProperty(const ActorProperty &actorProp) {
// The function call operator is used explicitly because
// Visual C++ 4.0 doesn't like it otherwise.
return actorProp.operator()(this);
}
// Determine if specified point is within actor's arms' reach
bool inReach(const TilePoint &tp);
// Determine if specified point is within an objects use range
bool inUseRange(const TilePoint &tp, GameObject *obj);
// Determine if actor is dead
bool isDead(void) {
return effectiveStats.vitality <= 0;
}
// Determine if actor is immobile (i.e. can't walk)
bool isImmobile(void);
// Return a pointer to this actor's currently readied offensive
// object
GameObject *offensiveObject(void);
// Returns pointers to this actor's readied primary defensive object
// and optionally their scondary defensive object
void defensiveObject(GameObject **priPtr, GameObject **secPtr = NULL);
// Returns a pointer to the object with which this actor is
// currently blocking, if any
GameObject *blockingObject(Actor *attacker);
// Return the total used armor attributes
void totalArmorAttributes(ArmorAttributes &armorAttribs);
// Determine if specified point is within actor's attack range
bool inAttackRange(const TilePoint &tp);
// Attack the specified object with the currently selected weapon
void attack(GameObject *obj);
// Stop any attack on the specified object
void stopAttack(GameObject *obj);
// Determine if this actor can block an attack with objects
// currently being held
bool canDefend(void);
// Return a numeric value which roughly estimates this actor's
// offensive strength
int16 offenseScore(void);
// Return a numeric value which roughly estimates this actor's
// defensive strenght
int16 defenseScore(void);
// Handle the effect of a successful hit on an opponent in combat
void handleSuccessfulStrike(GameObject *weapon) {
weapon->proto()->applySkillGrowth(thisID());
}
// Return the value of this actor's disposition
int16 getDisposition(void) {
return disposition;
}
// Give the actor a new disposition
int16 setDisposition(int16 newDisp) {
int16 oldDisp = disposition;
if (newDisp < dispositionPlayer) disposition = newDisp;
return oldDisp;
}
// Return a pointer to the effective stats
ActorAttributes *getStats(void) {
return &effectiveStats;
}
// Return a pointer to this actor's base stats
ActorAttributes *getBaseStats(void);
// Return the color remapping table
void getColorTranslation(ColorTable map);
// Determine if this actor is interruptable
bool isInterruptable(void) {
return actionCounter == 0;
}
// Determine if this actor is permanently uninterruptable
bool isPermanentlyUninterruptable(void) {
return actionCounter == maxuint8;
}
// Set the inturruptability for this actor
void setInterruptablity(bool val) {
actionCounter = val ? 0 : maxuint8;
}
// Set action time counter for this actor
// REM: the action points will eventually need to be scaled based
// upon enchantments and abilities
void setActionPoints(uint8 points) {
actionCounter = points;
}
// Drop the all of the actor's inventory
void dropInventory(void);
// Place an object into this actor's right or left hand
void holdInRightHand(ObjectID objID);
void holdInLeftHand(ObjectID objID);
// Wear a piece of armor
void wear(ObjectID objID, uint8 where);
// Update the appearance of an actor with no motion task.
void updateAppearance(int32 deltaTime);
// Used To Find Wait State When Preffered Not Available
bool SetAvailableAction(int16, ...);
// Set the current animation sequence that the actor is doing.
// Returns the number of poses in the sequence, or 0 if there
// are no poses in the sequence.
int16 setAction(int16 newState, int16 flags);
// returns true if the action is available in the current
// direction.
bool isActionAvailable(int16 newState, bool anyDir = false);
// Return the number of animation frames in the specified action
// for the specified direction
int16 animationFrames(int16 actionType, Direction dir);
// Update the current animation sequence to the next frame
bool nextAnimationFrame(void);
// calculate which sprite frames to show. Return false if
// sprite frames are not loaded.
bool calcSpriteFrames(void);
// Calculate the frame list entry, given the current actor's
// body state, and facing direction.
// FrameListEntry *calcFrameState( int16 bodyState );
// Returns 0 if not moving, 1 if path being calculated,
// 2 if path being followed.
bool pathFindState(void);
// High level actor behavior functions
private:
void setGoal(uint8 newGoal);
public:
void evaluateNeeds(void);
// Called every frame to update the state of this actor
void updateState(void);
void handleTaskCompletion(TaskResult result);
void handleOffensiveAct(Actor *attacker);
void handleDamageTaken(uint8 damage);
void handleSuccessfulStrike(Actor *target, int8 damage);
void handleSuccessfulKill(Actor *target);
private:
static bool canBlockWith(GameObject *defenseObj, Direction relativeDir);
public:
void evaluateMeleeAttack(Actor *attacker);
// Banding related functions
void bandWith(Actor *newLeader);
void disband(void);
bool inBandingRange(void) {
assert(leader != NULL);
return leader->IDParent() == IDParent()
&& (leader->getLocation() - getLocation()).quickHDistance()
<= bandingDist;
}
private:
bool addFollower(Actor *newBandMember);
void removeFollower(Actor *bandMember);
TaskStack *createFollowerTask(Actor *bandMember);
uint8 evaluateFollowerNeeds(Actor *follower);
public:
// Knowledge-related member functions
bool addKnowledge(uint16 kID);
bool removeKnowledge(uint16 kID);
void clearKnowledge(void);
void useKnowledge(scriptCallFrame &scf);
bool canSenseProtaganistIndirectly(SenseInfo &info, int16 range);
bool canSenseSpecificActorIndirectly(
SenseInfo &info,
int16 range,
Actor *a);
bool canSenseSpecificObjectIndirectly(
SenseInfo &info,
int16 range,
ObjectID obj);
bool canSenseActorPropertyIndirectly(
SenseInfo &info,
int16 range,
ActorPropertyID prop);
bool canSenseObjectPropertyIndirectly(
SenseInfo &info,
int16 range,
ObjectPropertyID prop);
// Take mana from actor's mana pool (if possible)
bool takeMana(ActorManaID i, int8 dMana);
bool hasMana(ActorManaID i, int8 dMana);
uint32 getBaseEnchantmentEffects(void);
uint16 getBaseResistance(void);
uint16 getBaseImmunity(void);
uint16 getBaseRecovery(void);
bool resists(effectResistTypes r) {
return effectiveResistance & (1 << r);
}
bool isImmuneTo(effectImmuneTypes r) {
return effectiveImmunity & (1 << r);
}
bool hasEffect(effectOthersTypes e) {
return (enchantmentFlags & (1 << e)) != 0;
}
void setResist(effectResistTypes r, bool on) {
effectiveResistance = on ?
effectiveResistance | (1 << r) :
effectiveResistance & ~(1 << r);
}
void setImmune(effectImmuneTypes r, bool on) {
effectiveImmunity = on ?
effectiveImmunity | (1 << r) :
effectiveImmunity & ~(1 << r);
}
void setEffect(effectOthersTypes e, bool on) {
enchantmentFlags = on ?
enchantmentFlags | (1 << e) :
enchantmentFlags & ~(1 << e);
}
bool makeSavingThrow(void);
void setFightStance(bool val) {
if (val)
flags |= fightStance;
else
flags &= ~fightStance;
}
};
inline bool isPlayerActor(Actor *a) {
return a->disposition >= dispositionPlayer;
}
inline bool isPlayerActor(ObjectID obj) {
return isActor(obj)
&& isPlayerActor((Actor *)GameObject::objectAddress(obj));
}
inline bool isEnemy(Actor *a) {
return !a->isDead() && a->disposition == dispositionEnemy;
}
inline bool isEnemy(ObjectID obj) {
return isActor(obj)
&& isEnemy((Actor *)GameObject::objectAddress(obj));
}
void updateActorStates(void);
void pauseActorStates(void);
void resumeActorStates(void);
void setCombatBehavior(bool enabled);
// Determine if the actors are currently initialized
bool areActorsInitialized(void);
void clearEnchantments(Actor *a);
void addEnchantment(Actor *a, uint16 enchantmentID);
/* ============================================================================ *
Actor factions table
* ============================================================================ */
// Let's assume 64 factions maximum for now
const int maxFactions = 64;
enum factionTallyTypes {
factionNumKills = 0, // # of times faction member killed by PC
factionNumThefts, // # of times PC steals from faction member
factionNumFavors, // accumulated by SAGA script.
factionNumColumns
};
// Get the attitude a particular faction has for a char.
int16 GetFactionTally(int faction, enum factionTallyTypes act);
// Increment / Decrement faction attitude
// Whenever an actor is killed, call:
// AddFactionAttitude( actor.faction, factionNumKills, 1 );
// Whenever an actor is robbed, call:
// AddFactionAttitude( actor.faction, factionNumThefts, 1 );
int16 AddFactionTally(int faction, enum factionTallyTypes act, int amt);
// Initialize the faction tally table
void initFactionTallies(void);
// Save the faction tallies to a save file
void saveFactionTallies(SaveFileConstructor &saveGame);
// Load the faction tallies from a save file
void loadFactionTallies(SaveFileReader &saveGame);
// Cleanup the faction tally table
inline void cleanupFactionTallies(void) { /* Nothing to do */ }
} // end of namespace Saga2
#endif