combat: rewrite in Zig; add basic damage types and weapon archetypes
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ic8055a1cf6bdad1aca13673ea171b4b46a6a6964
This commit is contained in:
parent
7af642612b
commit
22ab6fc6eb
15 changed files with 802 additions and 158 deletions
79
src/main.c
79
src/main.c
|
|
@ -25,14 +25,26 @@ static void add_log(GameState *gs, const char *msg) {
|
|||
|
||||
// spawn floating damage text
|
||||
static void spawn_floating_text(GameState *gs, int x, int y, int value, int is_critical) {
|
||||
// Reuse an expired slot if all slots are taken
|
||||
int slot = -1;
|
||||
if (gs->floating_count < 8) {
|
||||
gs->floating_texts[gs->floating_count].x = x;
|
||||
gs->floating_texts[gs->floating_count].y = y;
|
||||
gs->floating_texts[gs->floating_count].value = value;
|
||||
gs->floating_texts[gs->floating_count].lifetime = 60;
|
||||
gs->floating_texts[gs->floating_count].is_critical = is_critical;
|
||||
slot = gs->floating_count;
|
||||
gs->floating_count++;
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (gs->floating_texts[i].lifetime <= 0) {
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (slot < 0)
|
||||
return;
|
||||
gs->floating_texts[slot].x = x;
|
||||
gs->floating_texts[slot].y = y;
|
||||
gs->floating_texts[slot].value = value;
|
||||
gs->floating_texts[slot].lifetime = 60;
|
||||
gs->floating_texts[slot].is_critical = is_critical;
|
||||
}
|
||||
|
||||
// update floating texts and screen shake
|
||||
|
|
@ -87,6 +99,37 @@ static void init_floor(GameState *gs, int floor_num) {
|
|||
gs->turn_count = 0;
|
||||
}
|
||||
|
||||
// Tick all status effects at the start of a turn
|
||||
static void tick_all_effects(GameState *gs) {
|
||||
// Player effects
|
||||
int player_effect_dmg = combat_tick_effects(&gs->player);
|
||||
if (player_effect_dmg > 0) {
|
||||
spawn_floating_text(gs, gs->player.x * TILE_SIZE + 8, gs->player.y * TILE_SIZE, player_effect_dmg, 0);
|
||||
gs->screen_shake = 4;
|
||||
}
|
||||
|
||||
// Check if player died from effects
|
||||
if (gs->player.hp <= 0) {
|
||||
gs->player.hp = 0;
|
||||
gs->game_over = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Enemy effects
|
||||
for (int i = 0; i < gs->enemy_count; i++) {
|
||||
Enemy *e = &gs->enemies[i];
|
||||
if (!e->alive)
|
||||
continue;
|
||||
int enemy_effect_dmg = combat_tick_enemy_effects(e);
|
||||
if (enemy_effect_dmg > 0) {
|
||||
spawn_floating_text(gs, e->x * TILE_SIZE + 8, e->y * TILE_SIZE, enemy_effect_dmg, 0);
|
||||
}
|
||||
if (!e->alive) {
|
||||
add_log(gs, "Enemy died from effects!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle player input - returns: 0=continue, 1=acted, -1=quit
|
||||
static int handle_input(GameState *gs) {
|
||||
int dx = 0, dy = 0;
|
||||
|
|
@ -103,6 +146,25 @@ static int handle_input(GameState *gs) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// If player is stunned, wait for any key then consume the turn
|
||||
if (combat_has_effect(gs->player.effects, gs->player.effect_count, EFFECT_STUN)) {
|
||||
if (!(IsKeyDown(KEY_W) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_A) ||
|
||||
IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT)))
|
||||
return 0;
|
||||
gs->turn_count++;
|
||||
tick_all_effects(gs);
|
||||
if (gs->game_over)
|
||||
return 1;
|
||||
enemy_update_all(gs->enemies, gs->enemy_count, &gs->player, &gs->map);
|
||||
if (gs->player.hp <= 0) {
|
||||
gs->game_over = 1;
|
||||
}
|
||||
gs->last_message = "You are stunned!";
|
||||
gs->message_timer = 60;
|
||||
add_log(gs, "Stunned! Lost a turn.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gs->show_inventory) {
|
||||
if (IsKeyPressed(KEY_I) || IsKeyPressed(KEY_ESCAPE)) {
|
||||
gs->show_inventory = 0;
|
||||
|
|
@ -298,6 +360,11 @@ static int handle_input(GameState *gs) {
|
|||
// Increment turn counter
|
||||
gs->turn_count++;
|
||||
|
||||
// Tick status effects at the start of this turn
|
||||
tick_all_effects(gs);
|
||||
if (gs->game_over)
|
||||
return 1;
|
||||
|
||||
// Check if stepped on stairs
|
||||
if (gs->map.tiles[gs->player.y][gs->player.x] == TILE_STAIRS) {
|
||||
gs->awaiting_descend = 1;
|
||||
|
|
@ -358,6 +425,8 @@ static void game_loop(void) {
|
|||
while (!WindowShouldClose()) {
|
||||
// Handle input
|
||||
if (!gs.game_over) {
|
||||
// Tick status effects at the start of each frame where input is checked
|
||||
// (effects tick once per player action via the acted flag below)
|
||||
int quit = handle_input(&gs);
|
||||
if (quit == -1)
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue