From dd632b6b11bc0c96845a400d9d55572f4dc0aeb7 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Mon, 23 Jan 2023 21:56:55 +0100 Subject: [PATCH] implement time freezing potion --- src/game.c | 6 ++++++ src/game.h | 6 ++++++ src/item.c | 12 ++++++++---- src/item.h | 4 +++- src/main.c | 17 +++++++++++++---- src/render.c | 29 +++++++++++++++++++++-------- 6 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/game.c b/src/game.c index c5b2b04..ae7add9 100644 --- a/src/game.c +++ b/src/game.c @@ -37,6 +37,7 @@ bool game_load(game_t *g, level_t const *level) g->level = level; g->event = -1; g->event_time = fix(0); + g->freeze_time = fix(0); g->wave_number = 0; g->wave_spawned = 0; g->wave_left = NULL; @@ -187,6 +188,11 @@ void game_shake(game_t *g, int amplitude, fixed_t duration) g->screenshake_amplitude = amplitude; } +void game_freeze(game_t *g, fixed_t duration) +{ + g->freeze_time = max(g->freeze_time, duration); +} + void game_message(game_t *g, fixed_t duration, char const *fmt, ...) { static char message[128]; diff --git a/src/game.h b/src/game.h index 8ebe678..c0204ac 100644 --- a/src/game.h +++ b/src/game.h @@ -66,6 +66,8 @@ typedef struct game { /* Current event, time spent in event */ int event; fixed_t event_time; + /* Current freeze time left */ + fixed_t freeze_time; /* Number of waves encountered so far; if current event is a wave, number of enemies spawned so far and enemies left to spawn */ int wave_number; @@ -89,6 +91,7 @@ typedef struct game { bool menu_open; /* Cursor within the inventory menu */ int menu_cursor; + /* Time when the game was finished (0 while playing) */ fixed_t finish_time; /* Whether the game was won (valid when finish_time > 0) */ @@ -125,6 +128,9 @@ void game_next_event(game_t *g); /* Shake the screen for the specified amount of time */ void game_shake(game_t *g, int amplitude, fixed_t duration); +/* Freeze enemies and waves for the specified time */ +void game_freeze(game_t *g, fixed_t duration); + /* Set the current game message */ void game_message(game_t *g, fixed_t duration, char const *fmt, ...); diff --git a/src/item.c b/src/item.c index 5e9c960..95d9d7a 100644 --- a/src/item.c +++ b/src/item.c @@ -95,7 +95,7 @@ char const *item_description(int item) else if(item == ITEM_POTION_DEF) return NULL; else if(item == ITEM_POTION_FRZ) - return NULL; + return "Freezes time\nfor 5 sec."; else if(item == ITEM_POTION_HP) return "Restores 50% HP"; else if(item == ITEM_POTION_SPD) @@ -136,7 +136,7 @@ entity_t *item_make(int type, vec2 position) return e; } -bool item_use(int type, entity_t *player) +bool item_use(int type, game_t *game, entity_t *player) { fighter_t *f = getcomp(player, fighter); @@ -150,13 +150,17 @@ bool item_use(int type, entity_t *player) /* TODO: Double attack for 10 seconds */ } else if(type == ITEM_POTION_COOLDOWN && f) { - /* TODO: Restore all cooldowns */ + for(int i = 0; i < 6; i++) { + f->actions_cooldown[i] = 0; + } + return true; } else if(type == ITEM_POTION_DEF && f) { /* TODO: Defense +50% for 10 seconds */ } else if(type == ITEM_POTION_FRZ && f) { - /* TODO: Freeze all monsters for 5 seconds */ + game_freeze(game, fix(5.0)); + return true; } else if(type == ITEM_POTION_HP && f) { int restored = min(max(f->HP_max / 2, 8), f->HP_max - f->HP); diff --git a/src/item.h b/src/item.h index a1c0e8c..ce15b2f 100644 --- a/src/item.h +++ b/src/item.h @@ -9,6 +9,8 @@ #include "geometry.h" #include "anim.h" +struct game; + enum { ITEM_LIFE = 0, ITEM_POTION_ATK = 1, @@ -47,7 +49,7 @@ char const *item_description(int item); entity_t *item_make(int item, vec2 position); /* Give an item to a player entity. */ -bool item_use(int item, entity_t *player); +bool item_use(int item, struct game *game, entity_t *player); /* Which equipment slot an item goes in. */ int item_equipment_slot(int item); diff --git a/src/main.c b/src/main.c index 63f2aef..b80a636 100644 --- a/src/main.c +++ b/src/main.c @@ -94,7 +94,7 @@ static int menu_select_play_repeat(void) .xp_level = 0, .xp_to_next_level = 0, .xp_current = 0, - .inventory = { ITEM_POTION_HP, ITEM_POTION_ATK, -1, -1, + .inventory = { ITEM_POTION_HP, ITEM_POTION_FRZ, -1, -1, -1, -1, -1, -1 }, .equipment = { -1, -1, -1 }, }; @@ -492,7 +492,7 @@ static int menu_select_play_repeat(void) player_f->skills[i] = sk[i]; } } - else if(item >= 0 && item_use(item, player)) { + else if(item >= 0 && item_use(item, &game, player)) { player_data.inventory[game.menu_cursor] = -1; int color = item_buff_color(item); @@ -565,7 +565,7 @@ static int menu_select_play_repeat(void) vec_f2i(physical_pos(player)), game.occupation); /* Enemy AI */ - if(player_f->HP > 0) + if(player_f->HP > 0 && game.freeze_time == 0) for(int i = 0; i < game.entity_count; i++) { entity_t *e = game.entities[i]; fighter_t *f = getcomp(e, fighter); @@ -672,7 +672,16 @@ static int menu_select_play_repeat(void) } game.time_total += dt; - game.event_time += dt; + if(game.freeze_time >= 0) { + game.freeze_time -= dt; + if(game.freeze_time < 0) { + game.event_time += -game.freeze_time; + game.freeze_time = 0; + } + } + else { + game.event_time += dt; + } /* Next wave */ if(player_f->HP > 0 && game_current_event_finished(&game)) diff --git a/src/render.c b/src/render.c index 5f20222..be5a85e 100644 --- a/src/render.c +++ b/src/render.c @@ -370,18 +370,31 @@ static void render_info(int x, int y, game_t const *g) if(!g->level) return; - int intro_w; + /* Determine maximum length of message that can be rendered */ + int intro_w, frozen_w; char str[32]; snprintf(str, 32, "Wave %d", level_wave_count(g->level)); dsize(str, NULL, &intro_w, NULL); - snprintf(str, 32, "Wave %d", g->wave_number); + dsize("Frozen", NULL, &frozen_w, NULL); + intro_w = max(intro_w, frozen_w); - int wave_color_r = fround(g->hud_wave_number_timer * 31); - if(g->hud_wave_number_timer) { - dtext(x+8, y-2, C_RGB(wave_color_r, 0, 0), str); - dtext(x+8, y, C_RGB(wave_color_r, 0, 0), str); - dtext(x+7, y-1, C_RGB(wave_color_r, 0, 0), str); - dtext(x+9, y-1, C_RGB(wave_color_r, 0, 0), str); + int overlay_color = -1; + + if(g->freeze_time > 0) { + strcpy(str, "Frozen"); + overlay_color = 0x5555; + } + else { + snprintf(str, 32, "Wave %d", g->wave_number); + if(g->hud_wave_number_timer) + overlay_color = C_RGB(fround(g->hud_wave_number_timer * 31), 0, 0); + } + + if(overlay_color >= 0) { + dtext(x+8, y-2, overlay_color, str); + dtext(x+8, y, overlay_color, str); + dtext(x+7, y-1, overlay_color, str); + dtext(x+9, y-1, overlay_color, str); } dtext(x+8, y-1, C_WHITE, str); x += intro_w + 20;