implement time freezing potion

This commit is contained in:
Lephenixnoir 2023-01-23 21:56:55 +01:00
parent 7f91989ec3
commit dd632b6b11
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
6 changed files with 57 additions and 17 deletions

View File

@ -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];

View File

@ -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, ...);

View File

@ -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);

View File

@ -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);

View File

@ -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))

View File

@ -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;