Fixes: #4 Room stuff: Traps

- Adds traps
- Adds lua hooks for traps
- Fixes level exit in pit bug
This commit is contained in:
Linus Probert 2018-08-06 00:28:23 +02:00
parent a3c3c634d6
commit ffde0793e5
13 changed files with 270 additions and 44 deletions

View File

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

View File

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

View File

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

61
data/trapgen.lua Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

59
src/trap.c Normal file
View File

@ -0,0 +1,59 @@
/*
* BreakHack - A dungeone crawler RPG
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <SDL.h>
#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);
}

41
src/trap.h Normal file
View File

@ -0,0 +1,41 @@
/*
* BreakHack - A dungeone crawler RPG
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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*);