From ffde0793e507f901550cf7202a78342af5eb0ff6 Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Mon, 6 Aug 2018 00:28:23 +0200 Subject: [PATCH] Fixes: #4 Room stuff: Traps - Adds traps - Adds lua hooks for traps - Fixes level exit in pit bug --- CMakeLists.txt | 2 + data/mapgen.lua | 3 ++ data/maproombuilder.lua | 13 ++++-- data/trapgen.lua | 61 +++++++++++++++++++++++++++ src/map.c | 18 ++++++++ src/map.h | 9 +++- src/map_lua.c | 92 ++++++++++++++++++++++++----------------- src/monster.c | 6 ++- src/player.c | 5 +++ src/roommatrix.c | 3 ++ src/roommatrix.h | 2 + src/trap.c | 59 ++++++++++++++++++++++++++ src/trap.h | 41 ++++++++++++++++++ 13 files changed, 270 insertions(+), 44 deletions(-) create mode 100644 data/trapgen.lua create mode 100644 src/trap.c create mode 100644 src/trap.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c62912..c7fc473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,7 @@ add_executable(breakhack src/settings src/actiontextbuilder src/animation + src/trap ) # Sqlite has some warnings that I we don't need to see @@ -261,6 +262,7 @@ if (NOT DEBUG_BUILD) "maproombuilder.lua" "menumapgen.lua" "monstergen.lua" + "trapgen.lua" "pitlayouts.dat" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data ) diff --git a/data/mapgen.lua b/data/mapgen.lua index 4531810..ecb7b2e 100644 --- a/data/mapgen.lua +++ b/data/mapgen.lua @@ -1,5 +1,6 @@ local room_builder = require "maproombuilder" local monster_gen = require "monstergen" +local trap_gen = require "trapgen" -- Setting up some functions local time = os.time @@ -115,6 +116,7 @@ local function generate_path () if room then room_builder.build_room(room) monster_gen.add_monsters_to_room(room, i-1, j-1) + trap_gen.add_traps_to_room(room, i-1, j-1) end end end @@ -138,6 +140,7 @@ for i=1,10 do set_current_room(map, i-1, j-1); room_builder.load_room(map, room) monster_gen.load_monsters(map, room.monsters) + trap_gen.load_traps(map, room.traps) end end end diff --git a/data/maproombuilder.lua b/data/maproombuilder.lua index c230503..899b017 100644 --- a/data/maproombuilder.lua +++ b/data/maproombuilder.lua @@ -294,7 +294,6 @@ local function build_vert_center_coridoor(room, offset) end local function build_horiz_center_coridoor(room, offset) - info("Building horizontal corrdior: " .. offset) for i=0,6 do room.tiles[offset+i][4] = wall.horizontal room.tiles[offset+i][5] = floor.center @@ -412,7 +411,12 @@ local function add_level_exit(room) while not success do x = random(14) y = random(10) - if not room.decor[x][y] then + if not room.decor[x][y] + and not room.traps[x][y] + and (room.tiles[x][y] + and not room.tiles[x][y][5] + and not room.tiles[x][y][8]) + then success = true room.tiles[x][y] = special.level_exit end @@ -469,16 +473,19 @@ function module.create_empty_room() type = nil, arg = nil }, - monsters = {} + monsters = {}, + traps = {} } for i=0,15 do room.tiles[i] = {} room.decor[i] = {} room.monsters[i] = {} + room.traps[i] = {} for j=0,11 do room.tiles[i][j] = nil room.decor[i][j] = nil room.monsters[i][j] = nil + room.traps[i][j] = nil end end return room diff --git a/data/trapgen.lua b/data/trapgen.lua new file mode 100644 index 0000000..67fc4a0 --- /dev/null +++ b/data/trapgen.lua @@ -0,0 +1,61 @@ +local module = {} +local random = math.random + +local textures = { + "Objects/Trap1.png", + "Objects/Trap0.png" +} + +local traps = {} +for i=1,7 do + trap = { textures[1], textures[2], i*16, 3*16, CURRENT_LEVEL * 4 } + table.insert(traps, trap) +end + +local function repack(data) + return { + texturePath1 = data[1], + texturePath2 = data[2], + clipX = data[3], + clipY = data[4], + damage = data[5] + } +end + +function module.add_traps_to_room(room) + if room.type == "coridoor" then + if random(2) ~= 1 then return end + else + if random(4) ~= 1 then return end + end + + local count = random(4) + local i = 0 + while i < count do + local rx = random(13) + 1 + local ry = random(9) + 1 + if not room.decor[rx][ry] + and not room.monsters[rx][ry] + and (room.tiles[rx][ry] + and not room.tiles[rx][ry][5] + and not room.tiles[rx][ry][8]) + then + + room.traps[rx][ry] = traps[random(#traps)] + i = i + 1 + end + end +end + +function module.load_traps(map, traps) + for i=0,15 do + for j=0,11 do + trap = traps[i][j] + if trap then + add_trap(map, i, j, repack(trap)) + end + end + end +end + +return module diff --git a/src/map.c b/src/map.c index 873709e..240de5d 100644 --- a/src/map.c +++ b/src/map.c @@ -25,6 +25,7 @@ #include "gui.h" #include "particle_engine.h" #include "update_data.h" +#include "trap.h" static Room* create_room(void) @@ -38,6 +39,7 @@ Room* create_room(void) for (j=0; j < MAP_ROOM_HEIGHT; ++j) { room->tiles[i][j] = NULL; room->decorations[i][j] = NULL; + room->traps[i][j] = NULL; } } return room; @@ -113,6 +115,17 @@ void map_add_decoration(Map *map, Position *tile_pos, MapTile *tile) *oldTile = tile; } +void +map_add_trap(Map *map, Position *pos, Trap *trap) +{ + const Position *cr = &map->currentRoom; + Trap **oldTrap = &map->rooms[cr->x][cr->y]->traps[pos->x][pos->y]; + if (*oldTrap) + trap_destroy(*oldTrap); + + *oldTrap = trap; +} + void map_clear_dead_monsters(Map *map, Player *player) { @@ -270,6 +283,8 @@ void map_render(Map *map, Camera *cam) room->decorations[i][j], &tilePos, cam); + if (room->traps[i][j]) + trap_render(room->traps[i][j], cam); } } if (room->modifier.type == RMOD_TYPE_WINDY) { @@ -335,6 +350,9 @@ void map_room_destroy(Room *room) if (room->decorations[i][j]) { free(room->decorations[i][j]); } + if (room->traps[i][j]) { + trap_destroy(room->traps[i][j]); + } } } free(room); diff --git a/src/map.h b/src/map.h index 54de725..2524b7c 100644 --- a/src/map.h +++ b/src/map.h @@ -32,7 +32,8 @@ #include "player.h" #include "map_room_modifiers.h" -struct UpdateData; +typedef struct UpdateData UpdateData; +typedef struct Trap Trap; typedef struct MapTile_t { int textureIndex0; @@ -47,6 +48,7 @@ typedef struct MapTile_t { typedef struct Room_t { MapTile* tiles[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT]; MapTile* decorations[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT]; + Trap* traps[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT]; RoomModifierData modifier; } Room; @@ -76,6 +78,9 @@ map_add_tile(Map *map, Position *tile_pos, MapTile*); void map_add_decoration(Map *map, Position *tile_pos, MapTile*); +void +map_add_trap(Map*, Position*, Trap*); + void map_add_monster(Map*, Monster*); @@ -89,7 +94,7 @@ void map_clear_collected_items(Map*); void -map_update(struct UpdateData*); +map_update(UpdateData*); void map_render(Map*, Camera*); diff --git a/src/map_lua.c b/src/map_lua.c index 7db049f..3d062fb 100644 --- a/src/map_lua.c +++ b/src/map_lua.c @@ -32,6 +32,7 @@ #include "stats.h" #include "io_util.h" #include "texturecache.h" +#include "trap.h" static lua_State* load_lua_state(void) @@ -235,47 +236,67 @@ lua_checkstats(lua_State *L, int index) return stats; } -static -int l_tile_occupied(lua_State *L) -{ - Map *map; - Room *room; - MapTile *tile, *decor; - Position *rPos; - int x, y; - bool response = false; - - map = luaL_checkmap(L, 1); - x = (int) luaL_checkinteger(L, 2); - y = (int) luaL_checkinteger(L, 3); - - rPos = &map->currentRoom; - room = map->rooms[rPos->x][rPos->y]; - - tile = room->tiles[x][y]; - decor = room->decorations[x][y]; - - response = response || (tile && (tile->collider || tile->levelExit || tile->lethal)); - response = response || (decor && (decor->collider || decor->levelExit)); - - lua_pushboolean(L, response); - return 1; -} - -static -int l_add_tile(lua_State *L) +static int +l_add_tile(lua_State *L) { extract_tile_data(L, &map_add_tile); return 0; } -static -int l_add_decoration(lua_State *L) +static int +l_add_decoration(lua_State *L) { extract_tile_data(L, &map_add_decoration); return 0; } +static int +l_add_trap(lua_State *L) +{ + Map *map = luaL_checkmap(L, 1); + int xpos = (int) luaL_checkinteger(L, 2); + int ypos = (int) luaL_checkinteger(L, 3); + + // Read the table + lua_settop(L, 4); + luaL_checktype(L, 4, LUA_TTABLE); + + // Get the fields from the table + lua_getfield(L, 4, "texturePath1"); + lua_getfield(L, 4, "texturePath2"); + lua_getfield(L, 4, "clipX"); + lua_getfield(L, 4, "clipY"); + lua_getfield(L, 4, "damage"); + + const char *texturePath1 = luaL_checkstring(L, -5); + const char *texturePath2 = luaL_checkstring(L, -4); + int clipx = (int) luaL_checkinteger(L, -3); + int clipy = (int) luaL_checkinteger(L, -2); + int damage = (int) luaL_checkinteger(L, -1); + + Texture *t0 = texturecache_add(texturePath1); + Texture *t1 = texturecache_add(texturePath2); + + lua_pop(L, 5); + + const Position *cr = &map->currentRoom; + + Trap *trap = trap_create(); + sprite_set_texture(trap->sprite, t0, 0); + sprite_set_texture(trap->sprite, t1, 1); + trap->sprite->clip = CLIP16(clipx, clipy); + trap->sprite->pos = (Position) { + cr->x * MAP_ROOM_WIDTH * TILE_DIMENSION + xpos * TILE_DIMENSION, + cr->y * MAP_ROOM_HEIGHT * TILE_DIMENSION + ypos * TILE_DIMENSION + }; + trap->damage = damage; + + Position trapPos = { xpos, ypos }; + map_add_trap(map, &trapPos, trap); + + return 0; +} + static int l_add_monster(lua_State *L) { @@ -316,9 +337,6 @@ l_add_monster(lua_State *L) label = strdup(tmp_label); - texture1->dim = GAME_DIMENSION; - texture2->dim = GAME_DIMENSION; - lua_pop(L, 8); monster = monster_create(); @@ -419,6 +437,9 @@ generate_map(unsigned int level, const char *file, SDL_Renderer *renderer) lua_pushcfunction(L, l_add_decoration); lua_setglobal(L, "add_decoration"); + lua_pushcfunction(L, l_add_trap); + lua_setglobal(L, "add_trap"); + lua_pushcfunction(L, l_add_texture); lua_setglobal(L, "add_texture"); @@ -434,9 +455,6 @@ generate_map(unsigned int level, const char *file, SDL_Renderer *renderer) lua_pushcfunction(L, l_add_monster); lua_setglobal(L, "add_monster"); - lua_pushcfunction(L, l_tile_occupied); - lua_setglobal(L, "tile_occupied"); - lua_pushinteger(L, level); lua_setglobal(L, "CURRENT_LEVEL"); diff --git a/src/monster.c b/src/monster.c index 1a3f666..a4229a2 100644 --- a/src/monster.c +++ b/src/monster.c @@ -221,7 +221,7 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction) monster_behaviour_check_post_attack(monster); } - return space->occupied || space->lethal; + return space->occupied || space->lethal || space->trap; } static bool @@ -299,7 +299,9 @@ get_optimal_move_towards(Monster *m, RoomMatrix *rm, const Position *dest) x_dist = abs(next.x - dest->x); y_dist = abs(next.y - dest->y); - if (rm->spaces[next.x][next.y].occupied || rm->spaces[next.x][next.y].lethal) { + if (rm->spaces[next.x][next.y].occupied + || rm->spaces[next.x][next.y].lethal + || rm->spaces[next.x][next.y].trap) { nextScore += 50; } diff --git a/src/player.c b/src/player.c index 4397a63..9fd4e63 100644 --- a/src/player.c +++ b/src/player.c @@ -34,6 +34,7 @@ #include "vector2d.h" #include "actiontextbuilder.h" #include "animation.h" +#include "trap.h" #define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1, false, false } #define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1, false, false } @@ -169,6 +170,10 @@ has_collided(Player *player, RoomMatrix *matrix, Vector2d direction) player->state = FALLING; } + if (space->trap && !collided) { + trap_activate(space->trap, player); + } + return collided; } diff --git a/src/roommatrix.c b/src/roommatrix.c index d53ee4e..dc57a6f 100644 --- a/src/roommatrix.c +++ b/src/roommatrix.c @@ -26,6 +26,7 @@ #include "item.h" #include "update_data.h" #include "defines.h" +#include "trap.h" static void roommatrix_reset(RoomMatrix *m) @@ -42,6 +43,7 @@ roommatrix_reset(RoomMatrix *m) space->light = 0; space->monster = NULL; space->player = NULL; + space->trap = NULL; while (space->items != NULL) linkedlist_pop(&space->items); } @@ -120,6 +122,7 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m) space->lightsource |= r->decorations[i][j]->lightsource; } + space->trap = r->traps[i][j]; } } diff --git a/src/roommatrix.h b/src/roommatrix.h index 0128f8e..14e9748 100644 --- a/src/roommatrix.h +++ b/src/roommatrix.h @@ -32,6 +32,7 @@ typedef struct Monster_t Monster; typedef struct Player_t Player; typedef struct Item_t Item; typedef struct Node LinkedList; +typedef struct Trap Trap; struct UpdateData; @@ -42,6 +43,7 @@ typedef struct { int light; Monster *monster; Player *player; + Trap *trap; LinkedList *items; } RoomSpace; diff --git a/src/trap.c b/src/trap.c new file mode 100644 index 0000000..c216c67 --- /dev/null +++ b/src/trap.c @@ -0,0 +1,59 @@ +/* + * BreakHack - A dungeone crawler RPG + * Copyright (C) 2018 Linus Probert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "trap.h" +#include "util.h" +#include "gui.h" + +Trap * +trap_create() +{ + Trap *trap = ec_malloc(sizeof(Trap)); + trap->sprite = sprite_create(); + trap->sprite->animate = false; + trap->sprite->dim = GAME_DIMENSION; + trap->damage = 10; + return trap; +} + +void +trap_activate(Trap *trap, Player *player) +{ + player->stats.hp -= trap->damage; + player_hit(player, trap->damage); + if (!trap->sprite->animate) { + gui_log("A trap is sprung!"); + trap->sprite->animate = true; + } else { + gui_log("You step in a trap!"); + } +} + +void +trap_render(Trap *trap, Camera *cam) +{ + sprite_render(trap->sprite, cam); +} + +void +trap_destroy(Trap *trap) +{ + sprite_destroy(trap->sprite); + free(trap); +} diff --git a/src/trap.h b/src/trap.h new file mode 100644 index 0000000..0bc13a1 --- /dev/null +++ b/src/trap.h @@ -0,0 +1,41 @@ +/* + * BreakHack - A dungeone crawler RPG + * Copyright (C) 2018 Linus Probert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "sprite.h" +#include "player.h" +#include "update_data.h" +#include "camera.h" + +typedef struct Trap { + Sprite *sprite; + Uint32 damage; +} Trap; + +Trap * +trap_create(void); + +void +trap_activate(Trap*, Player*); + +void +trap_render(Trap*, Camera*); + +void +trap_destroy(Trap*);