1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: interface.hpp
5 	Desc: contains interface related declarations
6 
7 	Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 	See LICENSE for details.
9 
10 -------------------------------------------------------------------------------*/
11 
12 #pragma once
13 
14 #include "../main.hpp"
15 #include "../game.hpp"
16 
17 class Item;
18 
19 typedef struct damageIndicator_t
20 {
21 	double x, y;  // x and y of the attacker in world coordinates
22 	double alpha; // alpha value of the indicator
23 	node_t* node; // node in the damageIndicator list
24 	Sint32 ticks; // birthtime of the damage indicator
25 } damageIndicator_t;
26 extern list_t damageIndicators;
27 
28 #define STATUS_BAR_Y_OFFSET (status_bmp->h * uiscale_chatlog * !hide_statusbar)
29 #define INVENTORY_SLOTSIZE (40 * uiscale_inventory)
30 #define STATUS_X (xres / 2 - status_bmp->w * uiscale_chatlog / 2)
31 #define STATUS_Y (yres - STATUS_BAR_Y_OFFSET)
32 #define HOTBAR_START_X ((xres / 2) - (5 * hotbar_img->w * uiscale_hotbar))
33 extern bool hide_statusbar;
34 extern real_t uiscale_chatlog;
35 extern real_t uiscale_playerbars;
36 extern bool uiscale_charactersheet;
37 extern bool uiscale_skillspage;
38 extern real_t uiscale_hotbar;
39 extern real_t uiscale_inventory;
40 
41 class EnemyHPDamageBarHandler
42 {
43 	const int k_maxTickLifetime = 120;
44 public:
45 
46 	struct EnemyHPDetails
47 	{
48 		char enemy_name[128] = "";
49 		Sint32 enemy_hp = 0;
50 		Sint32 enemy_maxhp = 0;
51 		Sint32 enemy_oldhp = 0;
52 		Uint32 enemy_timer = 0;
53 		Uint32 enemy_bar_color = 0;
54 		bool lowPriorityTick = false;
55 		bool shouldDisplay = true;
EnemyHPDetailsEnemyHPDamageBarHandler::EnemyHPDetails56 		EnemyHPDetails(Sint32 HP, Sint32 maxHP, Sint32 oldHP, Uint32 color, char* name, bool isLowPriority)
57 		{
58 			memset(enemy_name, 0, 128);
59 			enemy_hp = HP;
60 			enemy_maxhp = maxHP;
61 			enemy_oldhp = oldHP;
62 			enemy_timer = ticks;
63 			enemy_bar_color = color;
64 			lowPriorityTick = isLowPriority;
65 			shouldDisplay = true;
66 			strcpy(enemy_name, name);
67 		}
68 	};
69 
70 	Uint32 enemy_bar_client_colors[MAXPLAYERS];
71 	std::unordered_map<Uint32, EnemyHPDetails> HPBars;
72 	void addEnemyToList(Sint32 HP, Sint32 maxHP, Sint32 oldHP, Uint32 color, Uint32 uid, char* name, bool isLowPriority);
73 	void displayCurrentHPBar();
74 };
75 extern EnemyHPDamageBarHandler enemyHPDamageBarHandler;
76 
77 extern int magicBoomerangHotbarSlot;
78 
79 #ifndef SHOPWINDOW_SIZE
80 #define SHOPWINDOW_SIZE
81 #define SHOPWINDOW_SIZEX 576
82 #define SHOPWINDOW_SIZEY 324
83 #endif
84 
85 static const int GUI_MODE_NONE = -1; //GUI closed, ingame & playing.
86 static const int GUI_MODE_INVENTORY = 0;
87 static const int GUI_MODE_MAGIC = 1;
88 static const int GUI_MODE_SHOP = 2;
89 extern int gui_mode;
90 
91 /*
92  * So that the cursor jumps back to the hotbar instead of the inventory if a picked up hotbar item is canceled.
93  * Its value indicates which hotbar slot it's from.
94  * -1 means it's not from the hotbar.
95  */
96 extern int selectedItemFromHotbar;
97 
98 extern SDL_Surface* font12x12_small_bmp;
99 extern SDL_Surface* backdrop_minotaur_bmp;
100 extern SDL_Surface* backdrop_blessed_bmp;
101 extern SDL_Surface* backdrop_cursed_bmp;
102 extern SDL_Surface* status_bmp;
103 extern SDL_Surface* character_bmp;
104 extern SDL_Surface* hunger_bmp;
105 extern SDL_Surface* hunger_blood_bmp;
106 extern SDL_Surface* hunger_boiler_bmp;
107 extern SDL_Surface* hunger_boiler_hotflame_bmp;
108 extern SDL_Surface* hunger_boiler_flame_bmp;
109 extern SDL_Surface* minotaur_bmp;
110 extern SDL_Surface* textup_bmp;
111 extern SDL_Surface* textdown_bmp;
112 extern SDL_Surface* attributesleft_bmp, *attributesleftunclicked_bmp;
113 extern SDL_Surface* attributesright_bmp, *attributesrightunclicked_bmp;
114 extern SDL_Surface* button_bmp, *smallbutton_bmp, *invup_bmp, *invdown_bmp;
115 extern SDL_Surface* inventory_bmp, *inventoryoption_bmp, *inventoryoptionChest_bmp, *equipped_bmp;
116 extern SDL_Surface* itembroken_bmp;
117 //extern SDL_Surface *category_bmp[NUMCATEGORIES];
118 extern SDL_Surface* shopkeeper_bmp;
119 extern SDL_Surface* shopkeeper2_bmp;
120 extern SDL_Surface* damage_bmp;
121 extern int textscroll;
122 extern int attributespage;
123 extern int proficienciesPage;
124 extern int inventorycategory;
125 extern int itemscroll;
126 extern view_t camera_charsheet;
127 extern real_t camera_charsheet_offsetyaw;
128 
129 extern int selected_inventory_slot_x;
130 extern int selected_inventory_slot_y;
131 
132 void select_inventory_slot(int x, int y);
133 
134 extern SDL_Surface* inventoryChest_bmp;
135 extern SDL_Surface* invclose_bmp;
136 extern SDL_Surface* invgraball_bmp;
137 extern int chestitemscroll; //Same as itemscroll, but for the chest inventory GUI.
138 extern Entity* openedChest[MAXPLAYERS]; //One for each client. //TODO: Clientside, [0] will always point to something other than NULL when a chest is open and it will be NULL when a chest is closed.
139 extern list_t chestInv; //This is just for the client, so that it can populate the chest inventory on its end.
140 static const int kNumChestItemsToDisplay = 4;
141 extern Item* invitemschest[kNumChestItemsToDisplay];
142 
143 extern bool gui_clickdrag; //True as long as an interface element is being dragged.
144 extern int dragoffset_x;
145 extern int dragoffset_y;
146 extern int buttonclick;
147 
148 extern bool draw_cursor; //True if the gamepad's d-pad has been used to navigate menus and such. //TODO: Off by default on consoles and the like.
149 
150 // function prototypes
151 void takeScreenshot();
152 bool loadInterfaceResources();
153 void freeInterfaceResources();
154 void clickDescription(int player, Entity* entity);
155 void consoleCommand(char const * const command);
156 void drawMinimap();
157 void handleDamageIndicators(int player);
158 void handleDamageIndicatorTicks();
159 void drawStatus();
160 void saveCommand(char* content);
161 int loadConfig(char* filename);
162 int saveConfig(char const * const filename);
163 void defaultConfig();
164 void updateChestInventory();
165 void updateAppraisalItemBox();
166 void updatePlayerInventory();
167 void updateShopWindow();
168 void updateEnemyBar(Entity* source, Entity* target, char* name, Sint32 hp, Sint32 maxhp, bool lowPriorityTick = false);
169 damageIndicator_t* newDamageIndicator(double x, double y);
170 
171 void selectItemMenuSlot(const Item& item, int entry);
172 bool autoAddHotbarFilter(const Item& item);
173 void quickStackItems();
174 void sortInventoryItemsOfType(int categoryInt, bool sortRightToLeft); // sort inventory items matching category. -1 is everything, -2 is only equipped items.
175 void autosortInventory();
176 bool mouseInsidePlayerInventory();
177 bool mouseInsidePlayerHotbar();
178 bool playerLearnedSpellbook(Item* current_item);
179 extern Uint32 itemMenuItem;
180 extern bool itemMenuOpen;
181 extern int itemMenuSelected;
182 
183 /*
184  * Used for two purposes:
185  * * In inventory navigation, if you pick up an item, drops it only if detects a second click, not if the button is released.
186  * * In the item context menu, toggles if it should pop open or not.
187  * This makes this variable super useful for gamepad support.
188  */
189 extern bool toggleclick;
190 
191 //Inventory GUI definitions.
192 static const int INVENTORY_MODE_ITEM = 0;
193 static const int INVENTORY_MODE_SPELL = 1;
194 extern SDL_Surface* inventory_mode_item_img;
195 extern SDL_Surface* inventory_mode_item_highlighted_img;
196 extern SDL_Surface* inventory_mode_spell_img;
197 extern SDL_Surface* inventory_mode_spell_highlighted_img;
198 extern int inventory_mode;
199 
200 /*
201  * Determines how item select (pick up, release) mechanic works.
202  *		BEHAVIOR_MOUSE = press left button to pick up, release left button to drop,
203  *		BEHAVIOR_GAMEPAD = press mapped button (x by default) to select/"grab" item, press again to drop.
204  */
205 enum selectBehavior_t
206 {
207 	BEHAVIOR_MOUSE = 0,
208 	BEHAVIOR_GAMEPAD = 1,
209 	ENUM_LEN = 2
210 } extern itemSelectBehavior;
211 
212 //Chest GUI definitions.
213 #define CHEST_INVENTORY_X (((xres / 2) - (inventoryChest_bmp->w / 2)) + chestgui_offset_x)
214 #define CHEST_INVENTORY_Y (((yres / 2) - (inventoryChest_bmp->h / 2)) + chestgui_offset_y)
215 extern int chestgui_offset_x;
216 extern int chestgui_offset_y;
217 extern bool dragging_chestGUI; //The chest GUI is being dragged.
218 /*
219  * Currently selected chest inventory slot.
220  * Same deal as with hotbar & inventory selection (exists for gamepad support).
221  * -1 = no selection (e.g. mouse out or no items in the first place).
222  */
223 extern int selectedChestSlot;
224 void selectChestSlot(int slot);
225 int numItemsInChest();
226 void warpMouseToSelectedChestSlot();
227 
228 void warpMouseToSelectedInventorySlot();
229 
230 //Magic GUI definitions.
231 extern SDL_Surface* magicspellList_bmp;
232 extern SDL_Surface* spell_list_titlebar_bmp;
233 extern SDL_Surface* spell_list_gui_slot_bmp;
234 extern SDL_Surface* spell_list_gui_slot_highlighted_bmp;
235 extern int spellscroll; //Same as itemscroll, but for the spell list GUI.
236 extern int magicspell_list_offset_x;
237 extern int magicspell_list_offset_y;
238 #define MAGICSPELL_LIST_X (((xres / 2) - (magicspellList_bmp->w / 2)) + magicspell_list_offset_x)
239 #define MAGICSPELL_LIST_Y (((yres / 2) - (magicspellList_bmp->h / 2)) + magicspell_list_offset_y)
240 extern bool dragging_magicspell_list_GUI; //The magic spell list GUI is being dragged.
241 /*
242  * The state of the magic GUI.
243  * 0 = spell list.
244  * 1 = spell editor.
245  */
246 extern int magic_GUI_state;
247 extern SDL_Rect magic_gui_pos; //The position of the magic GUI is stored here.
248 extern SDL_Surface* sustained_spell_generic_icon; //The goto icon when no other is available.
249 
250 void renderMagicGUI(int winx, int winy, int winw, int winh);
251 void updateMagicGUI();
252 #define SUST_DIR_HORZ 0
253 #define SUST_DIR_VERT 1
254 #define SUST_SPELLS_DIRECTION SUST_DIR_VERT //0 = horizontal, 1 = vertical.
255 //sust_spells_x & sust_spells_y define the top left corner of where the sustained spells icons start drawing.
256 #define SUST_SPELLS_X 32
257 #define SUST_SPELLS_Y 32
258 #define SUST_SPELLS_RIGHT_ALIGN true //If true, overrides settings and makes the sustained spells draw alongside the right edge of the screen, vertically.
259 void drawSustainedSpells(); //Draws an icon for every sustained spell.
260 
261 //Identify GUI definitions.
262 //NOTE: Make sure to always reset identifygui_appraising back to false.
263 #define IDENTIFY_GUI_X (((xres / 2) - (inventoryChest_bmp->w / 2)) + identifygui_offset_x)
264 #define IDENTIFY_GUI_Y (((yres / 2) - (inventoryChest_bmp->h / 2)) + identifygui_offset_y)
265 extern bool identifygui_active;
266 extern bool identifygui_appraising; //If this is true, the appraisal skill is controlling the identify GUI. If this is false, it originated from an identify spell.
267 extern int identifygui_offset_x;
268 extern int identifygui_offset_y;
269 extern bool dragging_identifyGUI; //The identify GUI is being dragged.
270 extern int identifyscroll;
271 static const int NUM_IDENTIFY_GUI_ITEMS = 4;
272 extern Item* identify_items[NUM_IDENTIFY_GUI_ITEMS];
273 extern SDL_Surface* identifyGUI_img;
274 
275 extern int selectedIdentifySlot;
276 
277 void selectIdentifySlot(int slot);
278 void warpMouseToSelectedIdentifySlot();
279 
280 void CloseIdentifyGUI();
281 void updateIdentifyGUI(); //Updates the identify item GUI.
282 void identifyGUIIdentify(Item* item); //Identify the given item.
283 int getAppraisalTime(Item* item); // Return time in ticks needed to appraise an item
284 void drawSustainedSpells(); //Draws an icon for every sustained spell.
285 
286 //Remove curse GUI definitions.
287 #define REMOVECURSE_GUI_X (((xres / 2) - (inventoryChest_bmp->w / 2)) + removecursegui_offset_x)
288 #define REMOVECURSE_GUI_Y (((yres / 2) - (inventoryChest_bmp->h / 2)) + removecursegui_offset_y)
289 extern bool removecursegui_active;
290 extern int removecursegui_offset_x;
291 extern int removecursegui_offset_y;
292 extern bool dragging_removecurseGUI; //The remove curse GUI is being dragged.
293 extern int removecursescroll;
294 static const int NUM_REMOVE_CURSE_GUI_ITEMS = 4;
295 extern Item* removecurse_items[NUM_REMOVE_CURSE_GUI_ITEMS];
296 //extern SDL_Surface *removecurseGUI_img; //Nah, just use the identify GUI's image. It works well enough. No need to double the resources.
297 
298 void closeRemoveCurseGUI();
299 void updateRemoveCurseGUI(); //Updates the remove curse GUI.
300 void removecurseGUIRemoveCurse(Item* item); //Uncurse the given item.
301 
302 //Gamepad-support related stuff.
303 extern int selectedRemoveCurseSlot;
304 void selectRemoveCurseSlot(int slot);
305 void warpMouseToSelectedRemoveCurseSlot();
306 
307 enum GUICurrentType
308 {
309 	GUI_TYPE_NONE,
310 	GUI_TYPE_REPAIR,
311 	GUI_TYPE_ALCHEMY,
312 	GUI_TYPE_TINKERING,
313 	GUI_TYPE_SCRIBING
314 };
315 
316 // Generic GUI Stuff (repair/alchemy)
317 class GenericGUIMenu
318 {
319 	int gui_starty = ((xres / 2) - (420 / 2)) + offsetx;
320 	int gui_startx = ((yres / 2) - (96 / 2)) + offsety;
321 	int usingScrollBeatitude = 0;
322 	int offsetx;
323 	int offsety;
324 	int scroll;
325 	GUICurrentType guiType;
326 public:
327 	static const int kNumShownItems = 4;
328 	bool draggingGUI; // if gui is being dragged
329 	Item* itemsDisplayed[kNumShownItems];
330 	bool guiActive;
331 	int selectedSlot;
332 
333 	// Repair
334 	int repairItemType;
335 
336 	// Alchemy
337 	Item* basePotion;
338 	Item* secondaryPotion;
339 	Item* alembicItem;
340 	bool experimentingAlchemy;
341 
342 	// Tinkering
343 	enum TinkeringFilter
344 	{
345 		TINKER_FILTER_ALL,
346 		TINKER_FILTER_CRAFTABLE,
347 		TINKER_FILTER_SALVAGEABLE,
348 		TINKER_FILTER_REPAIRABLE
349 	};
350 	Item* tinkeringKitItem;
351 	list_t tinkeringTotalItems;
352 	node_t* tinkeringTotalLastCraftableNode;
353 	TinkeringFilter tinkeringFilter;
354 	std::unordered_set<Uint32> tinkeringMetalScrap;
355 	std::unordered_set<Uint32> tinkeringMagicScrap;
356 	Item* tinkeringAutoSalvageKitItem;
357 	Item* tinkeringAutoSalvageThisItem;
358 	Uint32 tinkeringSfxLastTicks = 0;
359 
360 	// Scribing
361 	Item* scribingToolItem;
362 	list_t scribingTotalItems;
363 	node_t* scribingTotalLastCraftableNode;
364 	Item* scribingBlankScrollTarget;
365 	enum ScribingFilter
366 	{
367 		SCRIBING_FILTER_CRAFTABLE,
368 		SCRIBING_FILTER_REPAIRABLE
369 	};
370 	ScribingFilter scribingFilter;
371 
GenericGUIMenu()372 	GenericGUIMenu() :
373 		guiActive(false),
374 		offsetx(0),
375 		offsety(0),
376 		selectedSlot(-1),
377 		scroll(0),
378 		draggingGUI(false),
379 		basePotion(nullptr),
380 		secondaryPotion(nullptr),
381 		alembicItem(nullptr),
382 		experimentingAlchemy(false),
383 		tinkeringKitItem(nullptr),
384 		tinkeringTotalLastCraftableNode(nullptr),
385 		tinkeringFilter(TINKER_FILTER_ALL),
386 		tinkeringAutoSalvageKitItem(nullptr),
387 		tinkeringAutoSalvageThisItem(nullptr),
388 		scribingFilter(SCRIBING_FILTER_CRAFTABLE),
389 		scribingToolItem(nullptr),
390 		scribingTotalLastCraftableNode(nullptr),
391 		scribingBlankScrollTarget(nullptr),
392 		scribingLastUsageAmount(0),
393 		scribingLastUsageDisplayTimer(0),
394 		repairItemType(0)
395 	{
396 		for ( int i = 0; i < kNumShownItems; ++i )
397 		{
398 			itemsDisplayed[i] = nullptr;
399 		}
400 		tinkeringTotalItems.first = nullptr;
401 		tinkeringTotalItems.last = nullptr;
402 		scribingTotalItems.first = nullptr;
403 		scribingTotalItems.last = nullptr;
404 	};
405 
406 	void warpMouseToSelectedSlot();
407 	void selectSlot(int slot);
408 	void closeGUI();
409 	void openGUI(int type, int scrollBeatitude, int scrollType);
410 	void openGUI(int type, bool experimenting, Item* itemOpenedWith);
411 	void openGUI(int type, Item* itemOpenedWith);
412 	inline Item* getItemInfo(int slot);
413 	void updateGUI();
414 	void rebuildGUIInventory();
415 	void initGUIControllerCode();
416 	bool shouldDisplayItemInGUI(Item* item);
417 	bool executeOnItemClick(Item* item);
418 
419 	// repair menu funcs
420 	void repairItem(Item* item);
421 	bool isItemRepairable(const Item* item, int repairScroll);
422 
423 	//alchemy menu funcs
424 	bool isItemMixable(const Item* item);
425 	void alchemyCombinePotions();
426 	bool alchemyLearnRecipe(int type, bool increaseskill, bool notify = true);
427 	bool isItemBaseIngredient(int type);
428 	bool isItemSecondaryIngredient(int type);
429 	void alchemyLearnRecipeOnLevelUp(int skill);
430 
431 	// tinkering menu foncs
432 	bool tinkeringSalvageItem(Item* item, bool outsideInventory, int player);
433 	bool tinkeringCraftItem(Item* item);
434 	void tinkeringCreateCraftableItemList();
435 	void tinkeringFreeLists();
436 	bool isItemSalvageable(const Item* item, int player);
437 	bool tinkeringGetItemValue(const Item* item, int* metal, int* magic);
438 	bool tinkeringGetCraftingCost(const Item* item, int* metal, int* magic);
439 	bool tinkeringPlayerCanAffordCraft(const Item* item);
440 	Item* tinkeringCraftItemAndConsumeMaterials(const Item* item);
441 	int tinkeringPlayerHasSkillLVLToCraft(const Item* item);
442 	bool tinkeringKitDegradeOnUse(int player);
443 	Item* tinkeringKitFindInInventory();
444 	bool tinkeringKitRollIfShouldBreak();
445 	bool tinkeringGetRepairCost(Item* item, int* metal, int* magic);
446 	bool tinkeringIsItemRepairable(Item* item, int player);
447 	bool tinkeringIsItemUpgradeable(const Item* item);
448 	bool tinkeringRepairItem(Item* item);
449 	int tinkeringUpgradeMaxStatus(Item* item);
450 	bool tinkeringConsumeMaterialsForRepair(Item* item, bool upgradingItem);
451 	bool tinkeringPlayerCanAffordRepair(Item* item);
452 	int tinkeringRepairGeneralItemSkillRequirement(Item* item);
453 	bool tinkeringPlayerHasMaterialsInventory(int metal, int magic);
454 	Uint32 tinkeringRetrieveLeastScrapStack(int type);
455 	int tinkeringCountScrapTotal(int type);
456 
457 	void scribingCreateCraftableItemList();
458 	void scribingFreeLists();
459 	int scribingToolDegradeOnUse(Item* itemUsedWith);
460 	Item* scribingToolFindInInventory();
461 	bool scribingWriteItem(Item* item);
462 	int scribingLastUsageAmount;
463 	int scribingLastUsageDisplayTimer;
464 
isGUIOpen()465 	inline bool isGUIOpen()
466 	{
467 		return guiActive;
468 	};
isNodeTinkeringCraftableItem(node_t * node)469 	inline bool isNodeTinkeringCraftableItem(node_t* node)
470 	{
471 		if ( !node )
472 		{
473 			return false;
474 		}
475 		return (node->list == &tinkeringTotalItems);
476 	};
isNodeScribingCraftableItem(node_t * node)477 	inline bool isNodeScribingCraftableItem(node_t* node)
478 	{
479 		if ( !node )
480 		{
481 			return false;
482 		}
483 		return (node->list == &scribingTotalItems);
484 	};
isItemUsedForCurrentGUI(const Item & item)485 	inline bool isItemUsedForCurrentGUI(const Item& item)
486 	{
487 		if ( &item == scribingToolItem || &item == tinkeringKitItem || &item == alembicItem )
488 		{
489 			return true;
490 		}
491 		return false;
492 	}
clearCurrentGUIFromItem(const Item & item)493 	inline void clearCurrentGUIFromItem(const Item& item)
494 	{
495 		if ( &item == scribingToolItem )
496 		{
497 			scribingToolItem = nullptr;
498 		}
499 		if ( &item == tinkeringKitItem )
500 		{
501 			tinkeringKitItem = nullptr;
502 		}
503 		if ( &item == alembicItem )
504 		{
505 			alembicItem = nullptr;
506 		}
507 	}
508 	bool isNodeFromPlayerInventory(node_t* node);
509 };
510 extern GenericGUIMenu GenericGUI;
511 
512 /*
513  * Returns true if the mouse is in the specified bounds, with x1 and y1 specifying the top left corner, and x2 and y2 specifying the bottom right corner.
514  */
515 bool mouseInBounds(int x1, int x2, int y1, int y2);
516 
517 void updateCharacterSheet();
518 void drawPartySheet();
519 void drawSkillsSheet();
520 
521 //Right sidebar defines.
522 #define RIGHTSIDEBAR_X (xres - rightsidebar_titlebar_img->w)
523 #define RIGHTSIDEBAR_Y 0
524 //Note: Just using the spell versions of these for now.
525 extern SDL_Surface* rightsidebar_titlebar_img;
526 extern SDL_Surface* rightsidebar_slot_img;
527 extern SDL_Surface* rightsidebar_slot_highlighted_img;
528 extern SDL_Surface* rightsidebar_slot_grayedout_img;
529 extern int rightsidebar_height;
530 extern int appraisal_timer; //There is a delay after the appraisal skill is activated before the item is identified.
531 extern int appraisal_timermax;
532 extern Uint32 appraisal_item; //The item being appraised (or rather its uid)
533 
534 void updateRightSidebar(); //Updates the sidebar on the right side of the screen, the one containing spells, skills, etc.
535 
536 //------book_t Defines-----
537 extern SDL_Surface* bookgui_img;
538 //extern SDL_Surface *nextpage_img;
539 //extern SDL_Surface *previouspage_img;
540 //extern SDL_Surface *bookclose_img;
541 extern SDL_Surface* book_highlighted_left_img; //Draw this when the mouse is over the left half of the book.
542 extern SDL_Surface* book_highlighted_right_img; //Draw this when the mouse is over the right half of the book.
543 extern node_t* book_page;
544 extern int bookgui_offset_x;
545 extern int bookgui_offset_y;
546 #define BOOK_GUI_X (((xres / 2) - (bookgui_img->w / 2)) + bookgui_offset_x)
547 #define BOOK_GUI_Y (((yres / 2) - (bookgui_img->h / 2)) + bookgui_offset_y)
548 extern bool dragging_book_GUI; //The book GUI is being dragged.
549 extern bool book_open; //Is there a book open?
550 struct book_t;
551 extern struct book_t* open_book;
552 extern Item* open_book_item; //A pointer to the open book's item, so that the game knows to close the book when the player drops that item.
553 #define BOOK_FONT ttf12
554 #define BOOK_FONT_WIDTH TTF12_WIDTH
555 #define BOOK_FONT_HEIGHT TTF12_HEIGHT
556 //TODO: Calculate these two automatically based off of the buttons?
557 #define BOOK_PAGE_WIDTH 248
558 #define BOOK_PAGE_HEIGHT 256
559 #define BOOK_TITLE_PADDING 2 //The amount of empty space above and below the book titlename.
560 //#define BOOK_TITLE_HEIGHT (BOOK_TITLE_FONT_SIZE + BOOK_TITLE_PADDING) //The total y space the book's title takes up. Used for calculating BOOK_DRAWSPACE_Y.
561 int bookTitleHeight(struct book_t* book); //Returns how much space the book's title will occupy.
562 //#define BOOK_DRAWSPACE_X 280
563 //#define BOOK_DRAWSPACE_X (bookgui_img->w - (BOOK_BORDER_THICKNESS * 2))
564 #define START_OF_BOOKDRAWSPACE_X (BOOK_BORDER_THICKNESS) //This is the amount to add to BOOK_GUI_X to get the render area for the text.
565 //#define BOOK_DRAWSPACE_Y 180
566 //#define BOOK_DRAWSPACE_Y (bookgui_img->h - (BOOK_BORDER_THICKNESS * 2) - std::max(previouspage_img->h, nextpage_img->h)) //NOTE: You need to manually add  "- bookTitleHeight(open_book)" wherever you use this define.
567 #define START_OF_BOOK_DRAWSPACE_Y (BOOK_BORDER_THICKNESS) //This is the amount to add to BOOK_GUI_Y to get the render area for the text. //NOTE: You need to manually add  "+ bookTitleHeight(open_book)" wherever you use this define.
568 #define FLIPMARGIN 240
569 #define DRAGHEIGHT_BOOK 32
570 //extern int book_characterspace_x; //How many characters can fit along the x axis.
571 //extern int book_characterspace_y; //How many characters can fit along the y axis.
572 void updateBookGUI();
573 void closeBookGUI();
574 void openBook(struct book_t* book, Item* item);
575 
576 extern Entity* hudweapon; //A pointer to the hudweapon entity.
577 
578 
579 //------Hotbar Defines-----
580 /*
581  * The hotbar itself is an array.
582  * NOTE: If the status bar width is changed, you need to change the slot image too. Make sure the status bar width stays divisible by 10.
583  */
584 
585 //NOTE: Each hotbar slot is "constructed" in loadInterfaceResources() in interface.c. If you add anything, make sure to initialize it there.
586 typedef struct hotbar_slot_t
587 {
588 	/*
589 	 * This is an item's ID. It just resolves to NULL if an item is no longer valid.
590 	 */
591 	Uint32 item;
592 } hotbar_slot_t;
593 
594 #define HOTBAR_EMPTY 0
595 #define HOTBAR_ITEM 1
596 #define HOTBAR_SPELL 2
597 
598 static const unsigned NUM_HOTBAR_SLOTS = 10; //NOTE: If you change this, you must dive into drawstatus.c and update the hotbar code. It expects 10.
599 static const unsigned NUM_HOTBAR_ALTERNATES = 5;
600 extern hotbar_slot_t hotbar[NUM_HOTBAR_SLOTS];
601 extern hotbar_slot_t hotbar_alternate[NUM_HOTBAR_ALTERNATES][NUM_HOTBAR_SLOTS];
602 extern int swapHotbarOnShapeshift;
603 extern bool hotbarShapeshiftInit[NUM_HOTBAR_ALTERNATES];
604 extern int current_hotbar; //For use with gamepads and stuff because no hotkeys like a keyboard.
605 enum HotbarLoadouts : int
606 {
607 	HOTBAR_DEFAULT,
608 	HOTBAR_RAT,
609 	HOTBAR_SPIDER,
610 	HOTBAR_TROLL,
611 	HOTBAR_IMP
612 };
613 
614 extern SDL_Surface* hotbar_img; //A 64x64 slot.
615 extern SDL_Surface* hotbar_spell_img; //Drawn when a spell is in the hotbar. TODO: Replace with unique images for every spell. (Or draw this by default if none found?)
616 
617 //Returns a pointer to a hotbar slot if the specified coordinates are in the area of the hotbar. Used for such things as dragging and dropping items.
618 hotbar_slot_t* getHotbar(int x, int y);
619 
620 void selectHotbarSlot(int slot);
621 extern bool hotbarHasFocus;
622 void warpMouseToSelectedHotbarSlot();
623 
624 /*
625  * True = automatically place items you pick up in your hotbar.
626  * False = don't.
627  */
628 extern bool auto_hotbar_new_items;
629 
630 extern bool auto_hotbar_categories[NUM_HOTBAR_CATEGORIES]; // true = enable auto add to hotbar. else don't add.
631 
632 extern int autosort_inventory_categories[NUM_AUTOSORT_CATEGORIES]; // 0 = disable priority sort, fill rightmost first. greater than 0, fill leftmost using value as priority (0 = lowest priority)
633 
634 extern bool hotbar_numkey_quick_add; // use number keys to add items to hotbar if mouse in inventory panel.
635 
636 extern bool disable_messages;
637 
638 extern bool right_click_protect;
639 
640 extern bool auto_appraise_new_items;
641 
642 extern bool lock_right_sidebar;
643 
644 extern bool show_game_timer_always;
645 
646 extern bool hide_playertags;
647 
648 extern bool show_skill_values;
649 
650 const char* getInputName(Uint32 scancode);
651 Sint8* inputPressed(Uint32 scancode);
652 
653 //All the code that sets shootmode = false. Display chests, inventory, books, shopkeeper, identify, whatever.
654 void openStatusScreen(int whichGUIMode, int whichInventoryMode); //TODO: Make all the everything use this. //TODO: Make an accompanying closeStatusScreen() function.
655 enum CloseGUIShootmode : int
656 {
657 	DONT_CHANGE_SHOOTMODE,
658 	CLOSEGUI_ENABLE_SHOOTMODE
659 };
660 enum CloseGUIIgnore : int
661 {
662 	CLOSEGUI_CLOSE_ALL,
663 	CLOSEGUI_DONT_CLOSE_FOLLOWERGUI,
664 	CLOSEGUI_DONT_CLOSE_CHEST,
665 	CLOSEGUI_DONT_CLOSE_SHOP
666 };
667 
668 void closeAllGUIs(CloseGUIShootmode shootmodeAction, CloseGUIIgnore whatToClose);
669 
670 static const int SCANCODE_UNASSIGNED_BINDING = 399;
671 
hotbarGamepadControlEnabled()672 inline bool hotbarGamepadControlEnabled()
673 {
674 	return ( !openedChest[clientnum]
675 		&& gui_mode != GUI_MODE_SHOP
676 		&& !identifygui_active
677 		&& !removecursegui_active
678 		&& !GenericGUI.isGUIOpen() );
679 }
680 
681 extern SDL_Surface *str_bmp64u;
682 extern SDL_Surface *dex_bmp64u;
683 extern SDL_Surface *con_bmp64u;
684 extern SDL_Surface *int_bmp64u;
685 extern SDL_Surface *per_bmp64u;
686 extern SDL_Surface *chr_bmp64u;
687 extern SDL_Surface *str_bmp64;
688 extern SDL_Surface *dex_bmp64;
689 extern SDL_Surface *con_bmp64;
690 extern SDL_Surface *int_bmp64;
691 extern SDL_Surface *per_bmp64;
692 extern SDL_Surface *chr_bmp64;
693 
694 extern SDL_Surface *sidebar_lock_bmp;
695 extern SDL_Surface *sidebar_unlock_bmp;
696 
697 extern SDL_Surface *effect_drunk_bmp;
698 extern SDL_Surface *effect_polymorph_bmp;
699 extern SDL_Surface *effect_hungover_bmp;
700 
701 void printStatBonus(TTF_Font* outputFont, Sint32 stat, Sint32 statWithModifiers, int x, int y);
702 void attackHoverText(Sint32 input[6]);
703 Sint32 displayAttackPower(Sint32 output[6]);
704 
705 class MinimapPing
706 {
707 public:
708 	Sint32 tickStart;
709 	Uint8 player;
710 	Uint8 x;
711 	Uint8 y;
712 	bool radiusPing;
MinimapPing(Sint32 tickStart,Uint8 player,Uint8 x,Uint8 y)713 	MinimapPing(Sint32 tickStart, Uint8 player, Uint8 x, Uint8 y) :
714 		tickStart(tickStart),
715 		player(player),
716 		x(x),
717 		y(y),
718 		radiusPing(false) {}
719 
MinimapPing(Sint32 tickStart,Uint8 player,Uint8 x,Uint8 y,bool radiusPing)720 	MinimapPing(Sint32 tickStart, Uint8 player, Uint8 x, Uint8 y, bool radiusPing) :
721 		tickStart(tickStart),
722 		player(player),
723 		x(x),
724 		y(y),
725 		radiusPing(radiusPing) {}
726 };
727 
728 extern std::vector<MinimapPing> minimapPings;
729 void minimapPingAdd(MinimapPing newPing);
730 extern int minimapPingGimpTimer;
731 
732 extern std::vector<std::pair<SDL_Surface**, std::string>> systemResourceImages;
733 
734 class FollowerRadialMenu
735 {
736 public:
737 	Entity* followerToCommand;
738 	Entity* recentEntity;
739 	Entity* entityToInteractWith;
740 	int menuX; // starting mouse coordinates that are the center of the circle.
741 	int menuY; // starting mouse coordinates that are the center of the circle.
742 	int optionSelected; // current moused over option.
743 	int optionPrevious; // previously selected option.
744 	bool selectMoveTo; // player is choosing a point or target to interact with.
745 	int moveToX; // x position for follower to move to.
746 	int moveToY; // y position for follower to move to.
747 	bool menuToggleClick; // user pressed menu key but did not select option before letting go. keeps the menu open without input.
748 	bool holdWheel; // user pressed quick menu for last follower.
749 	char interactText[128]; // user moused over object while selecting interact object.
750 	bool accessedMenuFromPartySheet; // right click from party sheet will warp mouse back after a selection.
751 	int partySheetMouseX; // store mouse x cooord for accessedMenuFromPartySheet warp.
752 	int partySheetMouseY; // store mouse y cooord for accessedMenuFromPartySheet warp.
753 	int sidebarScrollIndex; // entries scrolled in the sidebar list if overflowed with followers.
754 	int maxMonstersToDraw;
755 
FollowerRadialMenu()756 	FollowerRadialMenu() :
757 		followerToCommand(nullptr),
758 		recentEntity(nullptr),
759 		entityToInteractWith(nullptr),
760 		menuX(-1),
761 		menuY(-1),
762 		optionSelected(-1),
763 		optionPrevious(-1),
764 		selectMoveTo(false),
765 		moveToX(-1),
766 		moveToY(-1),
767 		menuToggleClick(false),
768 		holdWheel(false),
769 		accessedMenuFromPartySheet(false),
770 		partySheetMouseX(-1),
771 		partySheetMouseY(-1),
772 		sidebarScrollIndex(0),
773 		maxMonstersToDraw(5)
774 	{
775 		memset(interactText, 0, 128);
776 	}
777 
778 	bool followerMenuIsOpen();
779 	void drawFollowerMenu();
780 	void initFollowerMenuGUICursor(bool openInventory = true);
781 	void closeFollowerMenuGUI(bool clearRecentEntity = false);
782 	void selectNextFollower();
783 	int numMonstersToDrawInParty();
784 	void updateScrollPartySheet();
785 	bool allowedInteractEntity(Entity& selectedEntity);
786 	int optionDisabledForCreature(int playerSkillLVL, int monsterType, int option);
787 	bool allowedClassToggle(int monsterType);
788 	bool allowedItemPickupToggle(int monsterType);
789 	bool allowedInteractFood(int monsterType);
790 	bool allowedInteractWorld(int monsterType);
791 	bool allowedInteractItems(int monsterType);
792 	bool attackCommandOnly(int monsterType);
793 	void monsterGyroBotConvertCommand(int* option);
794 	bool monsterGyroBotOnlyCommand(int option);
795 	bool monsterGyroBotDisallowedCommands(int option);
796 	bool isTinkeringFollower(int type);
797 };
798 extern FollowerRadialMenu FollowerMenu;
799 extern SDL_Rect interfaceSkillsSheet;
800 extern SDL_Rect interfacePartySheet;
801 extern SDL_Rect interfaceCharacterSheet;
802 extern SDL_Rect interfaceMessageStatusBar;