dev: added step_count and health recovery #1
2 changed files with 126 additions and 113 deletions
dev: added step_count and health recovery
Every 15 steps the player will regain 1 HP, unless they are at max HP. Also added commented code for later hunger if this is to be implemented. Played around with step # and 15 seems okay until hunger is implemented
commit
5e3ba209e0
|
|
@ -44,6 +44,7 @@ typedef struct {
|
||||||
int attack;
|
int attack;
|
||||||
int defense;
|
int defense;
|
||||||
int floor;
|
int floor;
|
||||||
|
int step_count;
|
||||||
Item inventory[MAX_INVENTORY];
|
Item inventory[MAX_INVENTORY];
|
||||||
int inventory_count;
|
int inventory_count;
|
||||||
} Player;
|
} Player;
|
||||||
|
|
|
||||||
254
src/player.c
254
src/player.c
|
|
@ -1,142 +1,154 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "combat.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "items.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "combat.h"
|
|
||||||
#include "items.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void player_init(Player* p, int x, int y) {
|
void player_init(Player *p, int x, int y) {
|
||||||
p->x = x;
|
p->x = x;
|
||||||
p->y = y;
|
p->y = y;
|
||||||
p->hp = PLAYER_BASE_HP;
|
p->hp = PLAYER_BASE_HP;
|
||||||
p->max_hp = PLAYER_BASE_HP;
|
p->max_hp = PLAYER_BASE_HP;
|
||||||
p->attack = PLAYER_BASE_ATTACK;
|
p->attack = PLAYER_BASE_ATTACK;
|
||||||
p->defense = 0;
|
p->defense = 0;
|
||||||
p->floor = 1;
|
p->floor = 1;
|
||||||
p->inventory_count = 0;
|
p->step_count = 0;
|
||||||
|
p->inventory_count = 0;
|
||||||
// Initialize inventory to empty
|
|
||||||
for (int i = 0; i < MAX_INVENTORY; i++) {
|
// Initialize inventory to empty
|
||||||
p->inventory[i].picked_up = 1; // mark as invalid
|
for (int i = 0; i < MAX_INVENTORY; i++) {
|
||||||
}
|
p->inventory[i].picked_up = 1; // mark as invalid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position has an enemy
|
// Check if position has an enemy
|
||||||
static Enemy* get_enemy_at(Enemy* enemies, int count, int x, int y) {
|
static Enemy *get_enemy_at(Enemy *enemies, int count, int x, int y) {
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (enemies[i].alive && enemies[i].x == x && enemies[i].y == y) {
|
if (enemies[i].alive && enemies[i].x == x && enemies[i].y == y) {
|
||||||
return &enemies[i];
|
return &enemies[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position has an item
|
// Check if position has an item
|
||||||
static Item* get_item_at(Item* items, int count, int x, int y) {
|
static Item *get_item_at(Item *items, int count, int x, int y) {
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (!items[i].picked_up && items[i].x == x && items[i].y == y) {
|
if (!items[i].picked_up && items[i].x == x && items[i].y == y) {
|
||||||
return &items[i];
|
return &items[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int player_move(Player* p, int dx, int dy, Map* map, Enemy* enemies, int enemy_count, Item* items, int item_count) {
|
int player_move(Player *p, int dx, int dy, Map *map, Enemy *enemies,
|
||||||
int new_x = p->x + dx;
|
int enemy_count, Item *items, int item_count) {
|
||||||
int new_y = p->y + dy;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for enemy at target position
|
|
||||||
Enemy* enemy = get_enemy_at(enemies, enemy_count, new_x, new_y);
|
|
||||||
if (enemy != NULL) {
|
|
||||||
// Attack the enemy
|
|
||||||
player_attack(p, enemy);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for item at target position
|
|
||||||
Item* item = get_item_at(items, item_count, new_x, new_y);
|
|
||||||
if (item != NULL) {
|
|
||||||
// Pick up the item
|
|
||||||
player_pickup(p, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move player
|
|
||||||
p->x = new_x;
|
|
||||||
p->y = new_y;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void player_attack(Player* p, Enemy* e) {
|
// Check bounds
|
||||||
// Use combat system
|
if (!in_bounds(new_x, new_y, MAP_WIDTH, MAP_HEIGHT)) {
|
||||||
combat_player_attack(p, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void player_pickup(Player* p, Item* i) {
|
|
||||||
if (p->inventory_count >= MAX_INVENTORY) {
|
|
||||||
return; // inventory full
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i->picked_up) {
|
|
||||||
return; // already picked up
|
|
||||||
}
|
|
||||||
|
|
||||||
i->picked_up = 1;
|
|
||||||
p->inventory[p->inventory_count] = *i; // copy item to inventory
|
|
||||||
p->inventory_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void player_use_item(Player* p, Item* i) {
|
|
||||||
if (p == NULL || i == NULL) return;
|
|
||||||
if (i->picked_up) return; // invalid item
|
|
||||||
|
|
||||||
// Apply item effect
|
|
||||||
item_use(p, i);
|
|
||||||
|
|
||||||
// Mark item as used (remove from inventory)
|
|
||||||
i->picked_up = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int player_use_first_item(Player* p) {
|
|
||||||
if (p == NULL || p->inventory_count == 0) return 0;
|
|
||||||
|
|
||||||
// Find first valid item in inventory
|
|
||||||
for (int i = 0; i < MAX_INVENTORY; i++) {
|
|
||||||
if (!p->inventory[i].picked_up) {
|
|
||||||
Item* item = &p->inventory[i];
|
|
||||||
|
|
||||||
// Apply item effect
|
|
||||||
item_use(p, item);
|
|
||||||
|
|
||||||
// Remove from inventory (shift remaining items)
|
|
||||||
for (int j = i; j < MAX_INVENTORY - 1; j++) {
|
|
||||||
p->inventory[j] = p->inventory[j + 1];
|
|
||||||
}
|
|
||||||
p->inventory_count--;
|
|
||||||
|
|
||||||
// Mark last slot as invalid
|
|
||||||
p->inventory[MAX_INVENTORY - 1].picked_up = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if walkable
|
||||||
|
if (!is_floor(map, new_x, new_y)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for enemy at target position
|
||||||
|
Enemy *enemy = get_enemy_at(enemies, enemy_count, new_x, new_y);
|
||||||
|
if (enemy != NULL) {
|
||||||
|
// Attack the enemy
|
||||||
|
player_attack(p, enemy);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for item at target position
|
||||||
|
Item *item = get_item_at(items, item_count, new_x, new_y);
|
||||||
|
if (item != NULL) {
|
||||||
|
// Pick up the item
|
||||||
|
player_pickup(p, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move player
|
||||||
|
p->x = new_x;
|
||||||
|
p->y = new_y;
|
||||||
|
p->step_count += 1;
|
||||||
|
if (p->step_count % 15 == 0 && p->hp < p->max_hp) {
|
||||||
|
p->hp += 1;
|
||||||
|
// p->hunger -= 0.1; ??
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item* player_get_inventory_item(Player* p, int index) {
|
void player_attack(Player *p, Enemy *e) {
|
||||||
if (p == NULL) return NULL;
|
// Use combat system
|
||||||
if (index < 0 || index >= MAX_INVENTORY) return NULL;
|
combat_player_attack(p, e);
|
||||||
if (p->inventory[index].picked_up) return NULL; // invalid/empty
|
}
|
||||||
return &p->inventory[index];
|
|
||||||
|
void player_pickup(Player *p, Item *i) {
|
||||||
|
if (p->inventory_count >= MAX_INVENTORY) {
|
||||||
|
return; // inventory full
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i->picked_up) {
|
||||||
|
return; // already picked up
|
||||||
|
}
|
||||||
|
|
||||||
|
i->picked_up = 1;
|
||||||
|
p->inventory[p->inventory_count] = *i; // copy item to inventory
|
||||||
|
p->inventory_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void player_use_item(Player *p, Item *i) {
|
||||||
|
if (p == NULL || i == NULL)
|
||||||
|
return;
|
||||||
|
if (i->picked_up)
|
||||||
|
return; // invalid item
|
||||||
|
|
||||||
|
// Apply item effect
|
||||||
|
item_use(p, i);
|
||||||
|
|
||||||
|
// Mark item as used (remove from inventory)
|
||||||
|
i->picked_up = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int player_use_first_item(Player *p) {
|
||||||
|
if (p == NULL || p->inventory_count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Find first valid item in inventory
|
||||||
|
for (int i = 0; i < MAX_INVENTORY; i++) {
|
||||||
|
if (!p->inventory[i].picked_up) {
|
||||||
|
Item *item = &p->inventory[i];
|
||||||
|
|
||||||
|
// Apply item effect
|
||||||
|
item_use(p, item);
|
||||||
|
|
||||||
|
// Remove from inventory (shift remaining items)
|
||||||
|
for (int j = i; j < MAX_INVENTORY - 1; j++) {
|
||||||
|
p->inventory[j] = p->inventory[j + 1];
|
||||||
|
}
|
||||||
|
p->inventory_count--;
|
||||||
|
|
||||||
|
// Mark last slot as invalid
|
||||||
|
p->inventory[MAX_INVENTORY - 1].picked_up = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue