From cb732a80ec5da1daa86e23458388d19da10b5eff Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Mon, 10 Sep 2018 22:27:26 +0200 Subject: [PATCH] Adds possibility to push monsters into pits and traps. --- .vimrc | 2 +- data/maproombuilder.lua | 2 +- src/monster.c | 76 ++++++++++++++++++++++++++++++++++------- src/monster.h | 2 +- src/player.c | 43 +++++++++++------------ src/player.h | 2 +- src/position.c | 2 +- src/position.h | 2 +- src/roommatrix.c | 7 ++++ src/roommatrix.h | 27 ++++++++++----- src/sprite.c | 31 +++++++++++++++++ src/sprite.h | 12 +++++++ 12 files changed, 158 insertions(+), 50 deletions(-) diff --git a/.vimrc b/.vimrc index ebf83fd..d78c658 100644 --- a/.vimrc +++ b/.vimrc @@ -1,7 +1,7 @@ nnoremap :Make nnoremap :Make lint test nnoremap :Termdebug _build/breakhack -nnoremap :ter ++close ./_build/breakhack +nnoremap :ter ++close env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/breakhack packadd termdebug let g:termdebug_wide = 1 diff --git a/data/maproombuilder.lua b/data/maproombuilder.lua index 6fab5b4..9eae44a 100644 --- a/data/maproombuilder.lua +++ b/data/maproombuilder.lua @@ -156,7 +156,7 @@ end local function add_pits_to_room(room) - if CURRENT_LEVEL < 3 then + if CURRENT_LEVEL < 1 then return elseif random(5) ~= 1 then return diff --git a/src/monster.c b/src/monster.c index 8334857..7926613 100644 --- a/src/monster.c +++ b/src/monster.c @@ -33,6 +33,8 @@ #include "update_data.h" #include "actiontextbuilder.h" #include "texturecache.h" +#include "trap.h" +#include "object.h" static void monster_set_sprite_clip_for_current_state(Monster *m) @@ -278,8 +280,7 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction) if (!position_in_room(&monster->sprite->pos, &matrix->roomPos)) return true; - Position roomPos = position_to_matrix_coords(&monster->sprite->pos); - RoomSpace *space = &matrix->spaces[roomPos.x][roomPos.y]; + RoomSpace *space = roommatrix_get_space_for(matrix, &monster->sprite->pos); if (space->player && monster->state.current == AGRESSIVE) { unsigned int dmg = stats_fight(&monster->stats, @@ -297,7 +298,7 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction) monster_behaviour_check_post_attack(monster); } - return space->occupied || space->lethal || space->trap || space->damaging; + return space->occupied; } static bool @@ -305,7 +306,9 @@ move(Monster *m, RoomMatrix *rm, Vector2d direction) { m->sprite->pos.x += TILE_DIMENSION * (int) direction.x; m->sprite->pos.y += TILE_DIMENSION * (int) direction.y; - if (has_collided(m, rm, direction)) { + + RoomSpace *space = roommatrix_get_space_for(rm, &m->sprite->pos); + if (has_collided(m, rm, direction) || space->lethal || space->trap || space->damaging) { m->sprite->pos.x -= TILE_DIMENSION * (int) direction.x; m->sprite->pos.y -= TILE_DIMENSION * (int) direction.y; return false; @@ -439,6 +442,9 @@ monster_coward_walk(Monster *m, RoomMatrix *rm) bool monster_move(Monster *m, RoomMatrix *rm, Map *map) { + if (m->stats.hp <= 0 || m->sprite->state == SPRITE_STATE_FALLING) + return true; + if (m->state.forceCount) { if (m->state.stepsSinceChange >= m->state.forceCount) { monster_state_change(m, m->state.last); @@ -545,6 +551,17 @@ monster_reset_steps(Monster *m) void monster_update(Monster *m, UpdateData *data) { + if (m->stats.hp <= 0) + return; + + sprite_update(m->sprite, data); + + if (m->sprite->state == SPRITE_STATE_FALLING && m->sprite->dim.width < 4) { + m->stats.hp = 0; + player_monster_kill_check(data->player, m); + return; + } + Position monsterRoomPos = position_to_room_coords(&m->sprite->pos); if (position_equals(&data->matrix->roomPos, &monsterRoomPos) && !m->stateIndicator.shownOnPlayerRoomEnter) @@ -608,23 +625,30 @@ monster_drop_loot(Monster *monster, Map *map, Player *player) static unsigned int treasure_drop_chance = 1; unsigned int item_drop_chance = 1; + if (monster->sprite->state == SPRITE_STATE_FALLING) + return; + Item *item; Item *items[3]; unsigned int item_count = 0; bool player_full_health = player->stats.hp >= player->stats.maxhp; + Position monsterTilePos = monster->sprite->pos; + monsterTilePos.x -= (monsterTilePos.x % TILE_DIMENSION); + monsterTilePos.y -= (monsterTilePos.y % TILE_DIMENSION); + if (monster->boss) { Artifact *a = artifact_create_random(player, 2); - a->sprite->pos = monster->sprite->pos; + a->sprite->pos = monsterTilePos; linkedlist_append(&map->artifacts, a); Item *treasure = item_builder_build_item(TREASURE, map->level*2); - treasure->sprite->pos = monster->sprite->pos; + treasure->sprite->pos = monsterTilePos; linkedlist_append(&map->items, treasure); } if (monster->stats.lvl > 2 && get_random(29) == 0) { Artifact *a = artifact_create_random(player, 1); - a->sprite->pos = monster->sprite->pos; + a->sprite->pos = monsterTilePos; linkedlist_append(&map->artifacts, a); } @@ -633,19 +657,19 @@ monster_drop_loot(Monster *monster, Map *map, Player *player) if (get_random(treasure_drop_chance) == 0) { item = item_builder_build_item(TREASURE, map->level); - item->sprite->pos = monster->sprite->pos; + item->sprite->pos = monsterTilePos; items[item_count++] = item; } if (get_random(item_drop_chance) == 0) { ItemKey key; key = get_random(DAGGER); item = item_builder_build_item(key, map->level); - item->sprite->pos = monster->sprite->pos; + item->sprite->pos = monsterTilePos; items[item_count++] = item; } if (!player_full_health && get_random(2) == 0) { item = item_builder_build_item(FLESH, map->level); - item->sprite->pos = monster->sprite->pos; + item->sprite->pos = monsterTilePos; items[item_count++] = item; } @@ -658,7 +682,7 @@ monster_drop_loot(Monster *monster, Map *map, Player *player) linkedlist_append(&map->items, items[0]); } else { Item *container = item_builder_build_sack(); - container->sprite->pos = monster->sprite->pos; + container->sprite->pos = monsterTilePos; unsigned int i; for (i = 0; i < item_count; ++i) { linkedlist_append(&container->items, items[i]); @@ -733,9 +757,35 @@ monster_set_state(Monster *m, StateType state, Uint8 forceCount) } void -monster_push(Monster *m, RoomMatrix *rm, Vector2d dir) +monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction) { - move(m, rm, dir); + m->sprite->pos.x += TILE_DIMENSION * (int) direction.x; + m->sprite->pos.y += TILE_DIMENSION * (int) direction.y; + + RoomSpace *space = roommatrix_get_space_for(rm, &m->sprite->pos); + if (space->lethal) { + m->sprite->state = SPRITE_STATE_FALLING; + } else if (space->trap) { + m->stats.hp -= space->trap->damage; + monster_hit(m, space->trap->damage); + gui_log("%s takes %d damage from a trap", m->label, space->trap->damage); + } else if (space->damaging) { + LinkedList *objects = space->objects; + while (objects) { + Object *o = objects->data; + objects = objects->next; + if (!o->damage) + return; + m->stats.hp -= o->damage; + monster_hit(m, o->damage); + } + } else if (has_collided(m, rm, direction)) { + m->sprite->pos.x -= TILE_DIMENSION * (int) direction.x; + m->sprite->pos.y -= TILE_DIMENSION * (int) direction.y; + } + + monster_update_pos(m, m->sprite->pos); + player_monster_kill_check(p, m); } void diff --git a/src/monster.h b/src/monster.h index 5faf665..acdbc83 100644 --- a/src/monster.h +++ b/src/monster.h @@ -108,7 +108,7 @@ void monster_set_state(Monster *m, StateType state, Uint8 forceCount); void -monster_push(Monster *, RoomMatrix*, Vector2d dir); +monster_push(Monster *, Player *, RoomMatrix*, Vector2d dir); void monster_reset_steps(Monster *m); diff --git a/src/player.c b/src/player.c index 75a11b1..7495db5 100644 --- a/src/player.c +++ b/src/player.c @@ -133,7 +133,7 @@ on_monster_collision(Player *player, if (get_random(10) < player_has_artifact(player, PUSH_BACK)) { gui_log("The force of your blow sends %s reeling", monster->lclabel); - monster_push(monster, matrix, direction); + monster_push(monster, player, matrix, direction); } if (get_random(10) < player_has_artifact(player, FEAR_INDUCING)) { @@ -163,12 +163,22 @@ has_collided(Player *player, RoomMatrix *matrix, Vector2d direction) RoomSpace *space = &matrix->spaces[matrixPos.x][matrixPos.y]; collided = space->occupied; + if (space->monster != NULL + && (space->monster->sprite->state == SPRITE_STATE_FALLING + || space->monster->stats.hp <= 0)) + { + collided = false; + } + if (collided) { player->sprite->pos.x -= TILE_DIMENSION * (int)direction.x; player->sprite->pos.y -= TILE_DIMENSION * (int)direction.y; } - if (space->monster != NULL) { + if (space->monster != NULL + && space->monster->stats.hp > 0 + && space->monster->sprite->state != SPRITE_STATE_FALLING) + { on_monster_collision(player, space->monster, matrix, direction); } else if (collided) { mixer_play_effect(BONK); @@ -595,29 +605,16 @@ void player_update(UpdateData *data) if (player->stats.hp <= 0) return; + sprite_update(player->sprite, data); + check_skill_activation(data); - if (player->state != FALLING && !check_skill_trigger(data)) + if (player->sprite->state != SPRITE_STATE_FALLING && !check_skill_trigger(data)) handle_next_move(data); - if (player->state == FALLING && player->stats.hp > 0) { - if (!timer_started(player->animationTimer)) { - timer_start(player->animationTimer); - player->sprite->clip = CLIP16(0, 0); - } else { - if (timer_get_ticks(player->animationTimer) > 100) { - timer_start(player->animationTimer); - player->sprite->angle += 60; - player->sprite->dim.width -= 4; - player->sprite->dim.height -= 4; - player->sprite->pos.x += 2; - player->sprite->pos.y += 2; - player->sprite->rotationPoint = (SDL_Point) { - player->sprite->dim.width /2, - player->sprite->dim.height /2 - }; - if (player->sprite->dim.width <= 4) - player->stats.hp = 0; - } + if (player->sprite->state == SPRITE_STATE_FALLING && player->stats.hp > 0) { + if (player->sprite->dim.width <= 4) { + player->stats.hp = 0; + player->sprite->state = SPRITE_STATE_DEFAULT; } } @@ -705,5 +702,5 @@ void player_set_falling(Player *player) { mixer_play_effect(FALL0 + get_random(1)); - player->state = FALLING; + player->sprite->state = SPRITE_STATE_FALLING; } diff --git a/src/player.h b/src/player.h index d3a9765..8e0f4a8 100644 --- a/src/player.h +++ b/src/player.h @@ -34,7 +34,7 @@ typedef struct UpdateData UpdateData; typedef struct Animation Animation; typedef enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR } class_t; -typedef enum PlayerState { ALIVE, DEAD, FALLING } state_t; +typedef enum PlayerState { ALIVE, DEAD } state_t; typedef struct PlayerStatData { unsigned int total_steps; diff --git a/src/position.c b/src/position.c index 3e516b9..3c2721f 100644 --- a/src/position.c +++ b/src/position.c @@ -21,7 +21,7 @@ #include "defines.h" Position -position_to_matrix_coords(Position *src) +position_to_matrix_coords(const Position *src) { unsigned int room_px_width, room_px_height; Position pos; diff --git a/src/position.h b/src/position.h index e50d1b0..330af4a 100644 --- a/src/position.h +++ b/src/position.h @@ -32,7 +32,7 @@ typedef struct { * Return a matrix coord position for a given position */ Position -position_to_matrix_coords(Position*); +position_to_matrix_coords(const Position*); /* * Get the room coord for the room containing the given position diff --git a/src/roommatrix.c b/src/roommatrix.c index 519b37e..af56296 100644 --- a/src/roommatrix.c +++ b/src/roommatrix.c @@ -284,6 +284,13 @@ roommatrix_render_lightmap(RoomMatrix *matrix, Camera *cam) } } +RoomSpace* +roommatrix_get_space_for(RoomMatrix *matrix, const Position *p) +{ + Position roomPos = position_to_matrix_coords(p); + return &matrix->spaces[roomPos.x][roomPos.y]; +} + void roommatrix_destroy(RoomMatrix *m) { // Clear the list but don't destroy the items diff --git a/src/roommatrix.h b/src/roommatrix.h index dd2dde6..1b6370e 100644 --- a/src/roommatrix.h +++ b/src/roommatrix.h @@ -61,22 +61,33 @@ typedef struct RoomMatrix_t { RoomMatrix* roommatrix_create(void); -void roommatrix_update(struct UpdateData*); +void +roommatrix_update(struct UpdateData*); -void roommatrix_populate_from_map(RoomMatrix*, Map*); +void +roommatrix_populate_from_map(RoomMatrix*, Map*); -void roommatrix_add_lightsource(RoomMatrix*, Position*); +void +roommatrix_add_lightsource(RoomMatrix*, Position*); -void roommatrix_build_lightmap(RoomMatrix*); +void +roommatrix_build_lightmap(RoomMatrix*); -void roommatrix_render_mouse_square(RoomMatrix*, Camera*); +void +roommatrix_render_mouse_square(RoomMatrix*, Camera*); -void roommatrix_render_lightmap(RoomMatrix*, Camera*); +void +roommatrix_render_lightmap(RoomMatrix*, Camera*); + +RoomSpace* +roommatrix_get_space_for(RoomMatrix*, const Position *p); #ifdef DEBUG -void roommatrix_render_debug(RoomMatrix*, Camera*); +void +roommatrix_render_debug(RoomMatrix*, Camera*); #endif -void roommatrix_destroy(RoomMatrix*); +void +roommatrix_destroy(RoomMatrix*); #endif // ROOMMATRIX_H_ diff --git a/src/sprite.c b/src/sprite.c index 6a1a1a6..7d51041 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -19,11 +19,13 @@ #include #include "sprite.h" #include "util.h" +#include "update_data.h" static Sprite* sprite_create_default(void) { Sprite *s = ec_malloc(sizeof(Sprite)); + s->state = SPRITE_STATE_DEFAULT; s->textures[0] = NULL; s->textures[1] = NULL; s->clip = (SDL_Rect) { 0, 0, 0, 0 }; @@ -34,6 +36,7 @@ sprite_create_default(void) s->rotationPoint = (SDL_Point) { 0, 0 }; s->flip = SDL_FLIP_NONE; s->renderTimer = timer_create(); + s->animationTimer = timer_create(); s->texture_index = 0; s->fixed = false; s->animate = true; @@ -112,6 +115,33 @@ sprite_set_alpha(Sprite *s, Uint8 alpha) texture_set_alpha(s->textures[1], alpha); } +void +sprite_update(Sprite *s, UpdateData *data) +{ + UNUSED(data); + + if (s->state == SPRITE_STATE_FALLING) { + if (!timer_started(s->animationTimer)) { + timer_start(s->animationTimer); + s->clip = CLIP16(0, 0); + } else { + if (timer_get_ticks(s->animationTimer) > 100) { + timer_start(s->animationTimer); + s->angle += 60; + s->dim.width -= 4; + s->dim.height -= 4; + s->pos.x += 2; + s->pos.y += 2; + s->rotationPoint = (SDL_Point) { + s->dim.width /2, + s->dim.height /2 + }; + } + } + } + +} + void sprite_render(Sprite *s, Camera *cam) { @@ -169,5 +199,6 @@ void sprite_destroy(Sprite *sprite) texture_destroy(sprite->textures[1]); } timer_destroy(sprite->renderTimer); + timer_destroy(sprite->animationTimer); free(sprite); } diff --git a/src/sprite.h b/src/sprite.h index 045ebea..1b33660 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -27,7 +27,15 @@ #include "roommatrix.h" #include "timer.h" +typedef struct UpdateData UpdateData; + +typedef enum SpriteState { + SPRITE_STATE_FALLING, + SPRITE_STATE_DEFAULT +} SpriteState; + typedef struct Sprite { + SpriteState state; Texture* textures[2]; SDL_Rect clip; bool destroyTextures; @@ -37,6 +45,7 @@ typedef struct Sprite { SDL_Point rotationPoint; SDL_RendererFlip flip; Timer *renderTimer; + Timer *animationTimer; unsigned int texture_index; bool fixed; bool animate; @@ -56,6 +65,9 @@ sprite_load_text_texture(Sprite *, const char *path, int index, int size, int ou void sprite_set_texture(Sprite *, Texture *, int index); +void +sprite_update(Sprite*, UpdateData *data); + void sprite_render(Sprite*, Camera*);