14#include "../src/combat/combat_mode.h"
47int inventory_gear_count = 0;
48int inventory_potion_count = 0;
50char** inventory_gear_options = NULL;
51char** inventory_equipment_options = NULL;
52char** inventory_potion_options = NULL;
55 inventory_mode_strings = (
char**) malloc(
sizeof(
char*) * MAX_INVENTORY_STRINGS);
56 RETURN_WHEN_NULL(inventory_mode_strings, -1,
"Inventory Mode",
"Failed to allocate memory for inventory mode strings");
58 inventory_equipment_options = (
char**) malloc(
sizeof(
char*) * MAX_SLOT);
59 if (inventory_equipment_options == NULL) {
60 free(inventory_mode_strings);
61 log_msg(ERROR,
"Inventory Mode",
"Failed to allocate memory for inventory equipment options");
66 for (
int i = 0; i < MAX_INVENTORY_STRINGS; i++) {
67 inventory_mode_strings[i] = NULL;
70 for (
int i = 0; i < MAX_SLOT; i++) {
71 inventory_equipment_options[i] = NULL;
82 if (monster != NULL) {
92 switch (inventory_state) {
96 case INVENTORY_GEAR_MENU:
99 case INVENTORY_EQUIPMENT_MENU:
102 case INVENTORY_POTION_MENU:
106 inventory_state = INVENTORY_MENU;
109 return CONTINUE_INVENTORY;
113 const character_t* target = (monster != NULL) ? monster : player;
115 int selected_index = 0;
118 bool submenu_selected =
false;
120 while (!submenu_selected) {
121 if (monster != NULL) {
123 inventory_mode_strings[LOOT_MAIN_MENU_TITLE],
125 &inventory_mode_strings[LOOT_OPTION_SHOW_GEAR],
129 inventory_mode_strings[FINISH_LOOTING_MSG]);
132 inventory_mode_strings[MAIN_MENU_TITLE],
134 &inventory_mode_strings[SHOW_GEAR],
138 inventory_mode_strings[PRESS_C_RETURN]);
148 switch (input_event.type) {
150 selected_index = (selected_index - 1 + 3) % 3;
153 selected_index = (selected_index + 1) % 3;
156 if (selected_index == 0) {
157 new_state = INVENTORY_GEAR_MENU;
158 }
else if (selected_index == 1) {
159 new_state = INVENTORY_EQUIPMENT_MENU;
160 }
else if (selected_index == 2) {
161 new_state = INVENTORY_POTION_MENU;
163 submenu_selected =
true;
166 case INPUT_INVENTORY:
167 new_state = INVENTORY_EXIT;
168 submenu_selected =
true;
178 const character_t* target = (monster != NULL) ? monster : player;
180 int selected_index = 0;
182 if (target->gear_count == 0) {
184 return INVENTORY_MENU;
188 bool item_selected_or_esc =
false;
190 while (!item_selected_or_esc) {
191 if (monster != NULL) {
193 inventory_mode_strings[INVENTORY_MENU_TITLE],
194 inventory_mode_strings[LOOT_GEAR_MENU_HEADER],
195 inventory_gear_options,
199 inventory_mode_strings[PRESS_C_RETURN]);
202 inventory_mode_strings[INVENTORY_MENU_TITLE],
203 inventory_mode_strings[INVENTORY_MENU_HEADER],
204 inventory_gear_options,
207 inventory_mode_strings[INVENTORY_DROP_GEAR_MSG],
208 inventory_mode_strings[PRESS_C_RETURN]);
218 uint32_t key_id = input_event.raw_input.id;
221 switch (input_event.type) {
223 selected_index = (selected_index - 1 + target->gear_count) % target->gear_count;
226 selected_index = (selected_index + 1) % target->gear_count;
229 if (monster != NULL) {
230 if (player->gear_count < MAX_GEAR_LIMIT) {
231 add_gear(player, monster->gear_inventory[selected_index]);
232 remove_gear(monster, monster->gear_inventory[selected_index]);
239 if (player->equipment[player->gear_inventory[selected_index]->slot] == NULL) {
240 if (
can_equip_gear(player, player->gear_inventory[selected_index])) {
241 equip_gear(player, player->gear_inventory[selected_index]);
252 return INVENTORY_GEAR_MENU;
254 new_state = INVENTORY_MENU;
255 item_selected_or_esc =
true;
259 if ((key_id ==
'd' || key_id ==
'D') && monster == NULL) {
260 remove_gear(player, player->gear_inventory[selected_index]);
262 return INVENTORY_GEAR_MENU;
278 if (gear->slot == SLOT_BOTH_HANDS) {
279 if (player->equipment[SLOT_LEFT_HAND] != NULL || player->equipment[SLOT_RIGHT_HAND] != NULL) {
282 }
else if (gear->slot == SLOT_LEFT_HAND || gear->slot == SLOT_RIGHT_HAND) {
283 if (player->equipment[SLOT_BOTH_HANDS] != NULL) {
291 const character_t* target = (monster != NULL) ? monster : player;
293 int selected_index = 0;
296 bool item_selected_or_esc =
false;
298 while (!item_selected_or_esc) {
299 if (monster != NULL) {
301 inventory_mode_strings[EQUIPMENT_MENU_TITLE],
302 inventory_mode_strings[LOOT_EQUIPMENT_MENU_HEADER],
303 inventory_equipment_options,
307 inventory_mode_strings[PRESS_C_RETURN]);
310 inventory_mode_strings[EQUIPMENT_MENU_TITLE],
311 inventory_mode_strings[EQUIPMENT_MENU_HEADER],
312 inventory_equipment_options,
316 inventory_mode_strings[PRESS_C_RETURN]);
326 switch (input_event.type) {
328 selected_index = (selected_index - 1 + MAX_SLOT) % MAX_SLOT;
331 selected_index = (selected_index + 1) % MAX_SLOT;
334 if (monster != NULL) {
335 if (monster->equipment[selected_index] != NULL) {
336 if (player->gear_count < MAX_GEAR_LIMIT) {
337 add_gear(player, monster->equipment[selected_index]);
344 return INVENTORY_EQUIPMENT_MENU;
347 if (player->equipment[selected_index] != NULL) {
348 if (player->gear_count < MAX_GEAR_LIMIT) {
355 return INVENTORY_EQUIPMENT_MENU;
360 new_state = INVENTORY_MENU;
361 item_selected_or_esc =
true;
371 const character_t* target = (monster != NULL) ? monster : player;
373 int selected_index = 0;
375 if (target->potion_count == 0) {
377 return INVENTORY_MENU;
381 bool item_selected_or_esc =
false;
383 while (!item_selected_or_esc) {
384 if (monster != NULL) {
386 inventory_mode_strings[POTION_MENU_TITLE],
387 inventory_mode_strings[LOOT_POTION_MENU_HEADER],
388 inventory_potion_options,
389 monster->potion_count,
392 inventory_mode_strings[PRESS_C_RETURN]);
395 inventory_mode_strings[POTION_MENU_TITLE],
396 inventory_mode_strings[POTION_MENU_HEADER],
397 inventory_potion_options,
398 player->potion_count,
400 inventory_mode_strings[POTION_DROP_POTION_MSG],
401 inventory_mode_strings[PRESS_C_RETURN]);
411 uint32_t key_id = input_event.raw_input.id;
414 switch (input_event.type) {
416 selected_index = (selected_index - 1 + target->potion_count) % target->potion_count;
419 selected_index = (selected_index + 1) % target->potion_count;
422 if (monster != NULL) {
423 if (player->potion_count < MAX_POTION_LIMIT) {
424 add_potion(player, monster->potion_inventory[selected_index]);
425 remove_potion(monster, monster->potion_inventory[selected_index]);
432 char message[MAX_STRING_LENGTH];
433 snprintf(message,
sizeof(message), inventory_mode_strings[POTION_USE],
435 player->potion_inventory[selected_index]->name,
436 player->potion_inventory[selected_index]->value,
444 return INVENTORY_POTION_MENU;
446 new_state = INVENTORY_MENU;
447 item_selected_or_esc =
true;
451 if ((key_id ==
'd' || key_id ==
'D') && monster == NULL) {
452 remove_potion(player, player->potion_inventory[selected_index]);
454 return INVENTORY_POTION_MENU;
469 if (inventory_gear_options != NULL) {
470 for (
int i = 0; i < inventory_gear_count; i++) {
471 if (inventory_gear_options[i] != NULL) {
472 free(inventory_gear_options[i]);
473 inventory_gear_options[i] = NULL;
476 free(inventory_gear_options);
477 inventory_gear_options = NULL;
480 inventory_gear_count = count;
481 inventory_gear_options = (
char**) malloc(count *
sizeof(
char*));
482 RETURN_WHEN_NULL(inventory_gear_options, ,
"Inventory Mode",
"Failed to allocate memory for inventory gear options");
484 for (
int i = 0; i < count; i++) {
485 inventory_gear_options[i] = (
char*) malloc(MAX_STRING_LENGTH *
sizeof(
char));
486 if (inventory_gear_options[i] == NULL) {
487 for (
int j = 0; j < i; j++) {
488 free(inventory_gear_options[j]);
489 inventory_gear_options[j] = NULL;
491 free(inventory_gear_options);
492 inventory_gear_options = NULL;
493 log_msg(ERROR,
"Inventory Mode",
"Failed to allocate memory for inventory gear options");
498 for (
int i = 0; i < count; i++) {
499 snprintf(inventory_gear_options[i], MAX_STRING_LENGTH,
500 inventory_mode_strings[INVENTORY_GEAR_FORMAT],
501 gear_inventory[i]->local_key,
503 gear_inventory[i]->defenses.armor,
504 gear_inventory[i]->defenses.magic_resist);
514 if (inventory_equipment_options != NULL) {
515 for (
int i = 0; i < MAX_SLOT; i++) {
516 if (inventory_equipment_options[i] != NULL) {
517 free(inventory_equipment_options[i]);
518 inventory_equipment_options[i] = NULL;
521 for (
int i = 0; i < MAX_SLOT; i++) {
522 inventory_equipment_options[i] = (
char*) malloc(MAX_STRING_LENGTH *
sizeof(
char));
523 if (inventory_equipment_options[i] == NULL) {
524 for (
int j = 0; j < i; j++) {
525 free(inventory_equipment_options[j]);
526 inventory_equipment_options[j] = NULL;
528 log_msg(ERROR,
"Inventory Mode",
"Failed to allocate memory for inventory equipment options");
534 for (
int i = 0; i < MAX_SLOT; i++) {
535 if (equipment[i] != NULL) {
536 snprintf(inventory_equipment_options[i], MAX_STRING_LENGTH,
537 inventory_mode_strings[INVENTORY_GEAR_FORMAT],
538 equipment[i]->local_key,
540 equipment[i]->defenses.armor,
541 equipment[i]->defenses.magic_resist);
543 snprintf(inventory_equipment_options[i], MAX_STRING_LENGTH,
544 inventory_mode_strings[INVENTORY_GEAR_FORMAT_EMPTY],
557 if (inventory_potion_options != NULL) {
558 for (
int i = 0; i < inventory_potion_count; i++) {
559 if (inventory_potion_options[i] != NULL) {
560 free(inventory_potion_options[i]);
561 inventory_potion_options[i] = NULL;
564 free(inventory_potion_options);
565 inventory_potion_options = NULL;
568 inventory_potion_count = count;
569 inventory_potion_options = (
char**) malloc(count *
sizeof(
char*));
570 RETURN_WHEN_NULL(inventory_potion_options, ,
"Inventory Mode",
"Failed to allocate memory for inventory potion options");
572 for (
int i = 0; i < count; i++) {
573 inventory_potion_options[i] = (
char*) malloc(MAX_STRING_LENGTH *
sizeof(
char));
574 if (inventory_potion_options[i] == NULL) {
575 for (
int j = 0; j < i; j++) {
576 free(inventory_potion_options[j]);
577 inventory_potion_options[j] = NULL;
579 free(inventory_potion_options);
580 inventory_potion_options = NULL;
581 log_msg(ERROR,
"Inventory Mode",
"Failed to allocate memory for inventory potion options");
586 for (
int i = 0; i < count; i++) {
587 snprintf(inventory_potion_options[i], MAX_STRING_LENGTH,
588 inventory_mode_strings[POTION_FORMAT],
589 potion_inventory[i]->name,
591 potion_inventory[i]->value);
597 if (inventory_mode_strings != NULL) {
598 for (
int i = 0; i < MAX_INVENTORY_STRINGS; i++) {
599 if (inventory_mode_strings[i] != NULL) {
600 free(inventory_mode_strings[i]);
603 free(inventory_mode_strings);
606 if (inventory_gear_options != NULL) {
607 for (
int i = 0; i < inventory_gear_count; i++) {
608 if (inventory_gear_options[i] != NULL) {
609 free(inventory_gear_options[i]);
612 free(inventory_gear_options);
615 if (inventory_equipment_options != NULL) {
616 for (
int i = 0; i < MAX_SLOT; i++) {
617 if (inventory_equipment_options[i] != NULL) {
618 free(inventory_equipment_options[i]);
621 free(inventory_equipment_options);
624 if (inventory_potion_options != NULL) {
625 for (
int i = 0; i < inventory_potion_count; i++) {
626 if (inventory_potion_options[i] != NULL) {
627 free(inventory_potion_options[i]);
630 free(inventory_potion_options);
void add_gear(character_t *character, gear_t *gear)
Adds gear to a character's inventory.
void equip_gear(character_t *character, gear_t *gear)
Equips a gear item to a character.
void add_potion(character_t *character, potion_t *potion)
Adds a potion to a character's inventory.
void remove_gear(character_t *character, gear_t *gear)
Removes a gear item from a character's inventory.
void remove_potion(character_t *character, potion_t *potion)
Removes a potion from a character's inventory.
void remove_equipped_gear(character_t *character, gear_slot_t slot)
Removes the gear equipped in a specific slot of a character.
void unequip_gear(character_t *character, const gear_slot_t slot)
Unequips a gear item from a character and adds it to the character's inventory.
Exposes functions for working working with the character.
void invoke_potion_effect(character_t *character, potion_t *potion)
Invoke the effect of a potion on a character.
Defines common macros, types, and global variables for color schemes and utilities.
Declares core game states, global database connection, and main game control functions.
const char * gear_slot_to_string(gear_slot_t slot)
Converts a gear slot enumeration value to its string representation.
Exposes functions for working with gear.
internal_inventory_state_t inventory_menu(character_t *player, character_t *monster)
Displays the main inventory menu.
inventory_result_t start_inventory(character_t *player, character_t *monster)
Starts the inventory mode.
void collect_inventory_equipment_options(gear_t *equipment[])
Checks which options are available in the equipment menu for display.
bool can_equip_gear(character_t *player, gear_t *gear)
Checks if the equipment can be equipped in case it occupies a hands slot.
void collect_inventory_gear_options(gear_t *gear_inventory[], int count)
Checks which options are available in the inventory menu for display.
void shutdown_inventory_mode(void)
Shuts down the inventory mode and frees allocated resources.
void collect_inv_potion_options(potion_t *potion_inventory[], int count)
Checks which options are available in the potion menu for display.
internal_inventory_state_t inventory_equipment_menu(character_t *player, character_t *monster)
Displays the equipment inventory menu.
internal_inventory_state_t inventory_potion_menu(character_t *player, character_t *monster)
Displays the potion inventory menu.
internal_inventory_state_t inventory_gear_menu(character_t *player, character_t *monster)
Displays the gear inventory menu.
int init_inventory_mode()
Initialize the inventory mode.
Exposes functions for working with the inventory mode.
internal_inventory_state_t
Internal states for the inventory mode.
void update_inventory_local(void)
Updates the inventory mode strings with the actual local strings.
Exposes functions for localizing the inventory mode.
void draw_inventory_menu(const vector2d_t anchor, const char *menu_name, const char *header_msg, char **menu_options, const int menu_option_count, const int selected_index, const char *key_msg, const char *tail_msg)
Draws the inventory menu.
vector2d_t draw_inventory_view(const vector2d_t anchor, const character_t *player)
Draws the inventory view UI.
void draw_inventory_log(vector2d_t anchor, const char *inventory_log_message)
Draws the inventory log.
Exposes functions for outputing to the screen while in the inventory mode.
void observe_local(void(*update_func)(void))
Registers an observer function to be notified of updates from the local handler.
Exposes public functions for the localization handler.
void log_msg(const log_level_t level, const char *module, const char *format,...)
Logs a formatted message with a specified log level and module.
const char * potion_type_to_string(potion_type_t type)
Converts a potion type to a string representation.
2-dimensional vector struct