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.
26 #include "CharAnimations.h"
27 #include "Inventory.h"
28 #include "PathFinder.h"
30 #include "TileOverlay.h"
31 #include "Variables.h"
47 #define MAX_GROUND_ICON_DRAWN 3
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
57 #define SCR_SPECIFICS 2
58 #define SCR_RESERVED 3
64 //pst trap flags (portal)
65 #define PORTAL_CURSOR 1
66 #define PORTAL_TRAVEL 2
68 #define TRAP_INVISIBLE 1
70 #define TRAVEL_PARTY 4
71 #define TRAP_DETECTABLE 8
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
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
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
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
140 #define BT_ONCREATION 2
141 #define BT_BECAMEVISIBLE 4
142 #define BT_WASINDIALOG 8
143 #define BT_PARTYRESTED 16
146 //xp bonus types (for xpbonus.2da)
147 #define XP_LOCKPICK 0
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
{
161 Scriptable(ScriptableType type
);
162 virtual ~Scriptable(void);
164 TriggerObjects tolist
;
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
174 ieVariable scriptName
;
175 ieDword InternalFlags
; //for triggers
176 Scriptable
* CutSceneId
;
178 std::list
< Action
*> actionQueue
;
179 Action
* CurrentAction
;
181 int CurrentActionState
;
182 ieWord CurrentActionTarget
;
183 bool CurrentActionInterruptable
;
190 GameScript
* Scripts
[MAX_SCRIPTS
];
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
;
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
214 /** Gets the Dialog ResRef */
215 const char* GetDialog(void) const
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;
226 Scriptable
*GetCutsceneID() const;
227 void ClearCutsceneID();
228 void SetCutsceneID(Scriptable
*csid
);
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
246 //call this to enable script running as soon as possible
247 void ImmediateEvent();
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();
256 void ReleaseCurrentAction();
258 void ProcessActions(bool force
);
259 //these functions handle clearing of triggers that resulted a
260 //true condition (whole triggerblock returned true)
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
; }
280 /* used internally to handle start of spellcasting */
281 int SpellCast(const ieResRef SpellResRef
, bool instant
);
284 class GEM_EXPORT Selectable
: public Scriptable
{
286 Selectable(ScriptableType type
);
287 virtual ~Selectable(void);
290 ieWord Selected
; //could be 0x80 for unselectable
294 Sprite2D
*circleBitmap
[2];
297 // current SpriteCover for wallgroups
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 */
316 class GEM_EXPORT Highlightable
: public Scriptable
{
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;
324 Gem_Polygon
* outline
;
329 ieWord TrapDetectionDiff
;
330 ieWord TrapRemovalDiff
;
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
;
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
364 Movable(ScriptableType type
);
365 virtual ~Movable(void);
367 ieDword timeStartStep
;
371 PathNode
*GetNextStep(int x
);
373 //inliners to protect data consistency
374 inline PathNode
* GetNextStep() {
376 DoStep((unsigned int) ~0);
381 inline unsigned char GetOrientation() const {
385 inline unsigned char GetNextFace() {
387 if (Orientation
!= NewOrientation
) {
388 if ( ( (NewOrientation
-Orientation
) & (MAX_ORIENT
-1) ) <= MAX_ORIENT
/2) {
393 Orientation
= Orientation
&(MAX_ORIENT
-1);
398 inline unsigned char GetStance() const {
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));
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
);
418 void WalkTo(const Point
&Des
, int MinDistance
= 0);
419 void MoveTo(const Point
&Des
);
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
{
435 void SetOpenTiles(unsigned short *indices
, int count
);
436 void SetClosedTiles(unsigned short *indices
, int count
);
440 ieResRef Tileset
; //or wed door ID?
442 unsigned short* opentiles
;
444 unsigned short* closedtiles
;
448 class GEM_EXPORT Door
: public Highlightable
{
450 Door(TileOverlay
* Overlay
);
453 ieVariable LinkedInfo
;
454 ieResRef ID
; //WED ID
455 TileOverlay
* overlay
;
456 unsigned short* tiles
;
464 Point
* open_ib
; //impeded blocks stored in a Point array
469 unsigned int open_wg_index
;
470 unsigned int open_wg_count
;
471 unsigned int closed_wg_index
;
472 unsigned int closed_wg_count
;
477 ieResRef UnLockSound
;
478 ieDword DiscoveryDiff
;
479 ieDword LockDifficulty
; //this is a dword?
482 ieDword Unknown54
; //unused in tob
484 void SetWallgroups(int count
, int value
);
485 void ImpedeBlocks(int count
, Point
*points
, unsigned char value
);
487 bool BlockedOpen(int Open
, int ForceOpen
);
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
);
496 void TryPickLock(Actor
*actor
);
497 void TryBashLock(Actor
* actor
) ;
498 bool TryUnlock(Actor
*actor
);
499 void TryDetectSecret(int skill
);
501 void DebugDump() const;
502 int TrapResets() const { return Flags
& DOOR_RESET
; }
503 void SetNewOverlay(TileOverlay
*Overlay
);
506 class GEM_EXPORT Container
: public Highlightable
{
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
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
; }
528 //updates the ground icons for a pile
529 void RefreshGroundIcons();
530 void FreeGroundIcons();
531 void CreateGroundIconCover();
536 ieWord LockDifficulty
;
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
{
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;
562 ieResRef Destination
;
563 ieVariable EntranceName
;
565 //overheadtext contains the string, but we have to save this