1 /* GemRB - Infinity Engine Emulator
2  * Copyright (C) 2003 The GemRB Project
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  *
19  */
20 
21 #ifndef ACTOR_H
22 #define ACTOR_H
23 
24 #include "Scriptable/Scriptable.h"
25 
26 #include "Scriptable/PCStatStruct.h"
27 
28 #include "exports.h"
29 #include "ie_types.h"
30 
31 #include "Audio.h"
32 #include "CombatInfo.h"
33 #include "EffectQueue.h"
34 #include "Palette.h"
35 #include "Polygon.h"
36 #include "Video.h"
37 
38 #include <map>
39 #include <set>
40 #include <vector>
41 
42 namespace GemRB {
43 
44 class Animation;
45 class ArmorClass;
46 class CharAnimations;
47 class DataFileMgr;
48 class Map;
49 class ScriptedAnimation;
50 class StringBuffer;
51 class ToHitStats;
52 struct PolymorphCache;
53 
54 }
55 
56 /** USING DEFINITIONS AS DESCRIBED IN STATS.IDS */
57 #include "ie_stats.h"
58 
59 #include "Inventory.h"
60 #include "Spellbook.h"
61 
62 namespace GemRB {
63 
64 #define MAX_STATS 256
65 #define MAX_LEVEL 128
66 #define MAX_FEATS 96 //3*sizeof(ieDword)
67 
68 //lucky roll
69 #define LR_CRITICAL    1
70 #define LR_DAMAGELUCK  2
71 #define LR_NEGATIVE    4
72 
73 //modal states
74 #define MS_NONE        0
75 #define MS_BATTLESONG  1
76 #define MS_DETECTTRAPS 2
77 #define MS_STEALTH     3
78 #define MS_TURNUNDEAD  4
79 
80 //stat modifier type
81 #define MOD_ADDITIVE  0
82 #define MOD_ABSOLUTE  1
83 #define MOD_PERCENT   2
84 #define MOD_MULTIPLICATIVE 3
85 #define MOD_DIVISIVE  4
86 #define MOD_MODULUS   5
87 #define MOD_LOGAND    6
88 #define MOD_LOGOR     7
89 #define MOD_BITAND    8
90 #define MOD_BITOR     9
91 #define MOD_INVERSE   10
92 
93 //'do not jump' flags
94 #define DNJ_FIT        1
95 #define DNJ_UNHINDERED 2
96 #define DNJ_JUMP       4
97 #define DNJ_BIRD       (DNJ_FIT|DNJ_UNHINDERED)
98 
99 //add_animation flags (override vvc)
100 #define AA_PLAYONCE    1
101 #define AA_BLEND       2
102 
103 //GetDialog flags
104 #define GD_NORMAL      0
105 #define GD_CHECK       1
106 #define GD_FEEDBACK    2 //(also check)
107 
108 //Panic modes
109 #define PANIC_NONE       0
110 #define PANIC_BERSERK    1
111 #define PANIC_RUNAWAY    2
112 #define PANIC_RANDOMWALK 3
113 
114 //Game Difficulty
115 #define DIFF_DEFAULT       0
116 #define DIFF_EASY          1
117 #define DIFF_NORMAL        2
118 #define DIFF_CORE          3
119 #define DIFF_HARD          4
120 #define DIFF_INSANE        5
121 #define DIFF_NIGHTMARE     6 // rather check against the ini var where needed
122 
123 /** flags for GetActor */
124 //default action
125 #define GA_DEFAULT  0
126 //actor selected for talk
127 #define GA_TALK     1
128 //actor selected for attack
129 #define GA_ATTACK   2
130 //actor selected for spell target
131 #define GA_SPELL    3
132 //actor selected for defend
133 #define GA_DEFEND   4
134 //actor selected for pick pockets
135 #define GA_PICK     5
136 //action mask
137 #define GA_ACTION   15
138 //unselectable actor may not be selected (can still block)
139 #define GA_SELECT   16
140 //dead actor may not be selected
141 #define GA_NO_DEAD  32
142 //any point could be selected (area effect)
143 #define GA_POINT    64
144 //hidden actor may not be selected
145 #define GA_NO_HIDDEN 128
146 //party members cannot be selected
147 #define GA_NO_ALLY  256
148 //only party members could be selected
149 #define GA_NO_ENEMY 512
150 //
151 #define GA_NO_NEUTRAL 1024
152 //cannot target self
153 #define GA_NO_SELF    2048
154 //try other areas too
155 //(unused and removed, see git history of the commit which
156 //added this comment for some clues if you really need it)
157 //#define GA_GLOBAL     4096
158 
159 //line of sight is ignored (for GetAllActorsInRadius)
160 #define GA_NO_LOS 4096
161 
162 // Detect() mode: IDS matching ignores invisibility
163 #define GA_DETECT 8192
164 //cannot target unscheduled actors
165 #define GA_NO_UNSCHEDULED 16384
166 
167 #define GA_ONLY_BUMPABLE 32768
168 #define GA_CAN_BUMP 65536
169 
170 #define VCONST_COUNT 100
171 
172 //interact types
173 #define I_NONE       0
174 #define I_INSULT     1
175 #define I_COMPLIMENT 2
176 #define I_SPECIAL    3
177 #define I_INSULT_RESP 4
178 #define I_COMPL_RESP 5
179 #define I_DIALOG     6
180 
181 //flags for UseItem
182 #define UI_SILENT    1       //no sound when used up
183 #define UI_MISS      2       //ranged miss (projectile has no effects)
184 #define UI_CRITICAL  4       //a critical hit happened
185 #define UI_FAKE      8       //deplete the item but don't actually apply its effects
186 #define UI_NOAURA    16      //ignore spellcasting aura checks
187 #define UI_NOCHARGE  32      //don't deplete the item
188 
189 //used to mask off current profs
190 #define PROFS_MASK  0x07
191 
192 //locations of classes in the isclass/levelslots arrays
193 #define ISFIGHTER   0
194 #define ISMAGE      1
195 #define ISTHIEF     2
196 #define ISBARBARIAN 3
197 #define ISBARD      4
198 #define ISCLERIC    5
199 #define ISDRUID     6
200 #define ISMONK      7
201 #define ISPALADIN   8
202 #define ISRANGER    9
203 #define ISSORCERER  10
204 #define ISCLASS12   11
205 #define ISCLASS13   12
206 
207 #define ISCLASSES   13
208 
209 //appearance flags
210 
211 #define APP_HALFTRANS    2           //half transparent
212 #define APP_DEATHVAR     16          //set death variable
213 #define APP_DEATHTYPE    32          //count creature type deaths
214 #define APP_ADDKILL      64          //prepend KILL_ to the creature type
215 #define APP_FACTION      128         //count killed faction
216 #define APP_TEAM         0x100       //count killed team
217 #define APP_INVULNERABLE 0x200       //invulnerable
218 #define APP_GOOD         0x400       //good count
219 #define APP_LAW          0x800       //law count
220 #define APP_LADY         0x1000      //lady count
221 #define APP_MURDER       0x2000      //murder count
222 #define APP_NOTURN       0x4000      //doesn't face gabber in dialogue
223 #define APP_BUDDY        0x8000      // unused; supposedly: npcs will turn hostile if this one dies
224 #define APP_DEAD         0x40000000  //used by the engine to prevent dying twice
225 
226 #define DC_GOOD   0
227 #define DC_LAW    1
228 #define DC_LADY   2
229 #define DC_MURDER 3
230 
231 // used for distinguishing damage immunity from high damage resistance
232 #define DR_IMMUNE 999999
233 
234 // wild surge target change type
235 #define WSTC_SETTYPE   1 // change to this target type
236 #define WSTC_ADDTYPE   2 // affect also this target type
237 #define WSTC_RANDOMIZE 3 // choose a random target
238 struct WildSurgeSpellMods {
239 	unsigned int num_castings; // number of times to cast
240 	unsigned int num_wildrolls; // number of times to roll
241 	unsigned int projectile_id; // new projectile id
242 	unsigned int target_change_type; // settype, addtype, randomize
243 	unsigned int target_type; // type to use when target_change_type is not WSTC_RANDOMIZE
244 	unsigned int projectile_speed_mod; // factor in percents
245 	int saving_throw_mod;
246 };
247 
248 typedef ieByte ActionButtonRow[GUIBT_COUNT];
249 struct ActionButtonRow2 {
250 	ActionButtonRow buttons;
251 	ieByte clss;
252 };
253 
254 struct WeaponInfo {
255 	int slot;
256 	ieDword enchantment;
257 	unsigned int range;
258 	ieDword itemtype;
259 	ieDword itemflags;
260 	ieDword prof;
261 	bool backstabbing;
262 	ieDword wflags;
263 	int critmulti; //critical hit multiplier (usually 2)
264 	int critrange; // the lower value of the critical range (eg. 19 in 19-20/x3)
265 	int profdmgbon;
266 	int launcherdmgbon;
WeaponInfoWeaponInfo267 	WeaponInfo(): slot(0), enchantment(0), range(0), itemtype(0), itemflags(0), prof(0), backstabbing(false), wflags(0), critmulti(0), critrange(0), profdmgbon(0), launcherdmgbon(0) {};
268 };
269 
270 struct BABTable {
271 	ieDword level;
272 	int bab; // basic attack bonus
273 	int apr; // attacks per round
274 };
275 
276 struct ModalStatesStruct {
277 	ieResRef spell;
278 	char action[16];
279 	unsigned int entering_str;
280 	unsigned int leaving_str;
281 	unsigned int failed_str;
282 	unsigned int aoe_spell;
283 	unsigned int repeat_msg;
284 };
285 
286 struct ModalState {
287 	ieDword State;
288 	ieResRef Spell;             //apply this spell once per round
289 	ieResRef LingeringSpell;    //apply this spell once per round if the effects are lingering
290 	char LingeringCount;        //the count of rounds for which the modal spell will be reapplied after the state ends
291 	ieDword LastApplyTime;      //last time the modal effect used
292 	bool FirstApply;            //running for the first time?
293 };
294 
295 extern void ReleaseMemoryActor();
296 GEM_EXPORT void UpdateActorConfig(); //call this from guiscripts when some variable has changed
297 
298 bool VVCSort(const ScriptedAnimation* lhs, const ScriptedAnimation* rhs);
299 using vvcSet = std::multiset<ScriptedAnimation*, decltype(VVCSort)*>;
300 using vvcDict = std::multimap<ResRef, ScriptedAnimation*>;
301 
302 class GEM_EXPORT Actor : public Movable {
303 public:
304 	//CRE DATA FIELDS
305 	ieDword BaseStats[MAX_STATS];
306 	ieDword Modified[MAX_STATS];
307 	ieDword *PrevStats;
308 	ieByteSigned DeathCounters[4];   //PST specific (good, law, lady, murder)
309 
310 	ieResRef BardSong;               //custom bard song (updated by fx)
311 	ieResRef BackstabResRef;         //apply on successful backstab
312 
313 	PCStatsStruct*  PCStats;
314 	ieResRef SmallPortrait;
315 	ieResRef LargePortrait;
316 	/** 0: NPC, 1-8 party slot */
317 	ieByte InParty;
318 	//32 is the maximum possible length of the actor name in the original games
319 	char LongName[33], ShortName[33];
320 	ieStrRef ShortStrRef, LongStrRef;
321 	ieStrRef StrRefs[VCONST_COUNT];
322 
323 	ieDword AppearanceFlags;
324 
325 	ieVariable KillVar; //this second field is present in pst, iwd1 and iwd2
326 	ieVariable IncKillVar; // iwd1, iwd2
327 
328 	ieByte SetDeathVar, IncKillCount, UnknownField; // boolean fields from iwd1 and iwd2
329 
330 	Inventory inventory;
331 	Spellbook spellbook;
332 	//savefile version (creatures embedded in area)
333 	int version;
334 	//in game or area actor header
335 	ieDword TalkCount;
336 	ieDword RemovalTime;
337 	//FIXME: this is definitely not the same in bg2, in bg2 there are joinable npcs
338 	//which keep a matrix of counters
339 	ieDword InteractCount; //this is accessible in iwd2, probably exists in other games too
340 	ieDword appearance;
341 	ArmorClass AC;
342 	ToHitStats ToHit;
343 	ModalState Modal;
344 
345 	ieDword LastExit;    //the global ID of the exit to be used
346 	ieVariable UsedExit; // name of the exit, since global id is not stable after loading a new area
347 	ieResRef LastArea;
348 	char ShieldRef[2];
349 	char HelmetRef[2];
350 	char WeaponRef[2];
351 	int WeaponType;
352 	ieDword multiclass;
353 	bool GotLUFeedback;
354 	int WMLevelMod;
355 
356 	int LastDamageType;
357 	int LastDamage;
358 	Point FollowOffset;//follow lastfollowed at this offset
359 	bool Spawned;      //has been created by a spawn point
360 
361 	ieDword TargetDoor;
362 
363 	EffectQueue fxqueue;
364 
365 	vvcDict vfxDict;
366 	vvcSet vfxQueue = vvcSet(VVCSort); // sorted so we can distinguish effects infront and behind
367 	ieDword *projectileImmunity; //classic bitfield
368 	Holder<SoundHandle> casting_sound;
369 	ieDword roundTime;           //these are timers for attack rounds
370 	ieDword panicMode;           //runaway, berserk or randomwalk
371 	ieDword nextComment;         //do something random (area comment, interaction)
372 	ieDword nextBored;           //do something when bored
373 	int FatigueComplaintDelay;   // stagger tired messages
374 	ieDword lastInit;
375 	//how many attacks left in this round, must be public for cleave opcode
376 	int attackcount;
377 
378 	PolymorphCache *polymorphCache; // fx_polymorph etc
379 	WildSurgeSpellMods wildSurgeMods;
380 	ieByte DifficultyMargin;
381 	ieDword *spellStates;
382 	// set after modifying maxhp, adjusts hp next tick
383 	int checkHP;
384 	// to determine that a tick has passed
385 	ieDword checkHPTime;
386 	/**
387 	 * We don't know how to profit of them, but PST needs them saved.
388 	 * Otherwise, some actors are badly drawn, like TNO but not Morte.
389 	 * bit 0 for a "plasma" effect: palette color entries shift by one index position per cycle update
390 	 * bit 1 is for enabling pulsating for the particular color range (we store them in IE_COLOR*)
391 	 *   it periodically reduces brightness to ~50% and back to full
392 	 */
393 	ieByte pstColorBytes[10];
394 
395 	Region drawingRegion;
396 private:
397 	//this stuff doesn't get saved
398 	CharAnimations* anims;
399 
400 	using AnimationPart = std::pair<Animation*, PaletteHolder>;
401 	struct {
402 		std::vector<AnimationPart> anim;
403 		std::vector<AnimationPart> shadow;
404 	} currentStance;
405 
406 	ieByte SavingThrow[5];
407 	ieByte weapSlotCount;
408 	int walkScale = 0;
409 	// true when command has been played after select
410 	bool playedCommandSound;
411 	//true every second round of attack
412 	bool secondround;
413 	int attacksperround;
414 	//time of our next attack
415 	ieDword nextattack;
416 	ieDword nextWalk;
417 	ieDword lastattack;
418 	//trap we're trying to disarm
419 	ieDword disarmTrap;
420 	ieDword InTrap;
421 	char AttackStance;
422 	/*The projectile bringing the current attack*/
423 	Projectile* attackProjectile ;
424 	ieDword TicksLastRested;
425 	ieDword LastFatigueCheck;
426 	unsigned int remainingTalkSoundTime;
427 	unsigned int lastTalkTimeCheckAt;
428 	/** paint the actor itself. Called internally by Draw() */
429 	void DrawActorSprite(const Point& p, BlitFlags flags,
430 						 const std::vector<AnimationPart>& anims, const Color& tint) const;
431 
432 	/** fixes the palette */
433 	void SetupColors();
434 	/** debugging function, gets the scripting name of an actor referenced by a global ID */
435 	const char* GetActorNameByID(ieDword ID) const;
436 	/* checks a weapon quick slot and resets it to fist if it is empty */
437 	void CheckWeaponQuickSlot(unsigned int which);
438 	/* helper for usability checks */
439 	int CheckUsability(const Item *item) const;
440 	/* Set up all the missing stats on load time, or after level up */
441 	void CreateDerivedStatsBG();
442 	/* Set up all the missing stats on load time, or after level up */
443 	void CreateDerivedStatsIWD2();
444 	/* Gets the given ISCLASS level */
445 	ieDword GetClassLevel (const ieDword isclass) const;
446 	/* Returns true if the dual class is backwards */
447 	bool IsDualSwap() const;
448 	/* returns the weapon proficiency stat of the actor */
449 	int GetProficiency(int proftype) const;
450 	/** Re/Inits the Modified vector for PCs/NPCs */
451 	void RefreshPCStats();
452 	void RefreshHP();
453 	bool ShouldDrawCircle() const;
454 	bool HasBodyHeat() const;
455 	void SetupFistData() const;
456 	void UpdateFatigue();
457 	int GetSneakAttackDamage(Actor *target, WeaponInfo &wi, int &multiplier, bool weaponImmunity);
458 	int GetBackstabDamage(Actor *target, WeaponInfo &wi, int multiplier, int damage) const;
459 	/** for IE_EXISTANCEDELAY */
460 	void PlayExistenceSounds();
461 	ieDword GetKitIndex (ieDword kit, ieDword baseclass=0) const;
462 	char GetArmorCode() const;
463 	const char* GetArmorSound() const;
464 
465 	bool AdvanceAnimations();
466 	void UpdateDrawingRegion();
467 	/* applies modal spell etc, if needed */
468 	void UpdateModalState(ieDword gameTime);
469 
470 	int CalculateSpeedFromRate(bool feedback) const;
471 	int CalculateSpeedFromINI(bool feedback) const;
472 	ieDword IncrementDeathVariable(Variables *vars, const char *format, const char *name, ieDword start = 0) const;
473 
474 public:
475 	Actor(void);
476 	~Actor(void) override;
477 	/** releases memory */
478 	static void ReleaseMemory();
479 	/** sets game specific parameter (which stat should determine the fist weapon type */
480 	static void SetFistStat(ieDword stat);
481 	/** sets game specific default data about action buttons */
482 	static void SetDefaultActions(int qslot, ieByte slot1, ieByte slot2, ieByte slot3);
483 	/** prints useful information on console */
484 	void dump() const;
485 	/** prints useful information to given buffer */
486 	void dump(StringBuffer&) const;
487 	/** fixes the feet circle */
488 	void SetCircleSize();
489 	/** places the actor on the map */
490 	void SetMap(Map *map);
491 	/** sets the actor's position, calculating with the nojump flag*/
492 	void SetPosition(const Point &nmptTarget, int jump, int radiusx = 0, int radiusy = 0, int size = -1);
493 	/** you better use SetStat, this stuff is only for special cases*/
494 	void SetAnimationID(unsigned int AnimID);
495 	/** returns the animations */
496 	CharAnimations* GetAnims() const;
497 	/** returns the gender of actor for cg sound - illusions are tricky */
498 	ieDword GetCGGender() const;
499 	/** some hardcoded effects in puppetmaster based on puppet type */
500 	void CheckPuppet(Actor *puppet, ieDword type);
501 	/** Re/Inits the Modified vector */
502 	void RefreshEffects(EffectQueue *eqfx);
503 	/** gets saving throws */
504 	void RollSaves();
505 	/** returns a saving throw */
506 	bool GetSavingThrow(ieDword type, int modifier, const Effect *fx = nullptr);
507 	/** Returns true if the actor is targetable */
508 	bool ValidTarget(int ga_flags, const Scriptable *checker = NULL) const;
509 	/** Clamps a stat value to the valid range for the respective stat */
510 	ieDword ClampStat(unsigned int StatIndex, ieDword Value) const;
511 	/** Returns a Stat value */
512 	ieDword GetStat(unsigned int StatIndex) const;
513 	/** Returns a safe Stat value, one, that is not partially computed */
514 	ieDword GetSafeStat(unsigned int StatIndex) const;
515 	/** Sets a Stat Value (unsaved) */
516 	bool SetStat(unsigned int StatIndex, ieDword Value, int pcf);
517 	/** Returns the difference */
518 	int GetMod(unsigned int StatIndex) const;
519 	/** Returns a Stat Base Value */
520 	ieDword GetBase(unsigned int StatIndex) const;
521 	/** Sets a Base Stat Value */
522 	bool SetBase(unsigned int StatIndex, ieDword Value);
523 	bool SetBaseNoPCF(unsigned int StatIndex, ieDword Value);
524 	/** set/resets a Base Stat bit */
525 	bool SetBaseBit(unsigned int StatIndex, ieDword Value, bool setreset);
526 	/** Sets the modified value in different ways, returns difference */
527 	int NewStat(unsigned int StatIndex, ieDword ModifierValue, ieDword ModifierType);
528 	/** Modifies the base stat value in different ways, returns difference */
529 	int NewBase(unsigned int StatIndex, ieDword ModifierValue, ieDword ModifierType);
530 	void SetLeader(Actor *actor, int xoffset=0, int yoffset=0);
531 	/** Sets the Icon ResRef */
532 	//Which - 0 both, 1 Large, 2 Small
533 	void SetPortrait(const char* ResRef, int Which=0);
534 	void SetSoundFolder(const char *soundset);
535 	/* Use overrideSet to replace PCStats->SoundSet */
536 	void GetSoundFolder(char *soundset, int flag, ieResRef overrideSet = 0) const;
537 	/** Gets the Character Long Name/Short Name */
GetName(int which)538 	const char* GetName(int which) const override
539 	{
540 		if(which==-1) which=TalkCount;
541 		if (which) {
542 			return LongName;
543 		}
544 		return ShortName;
545 	}
546 	/** Gets the DeathVariable */
GetScriptName(void)547 	const char* GetScriptName(void) const
548 	{
549 		return scriptName;
550 	}
551 	/** Gets a Script ResRef */
552 	const char* GetScript(int ScriptIndex) const;
553 	/** Gets the Character's level for XP calculations */
554 	ieDword GetXPLevel(int modified) const;
555 	/** Guesses the (base) casting level */
556 	ieDword GetCasterLevel(int spelltype);
557 	ieDword GetBaseCasterLevel(int spelltype, int flags=0) const;
558 	ieDword GetAnyActiveCasterLevel() const;
559 	/** Returns the wild mage casting level modifier */
560 	int GetWildMod(int level);
561 	/** Returns any casting level modifier */
562 	int CastingLevelBonus(int level, int type);
563 
564 	/** Gets the Dialog ResRef */
565 	const char* GetDialog(int flags=GD_NORMAL) const;
566 	void SetDialog(const ieResRef resref);
567 	/** Gets the Portrait */
568 	Holder<Sprite2D> CopyPortrait(int which) const;
569 
570 	/** Gets the attack projectile */
GetAttackProjectile()571 	Projectile* GetAttackProjectile()
572 	{
573 		return attackProjectile;
574 	}
575 	void SetName(const char* ptr, unsigned char type);
576 	void SetName(int strref, unsigned char type);
577 	/* Returns by how much movement speed should be divided to account for loot weight */
578 	int GetEncumbranceFactor(bool feedback) const;
579 	/* calculates speed, encumbrance etc */
580 	int CalculateSpeed(bool feedback) const;
GetSpeed()581 	int GetSpeed() const { return walkScale; }
SetSpeed(bool feedback)582 	void SetSpeed(bool feedback) { walkScale = CalculateSpeed(feedback); }
583 	/* checks on death of actor, returns true if it should be removed*/
584 	bool CheckOnDeath();
585 	/* receives undead turning message */
586 	void Turn(Scriptable *cleric, ieDword turnlevel);
587 	/* call this on gui selects */
588 	void PlaySelectionSound();
589 	/* play a roar if the setting isn't disabled */
590 	bool PlayWarCry(int range) const;
591 	/* call this when adding actions via gui */
592 	void CommandActor(Action* action, bool clearPath=true);
593 	/** handle panic and other involuntary actions that mess with scripting */
594 	bool OverrideActions();
595 	/** handle idle actions, that shouldn't mess with scripting */
596 	void IdleActions(bool nonidle);
597 	/* sets the actor in panic (turn/morale break) */
598 	void Panic(const Scriptable *attacker, int panicmode);
599 	/* sets a multi class flag (actually this is a lot of else too) */
600 	void SetMCFlag(ieDword bitmask, int op);
601 	/* inlined dialogue start */
602 	void Interact(int type) const;
603 	/* returns a remapped verbal constant strref */
604 	ieStrRef GetVerbalConstant(int index) const;
605 	/* returns a random remapped verbal constant strref */
606 	ieStrRef GetVerbalConstant(int start, int count) const;
607 	/* displaying a random verbal constant */
608 	bool VerbalConstant(int start, int count=1, int flags=0) const;
609 	/* display string or verbal constant depending on what is available */
610 	void DisplayStringOrVerbalConstant(int str, int vcstat, int vccount=1) const;
611 	/* inlined dialogue response */
612 	void Response(int type) const;
613 	/* called when someone died in the party */
614 	bool HasSpecialDeathReaction(const char *deadname) const;
615 	void ReactToDeath(const char *deadname);
616 	/* sends trigger_died to everyone in visual range */
617 	void SendDiedTrigger() const;
618 	/* called when someone talks to Actor */
619 	void DialogInterrupt() const;
620 	/* called when actor was hit */
621 	void GetHit(int damage=0, int spellLevel=0);
622 	/* checks whether taking damage should disrupt spellcasting */
623 	bool CheckSpellDisruption(int damage, int spellLevel) const;
624 	/* called when actor starts to cast a spell*/
625 	bool HandleCastingStance(const ieResRef SpellResRef, bool deplete, bool instant);
626 	/* check if the actor should be just knocked out by a lethal hit */
627 	bool AttackIsStunning(int damagetype) const;
628 	/* check if the actor is silenced - for casting purposes */
629 	bool CheckSilenced() const;
630 	/* check and perform a cleave movement */
631 	void CheckCleave();
632 	/* deals damage to this actor */
633 	int Damage(int damage, int damagetype, Scriptable *hitter, int modtype=MOD_ADDITIVE, int critical=0, int saveflags=0);
634 	/* displays the damage taken and other details (depends on the game type) */
635 	void DisplayCombatFeedback (unsigned int damage, int resisted, int damagetype, Scriptable *hitter);
636 	/* play a random footstep sound */
637 	void PlayWalkSound();
638 	/* play the proper hit sound (in pst) */
639 	void PlayHitSound(DataFileMgr *resdata, int damagetype, bool suffix) const;
640 	void PlaySwingSound(WeaponInfo &wi) const;
641 	/* drops items from inventory to current spot */
642 	void DropItem(const ieResRef resref, unsigned int flags);
643 	void DropItem(int slot, unsigned int flags);
644 	/* returns item information in quickitem slot */
645 	void GetItemSlotInfo(ItemExtHeader *item, int which, int header);
646 	/* returns spell information in quickspell slot */
647 	void GetSpellSlotInfo(SpellExtHeader *spell, int which);
648 	/* updates quickslots */
649 	void ReinitQuickSlots();
650 	/* actor is in trap */
651 	void SetInTrap(ieDword tmp);
652 	/* sets some of the internal flags */
653 	void SetRunFlags(ieDword flags);
IsRunning()654 	bool IsRunning() const { return InternalFlags & IF_RUNFLAGS; }
655 	/* applies the kit abilities, returns false if kit is not applicable */
656 	bool ApplyKit(bool remove, ieDword baseclass=0, int diff=0);
657 	/* applies the class abilities*/
658 	void ApplyClab(const char *clab, ieDword max, int remove, int diff);
659 	/* calls InitQuickSlot in PCStatStruct */
660 	void SetupQuickSlot(unsigned int which, int slot, int headerindex);
661 	/* returns true if the actor is PC/joinable*/
662 	bool Persistent() const;
663 	/* assigns actor to party slot, 0 = NPC, areas won't remove it */
664 	void SetPersistent(int partyslot);
665 	/* resurrects actor */
666 	void Resurrect(const Point &destPoint);
667 	/* removes actor in the next update cycle */
668 	void DestroySelf();
669 	/* schedules actor to die */
670 	void Die(Scriptable *killer, bool grantXP = true);
671 	/* debug function */
672 	void GetNextAnimation();
673 	/* debug function */
674 	void GetPrevAnimation();
675 	/* debug function */
676 	void GetNextStance();
677 	void ClearCurrentStanceAnims();
678 	/* learns the given spell, possibly receive XP */
679 	int LearnSpell(const ieResRef resref, ieDword flags, int bookmask=-1, int level=-1);
680 	/* returns the ranged weapon header associated with the currently equipped projectile */
681 	ITMExtHeader *GetRangedWeapon(WeaponInfo &wi) const;
682 	/* Returns current weapon range and extended header
683 	if range is nonzero, then which is valid */
684 	ITMExtHeader* GetWeapon(WeaponInfo &wi, bool leftorright=false) const;
685 	/* Creates player statistics */
686 	void CreateStats();
687 	/* Heals actor */
688 	void Heal(int hp);
689 	/* Receive experience (handle dual/multi class) */
690 	void AddExperience(int exp, int combat);
691 	/* Calculate experience bonus */
692 	int CalculateExperience(int type, int level) const;
693 	/* Sets the modal state after checks */
694 	void SetModal(ieDword newstate, bool force=1);
695 	/* Sets the modal spell after checks */
696 	void SetModalSpell(ieDword state, const char *spell);
697 	/* casts the modal spell if any */
698 	void ApplyModal(ieResRef modalSpell);
699 	/* returns current attack style */
700 	int GetAttackStyle() const;
701 	/* adds the combatants to the attackers list */
702 	void AttackedBy(const Actor *actor);
703 	/* reorients to face target (for immediate attack) */
704 	void FaceTarget(Scriptable *actor);
705 	/* returns the number of attacks (handles monk barehanded bonus) */
706 	ieDword GetNumberOfAttacks();
707 	/* starts combat round*/
708 	void InitRound(ieDword gameTime);
709 	/* returns melee penalty */
710 	int MeleePenalty() const;
711 	/* gets the to hit value */
712 	int GetToHit(ieDword Flags, const Actor *target);
713 	void GetTHAbilityBonus(ieDword Flags);
714 	/* gets the defense against an attack */
715 	int GetDefense(int DamageType, ieDword wflags, const Actor *attacker) const;
716 	/* checks if something is wrong with the weapon we are using for the attack */
717 	bool WeaponIsUsable(bool leftorright, ITMExtHeader *header=NULL) const;
718 	/* get the current hit bonus */
719 	bool GetCombatDetails(int &tohit, bool leftorright, WeaponInfo &wi, ITMExtHeader *&header, ITMExtHeader *&hittingheader,\
720 		int &DamageBonus, int &speed, int &CriticalBonus, int &style, const Actor *target);
721 	/* performs attack against target */
722 	void PerformAttack(ieDword gameTime);
723 	/* returns the adjusted weapon range, since items have odd values stored */
724 	int GetWeaponRange(const WeaponInfo &wi) const;
725 	/* filter out any damage reduction that is cancelled by high weapon enchantment and return the resulting resistance */
726 	int GetDamageReduction(int resist_stat, ieDword weaponEnchantment) const;
727 	/* calculates strength (dexterity) based damage adjustment */
728 	int WeaponDamageBonus(const WeaponInfo &wi) const;
729 	/* handles critical, backstab, etc. damage modifications */
730 	void ModifyWeaponDamage(WeaponInfo &wi, Actor *target, int &damage, bool &critical);
731 	/* adjusts damage dealt to this actor, handles mirror images  */
732 	void ModifyDamage(Scriptable *hitter, int &damage, int &resisted, int damagetype);
733 	/* returns the hp adjustment based on constitution */
734 	int GetHpAdjustment(int multiplier, bool modified=true) const;
735 	/* does all the housekeeping after loading the actor from file */
736 	void InitStatsOnLoad();
737 	/* sets a colour gradient stat, handles location */
738 	void SetColor( ieDword idx, ieDword grd);
739 	/* sets an RGB colour modification effect; location 0xff for global */
740 	void SetColorMod( ieDword location, RGBModifier::Type type, int speed,
741 					 const Color&, int phase = -1) const;
742 	bool Schedule(ieDword gametime, bool checkhide) const;
743 	void NewPath();
744 	/* overridden method, won't walk if dead */
745 	void WalkTo(const Point &Des, ieDword flags, int MinDistance = 0);
746 	/* resolve string constant (sound will be altered) */
747 	void ResolveStringConstant(ieResRef& sound, unsigned int index) const;
748 	bool GetSoundFromFile(ieResRef &Sound, unsigned int index) const;
749 	bool GetSoundFromINI(ieResRef &Sound, unsigned int index) const;
750 	bool GetSoundFrom2DA(ieResRef &Sound, unsigned int index) const;
751 	/* generate area specific oneliner */
752 	void GetAreaComment(int areaflag) const;
753 	/* handle oneliner interaction, -1: unsuccessful (may comment area), 0: dialog banter, 1: oneliner */
754 	int HandleInteract(const Actor *target) const;
755 	/* start bg1-style banter dialog */
756 	void HandleInteractV1(const Actor *target);
757 	/* generate party banter, return true if successful */
758 	bool GetPartyComment();
759 	/* sets the quick slots */
760 	void SetActionButtonRow(ActionButtonRow &ar);
761 	/* updates the quick slots */
762 	void GetActionButtonRow(ActionButtonRow &qs);
763 	/* converts the iwd2 qslot index to our internal representation */
764 	int IWD2GemrbQslot (int slotindex) const;
765 	int Gemrb2IWD2Qslot(ieByte actslot, int slotindex) const;
766 	void dumpQSlots() const;
767 
768 	/* Handling automatic stance changes */
769 	bool HandleActorStance();
770 	void UpdateActorState();
771 	/* update internal per frame state and return true if state is suitable for drawing the actor */
772 	bool UpdateDrawingState();
773 	Region DrawingRegion() const override;
774 	uint8_t GetElevation() const;
775 	bool ShouldDrawReticle() const;
776 	void DoStep(unsigned int walkScale, ieDword time = 0) override;
777 	void Draw(const Region &screen, Color baseTint, Color tint, BlitFlags flags) const;
778 
779 	/* add mobile vvc (spell effects) to actor's list */
780 	void AddVVCell(ScriptedAnimation* vvc);
781 	/* remove a vvc from the list, graceful means animated removal */
782 	void RemoveVVCells(const ResRef& vvcname);
783 	/* returns true if actor already has the overlay (slow) */
784 	bool HasVVCCell(const ResRef& resource) const;
785 	/* returns overlay if actor already has it (slow) */
786 	std::pair<vvcDict::const_iterator, vvcDict::const_iterator>
787 	GetVVCCells(const ResRef& resource) const;
788 	/* returns the vvc pointer to a hardcoded overlay */
789 	/* if it exists (faster than hasvvccell) */
790 	ScriptedAnimation *FindOverlay(int index) const;
791 
792 	void SetLockedPalette(const ieDword *gradients);
793 	void UnlockPalette();
794 	void AddAnimation(const ieResRef resource, int gradient, int height, int flags);
795 	/* plays damage animation, if hit is not set, then plays only the splash part */
796 	void PlayDamageAnimation(int x, bool hit=true);
797 	void PlayCritDamageAnimation(int x);
798 	/* returns mage or cleric spell casting failure, iwd2 compatible */
799 	ieDword GetSpellFailure(bool arcana) const;
800 	/* returns the dexterity AC adjusted by armor, iwd2 compatible */
801 	int GetDexterityAC() const;
802 	/* returns the monk wisdom AC adjusted by armor (iwd2) */
803 	int GetWisdomAC() const;
804 	/* PST specific criticals */
805 	int GetCriticalType() const;
806 	/* restores a spell of maximum maxlevel level, type is a mask of disabled spells */
807 	int RestoreSpellLevel(ieDword maxlevel, ieDword typemask);
808 	/* rememorizes spells, cures fatigue, etc */
809 	void Rest(int hours);
810 	int GetConHealAmount() const;
811 	/* returns the portrait icons list */
812 	const unsigned char *GetStateString() const;
813 	/* adds a state icon to the list */
814 	void AddPortraitIcon(ieByte icon);
815 	/* disables a state icon in the list, doesn't remove it! */
816 	void DisablePortraitIcon(ieByte icon);
817 	/* returns which slot belongs to the quickweapon slot */
818 	int GetQuickSlot(int slot) const;
819 	/* Sets equipped Quick slot, if header is -1, then use the current one */
820 	int SetEquippedQuickSlot(int slot, int header);
821 	/* Uses an item on the target or point */
822 	bool UseItemPoint(ieDword slot, ieDword header, const Point &point, ieDword flags);
823 	bool UseItem(ieDword slot, ieDword header, Scriptable *target, ieDword flags, int damage = 0);
824 	/* Deducts a charge from an item */
825 	void ChargeItem(ieDword slot, ieDword header, CREItem *item, Item *itm, bool silent, bool expend = true);
826 	/* If it returns true, then default AC=10 and the lesser the better */
827 	static int IsReverseToHit();
828 	/* initialize the action buttons based on class. If forced, it will override
829 		previously customized or set buttons. */
830 	void InitButtons(ieDword cls, bool forced);
831 	int GetMaxEncumbrance() const;
832 	int GetAbilityBonus(unsigned int ability, int value = -1) const;
833 	int GetSkillStat(unsigned int skill) const;
834 	int GetSkill(unsigned int skill, bool ids=false) const;
835 	int GetFeat(unsigned int feat) const;
836 	void SetFeat(unsigned int feat, int mode);
837 	void SetFeatValue(unsigned int feat, int value, bool init = true);
838 	void SetUsedWeapon(const char (&AnimationType)[2], ieWord *MeleeAnimation,
839 		int WeaponType=-1);
840 	void SetUsedShield(const char (&AnimationType)[2], int WeaponType=-1);
841 	void SetUsedHelmet(const char (&AnimationType)[2]);
842 	void SetupFist();
843 	/* Returns nonzero if the caster is held */
844 	int Immobile() const;
845 	/* Returns strref if the item is unusable due to name/type restrictions */
846 	ieStrRef Disabled(const ieResRef name, ieDword type) const;
847 	/* Returns constant string if the item is unusable */
848 	int Unusable(const Item *item) const;
849 	/* Sets all clown colour to the given gradient */
850 	void SetGradient(ieDword gradient);
851 	/* Enables an overlay */
852 	void SetOverlay(unsigned int overlay);
853 	/* Checks and sets a spellstate if it wasn't set yet */
854 	bool SetSpellState(unsigned int spellstate);
855 	/* Checks a spellstate */
856 	bool HasSpellState(unsigned int spellstate) const;
857 	/* Checks a feat */
858 	bool HasFeat(unsigned int featindex) const;
859 	/* Reports projectile immunity, nonzero if immune */
860 	ieDword ImmuneToProjectile(ieDword projectile) const;
861 	/* Sets projectile immunity */
862 	void AddProjectileImmunity(ieDword projectile);
863 	/* Apply feats */
864 	void ApplyFeats();
865 	/* reapply modal feat spells */
866 	void ApplyExtraSettings();
867 	/* Set up all the missing stats on load time, chargen, or after level up */
868 	void CreateDerivedStats();
869 	/* Resets the internal multiclass bitfield */
870 	void ResetMC();
871 	/* Checks if the actor is multiclassed (excluding dualclassed actors)) */
872 	bool IsMultiClassed() const;
873 	/* Checks if the actor is dualclassed */
874 	bool IsDualClassed() const;
875 	/* Returns an exact copy of this actor */
876 	Actor *CopySelf(bool mislead) const;
877 	static ieDword GetClassID (const ieDword isclass);
878 	const char *GetClassName(ieDword classID) const;
879 	const char *GetKitName(ieDword kitID) const;
880 	/* Returns the actor's level of the given class */
GetFighterLevel()881 	ieDword GetFighterLevel() const { return GetClassLevel(ISFIGHTER); }
GetMageLevel()882 	ieDword GetMageLevel() const { return GetClassLevel(ISMAGE); }
GetThiefLevel()883 	ieDword GetThiefLevel() const { return GetClassLevel(ISTHIEF); }
GetBarbarianLevel()884 	ieDword GetBarbarianLevel() const { return GetClassLevel(ISBARBARIAN); }
GetBardLevel()885 	ieDword GetBardLevel() const { return GetClassLevel(ISBARD); }
GetClericLevel()886 	ieDword GetClericLevel() const { return GetClassLevel(ISCLERIC); }
GetDruidLevel()887 	ieDword GetDruidLevel() const { return GetClassLevel(ISDRUID); }
GetMonkLevel()888 	ieDword GetMonkLevel() const { return GetClassLevel(ISMONK); }
GetPaladinLevel()889 	ieDword GetPaladinLevel() const { return GetClassLevel(ISPALADIN); }
GetRangerLevel()890 	ieDword GetRangerLevel() const { return GetClassLevel(ISRANGER); }
GetSorcererLevel()891 	ieDword GetSorcererLevel() const { return GetClassLevel(ISSORCERER); }
892 	/* Returns true if the character is a warrior */
893 	ieDword GetWarriorLevel() const;
IsWarrior()894 	bool IsWarrior() const { return (GetFighterLevel()||GetBarbarianLevel()||GetRangerLevel()||GetPaladinLevel()); }
895 	/* Returns true if the old class is inactive */
896 	bool IsDualInactive() const;
897 	/* true if we are dual-wielding */
898 	int IsDualWielding() const;
899 	int GetFavoredPenalties() const;
900 	bool BlocksSearchMap() const override;
901 	bool CannotPassEntrance(ieDword exitID) const;
902 	void UseExit(ieDword exitID);
903 	//int GetReaction() const;
904 	/* Similar to Roll, but takes luck into account */
905 	int LuckyRoll(int dice, int size, int add, ieDword flags=LR_CRITICAL, Actor* opponent=NULL) const;
906 	/* removes normal invisibility (type 0) */
907 	void CureInvisibility();
908 	/* removes sanctuary */
909 	void CureSanctuary();
910 	/* resets the invisibility, sanctuary and modal states */
911 	void ResetState();
912 	/* checks whether the actor is behind the target */
913 	bool IsBehind(Actor* target) const;
914 	/* checks whether the target is the actor's racial enemy */
915 	int GetRacialEnemyBonus(const Actor *target) const;
916 	/* checks whether the actor can stay in the current modal state */
917 	bool ModalSpellSkillCheck();
918 	/* check if this actor is seen by or seeing anyone */
919 	bool SeeAnyOne(bool enemy, bool seen) const;
920 	/* does all the game logic checks to see if the actor can hide */
921 	bool TryToHide();
922 	bool TryToHideIWD2();
923 	/* checks if the alignment matches one of the masking constants */
924 	//bool MatchesAlignmentMask(ieDword mask);
925 	/** untargetable by spells/attack due to invisibility or sanctuary */
926 	bool Untargetable(ieResRef spellRef) const;
927 	/* returns true if this it is futile to try to harm actor (dead/sanctuaried) */
928 	bool InvalidSpellTarget() const;
929 	/* returns true if the spell is useless to cast on target
930 	or the spell's range is smaller than range */
931 	bool InvalidSpellTarget(int spellnum, Actor *caster, int range) const;
932 	/* function to get a class level used by scripting */
933 	ieDword GetLevelInClass (const ieDword classid) const;
934 	/* computes the actor's classmask (iwd2) */
935 	int GetClassMask() const;
936 	/* computes the actor's usable books (iwd2) */
937 	int GetBookMask() const;
938 	/* computes the thieving skill bonus from race and dexterity */
939 	int GetSkillBonus(unsigned int col) const;
940 	/* returns true for party members (and familiars) */
941 	bool IsPartyMember() const;
942 	/* resets the bored and area comment timers */
943 	void ResetCommentTime();
944 	/* returns the armor check penalty */
945 	int GetArmorSkillPenalty(int profcheck=1) const;
946 	int GetArmorSkillPenalty(int profcheck, int &armor, int &shield) const;
947 	int GetArmorWeightClass(ieWord armorType) const;
948 	int GetTotalArmorFailure() const;
949 	int GetArmorFailure(int &armor, int &shield) const;
950 	bool IsDead() const;
951 	bool IsInvisibleTo(const Scriptable *checker) const;
952 	int UpdateAnimationID(bool derived);
953 	void MovementCommand(char *command);
954 	/* shows hp/maxhp as overhead text */
955 	bool HasVisibleHP() const;
956 	void DisplayHeadHPRatio();
957 	/* if Lasttarget is gone, call this */
958 	void StopAttack();
959 	int SetBaseAPRandAB(bool CheckRapidShot);
960 	int BAB2APR(int pBAB, int pBABDecrement, int CheckRapidShot) const;
961 	/* set to trap id if current action is disarm; unset after */
SetDisarmingTrap(ieDword trapId)962 	void SetDisarmingTrap(ieDword trapId) { disarmTrap = trapId; }
GetDisarmingTrap()963 	ieDword GetDisarmingTrap() const { return disarmTrap; }
964 	void ReleaseCurrentAction() override;
965 	bool ConcentrationCheck() const;
966 	void ApplyEffectCopy(Effect *oldfx, EffectRef &newref, Scriptable *Owner, ieDword param1, ieDword param2);
GetLastRested()967 	ieDword GetLastRested() { return TicksLastRested; }
IncreaseLastRested(int inc)968 	void IncreaseLastRested(int inc) { TicksLastRested += inc; LastFatigueCheck += inc; }
969 	bool WasClass(ieDword oldClassID) const;
970 	ieDword GetActiveClass() const;
971 	bool IsKitInactive() const;
972 	const char* GetRaceName() const;
973 	unsigned int GetSubRace() const;
974 	std::list<int> ListLevels() const;
975 	void ChangeSorcererType (ieDword classIdx);
976 	unsigned int GetAdjustedTime(unsigned int time) const;
977 	void SetAnimatedTalking(unsigned int);
978 	bool HasPlayerClass() const;
979 	void PlayArmorSound() const;
980 	bool ShouldModifyMorale() const;
981 	bool HibernateIfAble();
982 };
983 }
984 
985 #endif
986