fixed the last commit to set and check the target more often, thanks fuzzie
[gemrb.git] / gemrb / core / Scriptable / ActorBlock.h
blobb616793a1d9243a0a3d9fbfac34f4d315a353257
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
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.
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.
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.
21 #ifndef ACTORBLOCK_H
22 #define ACTORBLOCK_H
24 #include "exports.h"
26 #include "CharAnimations.h"
27 #include "Inventory.h"
28 #include "PathFinder.h"
29 #include "Sprite2D.h"
30 #include "TileOverlay.h"
31 #include "Variables.h"
33 #include <list>
35 class Action;
36 class Actor;
37 class Door;
38 class GameScript;
39 class Gem_Polygon;
40 class Highlightable;
41 class Movable;
42 class Scriptable;
43 class Selectable;
44 class SpriteCover;
46 #define MAX_SCRIPTS 8
47 #define MAX_GROUND_ICON_DRAWN 3
48 #define MAX_TIMER 256
50 /** The distance of operating a trigger, container, etc. */
51 #define MAX_OPERATING_DISTANCE 40 //a search square is 16x12
52 /** The distance between PC's who are about to enter a new area */
53 #define MAX_TRAVELING_DISTANCE 400
55 #define SCR_OVERRIDE 0
56 #define SCR_AREA 1
57 #define SCR_SPECIFICS 2
58 #define SCR_RESERVED 3
59 #define SCR_CLASS 4
60 #define SCR_RACE 5
61 #define SCR_GENERAL 6
62 #define SCR_DEFAULT 7
64 //pst trap flags (portal)
65 #define PORTAL_CURSOR 1
66 #define PORTAL_TRAVEL 2
67 //trigger flags
68 #define TRAP_INVISIBLE 1
69 #define TRAP_RESET 2
70 #define TRAVEL_PARTY 4
71 #define TRAP_DETECTABLE 8
72 //#define TRAP_16 16
73 //#define TRAP_32 32
74 #define TRAP_NPC 64
75 //#define TRAP_128 128
76 #define TRAP_DEACTIVATED 256
77 #define TRAVEL_NONPC 512
78 #define TRAP_USEPOINT 1024 //override usage point of travel regions
79 #define INFO_DOOR 2048 //info trigger blocked by door
81 //door flags
82 #define DOOR_OPEN 1
83 #define DOOR_LOCKED 2
84 #define DOOR_RESET 4 //reset trap
85 #define DOOR_DETECTABLE 8 //trap detectable
86 #define DOOR_16 16 //unknown
87 #define DOOR_32 32 //unknown
88 #define DOOR_LINKED 64 //info trigger linked to this door
89 #define DOOR_SECRET 128 //door is secret
90 #define DOOR_FOUND 256 //secret door found
91 #define DOOR_TRANSPARENT 512 //obscures vision
92 #define DOOR_KEY 1024 //key removed when used
93 #define DOOR_SLIDE 2048 //impeded blocks ignored
95 //container flags
96 #define CONT_LOCKED 1
97 #define CONT_RESET 8
98 #define CONT_DISABLED 32
100 //internal actor flags
101 #define IF_GIVEXP 1 //give xp for this death
102 #define IF_JUSTDIED 2 //Died() will return true
103 #define IF_FROMGAME 4 //this is an NPC or PC
104 #define IF_REALLYDIED 8 //real death happened, actor will be set to dead
105 #define IF_NORECTICLE 16 //draw recticle (target mark)
106 #define IF_NOINT 32 //cannot interrupt the actions of this actor (save is not possible!)
107 #define IF_CLEANUP 64 //actor died chunky death, or other total destruction
108 #define IF_RUNNING 128 //actor is running
109 //these bits could be set by a WalkTo
110 #define IF_RUNFLAGS (IF_RUNNING|IF_NORECTICLE|IF_NOINT)
111 #define IF_BECAMEVISIBLE 0x100//actor just became visible (trigger event)
112 #define IF_INITIALIZED 0x200
113 #define IF_USEDSAVE 0x400 //actor needed saving throws
114 #define IF_TARGETGONE 0x800 //actor's target is gone (trigger event)
115 #define IF_USEEXIT 0x1000 //
116 #define IF_INTRAP 0x2000 //actor is currently in a trap (intrap trigger event)
117 #define IF_WASINDIALOG 0x4000 //actor just left dialog
119 //scriptable flags
120 #define IF_ACTIVE 0x10000
121 #define IF_CUTSCENEID 0x20000
122 #define IF_VISIBLE 0x40000
123 #define IF_ONCREATION 0x80000
124 #define IF_IDLE 0x100000
125 #define IF_PARTYRESTED 0x200000 //party rested trigger event
127 //the actor should stop attacking
128 #define IF_STOPATTACK (IF_JUSTDIED|IF_REALLYDIED|IF_CLEANUP|IF_IDLE)
130 //CheckTravel return value
131 #define CT_CANTMOVE 0 //inactive
132 #define CT_ACTIVE 1 //actor can move
133 #define CT_GO_CLOSER 2 //entire team would move, but not close enough
134 #define CT_WHOLE 3 //team can move
135 #define CT_SELECTED 4 //not all selected actors are there
136 #define CT_MOVE_SELECTED 5 //all selected can move
138 //bits for binary trigger bitfield
139 #define BT_DIE 1
140 #define BT_ONCREATION 2
141 #define BT_BECAMEVISIBLE 4
142 #define BT_WASINDIALOG 8
143 #define BT_PARTYRESTED 16
144 #define BT_VACANT 32
146 //xp bonus types (for xpbonus.2da)
147 #define XP_LOCKPICK 0
148 #define XP_DISARM 1
149 #define XP_LEARNSPELL 2
151 typedef enum ScriptableType { ST_ACTOR = 0, ST_PROXIMITY = 1, ST_TRIGGER = 2,
152 ST_TRAVEL = 3, ST_DOOR = 4, ST_CONTAINER = 5, ST_AREA = 6, ST_GLOBAL = 7 } ScriptableType;
154 typedef std::list<ieDword *> TriggerObjects;
156 //#define SEA_RESET 0x00000002
157 //#define SEA_PARTY_REQUIRED 0x00000004
159 class GEM_EXPORT Scriptable {
160 public:
161 Scriptable(ScriptableType type);
162 virtual ~Scriptable(void);
163 private:
164 TriggerObjects tolist;
165 ieDword bittriggers;
166 unsigned long startTime;
167 unsigned long interval;
168 unsigned long WaitCounter;
169 // script_timers should probably be a std::map to
170 // conserve memory (usually at most 2 ids are used)
171 ieDword script_timers[MAX_TIMER];
172 protected: //let Actor access this
173 Map *area;
174 ieVariable scriptName;
175 ieDword InternalFlags; //for triggers
176 Scriptable* CutSceneId;
177 ieResRef Dialog;
178 std::list< Action*> actionQueue;
179 Action* CurrentAction;
180 public:
181 int CurrentActionState;
182 ieWord CurrentActionTarget;
183 bool CurrentActionInterruptable;
184 ieDword lastDelay;
185 ieDword lastRunTime;
186 Variables* locals;
187 ScriptableType Type;
188 Point Pos;
189 ieStrRef DialogName;
190 GameScript* Scripts[MAX_SCRIPTS];
191 char* overHeadText;
192 Point overHeadTextPos;
193 unsigned char textDisplaying;
194 unsigned long timeStartDisplaying;
195 ieDword UnselectableTimer;
196 ieDword TriggerID; //for sendtrigger
197 ieDword LastTrigger; // also LastClosed
198 ieDword LastTriggerObject; // hack until someone fixes triggers
199 ieDword LastEntered; // also LastOpened
200 ieDword LastDisarmed; // also LastAttacker
201 ieDword LastDisarmFailed; //also LastTarget
202 ieDword LastUnlocked;
203 ieDword LastOpenFailed; // also LastPickpocketFailed
204 ieDword LastPickLockFailed;
205 int LastOrder;
206 ieDword LastOrderer;
207 ieDword LastSpellOnMe; //Last spell cast on this scriptable
208 ieDword LastCasterOnMe; //Last spellcaster on this scriptable
209 ieDword LastSpellSeen; //Last spell seen to be cast
210 ieDword LastCasterSeen; //Last spellcaster seen
211 Point LastTargetPos;
212 int SpellHeader;
213 public:
214 /** Gets the Dialog ResRef */
215 const char* GetDialog(void) const
217 return Dialog;
219 void SetDialog(const char *resref) {
220 strnuprcpy(Dialog, resref, 8);
222 void SetScript(const ieResRef aScript, int idx, bool ai=false);
223 void SetWait(unsigned long time);
224 unsigned long GetWait() const;
225 void LeaveDialog();
226 Scriptable *GetCutsceneID() const;
227 void ClearCutsceneID();
228 void SetCutsceneID(Scriptable *csid);
229 void Interrupt();
230 void NoInterrupt();
231 void Hide();
232 void Unhide();
233 void Activate();
234 void Deactivate();
235 void PartyRested();
236 ieDword GetInternalFlag();
237 const char* GetScriptName() const;
238 Map* GetCurrentArea() const;
239 void SetMap(Map *map);
240 void SetScript(int index, GameScript* script);
241 void DisplayHeadText(const char* text);
242 void FixHeadTextPos();
243 void SetScriptName(const char* text);
244 //call this to deny script running in the next AI cycle
245 void DelayedEvent();
246 //call this to enable script running as soon as possible
247 void ImmediateEvent();
248 bool IsPC() const;
249 void ExecuteScript(int scriptCount);
250 void AddAction(Action* aC);
251 void AddActionInFront(Action* aC);
252 Action* GetCurrentAction() const { return CurrentAction; }
253 Action* GetNextAction() const;
254 Action* PopNextAction();
255 void ClearActions();
256 void ReleaseCurrentAction();
257 bool InMove() const;
258 void ProcessActions(bool force);
259 //these functions handle clearing of triggers that resulted a
260 //true condition (whole triggerblock returned true)
261 void InitTriggers();
262 void ClearTriggers();
263 void SetBitTrigger(ieDword bittrigger);
264 void AddTrigger(ieDword *actorref);
265 /* re/draws overhead text on the map screen */
266 void DrawOverheadText(const Region &screen);
267 /* actor/scriptable casts spell */
268 int CastSpellPoint( const ieResRef SpellResRef, const Point &Target, bool deplete, bool instant = false );
269 int CastSpell( const ieResRef SpellResRef, Scriptable* Target, bool deplete, bool instant = false );
270 /* spellcasting finished */
271 void CastSpellPointEnd( const ieResRef SpellResRef);
272 void CastSpellEnd( const ieResRef SpellResRef);
273 ieWord GetGlobalID();
274 /** timer functions (numeric ID, not saved) */
275 bool TimerActive(ieDword ID);
276 bool TimerExpired(ieDword ID);
277 void StartTimer(ieDword ID, ieDword expiration);
278 virtual char* GetName(int /*which*/) const { return NULL; }
279 private:
280 /* used internally to handle start of spellcasting */
281 int SpellCast(const ieResRef SpellResRef, bool instant);
284 class GEM_EXPORT Selectable : public Scriptable {
285 public:
286 Selectable(ScriptableType type);
287 virtual ~Selectable(void);
288 public:
289 Region BBox;
290 ieWord Selected; //could be 0x80 for unselectable
291 bool Over;
292 Color selectedColor;
293 Color overColor;
294 Sprite2D *circleBitmap[2];
295 int size;
296 private:
297 // current SpriteCover for wallgroups
298 SpriteCover* cover;
299 public:
300 void SetBBox(const Region &newBBox);
301 void DrawCircle(const Region &vp);
302 bool IsOver(const Point &Pos) const;
303 void SetOver(bool over);
304 bool IsSelected() const;
305 void Select(int Value);
306 void SetCircle(int size, const Color &color, Sprite2D* normal_circle, Sprite2D* selected_circle);
308 /* store SpriteCover */
309 void SetSpriteCover(SpriteCover* c);
310 /* get stored SpriteCover */
311 SpriteCover* GetSpriteCover() const { return cover; }
312 /* want dithered SpriteCover */
313 int WantDither();
316 class GEM_EXPORT Highlightable : public Scriptable {
317 public:
318 Highlightable(ScriptableType type);
319 virtual ~Highlightable(void);
320 virtual int TrapResets() const = 0;
321 virtual bool CanDetectTrap() const { return true; }
322 virtual bool PossibleToSeeTrap() const;
323 public:
324 Gem_Polygon* outline;
325 Color outlineColor;
326 ieDword Cursor;
327 bool Highlight;
328 Point TrapLaunch;
329 ieWord TrapDetectionDiff;
330 ieWord TrapRemovalDiff;
331 ieWord Trapped;
332 ieWord TrapDetected;
333 ieResRef KeyResRef;
334 public:
335 bool IsOver(const Point &Pos) const;
336 void DrawOutline() const;
337 void SetCursor(unsigned char CursorIndex);
338 const char* GetKey(void) const
340 if (KeyResRef[0]) return KeyResRef;
341 return NULL;
343 void SetTrapDetected(int x);
344 void TryDisarm(Actor *actor);
345 //detect trap, set skill to 256 if you want sure fire
346 void DetectTrap(int skill);
347 //returns true if trap is visible, only_detected must be true
348 //if you want to see discovered traps, false is for cheats
349 bool VisibleTrap(int only_detected) const;
350 //returns true if trap has been triggered, tumble skill???
351 virtual bool TriggerTrap(int skill, ieDword ID);
352 bool TryUnlock(Actor *actor, bool removekey);
355 class GEM_EXPORT Movable : public Selectable {
356 private: //these seem to be sensitive, so get protection
357 unsigned char StanceID;
358 unsigned char Orientation, NewOrientation;
359 ieWord AttackMovements[3];
361 PathNode* path; //whole path
362 PathNode* step; //actual step
363 public:
364 Movable(ScriptableType type);
365 virtual ~Movable(void);
366 Point Destination;
367 ieDword timeStartStep;
368 Sprite2D* lastFrame;
369 ieResRef Area;
370 public:
371 PathNode *GetNextStep(int x);
372 int GetPathLength();
373 //inliners to protect data consistency
374 inline PathNode * GetNextStep() {
375 if (!step) {
376 DoStep((unsigned int) ~0);
378 return step;
381 inline unsigned char GetOrientation() const {
382 return Orientation;
385 inline unsigned char GetNextFace() {
386 //slow turning
387 if (Orientation != NewOrientation) {
388 if ( ( (NewOrientation-Orientation) & (MAX_ORIENT-1) ) <= MAX_ORIENT/2) {
389 Orientation++;
390 } else {
391 Orientation--;
393 Orientation = Orientation&(MAX_ORIENT-1);
396 return Orientation;
398 inline unsigned char GetStance() const {
399 return StanceID;
402 inline void SetOrientation(int value, bool slow) {
403 //MAX_ORIENT == 16, so we can do this
404 NewOrientation = (unsigned char) (value&(MAX_ORIENT-1));
405 if (!slow) {
406 Orientation = NewOrientation;
410 void SetStance(unsigned int arg);
411 void SetAttackMoveChances(ieWord *amc);
412 bool DoStep(unsigned int walk_speed, ieDword time = 0);
413 void AddWayPoint(const Point &Des);
414 void RunAwayFrom(const Point &Des, int PathLength, int flags);
415 void RandomWalk(bool can_stop, bool run);
416 void MoveLine(int steps, int Pass, ieDword Orient);
417 void FixPosition();
418 void WalkTo(const Point &Des, int MinDistance = 0);
419 void MoveTo(const Point &Des);
420 void ClearPath();
421 void DrawTargetPoint(const Region &vp);
422 /* returns the most likely position of this actor */
423 Point GetMostLikelyPosition();
424 virtual bool BlocksSearchMap() const = 0;
428 //Tiled objects are not used (and maybe not even implemented correctly in IE)
429 //they seem to be most closer to a door and probably obsoleted by it
430 //are they scriptable?
431 class GEM_EXPORT TileObject {
432 public:
433 TileObject(void);
434 ~TileObject(void);
435 void SetOpenTiles(unsigned short *indices, int count);
436 void SetClosedTiles(unsigned short *indices, int count);
438 public:
439 ieVariable Name;
440 ieResRef Tileset; //or wed door ID?
441 ieDword Flags;
442 unsigned short* opentiles;
443 ieDword opencount;
444 unsigned short* closedtiles;
445 ieDword closedcount;
448 class GEM_EXPORT Door : public Highlightable {
449 public:
450 Door(TileOverlay* Overlay);
451 ~Door(void);
452 public:
453 ieVariable LinkedInfo;
454 ieResRef ID; //WED ID
455 TileOverlay* overlay;
456 unsigned short* tiles;
457 int tilecount;
458 ieDword Flags;
459 int closedIndex;
460 //trigger areas
461 Gem_Polygon* open;
462 Gem_Polygon* closed;
463 //impeded blocks
464 Point* open_ib; //impeded blocks stored in a Point array
465 int oibcount;
466 Point* closed_ib;
467 int cibcount;
468 //wallgroup covers
469 unsigned int open_wg_index;
470 unsigned int open_wg_count;
471 unsigned int closed_wg_index;
472 unsigned int closed_wg_count;
473 Point toOpen[2];
474 ieResRef OpenSound;
475 ieResRef CloseSound;
476 ieResRef LockSound;
477 ieResRef UnLockSound;
478 ieDword DiscoveryDiff;
479 ieDword LockDifficulty; //this is a dword?
480 ieStrRef OpenStrRef;
481 ieStrRef NameStrRef;
482 ieDword Unknown54; //unused in tob
483 private:
484 void SetWallgroups(int count, int value);
485 void ImpedeBlocks(int count, Point *points, unsigned char value);
486 void UpdateDoor();
487 bool BlockedOpen(int Open, int ForceOpen);
488 public:
489 void ToggleTiles(int State, int playsound = false);
490 void SetName(const char* Name); // sets door ID
491 void SetTiles(unsigned short* Tiles, int count);
492 void SetDoorLocked(int Locked, int playsound);
493 void SetDoorOpen(int Open, int playsound, ieDword ID);
494 void SetPolygon(bool Open, Gem_Polygon* poly);
495 int IsOpen() const;
496 void TryPickLock(Actor *actor);
497 void TryBashLock(Actor* actor) ;
498 bool TryUnlock(Actor *actor);
499 void TryDetectSecret(int skill);
500 bool Visible();
501 void DebugDump() const;
502 int TrapResets() const { return Flags & DOOR_RESET; }
503 void SetNewOverlay(TileOverlay *Overlay);
506 class GEM_EXPORT Container : public Highlightable {
507 public:
508 Container(void);
509 ~Container(void);
510 void SetContainerLocked(bool lock);
511 //turns the container to a pile
512 void DestroyContainer();
513 //removes an item from the container's inventory
514 CREItem *RemoveItem(unsigned int idx, unsigned int count);
515 //adds an item to the container's inventory
516 int AddItem(CREItem *item);
517 //draws the ground icons
518 void DrawPile(bool highlight, Region screen, Color tint);
519 //returns dithering option
520 int WantDither();
521 int IsOpen() const;
522 void TryPickLock(Actor *actor);
523 void TryBashLock(Actor* actor) ;
524 bool TryUnlock(Actor *actor);
525 void DebugDump() const;
526 int TrapResets() const { return Flags & CONT_RESET; }
527 private:
528 //updates the ground icons for a pile
529 void RefreshGroundIcons();
530 void FreeGroundIcons();
531 void CreateGroundIconCover();
532 public:
533 Point toOpen;
534 ieWord Type;
535 ieDword Flags;
536 ieWord LockDifficulty;
537 Inventory inventory;
538 ieStrRef OpenFail;
539 //these are not saved
540 Sprite2D *groundicons[3];
541 SpriteCover *groundiconcover;
542 //keyresref is stored in Highlightable
545 class GEM_EXPORT InfoPoint : public Highlightable {
546 public:
547 InfoPoint(void);
548 ~InfoPoint(void);
549 //returns true if trap has been triggered, tumble skill???
550 bool TriggerTrap(int skill, ieDword ID);
551 //call this to check if an actor entered the trigger zone
552 bool Entered(Actor *actor);
553 //checks if the actor may use this travel trigger
554 int CheckTravel(Actor *actor);
555 void DebugDump() const;
556 int TrapResets() const { return Flags & TRAP_RESET; }
557 bool CanDetectTrap() const;
558 bool PossibleToSeeTrap() const;
559 bool IsPortal() const;
561 public:
562 ieResRef Destination;
563 ieVariable EntranceName;
564 ieDword Flags;
565 //overheadtext contains the string, but we have to save this
566 ieStrRef StrRef;
567 Point UsePoint;
568 Point TalkPos;
571 #endif