#include "player.h" #include "combat.h" #include "common.h" #include "items.h" #include "map.h" #include "settings.h" #include "utils.h" #include #include void player_init(Player *p, int x, int y) { p->x = x; p->y = y; p->hp = PLAYER_BASE_HP; p->max_hp = PLAYER_BASE_HP; p->attack = PLAYER_BASE_ATTACK; p->defense = 0; p->floor = 1; p->step_count = 0; p->speed = 100; p->cooldown = 0; p->dodge = PLAYER_BASE_DODGE; p->block = PLAYER_BASE_BLOCK; p->has_weapon = 0; p->has_armor = 0; memset(&p->equipped_weapon, 0, sizeof(Item)); memset(&p->equipped_armor, 0, sizeof(Item)); p->equipped_weapon.picked_up = 1; p->equipped_armor.picked_up = 1; // mark as invalid p->inventory_count = 0; p->effect_count = 0; memset(p->effects, 0, sizeof(p->effects)); // Initialize inventory to empty for (int i = 0; i < MAX_INVENTORY; i++) { p->inventory[i].picked_up = 1; // mark as invalid } } Enemy *player_find_enemy_at(Enemy *enemies, int count, int x, int y) { if (enemies == NULL || count <= 0) return NULL; if (count > MAX_ENEMIES) count = MAX_ENEMIES; for (int i = 0; i < count; i++) { if (enemies[i].alive && enemies[i].x == x && enemies[i].y == y) return &enemies[i]; } return NULL; } int player_move(Player *p, int dx, int dy, Map *map) { int new_x = p->x + dx; int new_y = p->y + dy; // Check bounds if (!in_bounds(new_x, new_y, MAP_WIDTH, MAP_HEIGHT)) return 0; // Check if walkable if (!is_floor(map, new_x, new_y)) return 0; // Move player p->x = new_x; p->y = new_y; p->step_count += 1; // Regen suppressed while poisoned, bleeding, or burning if (p->step_count % REGEN_STEP_INTERVAL == 0 && p->hp < p->max_hp && !combat_has_effect(p->effects, p->effect_count, EFFECT_POISON) && !combat_has_effect(p->effects, p->effect_count, EFFECT_BLEED) && !combat_has_effect(p->effects, p->effect_count, EFFECT_BURN)) { p->hp += 1; } return 1; } void player_attack(Player *p, Enemy *e) { // Use combat system combat_player_attack(p, e); } // Get item at player's current position (for pickup) Item *get_item_at_floor(Item *items, int count, int x, int y) { for (int i = 0; i < count; i++) { if (!items[i].picked_up && items[i].x == x && items[i].y == y) { return &items[i]; } } return NULL; } int player_pickup(Player *p, Item *i) { if (p->inventory_count >= MAX_INVENTORY) { return 0; } if (i->picked_up) { return 0; } p->inventory[p->inventory_count] = *i; p->inventory_count++; i->picked_up = 1; return 1; } void player_use_item(Player *p, Item *i) { if (p == NULL || i == NULL) return; if (i->picked_up) return; // invalid item // Apply item effect (only potions are consumed) if (i->type == ITEM_POTION) { item_use(p, i); } // Weapons and armor are equipped, not consumed } int player_use_first_item(Player *p) { if (p == NULL || p->inventory_count == 0) return 0; // Find first valid item in inventory (skip weapons/armor - must equip explicitly) for (int i = 0; i < MAX_INVENTORY; i++) { if (!p->inventory[i].picked_up) { Item *item = &p->inventory[i]; if (item->type == ITEM_POTION) { // Apply item effect item_use(p, item); // Remove from inventory (shift remaining items) player_remove_inventory_item(p, i); return 1; } // Weapons/armor can't be used this way - must equip } } return 0; } Item *player_get_inventory_item(Player *p, int index) { if (p == NULL) return NULL; if (index < 0 || index >= MAX_INVENTORY) return NULL; if (p->inventory[index].picked_up) return NULL; // invalid/empty return &p->inventory[index]; } void player_remove_inventory_item(Player *p, int index) { if (p == NULL) return; if (index < 0 || index >= MAX_INVENTORY) return; if (p->inventory[index].picked_up) return; // Shift remaining items for (int j = index; j < MAX_INVENTORY - 1; j++) { p->inventory[j] = p->inventory[j + 1]; } p->inventory_count--; p->inventory[MAX_INVENTORY - 1].picked_up = 1; } int player_equip_item(Player *p, int inv_index) { if (p == NULL) return 0; if (inv_index < 0 || inv_index >= MAX_INVENTORY) return 0; Item *item = player_get_inventory_item(p, inv_index); if (item == NULL) return 0; if (item->type == ITEM_WEAPON) { // Unequip current weapon first if (p->has_weapon) { p->attack -= p->equipped_weapon.power; } // Equip new weapon p->equipped_weapon = *item; p->has_weapon = 1; p->attack += item->power; // Remove from inventory player_remove_inventory_item(p, inv_index); return 1; } if (item->type == ITEM_ARMOR) { // Unequip current armor first if (p->has_armor) { p->defense -= p->equipped_armor.power; p->block -= p->equipped_armor.power / 2; if (p->block < PLAYER_BASE_BLOCK) p->block = PLAYER_BASE_BLOCK; } // Equip new armor p->equipped_armor = *item; p->has_armor = 1; p->defense += item->power; p->block += item->power / 2; // armor grants block bonus // Remove from inventory player_remove_inventory_item(p, inv_index); return 1; } return 0; // not equippable (potion) } int player_drop_item(Player *p, int inv_index, Item *items, int item_count) { if (p == NULL) return 0; if (inv_index < 0 || inv_index >= MAX_INVENTORY) return 0; Item *item = player_get_inventory_item(p, inv_index); if (item == NULL) return 0; // Find an empty slot in items array to place the dropped item for (int i = 0; i < item_count; i++) { if (items[i].picked_up) { // Place dropped item at this position items[i] = *item; items[i].x = p->x; items[i].y = p->y; items[i].picked_up = 0; // Remove from inventory player_remove_inventory_item(p, inv_index); return 1; } } return 0; // no room to drop }