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.
23 * Declares Game class, object representing current game state.
24 * @author The GemRB Project
38 #include "Particles.h"
39 #include "Variables.h"
43 //the length of a round in game ticks?
44 //default (ROUND_SIZE) is 6 seconds: 15 (AI_UPDATE_TIME)*6 (ROUND_SECODS)=90
46 #define ROUND_SECONDS 6
47 #define ROUND_PER_TURN 10
49 //the size of the bestiary register
50 #define BESTIARY_SIZE 260
53 #define SX_DIVIDE 1 //divide XP among team members
54 #define SX_CR 2 //use challenge rating resolution
57 #define JP_JOIN 1 //refresh join time
58 #define JP_INITPOS 2 //init startpos
61 #define PM_NO 0 //no death checks
62 #define PM_YES 1 //if protagonist dies, game over
63 #define PM_TEAM 2 //if team dies, game over
65 // Flags bits for SelectActor()
66 // !!! Keep these synchronized with GUIDefines.py !!!
67 #define SELECT_NORMAL 0x00
68 #define SELECT_REPLACE 0x01 // when selecting actor, deselect all others
69 #define SELECT_QUIET 0x02 // do not run handler when changing selection
71 // Flags bits for EveryoneNearPoint()
72 #define ENP_CANMOVE 1 // also check if the PC can move
73 #define ENP_ONLYSELECT 2 // check only selected PC
75 // GUI Control Status flags (saved in game)
76 #define CS_PARTY_AI 1 //enable party AI
77 #define CS_MEDIUM 2 //medium dialog
78 #define CS_LARGE 6 //large dialog, both bits set
79 #define CS_DIALOGSIZEMASK 6
80 #define CS_DIALOG 8 //dialog is running
81 #define CS_HIDEGUI 16 //hide all gui
82 #define CS_ACTION 32 //hide action pane
83 #define CS_PORTRAIT 64 //hide portrait pane
84 #define CS_MAPNOTES 128 //hide mapnotes
92 #define WB_LIGHTNING 8
93 #define WB_HASWEATHER 0x40
97 #define REST_NOAREA 1 //no area check
98 #define REST_NOSCATTER 2 //no scatter check
99 #define REST_NOMOVE 4 //no movement check
100 #define REST_NOCRITTER 8 //no hostiles check
103 * Information about party member.
120 unsigned char Unknown2c
[96];
121 ieWord QuickWeaponSlot
[MAX_QUICKWEAPONSLOT
];
122 ieWord QuickWeaponHeader
[MAX_QUICKWEAPONSLOT
];
123 ieResRef QuickSpellResRef
[MAX_QSLOTS
];
124 ieWord QuickItemSlot
[MAX_QUICKITEMSLOT
];
125 ieWord QuickItemHeader
[MAX_QUICKITEMSLOT
];
128 ieByte QSlots
[MAX_QSLOTS
];
129 ieByte QuickSpellClass
[MAX_QSLOTS
];
132 #define IE_GAM_JOURNAL 0
133 #define IE_GAM_QUEST_UNSOLVED 1
134 #define IE_GAM_QUEST_DONE 2
135 #define IE_GAM_JOURNAL_USER 3
138 * @struct GAMJournalEntry
139 * Single entry in a journal
142 struct GAMJournalEntry
{
144 ieDword GameTime
; // in game time seconds
148 ieByte Group
; // this is a GemRB extension
151 // Saved location of party member.
152 struct GAMLocationEntry
{
157 #define MAX_CRLEVEL 32
159 typedef int CRRow
[MAX_CRLEVEL
];
163 * Object representing current game state, mostly party.
166 class GEM_EXPORT Game
: public Scriptable
{
171 std::vector
< Actor
*> PCs
;
172 std::vector
< Actor
*> NPCs
;
173 std::vector
< Map
*> Maps
;
174 std::vector
< GAMJournalEntry
*> Journals
;
175 std::vector
< GAMLocationEntry
*> savedpositions
;
176 std::vector
< GAMLocationEntry
*> planepositions
;
177 std::vector
< char*> mastarea
;
178 std::vector
< ieDword
> Attackers
;
180 ieResRef restmovies
[8];
181 ieResRef daymovies
[8];
182 ieResRef nightmovies
[8];
185 std::vector
< Actor
*> selected
;
190 ieByte
* mazedata
; //only in PST
191 ieResRef Familiars
[9];
192 ieDword CombatCounter
;
193 ieDword StateOverrideFlag
, StateOverrideTime
;
194 ieDword BanterBlockFlag
, BanterBlockTime
;
196 /** Index of PC selected in non-walking environment (shops, inventory...) */
198 /** 0 if the protagonist's death doesn't cause game over */
199 /** 1 if the protagonist's death causes game over */
200 /** 2 if no check is needed (pst) */
202 /** if party size exceeds this amount, a callback will be called */
205 ieDword interval
; // 1000/AI_UPDATE (a tenth of a round in ms)
207 ieDword LastScriptUpdate
; // GameTime at which UpdateScripts last ran
209 ieWord WhichFormation
;
210 ieWord Formations
[5];
216 ieDword ControlStatus
;// used in bg2, iwd (where you can switch panes off)
217 ieResRef AnotherArea
;
218 ieResRef CurrentArea
;
220 Actor
*timestop_owner
;
221 ieDword timestop_end
;
224 char event_handler
[64]; //like in Control
226 /** reads the challenge rating table */
229 /** Returns the PC's slot count for partyID */
230 int FindPlayer(unsigned int partyID
);
231 /** Returns actor by slot */
232 Actor
* GetPC(unsigned int slot
, bool onlyalive
);
233 /** Finds an actor in party by party ID, returns Actor, if not there, returns NULL*/
234 Actor
* FindPC(unsigned int partyID
);
235 Actor
* FindNPC(unsigned int partyID
);
236 /** Finds an actor in party, returns slot, if not there, returns -1*/
237 int InParty(Actor
* pc
) const;
238 /** Finds an actor in store, returns slot, if not there, returns -1*/
239 int InStore(Actor
* pc
) const;
240 /** Finds an actor in party by scripting name*/
241 Actor
* FindPC(const char *deathvar
);
242 /** Finds an actor in store by scripting name*/
243 Actor
* FindNPC(const char *deathvar
);
244 /** Sets the area and position of the actor to the starting position */
245 void InitActorPos(Actor
*actor
);
247 int JoinParty(Actor
* pc
, int join
=JP_JOIN
);
248 /** Return current party size */
249 int GetPartySize(bool onlyalive
) const;
250 /** Returns the npcs count */
251 int GetNPCCount() const { return (int)NPCs
.size(); }
252 /** Sends the hotkey trigger to all selected pcs */
253 void SetHotKey(unsigned long Key
);
254 /** Select PC for non-walking environment (shops, inventory, ...) */
255 bool SelectPCSingle(int index
);
256 /** Get index of selected PC for non-walking env (shops, inventory, ...) */
257 int GetSelectedPCSingle() const;
258 /** (De)selects actor. */
259 bool SelectActor( Actor
* actor
, bool select
, unsigned flags
);
261 /** Return current party level count for xp calculations */
262 int GetPartyLevel(bool onlyalive
) const;
263 /** Reassigns inparty numbers, call it after party creation */
264 void ConsolidateParty();
265 /** Removes actor from party (if in there) */
266 int LeaveParty(Actor
* pc
);
268 int DelPC(unsigned int slot
, bool autoFree
= false);
269 int DelNPC(unsigned int slot
, bool autoFree
= false);
270 /** Returns map in index */
271 Map
* GetMap(unsigned int index
) const;
272 /** Returns a map from area name, loads it if needed
273 * use it for the biggest safety, change = true will change the current map */
274 Map
* GetMap(const char *areaname
, bool change
);
275 /** Returns slot of the map if found */
276 int FindMap(const char *ResRef
);
277 int AddMap(Map
* map
);
278 /** Determine if area is master area*/
279 bool MasterArea(const char *area
);
280 /** Dynamically adding an area to master areas*/
281 void SetMasterArea(const char *area
);
282 /** Returns slot of the map, if it was already loaded,
283 * don't load it again, set changepf == true,
284 * if you want to change the pathfinder too. */
285 int LoadMap(const char* ResRef
);
286 int DelMap(unsigned int index
, int forced
= 0);
287 int AddNPC(Actor
* npc
);
288 Actor
* GetNPC(unsigned int Index
);
289 void SwapPCs(unsigned int Index1
, unsigned int Index2
);
291 void InAttack(ieDword globalID
);
292 void OutAttack(ieDword globalID
);
293 int AttackersOf(ieDword globalID
, Map
*area
) const;
296 void DeleteJournalEntry(ieStrRef strref
);
297 void DeleteJournalGroup(int Group
);
298 /** Adds a journal entry from dialog data.
299 * Time and chapter are calculated on the fly
300 * Returns false if the entry already exists */
301 bool AddJournalEntry(ieStrRef strref
, int section
, int group
);
302 /** Adds a journal entry while loading the .gam structure */
303 void AddJournalEntry(GAMJournalEntry
* entry
);
304 unsigned int GetJournalCount() const;
305 GAMJournalEntry
* FindJournalEntry(ieStrRef strref
);
306 GAMJournalEntry
* GetJournalEntry(unsigned int Index
);
308 unsigned int GetSavedLocationCount() const;
309 void ClearSavedLocations();
310 GAMLocationEntry
* GetSavedLocationEntry(unsigned int Index
);
312 unsigned int GetPlaneLocationCount() const;
313 void ClearPlaneLocations();
314 GAMLocationEntry
* GetPlaneLocationEntry(unsigned int Index
);
316 char *GetFamiliar(unsigned int Index
);
318 bool IsBeastKnown(unsigned int Index
) const {
322 if (Index
>=BESTIARY_SIZE
) {
325 return beasts
[Index
] != 0;
327 void SetBeastKnown(unsigned int Index
) {
331 if (Index
>=BESTIARY_SIZE
) {
336 ieWord
GetFormation() const {
337 if (WhichFormation
>4) {
340 return Formations
[WhichFormation
];
342 size_t GetAttackerCount() const {
343 return Attackers
.size();
346 /** converts challenge rating to xp */
347 int GetXPFromCR(int cr
);
348 /** shares XP among all party members */
349 void ShareXP(int XP
, int flags
);
350 /** returns true if we should start the party overflow window */
351 bool PartyOverflow() const;
352 /** returns true if actor is an attacker or being attacked */
353 bool PCInCombat(Actor
*actor
) const;
354 /** returns true if any pc is attacker or being attacked */
355 bool AnyPCInCombat() const;
356 /** returns true if the party death condition is true */
357 bool EveryoneDead() const;
358 /** returns true if no one moves */
359 bool EveryoneStopped() const;
360 bool EveryoneNearPoint(Map
*map
, const Point
&p
, int flags
) const;
361 /** returns true if a PC just died */
362 int PartyMemberDied() const;
363 /** a party member just died now */
364 void PartyMemberDied(Actor
*);
365 /** Increments chapter variable and refreshes kill stats */
366 void IncrementChapter();
367 /** Sets party reputation */
368 void SetReputation(ieDword r
);
369 /** Sets the gamescreen control status (pane states, dialog textarea size) */
370 void SetControlStatus(int value
, int operation
);
371 /** Sets party size (1-32000) */
372 void SetPartySize(int value
);
373 /** Sets a guiscript function to happen after x AI cycles have elapsed */
374 void SetTimedEvent(const char *fname
, int count
);
375 /** Sets protagonist mode to 0-none,1-protagonist,2-team */
376 void SetProtagonistMode(int value
);
377 void StartRainOrSnow(bool conditional
, int weather
);
378 size_t GetLoadedMapCount() const { return Maps
.size(); }
379 /** Adds or removes gold */
380 void AddGold(ieDword add
);
381 /** Adds ticks to game time */
382 void AdvanceTime(ieDword add
);
383 /** Runs the script engine on the global script and the area scripts
384 areas run scripts on door, infopoint, container, actors too */
385 void UpdateScripts();
386 /** runs area functionality, sets partyrested trigger */
387 void RestParty(int checks
, int dream
, int hp
);
388 /** timestop effect initiated by actor */
389 void TimeStop(Actor
*actor
, ieDword end
);
390 /** gets the colour which should be applied over the game area,
392 const Color
*GetGlobalTint() const;
394 void DrawWeather(const Region
&screen
, bool update
);
395 /** updates current area music */
396 void ChangeSong(bool force
= true);
397 /** sets expansion mode */
398 void SetExpansion(int exp
);
399 /** Dumps information about the object */
401 /** Finds an actor by global ID */
402 Actor
*GetActorByGlobalID(ieWord objectID
);
404 bool DetermineStartPosType(const TableMgr
*strta
);
405 ieResRef
*GetDream(Map
*area
);