Adds possibility to push monsters into pits and traps.
This commit is contained in:
parent
2316d24942
commit
cb732a80ec
2
.vimrc
2
.vimrc
|
@ -1,7 +1,7 @@
|
|||
nnoremap <F1> :Make<cr>
|
||||
nnoremap <F2> :Make lint test<cr>
|
||||
nnoremap <F3> :Termdebug _build/breakhack<cr>
|
||||
nnoremap <F4> :ter ++close ./_build/breakhack<cr>
|
||||
nnoremap <F4> :ter ++close env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/breakhack<cr>
|
||||
|
||||
packadd termdebug
|
||||
let g:termdebug_wide = 1
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
43
src/player.c
43
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
31
src/sprite.c
31
src/sprite.c
|
@ -19,11 +19,13 @@
|
|||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
||||
|
|
12
src/sprite.h
12
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*);
|
||||
|
||||
|
|
Loading…
Reference in New Issue