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 /**
22  * @file Interface.h
23  * Declaration of Interface class, central interconnect for various GemRB parts
24  */
25 
26 #ifndef INTERFACE_H
27 #define INTERFACE_H
28 
29 #include "SClassID.h"
30 #include "exports.h"
31 
32 #include "Audio.h" // needed for _MSC_VER and SoundHandle (everywhere)
33 #include "Cache.h"
34 #include "Callback.h"
35 #include "GameData.h"
36 #include "GlobalTimer.h"
37 #include "GUI/Control.h"
38 #include "GUI/Tooltip.h"
39 #include "GUI/Window.h"
40 #include "GUI/GUIFactory.h"
41 #include "Holder.h"
42 #include "ImageMgr.h"
43 #include "InterfaceConfig.h"
44 #include "Resource.h"
45 #include "Timer.h"
46 #include "System/VFS.h"
47 
48 #include <array>
49 #include <map>
50 #include <string>
51 #include <vector>
52 
53 // No SFINAE
54 #if defined(_MSC_VER) || defined(__sgi)
55 #include "DataFileMgr.h"
56 #include "MusicMgr.h"
57 #include "SaveGame.h"
58 #include "ScriptEngine.h"
59 #include "StringMgr.h"
60 #include "SymbolMgr.h"
61 #include "Video.h"
62 #endif
63 
64 namespace GemRB {
65 
66 class Actor;
67 class Audio;
68 class CREItem;
69 class Calendar;
70 class Container;
71 class DataFileMgr;
72 struct Effect;
73 class EffectQueue;
74 class EffectDesc;
75 class Factory;
76 class Font;
77 class Game;
78 class GameControl;
79 class GlobalTimer;
80 class ITMExtHeader;
81 class Image;
82 class Item;
83 class KeyMap;
84 class Label;
85 class Map;
86 class MusicMgr;
87 class Palette;
88 using PaletteHolder = Holder<Palette>;
89 class ProjectileServer;
90 class Resource;
91 class SPLExtHeader;
92 class SaveGame;
93 class SaveGameIterator;
94 class ScriptEngine;
95 class ScriptedAnimation;
96 class Spell;
97 class Sprite2D;
98 class Store;
99 class StringMgr;
100 #ifndef __sgi
101 class SymbolMgr;
102 class TableMgr;
103 #endif
104 class TextArea;
105 class Variables;
106 class Video;
107 class WindowManager;
108 class WorldMap;
109 class WorldMapArray;
110 
111 struct Symbol {
112 	Holder<SymbolMgr> sm;
113 	char ResRef[8];
114 };
115 
116 struct SlotType {
117 	ieDword slot;
118 	ieDword slottype;
119 	ieDword slottip;
120 	ieDword slotid;
121 	ieDword sloteffects;
122 	ieDword slotflags;
123 	ieResRef slotresref;
124 };
125 
126 struct DamageInfoStruct {
127 	unsigned int strref;
128 	unsigned int resist_stat;
129 	unsigned int value;
130 	int iwd_mod_type;
131 	int reduction;
132 	// maybe also add the ac bonus and/or the DL_ constants
133 };
134 
135 struct TimeStruct {
136 	unsigned int round_sec;
137 	unsigned int turn_sec;
138 	unsigned int round_size; // in ticks
139 	unsigned int rounds_per_turn;
140 	unsigned int attack_round_size;
141 	unsigned int hour_sec;
142 	unsigned int hour_size;
143 	unsigned int day_sec;
144 	unsigned int day_size;
145 
GetHourTimeStruct146 	int GetHour(unsigned int time) { return (time/AI_UPDATE_TIME)%day_sec/hour_sec; }
147 };
148 
149 struct EncodingStruct
150 {
151 	std::string encoding;
152 	bool widechar;
153 	bool multibyte;
154 	bool zerospace;
155 };
156 
157 struct SpellDescType {
158 	ieResRef resref;
159 	ieStrRef value;
160 };
161 
162 struct SpecialSpellType {
163 	ieResRef resref;
164 	int flags;
165 	int amount;
166 	int bonus_limit;
167 };
168 #define SP_IDENTIFY  1      //any spell that cannot be cast from the menu
169 #define SP_SILENCE   2      //any spell that can be cast in silence
170 #define SP_SURGE     4      //any spell that cannot be cast during a wild surge
171 #define SP_REST      8      //any spell that is cast upon rest if memorized
172 #define SP_HEAL_ALL  16     //any healing spell that is cast upon rest at more than one target (healing circle, mass cure)
173 
174 struct SurgeSpell {
175 	ieResRef spell;
176 	ieStrRef message;
177 };
178 
179 class ItemList {
180 public:
181 	ieResRef *ResRefs;
182 	unsigned int Count;
183 	//if count is odd and the column titles start with 2, the random roll should be 2d((c+1)/2)-1
184 	bool WeightOdds;
185 
ItemList(unsigned int size,int label)186 	ItemList(unsigned int size, int label) {
187 		ResRefs = (ieResRef *) calloc(size, sizeof(ieResRef) );
188 		Count = size;
189 		if ((size&1) && (label==2)) {
190 			WeightOdds=true;
191 		} else {
192 			WeightOdds=false;
193 		}
194 	}
~ItemList()195 	~ItemList() {
196 		if (ResRefs) {
197 			free(ResRefs);
198 		}
199 	}
200 };
201 
202 //quitflags
203 #define QF_NORMAL        0
204 #define QF_QUITGAME      1
205 #define QF_EXITGAME      2
206 #define QF_CHANGESCRIPT  4
207 #define QF_LOADGAME      8
208 #define QF_ENTERGAME     16
209 #define QF_KILL			32
210 
211 //events that are called out of drawwindow
212 //they wait until the condition is right
213 #define EF_CONTROL       1        //updates the game window statuses
214 #define EF_SHOWMAP       2        //starts worldmap
215 #define EF_PORTRAIT      4        //updates portraits
216 #define EF_ACTION        8        //updates the actions bar
217 #define EF_UPDATEANIM    16       //updates avatar animation
218 #define EF_SEQUENCER     32       //starts sequencer/contingency creation
219 #define EF_IDENTIFY      64       //starts identify screen
220 #define EF_SELECTION     128      //selection changed
221 #define EF_OPENSTORE     256      //open store window
222 #define EF_EXPANSION     512      //upgrade game request
223 #define EF_CREATEMAZE    1024     //call the maze generator
224 #define EF_RESETTARGET   2048     //reset the mouse cursor
225 #define EF_TARGETMODE    4096     //update the mouse cursor
226 #define EF_TEXTSCREEN    8192     //start a textscreen
227 
228 //autopause
229 #define AP_UNUSABLE      0
230 #define AP_ATTACKED      1
231 #define AP_HIT           2
232 #define AP_WOUNDED       3
233 #define AP_DEAD          4
234 #define AP_NOTARGET      5
235 #define AP_ENDROUND      6
236 #define AP_ENEMY         7
237 #define AP_TRAP          8
238 #define AP_SPELLCAST     9
239 #define AP_GENERIC       10  //needed for Android stuff
240 
241 //pause flags
242 #define PF_QUIET  1        //no feedback
243 #define PF_FORCED 2        //pause even in cutscene/dialog
244 
245 /** ea relations (derivated from 2 actor's EA value) */
246 #define EAR_FRIEND  0
247 #define EAR_NEUTRAL 1
248 #define EAR_HOSTILE 2
249 
250 /** Max size of actor's ground circle (PST) */
251 #define MAX_CIRCLE_SIZE  3
252 
253 /** Summoning */
254 #define EAM_SOURCEALLY 0
255 #define EAM_SOURCEENEMY 1
256 #define EAM_ENEMY   2
257 #define EAM_ALLY    3
258 #define EAM_NEUTRAL 4
259 #define EAM_DEFAULT 5
260 //
261 #define STAT_CON_HP_NORMAL   0
262 #define STAT_CON_HP_WARRIOR  1
263 #define STAT_CON_HP_MIN      2
264 #define STAT_CON_HP_REGEN    3
265 #define STAT_CON_FATIGUE     4
266 #define STAT_CON_TNO_REGEN   4
267 
268 #define STAT_DEX_REACTION    0
269 #define STAT_DEX_MISSILE     1
270 #define STAT_DEX_AC          2
271 
272 #define STAT_INT_LEARN       0
273 #define STAT_INT_MAXLEVEL    1
274 #define STAT_INT_MAXNUMBER   2
275 
276 //sloteffects (querysloteffect returns it)
277 #define SLOT_EFFECT_NONE     0
278 #define SLOT_EFFECT_ITEM     1 //normal equipped item
279 #define SLOT_EFFECT_FIST     2 //fist slot
280 #define SLOT_EFFECT_MAGIC    3 //magic weapon slot
281 #define SLOT_EFFECT_MELEE    4 //normal weapon slot
282 #define SLOT_EFFECT_MISSILE  5 //quiver slots
283 #define SLOT_EFFECT_LEFT     6 //shield (left hand) slot
284 #define SLOT_EFFECT_HEAD     7 //head slot
285 
286 enum PluginFlagsType {
287 	PLF_NORMAL,
288 	PLF_SKIP,
289 	PLF_DELAY
290 };
291 
292 enum PauseSetting {
293 	PAUSE_OFF = 0,
294 	PAUSE_ON = 1
295 };
296 
297 enum RESOURCE_DIRECTORY {
298 	DIRECTORY_CHR_PORTRAITS,
299 	DIRECTORY_CHR_SOUNDS,
300 	DIRECTORY_CHR_EXPORTS,
301 	DIRECTORY_CHR_SCRIPTS
302 };
303 
304 enum FeedbackType {
305 	FT_TOHIT = 1,
306 	FT_COMBAT = 2,
307 	FT_ACTIONS = 4, // handled by Actor::CommandActor
308 	FT_STATES = 8,
309 	FT_SELECTION = 16, // handled by Actor::PlaySelectionSound
310 	FT_MISC = 32,
311 	FT_CASTING = 64
312 };
313 
314 enum DebugModeBits {
315 	ID_REFERENCE = 1,
316 	ID_CUTSCENE = 2,
317 	ID_VARIABLES = 4,
318 	ID_ACTIONS = 8,
319 	ID_TRIGGERS = 16,
320 	ID_VIEWS = 32,
321 	ID_WINDOWS = 64,
322 	ID_FONTS = 128,
323 	ID_TEXT = 256
324 };
325 
326 template<int SIZE>
327 using ColorPal = std::array<Color, SIZE>;
328 
329 // TODO: there is no reason why this can't be generated directly from
330 // the inventory button drag event using the button value as the slot id
331 // to get the appropriate CREItem
332 struct ItemDragOp : public Control::ControlDragOp {
333 	CREItem* item;
334 
335 	ItemDragOp(CREItem* item);
336 
337 private:
338 	static Control dragDummy;
339 };
340 
341 /**
342  * @class Interface
343  * Central interconnect for all GemRB parts, driving functions and utility functions possibly belonging to a better place
344  */
345 
346 class GEM_EXPORT Interface
347 {
348 private:
349 	// dirvers must be deallocated last (keep them at the top)
350 	// we hold onto resources (sprites etc) in Interface that must be destroyed prior to the respective driver
351 	Holder<Video> video;
352 	Holder<Audio> AudioDriver;
353 
354 	std::string VideoDriverName;
355 	std::string AudioDriverName;
356 	ProjectileServer * projserv;
357 
358 	WindowManager* winmgr;
359 	Holder<GUIFactory> guifact;
360 	Holder<ScriptEngine> guiscript;
361 	GameControl* gamectrl = nullptr;
362 	SaveGameIterator *sgiterator;
363 	Variables * vars;
364 	Variables * tokens;
365 	Variables * lists;
366 	Holder<MusicMgr> music;
367 	std::vector<Symbol> symbols;
368 	Holder<DataFileMgr> INIparty;
369 	Holder<DataFileMgr> INIbeasts;
370 	Holder<DataFileMgr> INIquests;
371 	Holder<DataFileMgr> INIresdata;
372 	Game * game;
373 	Calendar * calendar;
374 	WorldMapArray* worldmap;
375 	ieDword GameFeatures[(GF_COUNT+31)/32];
376 	ResRef MainCursorsImage;
377 	ResRef TextCursorBam;
378 	ResRef ScrollCursorBam;
379 	ieResRef GroundCircleBam[MAX_CIRCLE_SIZE];
380 	int GroundCircleScale[MAX_CIRCLE_SIZE];
381 
382 	std::map<ResRef, Font*> fonts;
383 	ResRef ButtonFontResRef;
384 	ResRef MovieFontResRef;
385 	ResRef TextFontResRef;
386 	ResRef TooltipFontResRef;
387 	std::string DefaultWindowTitle;
388 
389 	TooltipBackground* TooltipBG;
390 	ieResRef *DefSound; //default sounds
391 	int DSCount;
392 
393 	ResRef Palette16;
394 	ResRef Palette32;
395 	ResRef Palette256;
396 	std::vector<ColorPal<256>> palettes256;
397 	std::vector<ColorPal<32>>  palettes32;
398 	std::vector<ColorPal<16>>  palettes16;
399 
400 	ieDword* slotmatrix; //itemtype vs slottype
401 	std::vector<std::vector<int> > itemtypedata; //armor failure, critical multiplier, critical range
402 	SlotType* slottypes;
403 	int ItemTypes;
404 
405 	// Currently dragged item or NULL
406 	std::unique_ptr<ItemDragOp> DraggedItem;
407 	// Current Store
408 	Store* CurrentStore;
409 	// Index of current container
410 	Container* CurrentContainer;
411 	bool UseContainer;
412 	// Scrolling speed
413 	int mousescrollspd;
414 	bool update_scripts;
415 	/** Next Script Name */
416 	char NextScript[64];
417 
418 	std::deque<Timer> timers;
419 	int SpecialSpellsCount;
420 	SpecialSpellType *SpecialSpells;
421 	KeyMap *keymap;
422 	std::string Encoding;
423 	Scriptable *CutSceneRunner;
424 	int debugMode = 0;
425 
426 public:
427 	const char * SystemEncoding;
428 	EncodingStruct TLKEncoding;
429 	Holder<StringMgr> strings;
430 	Holder<StringMgr> strings2;
431 	GlobalTimer timer;
432 	Color InfoTextColor;
433 	int SaveAsOriginal; //if true, saves files in compatible mode
434 	int QuitFlag;
435 	int EventFlag;
436 	Holder<SaveGame> LoadGameIndex;
437 	int VersionOverride;
438 	unsigned int SlotTypes; //this is the same as the inventory size
439 	ResRef GlobalScript;
440 	ResRef WorldMapName[2];
441 	Variables * AreaAliasTable;
442 	std::vector<Holder<Sprite2D> > Cursors;
443 	Holder<Sprite2D> FogSprites[16] {};
444 	Holder<Sprite2D> GroundCircles[MAX_CIRCLE_SIZE][6] {};
445 	std::vector<char *> musiclist;
446 	std::multimap<ieDword, DamageInfoStruct> DamageInfoMap;
447 	TimeStruct Time;
448 	std::vector<SurgeSpell> SurgeSpells;
449 public:
450 	Interface();
451 	~Interface(void);
452 
453 	Interface(const Interface&) = delete;
454 
455 	int Init(InterfaceConfig* config);
456 	//TODO: Core Methods in Interface Class
457 	void SetFeature(int value, int position);
458 	/* don't rely on the exact return value of this function */
459 	ieDword HasFeature(int position) const;
460 	bool IsAvailable(SClass_ID filetype) const;
461 	const char * TypeExt(SClass_ID type) const;
462 	ProjectileServer* GetProjectileServer() const;
463 	Video * GetVideoDriver() const;
464 	/* create or change a custom string */
465 	ieStrRef UpdateString(ieStrRef strref, const char *text) const;
466 	/* returns a newly created c string */
467 	char* GetCString(ieStrRef strref, ieDword options = 0) const;
468 	/* returns a newly created string */
469 	String* GetString(ieStrRef strref, ieDword options = 0) const;
470 	/* sets the floattext color */
471 	void SetInfoTextColor(const Color &color);
472 	/** returns a gradient set */
GetPalette16(uint8_t idx)473 	const ColorPal<16>& GetPalette16(uint8_t idx) const { return (idx >= palettes16.size()) ? palettes16[0] : palettes16[idx]; }
GetPalette32(uint8_t idx)474 	const ColorPal<32>& GetPalette32(uint8_t idx) const { return (idx >= palettes32.size()) ? palettes32[0] : palettes32[idx]; }
GetPalette256(uint8_t idx)475 	const ColorPal<256>& GetPalette256(uint8_t idx) const { return (idx >= palettes256.size()) ? palettes256[0] : palettes256[idx]; }
476 	/** Returns a preloaded Font */
477 	Font* GetFont(const ResRef&) const;
478 	Font* GetTextFont() const;
479 	/** Returns the button font */
480 	Font * GetButtonFont() const;
481 	/** Get GUI Script Manager */
482 	ScriptEngine * GetGUIScriptEngine() const;
483 	/** core for summoning creatures, returns the last created Actor
484 	may apply a single fx on the summoned creature normally an unsummon effect */
485 	Actor *SummonCreature(const ieResRef resource, const ieResRef vvcres, Scriptable *Owner, Actor *target, const Point &position, int eamod, int level, Effect *fx, bool sexmod=1);
486 	/** Get the Window Manager */
GetWindowManager()487 	WindowManager *GetWindowManager() const { return winmgr; };
488 	/** Loads a Window in the Window Manager */
489 	Window* LoadWindow(ScriptingId WindowID, const ResRef& ref, Window::WindowPosition = Window::PosCentered);
490 	/** Creates a Window in the Window Manager */
491 #undef CreateWindow // Win32 might define this, so nix it
492 	Window* CreateWindow(unsigned short WindowID, const Region&);
493 	void ToggleViewsVisible(bool visible, const ResRef& group);
494 	void ToggleViewsEnabled(bool enabled, const ResRef& group);
495 
496 	Tooltip CreateTooltip();
497 	/** returns the label which should receive game messages (overrides messagetextarea) */
498 	Label *GetMessageLabel() const;
499 	/** returns the textarea of the main game screen */
500 	TextArea *GetMessageTextArea() const;
501 	void SetFeedbackLevel(int level);
502 	/** returns true if the passed feedback type is enabled */
503 	bool HasFeedback(int type) const;
504 	/** Get the SaveGameIterator */
505 	SaveGameIterator * GetSaveGameIterator() const;
506 	/** Get the Variables Dictionary */
507 	Variables * GetDictionary() const;
508 	/** Get the Token Dictionary */
509 	Variables * GetTokenDictionary() const;
510 	/** Get the Music Manager */
511 	MusicMgr * GetMusicMgr() const;
512 	/** Loads an IDS Table, returns -1 on error or the Symbol Table Index on success */
513 	int LoadSymbol(const char * ResRef);
514 	/** Gets the index of a loaded Symbol Table, returns -1 on error */
515 	int GetSymbolIndex(const char * ResRef) const;
516 	/** Gets a Loaded Symbol Table by its index, returns NULL on error */
517 	Holder<SymbolMgr> GetSymbol(unsigned int index) const;
518 	/** Frees a Loaded Symbol Table, returns false on error, true on success */
519 	bool DelSymbol(unsigned int index);
520 	/** Plays a Movie */
521 	int PlayMovie(const char * ResRef);
522 	/** Generates traditional random number xdy+z */
523 	int Roll(int dice, int size, int add) const;
524 	/** Loads a Game Compiled Script */
525 	int LoadScript(const char * ResRef);
526 	/** store the scriptable running the cutscene */
527 	void SetCutSceneRunner(Scriptable *runner);
GetCutSceneRunner()528 	Scriptable *GetCutSceneRunner() const { return CutSceneRunner; };
529 	/** Enables/Disables the CutScene Mode */
530 	void SetCutSceneMode(bool active);
531 	/** returns true if in cutscene mode */
532 	bool InCutSceneMode() const;
533 	/** Updates the Game Script Engine State */
534 	bool GSUpdate(bool update_scripts);
535 	/** Get the Party INI Interpreter */
GetPartyINI()536 	DataFileMgr * GetPartyINI() const
537 	{
538 		return INIparty.get();
539 	}
GetBeastsINI()540 	DataFileMgr * GetBeastsINI() const
541 	{
542 		return INIbeasts.get();
543 	}
GetQuestsINI()544 	DataFileMgr * GetQuestsINI() const
545 	{
546 		return INIquests.get();
547 	}
GetResDataINI()548 	DataFileMgr * GetResDataINI() const
549 	{
550 		return INIresdata.get();
551 	}
552 	/** Gets the Game class */
GetGame()553 	Game * GetGame() const
554 	{
555 		return game;
556 	}
557 	/** Gets the Calendar class */
GetCalendar()558 	Calendar * GetCalendar() const
559 	{
560 		return calendar;
561 	}
562 
563 	/** Gets the KeyMap class */
GetKeyMap()564 	KeyMap * GetKeyMap() const
565 	{
566 		return keymap;
567 	}
568 
569 	/** Gets the WorldMap class, returns the current worldmap or the first worldmap containing the area*/
570 	WorldMap * GetWorldMap(const char *area = NULL);
GetGameControl()571 	GameControl *GetGameControl() const { return game ? gamectrl : nullptr; }
572 	/** if backtomain is not null then goes back to main screen */
573 	void QuitGame(int backtomain);
574 	/** sets up load game */
575 	void SetupLoadGame(Holder<SaveGame> save, int ver_override);
576 	/** load saved game by index (-1 is default), ver_override is an optional parameter
577 	to override the saved game's version */
578 	void LoadGame(SaveGame *save, int ver_override);
579 	/** reloads the world map from a resource file */
580 	void UpdateWorldMap(ResRef wmResRef);
581 	/** fix changes in global script/worldmap*/
582 	void UpdateMasterScript();
583 
584 	DirectoryIterator GetResourceDirectory(RESOURCE_DIRECTORY);
585 
GetInventorySize()586 	unsigned int GetInventorySize() const { return SlotTypes-1; }
587 	ieDword FindSlot(unsigned int idx) const;
588 	ieDword QuerySlot(unsigned int idx) const;
589 	ieDword QuerySlotType(unsigned int idx) const;
590 	ieDword QuerySlottip(unsigned int idx) const;
591 	ieDword QuerySlotID(unsigned int idx) const;
592 	ieDword QuerySlotFlags(unsigned int idx) const;
593 	ieDword QuerySlotEffects(unsigned int idx) const;
594 	const char * QuerySlotResRef(unsigned int idx) const;
595 	int GetArmorFailure(unsigned int itemtype) const;
596 	int GetShieldFailure(unsigned int itemtype) const;
597 	int GetArmorPenalty(unsigned int itemtype) const;
598 	int GetShieldPenalty(unsigned int itemtype) const;
599 	int GetCriticalMultiplier(unsigned int itemtype) const;
600 	int GetCriticalRange(unsigned int itemtype) const;
601 	/*returns true if an itemtype is acceptable for a slottype, also checks the usability flags */
602 	int CanUseItemType(int slottype, const Item *item, const Actor *actor = nullptr, bool feedback = false, bool equipped = false) const;
603 	/*removes single file from cache*/
604 	void RemoveFromCache(const ieResRef resref, SClass_ID SClassID);
605 	/*removes all files from directory*/
606 	void DelTree(const char *path, bool onlysaved);
607 	/*returns 0,1,2 based on how the file should be saved */
608 	int SavedExtension(const char *filename);
609 	/*returns true if the file should never be deleted accidentally */
610 	bool ProtectedExtension(const char *filename);
611 	/*returns true if the directory path isn't good as a Cache */
612 	bool StupidityDetector(const char* Pt);
InDebugMode(int mode)613 	bool InDebugMode(int mode) const { return debugMode & mode; };
SetDebugMode(int mode)614 	void SetDebugMode(int mode) { debugMode = mode; };
615 	/*handles the load screen*/
616 	void LoadProgress(int percent);
617 
618 	void DragItem(CREItem* item, const ieResRef Picture);
GetDraggedItem()619 	const ItemDragOp* GetDraggedItem() const { return DraggedItem.get(); }
620 	/* use this only when the dragged item is dropped */
621 	void ReleaseDraggedItem();
622 	CREItem *ReadItem(DataStream *str);
623 	CREItem *ReadItem(DataStream *str, CREItem *itm);
624 	void SanitizeItem(CREItem *item) const;
625 	bool ResolveRandomItem(CREItem *itm);
626 	ieStrRef GetRumour(const ieResRef resname);
627 	Container *GetCurrentContainer();
628 	int CloseCurrentContainer();
629 	void SetCurrentContainer(Actor *actor, Container *arg, bool flag=false);
630 	Store *GetCurrentStore();
631 	void CloseCurrentStore();
632 	Store *SetCurrentStore(const ieResRef resname, ieDword owner);
633 	void SetMouseScrollSpeed(int speed);
634 	int GetMouseScrollSpeed();
635 
636 	//creates a standalone effect with opcode
637 	Effect *GetEffect(ieDword opcode);
638 	/** plays stock gui sound referenced by index */
639 	Holder<SoundHandle> PlaySound(int idx, unsigned int channel);
640 	/** returns the first selected PC, if forced is set, then it returns
641 	first PC if none was selected */
642 	Actor *GetFirstSelectedPC(bool forced);
643 	Actor *GetFirstSelectedActor();
644 	/** is an area loaded? (prefer Game::GetCurrentArea if including Game.h makes sense) */
645 	bool HasCurrentArea() const;
646 	/** returns a cursor sprite (not cached) */
647 	Holder<Sprite2D> GetCursorSprite();
648 	/** returns a scroll cursor sprite */
649 	Holder<Sprite2D> GetScrollCursorSprite(int frameNum, int spriteNum);
650 	/** returns 0 for unmovable, -1 for movable items, otherwise it
651 	returns gold value! */
652 	int CanMoveItem(const CREItem *item) const;
653 	int GetRareSelectSoundCount() const;
654 	int GetMaximumAbility() const;
655 	int GetStrengthBonus(int column, int value, int ex) const;
656 	int GetIntelligenceBonus(int column, int value) const;
657 	int GetDexterityBonus(int column, int value) const;
658 	int GetConstitutionBonus(int column, int value) const;
659 	int GetCharismaBonus(int column, int value) const;
660 	int GetLoreBonus(int column, int value) const;
661 	int GetWisdomBonus(int column, int value) const;
662 	int GetReputationMod(int column) const;
663 
664 	/** applies the spell on the target */
665 	void ApplySpell(const ieResRef resname, Actor *target, Scriptable *caster, int level);
666 	/** applies the spell on the area or on a scriptable object */
667 	void ApplySpellPoint(const ieResRef resname, Map *area, const Point &pos, Scriptable *caster, int level);
668 	/** applies a single effect on the target */
669 	int ApplyEffect(Effect *fx, Actor *target, Scriptable *caster);
670 	/** applies an effect queue on the target */
671 	int ApplyEffectQueue(EffectQueue *fxqueue, Actor *actor, Scriptable *caster);
672 	int ApplyEffectQueue(EffectQueue *fxqueue, Actor *actor, Scriptable *caster, Point p);
673 	Effect *GetEffect(const ieResRef resname, int level, const Point &p);
674 	/** dumps an area object to the cache */
675 	int SwapoutArea(Map *map);
676 	/** saves (exports a character to the characters folder */
677 	int WriteCharacter(const char *name, Actor *actor);
678 	/** saves the game object to the destination folder */
679 	int WriteGame(const char *folder);
680 	/** saves the worldmap object to the destination folder */
681 	int WriteWorldMap(const char *folder);
682 	/** saves the .are and .sto files to the destination folder */
683 	int CompressSave(const char *folder);
684 	/** toggles the pause. returns either PAUSE_ON or PAUSE_OFF to reflect the script state after toggling. */
685 	PauseSetting TogglePause();
686 	/** returns true the passed pause setting was applied. false otherwise. */
687 	bool SetPause(PauseSetting pause, int flags = 0);
688 	/** receives an autopause reason, returns true if autopause was accepted and successful */
689 	bool Autopause(ieDword flag, Scriptable *target);
690 	/** registers engine opcodes */
691 	void RegisterOpcodes(int count, const EffectDesc *opcodes);
692 	/** reads a list of resrefs into an array, returns array size */
693 	int ReadResRefTable(const ieResRef tablename, ieResRef *&data);
694 	/** frees the data */
695 	void FreeResRefTable(ieResRef *&table, int &count);
696 	/** Returns the virtual worldmap entry of a sub-area */
697 	int GetAreaAlias(const ieResRef areaname) const;
698 	/** Returns up to 3 resources from resref, choosing rows randomly
699 	unwanted return variables could be omitted */
700 	void GetResRefFrom2DA(const ieResRef resref, ieResRef resource1, ieResRef resource2 = NULL, ieResRef resource3 = NULL);
701 	/** returns a numeric list read from a 2da. The 0th element is the number of elements in the list */
702 	ieDword *GetListFrom2DA(const ieResRef resref);
703 	/** translates a stat symbol to numeric value */
704 	ieDword TranslateStat(const char *stat_name);
705 	/** resolves a stat bonus based on multiple stats */
706 	int ResolveStatBonus(Actor *actor, const char *tablename, ieDword flags = 0, int value = 0);
707 	/** Opens CD prompt window and waits for the specified disc */
708 	void WaitForDisc(int disc_number, const char* path);
709 	/** Returns the music playlist corresponding to the provided type */
710 	/** it allows scrapping the entry, hence it isn't const */
711 	char *GetMusicPlaylist(int SongType) const;
712 	/** Returns the DeathVarFormat of the day */
713 	static const char *GetDeathVarFormat();
714 	int CheckSpecialSpell(const ieResRef resref, Actor *actor);
715 	int GetSpecialSpell(const ieResRef resref);
GetSpecialSpellsCount()716 	int GetSpecialSpellsCount() { return SpecialSpellsCount; }
GetSpecialSpells()717 	SpecialSpellType *GetSpecialSpells() { return SpecialSpells; }
718 	/** Saves config variables to a file */
719 	bool SaveConfig();
720 private:
721 	int LoadSprites();
722 	int LoadFonts();
723 	bool LoadGemRBINI();
724 	/** Load the encoding table selected in gemrb.cfg */
725 	bool LoadEncoding();
726 
727 	template<int SIZE>
LoadPalette(ResRef resref,std::vector<ColorPal<SIZE>> & palettes)728 	bool LoadPalette(ResRef resref, std::vector<ColorPal<SIZE>>& palettes)
729 	{
730 		static_assert(SIZE == 16 || SIZE == 32 || SIZE == 256, "invalid palette size");
731 
732 		ResourceHolder<ImageMgr> palim = GetResourceHolder<ImageMgr>(resref);
733 		if (palim) {
734 			auto image = palim->GetImage();
735 			int height = image->GetHeight();
736 			palettes.resize(height);
737 			for (int row = 0; row < height; ++row) {
738 				for (int col = 0; col < SIZE; ++col) {
739 					palettes[row][col] = image->GetPixel(col, row);
740 				}
741 			}
742 			delete image;
743 			return true;
744 		}
745 		return false;
746 	}
747 
748 	bool InitializeVarsWithINI(const char * iniFileName);
749 	bool InitItemTypes();
750 	bool ReadRandomItems();
751 	bool ReadItemTable(const ieResRef item, const char *Prefix);
752 	bool ReadAbilityTables();
753 	bool ReadAbilityTable(const ieResRef name, ieWordSigned *mem, int cols, int rows);
754 	bool ReadMusicTable(const ieResRef name, int col);
755 	bool ReadDamageTypeTable();
756 	bool ReadReputationModTable();
757 	bool ReadGameTimeTable();
758 	bool ReadSpecialSpells();
759 	bool ReadSoundChannelsTable();
760 	/** Reads table of area name mappings for WorldMap (PST only) */
761 	bool ReadAreaAliasTable(const ieResRef name);
762 	/** handles the QuitFlag bits (main loop events) */
763 	void HandleFlags();
764 	/** handles the EventFlag bits (conditional events) */
765 	void HandleEvents();
766 	/** handles hardcoded gui behaviour */
767 	void HandleGUIBehaviour();
768 	/** Creates a game control, closes all other windows */
769 	GameControl* StartGameControl();
770 	/** Executes everything (non graphical) in the main game loop */
771 	void GameLoop(void);
772 	/** the internal (without cache) part of GetListFrom2DA */
773 	ieDword *GetListFrom2DAInternal(const ieResRef resref);
774 
775 public:
776 	char GameDataPath[_MAX_PATH];
777 	char GameOverridePath[_MAX_PATH];
778 	char GameSoundsPath[_MAX_PATH];
779 	char GameScriptsPath[_MAX_PATH];
780 	char GamePortraitsPath[_MAX_PATH];
781 	char GameCharactersPath[_MAX_PATH];
782 	char GemRBOverridePath[_MAX_PATH];
783 	char GemRBUnhardcodedPath[_MAX_PATH];
784 	ieResRef GameNameResRef;
785 	ieResRef GoldResRef; //MISC07.itm
786 	Variables *RtRows;
787 	char CustomFontPath[_MAX_PATH];
788 	char GameName[_MAX_PATH];
789 	char GameType[10];
790 	int GamepadPointerSpeed = 10;
791 	char GemRBPath[_MAX_PATH];
792 	char PluginsPath[_MAX_PATH];
793 	char CachePath[_MAX_PATH];
794 	char GUIScriptsPath[_MAX_PATH];
795 	char SavePath[_MAX_PATH];
796 	char INIConfig[_MAX_PATH];
797 	char GamePath[_MAX_PATH];
798 	std::vector<std::string> CD[MAX_CD];
799 	std::vector<std::string> ModPath;
800 	int Width = 640, Height = 480, Bpp = 32;
801 	int IgnoreOriginalINI;
802 	bool DitherSprites = true;
803 	bool CaseSensitive = true, DrawFPS = false;
804 	bool UseSoftKeyboard; // TODO: reevaluate the need for this, see comments in StartTextInput
805 	unsigned short NumFingScroll, NumFingKboard, NumFingInfo;
806 	int MouseFeedback;
807 	int MaxPartySize;
808 	bool KeepCache;
809 	bool MultipleQuickSaves;
810 	bool UseCorruptedHack;
811 	int FeedbackLevel;
812 
813 	Variables *plugin_flags;
814 	/** The Main program loop */
815 	void Main(void);
816 	/** returns true if the game is paused */
817 	bool IsFreezed();
818 	void AskAndExit();
819 	void ExitGemRB(void);
820 	/** CheatKey support */
EnableCheatKeys(int Flag)821 	inline void EnableCheatKeys(int Flag)
822 	{
823 		CheatFlag=(Flag > 0);
824 	}
825 
CheatEnabled()826 	inline bool CheatEnabled()
827 	{
828 		return CheatFlag;
829 	}
830 
SetEventFlag(int Flag)831 	inline void SetEventFlag(int Flag)
832 	{
833 		EventFlag|=Flag;
834 	}
ResetEventFlag(int Flag)835 	inline void ResetEventFlag(int Flag)
836 	{
837 		EventFlag&=~Flag;
838 	}
839 
840 	static void SanityCheck(const char *ver);
841 
842 	/** Set Next Script */
843 	void SetNextScript(const char *script);
844 	/** Cheats enabled? */
845 	bool CheatFlag;
846 
847 	Audio* GetAudioDrv(void) const;
848 
849 	Timer& SetTimer(const EventHandler&, unsigned long interval, int repeats = -1);
850 };
851 
852 extern GEM_EXPORT Interface * core;
853 
854 }
855 
856 #endif
857