diff --git a/TODO b/TODO index f011b12..670db5c 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,4 @@ Unused enemies: - slime/Attack,Fire - fire_slime/Attack,Fire water_slime chemical_slime albinos_bat @@ -19,3 +17,5 @@ Unused tilesets: crypt heaven machine +Unused animations: + items/upgrade diff --git a/assets-cg/levels/lv1.txt b/assets-cg/levels/lv1.txt index d5afa27..c1513c2 100644 --- a/assets-cg/levels/lv1.txt +++ b/assets-cg/levels/lv1.txt @@ -10,14 +10,16 @@ wave: 9s 3*slime/1 item: armor1 wave: 12s 4*slime/1 wave: 4s 1*bat/2 -wave: 20s 8*slime/1 item: sword1 +wave: 20s 6*slime/1 wave: 8s 2*bat/2 delay: 4s +wave: 10s 4*slime/1 +delay: 4s # "Boss" wave #1 item: potion_hp -wave: 8s 12*slime/1 4*bat/2 +wave: 8s 10*slime/1 3*bat/2 delay: 8s wave: 10s 10*slime/1 diff --git a/src/aoe.c b/src/aoe.c index 7980a0b..7db0f5b 100644 --- a/src/aoe.c +++ b/src/aoe.c @@ -113,8 +113,11 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir) if(type == AOE_HIT || type == AOE_SLASH - || type == AOE_IMPALE - || type == AOE_JUDGEMENT) { + || type == AOE_IMPALE) { + aoe->data.generic.strength = f->ATK; + aoe->data.generic.dir = p->facing; + } + else if(type == AOE_JUDGEMENT) { aoe->data.generic.strength = f->MAG; aoe->data.generic.dir = p->facing; } @@ -265,7 +268,7 @@ void aoe_apply(game_t *game, entity_t *entity, entity_t *e) fighter_t *e_f = getcomp(e, fighter); if(aoe->type == AOE_ITEM && e_f && e_f->player) { - bool picked = item_pick_up(aoe->data.item.type, e); + bool picked = player_give_item(e, aoe->data.item.type); if(picked) aoe->lifetime = 0; /* Don't bother recording the hit since the item will disappear */ diff --git a/src/game.c b/src/game.c index eae8141..397ea6b 100644 --- a/src/game.c +++ b/src/game.c @@ -12,6 +12,7 @@ #include #include #include +#include bool game_load(game_t *g, level_t const *level) { @@ -130,6 +131,8 @@ void game_next_event(game_t *g) for(int i = 0; i < event->wave->entry_count; i++) g->wave_left[i] = event->wave->entries[i].amount; + + game_message(g, fix(2.0), "Wave %d incoming!", g->wave_number); } if(event && event->type == LEVEL_EVENT_ITEM) { int x=-1, y=-1; @@ -157,6 +160,7 @@ void game_next_event(game_t *g) entity_t *item = item_make(event->item, (vec2){ fix(x)+fix(0.5), fix(y)+fix(0.5) }); game_add_entity(g, item); + game_message(g, fix(2.0), "A %s dropped!", item_name(event->item)); } } @@ -169,6 +173,18 @@ void game_shake(game_t *g, int amplitude, fixed_t duration) g->screenshake_amplitude = amplitude; } +void game_message(game_t *g, fixed_t duration, char const *fmt, ...) +{ + static char message[128]; + va_list args; + va_start(args, fmt); + vsnprintf(message, sizeof message, fmt, args); + va_end(args); + + g->message = message; + g->message_time = duration; +} + //--- // Object management functions //--- diff --git a/src/game.h b/src/game.h index 9c4914d..f40a979 100644 --- a/src/game.h +++ b/src/game.h @@ -60,6 +60,10 @@ typedef struct game { /* Cursor within the inventory menu */ int menu_cursor; + /* Current UI message, and how long it stays on (if not overwritten) */ + char const *message; + fixed_t message_time; + } game_t; /* Allocate resources to load a level. */ @@ -83,6 +87,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); +/* Set the current game message */ +void game_message(game_t *g, fixed_t duration, char const *fmt, ...); + //--- // Managing dynamic game elements //--- diff --git a/src/item.c b/src/item.c index 6a41526..25c0caf 100644 --- a/src/item.c +++ b/src/item.c @@ -78,7 +78,7 @@ char const *item_description(int item) else if(item == ITEM_POTION_FRZ) return NULL; else if(item == ITEM_POTION_HP) - return NULL; + return "Restores 50% HP"; else if(item == ITEM_POTION_SPD) return NULL; else if(item == ITEM_SCEPTER1) @@ -117,7 +117,7 @@ entity_t *item_make(int type, vec2 position) return e; } -bool item_pick_up(int type, entity_t *player) +bool item_use(int type, entity_t *player) { fighter_t *f = getcomp(player, fighter); @@ -148,11 +148,6 @@ bool item_pick_up(int type, entity_t *player) /* TODO: Speed +50% for 10 seconds */ } - else if(type > ITEM_EQUIPMENT_START && type < ITEM_EQUIPMENT_END - && f->player) { - return player_give_item(player, type); - } - return false; } diff --git a/src/item.h b/src/item.h index ef0b743..3f7de81 100644 --- a/src/item.h +++ b/src/item.h @@ -44,7 +44,7 @@ char const *item_description(int item); entity_t *item_make(int item, vec2 position); /* Give an item to a player entity. */ -bool item_pick_up(int item, entity_t *player); +bool item_use(int item, 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 3334d2d..86c8fe2 100644 --- a/src/main.c +++ b/src/main.c @@ -106,8 +106,8 @@ int main(void) .xp_level = 0, .xp_to_next_level = 0, .xp_current = 0, -// .inventory = { -1, -1, -1, -1, -1, -1, -1, -1 }, - .inventory = { 1, 2, 3, 5, 101, -1, -1, -1 }, + .inventory = { ITEM_POTION_HP, ITEM_POTION_ATK, -1, -1, + -1, -1, -1, -1 }, .equipment = { -1, -1, -1 }, }; @@ -449,7 +449,7 @@ int main(void) game.menu_cursor = 4 * y + x; } - /* Equipping and unequipping items */ + /* Using and equipping items */ if(!debug.paused && game.menu_open && ev.key == KEY_SHIFT) { int item = player_data.inventory[game.menu_cursor]; int slot = item_equipment_slot(item); @@ -473,6 +473,9 @@ int main(void) player_f->skills[i] = sk[i]; } } + else if(item >= 0 && item_use(item, player)) { + player_data.inventory[game.menu_cursor] = -1; + } } } @@ -619,6 +622,15 @@ int main(void) game.menu_time = max(game.menu_time - 2 * dt_rt, fix(0)); } + /* Reduce message time */ + if(game.message && game.message_time > 0) { + game.message_time -= dt_rt; + if(game.message_time <= 0) { + game.message_time = 0; + game.message = NULL; + } + } + game.time_total += dt; game.event_time += dt; diff --git a/src/render.c b/src/render.c index 098a67c..750cb15 100644 --- a/src/render.c +++ b/src/render.c @@ -43,7 +43,7 @@ void camera_init(camera_t *c, map_t const *m) c->y = (c->limits.y_min + c->limits.y_max) / 2; /* Vertical adjustment to add space for the HUD */ - c->y -= fix(0); + c->y -= fix(2)/16; } ivec2 camera_map2screen(camera_t const *c, vec2 p) @@ -582,6 +582,10 @@ void render_game(game_t const *g, bool show_hitboxes) /* Render wave information */ render_info(0, HEADER_Y, g); + /* Render current message */ + if(g->message) + dtext(8, HEADER_Y + 13, C_RGB(20, 20, 20), g->message); + /* Render HUD */ extern bopti_image_t img_hud; dimage(0, HUD_Y - img_hud.height, &img_hud); diff --git a/src/skills.c b/src/skills.c index a42522d..8872166 100644 --- a/src/skills.c +++ b/src/skills.c @@ -15,7 +15,7 @@ fixed_t skill_cooldown(int skill) else if(skill == AOE_PROJECTILE) return fix(2.0); else if(skill == AOE_SHOCK) - return fix(8.0); + return fix(6.0); else if(skill == AOE_JUDGEMENT) return fix(3.0); else if(skill == AOE_BULLET)