2018-02-16 18:11:26 +01:00
|
|
|
/*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
#include <stdio.h>
|
2017-12-21 11:57:12 +01:00
|
|
|
#include <stdlib.h>
|
2017-12-05 08:13:28 +01:00
|
|
|
#include <stdbool.h>
|
2018-01-23 21:03:43 +01:00
|
|
|
#include <string.h>
|
2017-12-02 23:32:40 +01:00
|
|
|
|
|
|
|
#include <lua.h>
|
|
|
|
#include <lualib.h>
|
|
|
|
#include <lauxlib.h>
|
|
|
|
|
2018-02-27 19:59:51 +01:00
|
|
|
#include <physfs.h>
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
#include "map_lua.h"
|
|
|
|
#include "util.h"
|
2018-02-20 14:22:26 +01:00
|
|
|
#include "stats.h"
|
2018-02-23 23:53:52 +01:00
|
|
|
#include "io_util.h"
|
|
|
|
#include "texturecache.h"
|
2018-08-06 00:28:23 +02:00
|
|
|
#include "trap.h"
|
2018-08-10 14:29:45 +02:00
|
|
|
#include "item.h"
|
|
|
|
#include "item_builder.h"
|
|
|
|
#include "random.h"
|
2019-02-22 00:09:31 +01:00
|
|
|
#include "bh_random.h"
|
2017-12-02 23:32:40 +01:00
|
|
|
|
|
|
|
static
|
2017-12-19 21:00:02 +01:00
|
|
|
lua_State* load_lua_state(void)
|
2017-12-02 23:32:40 +01:00
|
|
|
{
|
|
|
|
lua_State *L = luaL_newstate();
|
|
|
|
luaL_openlibs(L);
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int l_create_map(lua_State *L)
|
|
|
|
{
|
|
|
|
Map *map = map_create();
|
2018-01-30 21:05:33 +01:00
|
|
|
map->level = (int) luaL_checkinteger(L, 1);
|
2017-12-02 23:32:40 +01:00
|
|
|
lua_pushlightuserdata(L, map);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-02-01 09:55:12 +01:00
|
|
|
static int
|
|
|
|
l_print_info(lua_State *L)
|
|
|
|
{
|
2018-05-06 06:19:59 +02:00
|
|
|
UNUSED(L); // Compilers keep warning about L being unused
|
2018-04-28 19:10:49 +02:00
|
|
|
debug(luaL_checkstring(L, 1));
|
2018-02-01 09:55:12 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
static
|
|
|
|
Map* luaL_checkmap(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
Map *map;
|
|
|
|
|
|
|
|
if (!lua_islightuserdata(L, index))
|
|
|
|
fatal("in luaL_checkmap(), pointer lost in lua script");
|
|
|
|
|
|
|
|
map = lua_touserdata(L, index);
|
|
|
|
if (map == NULL)
|
|
|
|
fatal("in luaL_checkmap(), bad map pointer");
|
|
|
|
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
SDL_Renderer* luaL_checksdlrenderer(lua_State *L)
|
|
|
|
{
|
|
|
|
SDL_Renderer *renderer;
|
|
|
|
|
|
|
|
lua_getglobal(L, "_sdl_renderer");
|
|
|
|
if (!lua_islightuserdata(L, -1))
|
|
|
|
fatal("in luaL_checksdlrenderer(), pointer lost in lua script");
|
|
|
|
|
|
|
|
renderer = lua_touserdata(L, -1);
|
|
|
|
if (renderer == NULL)
|
|
|
|
fatal("in luaL_checksdlrenderer(), bad SDL_Renderer pointer");
|
|
|
|
|
|
|
|
return renderer;
|
|
|
|
}
|
|
|
|
|
2018-03-15 16:30:41 +01:00
|
|
|
static int
|
|
|
|
l_map_set_current_room_modifier(lua_State *L)
|
|
|
|
{
|
2018-03-16 10:04:43 +01:00
|
|
|
const char *modifier, *direction;
|
2018-03-15 16:30:41 +01:00
|
|
|
|
|
|
|
Map *map = luaL_checkmap(L, 1);
|
|
|
|
modifier = luaL_checkstring(L, 2);
|
2018-03-16 10:04:43 +01:00
|
|
|
direction = luaL_checkstring(L, 3);
|
|
|
|
|
|
|
|
Vector2d dir = VECTOR2D_LEFT;
|
|
|
|
if (strcmp(direction, "LEFT") == 0)
|
|
|
|
dir = VECTOR2D_LEFT;
|
|
|
|
else if (strcmp(direction, "RIGHT") == 0)
|
|
|
|
dir = VECTOR2D_RIGHT;
|
|
|
|
else if (strcmp(direction, "UP") == 0)
|
|
|
|
dir = VECTOR2D_UP;
|
|
|
|
else if (strcmp(direction, "DOWN") == 0)
|
|
|
|
dir = VECTOR2D_DOWN;
|
2018-03-15 16:30:41 +01:00
|
|
|
|
|
|
|
if (strcmp(modifier, "WINDY") == 0) {
|
2018-03-15 17:00:11 +01:00
|
|
|
Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y];
|
2018-03-15 16:30:41 +01:00
|
|
|
room->modifier.type = RMOD_TYPE_WINDY;
|
2018-03-16 10:04:43 +01:00
|
|
|
room->modifier.data.wind.direction = dir;
|
2018-08-13 13:11:32 +02:00
|
|
|
} else if (strcmp(modifier, "FIRE") == 0) {
|
|
|
|
Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y];
|
|
|
|
room->modifier.type = RMOD_TYPE_FIRE;
|
2018-10-15 22:19:23 +02:00
|
|
|
} else if (strcmp(modifier, "CRUMBLING") == 0) {
|
|
|
|
Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y];
|
|
|
|
room->modifier.type = RMOD_TYPE_CRUMBLING;
|
2018-03-15 16:30:41 +01:00
|
|
|
} else {
|
|
|
|
luaL_error(L, "Unknown room modifier: %s", modifier);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-26 18:37:50 +02:00
|
|
|
static int
|
|
|
|
l_map_set_current_room(lua_State *L)
|
2017-12-05 08:13:28 +01:00
|
|
|
{
|
|
|
|
Map *map;
|
|
|
|
unsigned int room_x, room_y;
|
|
|
|
|
|
|
|
map = luaL_checkmap(L, 1);
|
2017-12-19 22:51:00 +01:00
|
|
|
room_x = (int) luaL_checkinteger(L, 2);
|
|
|
|
room_y = (int) luaL_checkinteger(L, 3);
|
2017-12-05 08:13:28 +01:00
|
|
|
|
2017-12-06 11:44:17 +01:00
|
|
|
map->currentRoom = (Position) { room_x, room_y };
|
2017-12-05 08:13:28 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-26 18:37:50 +02:00
|
|
|
static int
|
|
|
|
l_add_texture(lua_State *L)
|
2017-12-02 23:32:40 +01:00
|
|
|
{
|
|
|
|
Map *map;
|
|
|
|
const char *path;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
map = luaL_checkmap(L, 1);
|
|
|
|
path = luaL_checkstring(L, 2);
|
|
|
|
SDL_Renderer *renderer = luaL_checksdlrenderer(L);
|
|
|
|
|
|
|
|
index = map_add_texture(map, path, renderer);
|
|
|
|
lua_pushinteger(L, index);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-12-10 19:51:24 +01:00
|
|
|
static void
|
|
|
|
extract_tile_data(lua_State *L,
|
|
|
|
void (*f_add_tile)(Map*, Position*, MapTile*))
|
2017-12-02 23:32:40 +01:00
|
|
|
{
|
|
|
|
Map *map;
|
2017-12-05 08:13:28 +01:00
|
|
|
int tile_x, tile_y;
|
2017-12-10 19:51:24 +01:00
|
|
|
int t_index0, t_index1, tile_clip_x, tile_clip_y;
|
2018-03-25 23:30:26 +02:00
|
|
|
bool collider, lightsource, levelExit, lethal;
|
2017-12-02 23:32:40 +01:00
|
|
|
|
|
|
|
map = luaL_checkmap(L, 1);
|
2017-12-19 22:51:00 +01:00
|
|
|
tile_x = (int) luaL_checkinteger(L, 2);
|
|
|
|
tile_y = (int) luaL_checkinteger(L, 3);
|
2017-12-02 23:32:40 +01:00
|
|
|
|
2017-12-10 19:51:24 +01:00
|
|
|
// Read the table
|
|
|
|
lua_settop(L, 4);
|
|
|
|
luaL_checktype(L, 4, LUA_TTABLE);
|
2017-12-02 23:32:40 +01:00
|
|
|
|
2017-12-10 19:51:24 +01:00
|
|
|
// Get the fields from the table
|
|
|
|
lua_getfield(L, 4, "textureIndex0");
|
|
|
|
lua_getfield(L, 4, "textureIndex1");
|
|
|
|
lua_getfield(L, 4, "tileClipX");
|
|
|
|
lua_getfield(L, 4, "tileClipY");
|
|
|
|
lua_getfield(L, 4, "isCollider");
|
|
|
|
lua_getfield(L, 4, "isLightSource");
|
2017-12-22 06:27:58 +01:00
|
|
|
lua_getfield(L, 4, "isLevelExit");
|
2018-03-25 23:30:26 +02:00
|
|
|
lua_getfield(L, 4, "isLethal");
|
2017-12-02 23:32:40 +01:00
|
|
|
|
2018-03-25 23:30:26 +02:00
|
|
|
t_index0 = (int) luaL_checkinteger(L, -8);
|
|
|
|
t_index1 = (int) luaL_checkinteger(L, -7);
|
|
|
|
tile_clip_x = (int) luaL_checkinteger(L, -6);
|
|
|
|
tile_clip_y = (int) luaL_checkinteger(L, -5);
|
|
|
|
collider = lua_toboolean(L, -4);
|
|
|
|
lightsource = lua_toboolean(L, -3);
|
|
|
|
levelExit = lua_toboolean(L, -2);
|
|
|
|
lethal = lua_toboolean(L, -1);
|
2017-12-08 09:45:57 +01:00
|
|
|
|
2017-12-10 19:51:24 +01:00
|
|
|
// Clear the stack
|
2018-03-25 23:30:26 +02:00
|
|
|
lua_pop(L, 8);
|
2017-12-08 09:45:57 +01:00
|
|
|
|
|
|
|
Position tilePos = (Position) { tile_x, tile_y };
|
|
|
|
SDL_Rect clip = (SDL_Rect) { tile_clip_x, tile_clip_y, 16, 16 };
|
|
|
|
|
2018-03-25 23:30:26 +02:00
|
|
|
MapTile *tile = map_create_tile();
|
2018-10-12 08:36:00 +02:00
|
|
|
if (t_index0 >= 0)
|
|
|
|
sprite_set_texture(tile->sprite, linkedlist_get(&map->textures, t_index0), 0);
|
|
|
|
if (t_index1 >= 0)
|
|
|
|
sprite_set_texture(tile->sprite, linkedlist_get(&map->textures, t_index1), 1);
|
|
|
|
tile->sprite->clip = clip;
|
|
|
|
|
2018-03-25 23:30:26 +02:00
|
|
|
tile->collider = collider;
|
|
|
|
tile->lightsource = lightsource;
|
|
|
|
tile->levelExit = levelExit;
|
|
|
|
tile->lethal = lethal;
|
2017-12-08 09:45:57 +01:00
|
|
|
|
2017-12-10 19:51:24 +01:00
|
|
|
f_add_tile(map, &tilePos, tile);
|
|
|
|
}
|
2017-12-08 09:45:57 +01:00
|
|
|
|
2018-02-20 14:22:26 +01:00
|
|
|
static Stats
|
|
|
|
lua_checkstats(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
// Confirm table
|
2018-09-09 01:25:32 +02:00
|
|
|
if (!lua_istable(L, index)) {
|
2018-09-08 23:23:49 +02:00
|
|
|
fatal("Bad table provided");
|
|
|
|
}
|
2018-02-20 14:22:26 +01:00
|
|
|
|
|
|
|
// Push to top of stack
|
|
|
|
lua_pushvalue(L, index);
|
|
|
|
// Stack: -1 => table
|
|
|
|
|
|
|
|
int tableIndex = lua_gettop(L);
|
|
|
|
|
|
|
|
lua_getfield(L, tableIndex, "hp");
|
|
|
|
lua_getfield(L, tableIndex, "dmg");
|
|
|
|
lua_getfield(L, tableIndex, "atk");
|
|
|
|
lua_getfield(L, tableIndex, "def");
|
|
|
|
lua_getfield(L, tableIndex, "speed");
|
|
|
|
|
2018-02-22 09:44:27 +01:00
|
|
|
int hp = (int) luaL_checkinteger(L, -5);
|
|
|
|
int dmg = (int) luaL_checkinteger(L, -4);
|
|
|
|
int atk = (int) luaL_checkinteger(L, -3);
|
|
|
|
int def = (int) luaL_checkinteger(L, -2);
|
|
|
|
int speed = (int) luaL_checkinteger(L, -1);
|
2018-02-20 14:22:26 +01:00
|
|
|
|
|
|
|
// Reset the stack
|
|
|
|
lua_pop(L, 6);
|
|
|
|
|
2018-08-04 23:52:52 +02:00
|
|
|
Stats stats = { hp, hp, dmg, atk, def, speed, 1, false, false };
|
2018-02-20 14:22:26 +01:00
|
|
|
return stats;
|
|
|
|
}
|
|
|
|
|
2018-08-06 00:28:23 +02:00
|
|
|
static int
|
|
|
|
l_add_tile(lua_State *L)
|
2018-02-05 16:15:45 +01:00
|
|
|
{
|
2018-08-06 00:28:23 +02:00
|
|
|
extract_tile_data(L, &map_add_tile);
|
|
|
|
return 0;
|
2018-02-05 16:15:45 +01:00
|
|
|
}
|
|
|
|
|
2018-08-06 00:28:23 +02:00
|
|
|
static int
|
|
|
|
l_add_decoration(lua_State *L)
|
2017-12-10 19:51:24 +01:00
|
|
|
{
|
2018-08-06 00:28:23 +02:00
|
|
|
extract_tile_data(L, &map_add_decoration);
|
2017-12-10 19:51:24 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-06 00:28:23 +02:00
|
|
|
static int
|
|
|
|
l_add_trap(lua_State *L)
|
2017-12-10 19:51:24 +01:00
|
|
|
{
|
2018-08-06 00:28:23 +02:00
|
|
|
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);
|
|
|
|
|
2017-12-08 09:45:57 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-10 14:29:45 +02:00
|
|
|
static int
|
|
|
|
l_add_chest(lua_State *L)
|
|
|
|
{
|
|
|
|
Map *map = luaL_checkmap(L, 1);
|
|
|
|
int x = (int) luaL_checkinteger(L, 2);
|
|
|
|
int y = (int) luaL_checkinteger(L, 3);
|
|
|
|
int level = (int) luaL_checkinteger(L, 4);
|
|
|
|
|
|
|
|
// Read the table
|
|
|
|
lua_settop(L, 5);
|
|
|
|
luaL_checktype(L, 5, LUA_TTABLE);
|
|
|
|
|
|
|
|
lua_getfield(L, 5, "texturePath1");
|
|
|
|
lua_getfield(L, 5, "texturePath2");
|
|
|
|
lua_getfield(L, 5, "clipX");
|
|
|
|
lua_getfield(L, 5, "clipY");
|
|
|
|
|
|
|
|
const char *texture_path_1 = luaL_checkstring(L, -4);
|
|
|
|
const char *texture_path_2 = luaL_checkstring(L, -3);
|
|
|
|
int clip_x = (int) luaL_checkinteger(L, -2);
|
|
|
|
int clip_y = (int) luaL_checkinteger(L, -1);
|
|
|
|
|
|
|
|
Item *chest = item_builder_build_container(texture_path_1,
|
|
|
|
texture_path_2,
|
|
|
|
CLIP16(clip_x, clip_y));
|
|
|
|
const Position *cr = &map->currentRoom;
|
|
|
|
chest->sprite->pos = (Position) {
|
|
|
|
cr->x * MAP_ROOM_WIDTH * TILE_DIMENSION + x * TILE_DIMENSION,
|
|
|
|
cr->y * MAP_ROOM_HEIGHT * TILE_DIMENSION + y * TILE_DIMENSION
|
|
|
|
};
|
2018-08-10 20:09:56 +02:00
|
|
|
lua_pop(L, 4);
|
|
|
|
|
|
|
|
if (get_random(1) == 0)
|
2018-08-10 22:31:06 +02:00
|
|
|
linkedlist_append(&chest->items, item_builder_build_item(TREASURE, level));
|
2018-08-10 14:29:45 +02:00
|
|
|
if (get_random(4) == 0)
|
2018-08-10 22:31:06 +02:00
|
|
|
linkedlist_append(&chest->items, item_builder_build_item(HEALTH, level));
|
2018-08-11 15:15:53 +02:00
|
|
|
if (get_random(4) == 0) {
|
|
|
|
Item *dagger = item_builder_build_item(DAGGER, level);
|
|
|
|
dagger->value = get_random(4) + 1;
|
|
|
|
linkedlist_append(&chest->items, dagger);
|
|
|
|
}
|
2018-08-10 14:29:45 +02:00
|
|
|
|
|
|
|
linkedlist_append(&map->items, chest);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-13 23:20:54 +01:00
|
|
|
static int
|
|
|
|
l_add_monster(lua_State *L)
|
|
|
|
{
|
|
|
|
Monster *monster;
|
|
|
|
Map *map;
|
2018-05-19 17:55:10 +02:00
|
|
|
int x, y, clip_x, clip_y, behaviour;
|
2018-01-17 09:32:49 +01:00
|
|
|
const char *texture_path_1, *texture_path_2, *tmp_label;
|
|
|
|
char *label;
|
2018-08-15 07:19:44 +02:00
|
|
|
bool boss;
|
2017-12-13 23:20:54 +01:00
|
|
|
Texture *texture1, *texture2;
|
2018-02-20 14:22:26 +01:00
|
|
|
Stats stats;
|
2017-12-13 23:20:54 +01:00
|
|
|
|
|
|
|
map = luaL_checkmap(L, 1);
|
2017-12-19 22:51:00 +01:00
|
|
|
x = (int) luaL_checkinteger(L, 2);
|
|
|
|
y = (int) luaL_checkinteger(L, 3);
|
2017-12-13 23:20:54 +01:00
|
|
|
|
|
|
|
// Read the table
|
|
|
|
lua_settop(L, 4);
|
|
|
|
luaL_checktype(L, 4, LUA_TTABLE);
|
|
|
|
|
2018-01-17 09:32:49 +01:00
|
|
|
lua_getfield(L, 4, "label");
|
2017-12-13 23:20:54 +01:00
|
|
|
lua_getfield(L, 4, "texturePath1");
|
|
|
|
lua_getfield(L, 4, "texturePath2");
|
2018-02-20 14:22:26 +01:00
|
|
|
lua_getfield(L, 4, "stats");
|
2017-12-13 23:20:54 +01:00
|
|
|
lua_getfield(L, 4, "clipX");
|
|
|
|
lua_getfield(L, 4, "clipY");
|
2018-05-19 17:55:10 +02:00
|
|
|
lua_getfield(L, 4, "behaviour");
|
2018-08-15 07:19:44 +02:00
|
|
|
lua_getfield(L, 4, "boss");
|
2018-05-19 17:55:10 +02:00
|
|
|
|
2018-08-15 07:19:44 +02:00
|
|
|
tmp_label = luaL_checkstring(L, -8);
|
|
|
|
texture_path_1 = luaL_checkstring(L, -7);
|
|
|
|
texture_path_2 = luaL_checkstring(L, -6);
|
|
|
|
stats = lua_checkstats(L, -5);
|
|
|
|
clip_x = (int) luaL_checkinteger(L, -4);
|
|
|
|
clip_y = (int) luaL_checkinteger(L, -3);
|
|
|
|
behaviour = (int) luaL_checkinteger(L, -2);
|
|
|
|
boss = (bool) lua_toboolean(L, -1);
|
2017-12-13 23:20:54 +01:00
|
|
|
|
2018-02-23 23:53:52 +01:00
|
|
|
texture1 = texturecache_add(texture_path_1);
|
|
|
|
texture2 = texturecache_add(texture_path_2);
|
2017-12-13 23:20:54 +01:00
|
|
|
|
2018-01-17 09:32:49 +01:00
|
|
|
label = strdup(tmp_label);
|
|
|
|
|
2018-02-20 14:22:26 +01:00
|
|
|
lua_pop(L, 8);
|
2017-12-13 23:20:54 +01:00
|
|
|
|
2018-05-15 11:16:56 +02:00
|
|
|
monster = monster_create();
|
2017-12-14 12:01:05 +01:00
|
|
|
monster->sprite->clip = (SDL_Rect) { clip_x, clip_y, 16, 16 };
|
2017-12-15 15:03:29 +01:00
|
|
|
monster_update_pos(monster, (Position) { x, y });
|
2017-12-13 23:20:54 +01:00
|
|
|
sprite_set_texture(monster->sprite, texture1, 0);
|
|
|
|
sprite_set_texture(monster->sprite, texture2, 1);
|
2018-05-19 17:55:10 +02:00
|
|
|
monster_set_behaviour(monster, behaviour);
|
2018-01-25 10:45:05 +01:00
|
|
|
if (strlen(label)) {
|
2018-01-17 09:32:49 +01:00
|
|
|
monster->label = label;
|
2018-01-25 10:45:05 +01:00
|
|
|
monster->lclabel = to_lower(label);
|
|
|
|
}
|
2017-12-13 23:20:54 +01:00
|
|
|
|
2018-02-20 14:22:26 +01:00
|
|
|
monster->stats = stats;
|
2018-08-15 07:19:44 +02:00
|
|
|
monster->boss = boss;
|
2018-02-20 14:22:26 +01:00
|
|
|
|
2017-12-13 23:20:54 +01:00
|
|
|
map_add_monster(map, monster);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-27 19:59:51 +01:00
|
|
|
static int
|
|
|
|
l_load_script(lua_State *L)
|
|
|
|
{
|
|
|
|
unsigned long size;
|
|
|
|
const char *name = luaL_checkstring(L, 1);
|
|
|
|
char *content;
|
|
|
|
|
|
|
|
char filename[20];
|
|
|
|
|
|
|
|
m_sprintf(filename, 20, "%s.lua", name);
|
|
|
|
|
|
|
|
if (!PHYSFS_exists(filename)) {
|
|
|
|
luaL_error(L, "Unable to locate module: %s\n", name);
|
|
|
|
return 1; // Unable to locate file
|
|
|
|
}
|
|
|
|
debug("Loading module: %s from %s", name, filename);
|
|
|
|
|
2018-03-20 21:54:57 +01:00
|
|
|
io_load_file_buffer(&content, &size, filename);
|
2018-02-27 19:59:51 +01:00
|
|
|
if (luaL_loadbuffer(L, content, size, name) != 0) {
|
|
|
|
luaL_error(L, "Error loading module %s from file %s\n\t%s", lua_tostring(L, 1), filename, lua_tostring(L, -1));
|
|
|
|
}
|
|
|
|
free(content);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-03-20 21:54:57 +01:00
|
|
|
static int
|
|
|
|
l_read_file(lua_State *L)
|
|
|
|
{
|
|
|
|
unsigned long size;
|
|
|
|
const char *filename = luaL_checkstring(L, 1);
|
|
|
|
char *content;
|
|
|
|
|
|
|
|
if (!PHYSFS_exists(filename)) {
|
|
|
|
luaL_error(L, "Unable to locate file: %s\n", filename);
|
|
|
|
return 1; // Unable to locate file
|
|
|
|
}
|
|
|
|
|
|
|
|
io_load_file_buffer(&content, &size, filename);
|
|
|
|
lua_pushstring(L, content);
|
|
|
|
free(content);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-12-17 13:10:11 +01:00
|
|
|
static int
|
|
|
|
l_get_random_seed(lua_State *L)
|
|
|
|
{
|
2019-01-10 19:26:19 +01:00
|
|
|
unsigned int level = (unsigned int) luaL_checkinteger(L, 1);
|
|
|
|
lua_pushnumber(L, get_random_map_seed(level));
|
2018-12-17 13:10:11 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-22 00:09:31 +01:00
|
|
|
static int
|
|
|
|
l_set_random_seed(lua_State *L)
|
|
|
|
{
|
|
|
|
unsigned int seed = (unsigned int) luaL_checkinteger(L, 1);
|
|
|
|
bh_map_srand(seed);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
l_get_random(lua_State *L)
|
|
|
|
{
|
|
|
|
unsigned int max = (unsigned int) luaL_checkinteger(L, 1);
|
|
|
|
lua_pushnumber(L, (bh_map_rand() % max) + 1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-02-09 13:27:25 +01:00
|
|
|
static Map*
|
2018-10-26 18:37:50 +02:00
|
|
|
generate_map(unsigned int level, const char *file, GameMode gameMode, SDL_Renderer *renderer)
|
2017-12-02 23:32:40 +01:00
|
|
|
{
|
|
|
|
int status, result;
|
|
|
|
|
2018-02-27 19:59:51 +01:00
|
|
|
debug("Running lua map script: %s", file);
|
2017-12-02 23:32:40 +01:00
|
|
|
|
|
|
|
lua_State *L = load_lua_state();
|
2018-02-23 19:32:01 +01:00
|
|
|
|
|
|
|
char *buffer = NULL;
|
|
|
|
long unsigned int len;
|
2018-03-20 21:54:57 +01:00
|
|
|
io_load_file_buffer(&buffer, &len, file);
|
2018-02-23 19:32:01 +01:00
|
|
|
status = luaL_loadbuffer(L, buffer, len, file);
|
|
|
|
free(buffer);
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
if (status) {
|
2018-01-23 22:54:02 +01:00
|
|
|
fatal("Couldn't load file: %s\n", lua_tostring(L, -1));
|
2017-12-02 23:32:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Present stuff to lua
|
|
|
|
lua_pushlightuserdata(L, renderer);
|
|
|
|
lua_setglobal(L, "_sdl_renderer");
|
|
|
|
|
|
|
|
lua_pushcfunction(L, l_create_map);
|
|
|
|
lua_setglobal(L, "create_map");
|
|
|
|
|
2018-02-01 09:55:12 +01:00
|
|
|
lua_pushcfunction(L, l_print_info);
|
|
|
|
lua_setglobal(L, "info");
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
lua_pushcfunction(L, l_add_tile);
|
|
|
|
lua_setglobal(L, "add_tile");
|
|
|
|
|
2017-12-08 09:45:57 +01:00
|
|
|
lua_pushcfunction(L, l_add_decoration);
|
|
|
|
lua_setglobal(L, "add_decoration");
|
|
|
|
|
2018-08-06 00:28:23 +02:00
|
|
|
lua_pushcfunction(L, l_add_trap);
|
|
|
|
lua_setglobal(L, "add_trap");
|
|
|
|
|
2018-08-10 14:29:45 +02:00
|
|
|
lua_pushcfunction(L, l_add_chest);
|
|
|
|
lua_setglobal(L, "add_chest");
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
lua_pushcfunction(L, l_add_texture);
|
|
|
|
lua_setglobal(L, "add_texture");
|
|
|
|
|
2018-03-20 21:54:57 +01:00
|
|
|
lua_pushcfunction(L, l_read_file);
|
|
|
|
lua_setglobal(L, "read_file");
|
|
|
|
|
2017-12-05 08:13:28 +01:00
|
|
|
lua_pushcfunction(L, l_map_set_current_room);
|
|
|
|
lua_setglobal(L, "set_current_room");
|
2018-03-15 16:30:41 +01:00
|
|
|
|
|
|
|
lua_pushcfunction(L, l_map_set_current_room_modifier);
|
|
|
|
lua_setglobal(L, "set_modifier");
|
2017-12-05 08:13:28 +01:00
|
|
|
|
2017-12-13 23:20:54 +01:00
|
|
|
lua_pushcfunction(L, l_add_monster);
|
|
|
|
lua_setglobal(L, "add_monster");
|
|
|
|
|
2018-12-17 13:10:11 +01:00
|
|
|
lua_pushcfunction(L, l_get_random_seed);
|
|
|
|
lua_setglobal(L, "get_random_seed");
|
|
|
|
|
2019-02-22 00:09:31 +01:00
|
|
|
lua_pushcfunction(L, l_set_random_seed);
|
|
|
|
lua_setglobal(L, "map_randomseed");
|
|
|
|
|
|
|
|
lua_pushcfunction(L, l_get_random);
|
|
|
|
lua_setglobal(L, "map_random");
|
|
|
|
|
2018-01-22 10:12:44 +01:00
|
|
|
lua_pushinteger(L, level);
|
|
|
|
lua_setglobal(L, "CURRENT_LEVEL");
|
|
|
|
|
2018-10-26 18:37:50 +02:00
|
|
|
lua_pushboolean(L, gameMode == QUICK);
|
2018-10-22 09:38:05 +02:00
|
|
|
lua_setglobal(L, "QUICK_MODE");
|
|
|
|
|
2018-10-26 18:37:50 +02:00
|
|
|
lua_pushboolean(L, gameMode == ARCADE);
|
|
|
|
lua_setglobal(L, "ARCADE_MODE");
|
|
|
|
|
2018-02-27 19:59:51 +01:00
|
|
|
// Add custom searcher
|
|
|
|
lua_getglobal(L, "package");
|
|
|
|
lua_getfield(L, -1, "searchers");
|
|
|
|
lua_pushcfunction(L, l_load_script);
|
|
|
|
lua_rawseti(L, -2, 1);
|
|
|
|
lua_pop(L, 2);
|
|
|
|
|
2017-12-02 23:32:40 +01:00
|
|
|
result = lua_pcall(L, 0, LUA_MULTRET, 0);
|
|
|
|
if (result) {
|
2018-01-23 22:54:02 +01:00
|
|
|
fatal("Failed to run script: %s\n", lua_tostring(L, -1));
|
2017-12-02 23:32:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
lua_getglobal(L, "map");
|
|
|
|
Map *map = lua_touserdata(L, 1);
|
|
|
|
|
|
|
|
lua_close(L);
|
|
|
|
|
2018-02-09 09:36:24 +01:00
|
|
|
// Reset the map
|
|
|
|
map->currentRoom = (Position) { 0, 0 };
|
|
|
|
|
2018-03-13 16:13:54 +01:00
|
|
|
debug("Running lua script %s: Done", file);
|
2017-12-02 23:32:40 +01:00
|
|
|
|
|
|
|
return map;
|
|
|
|
}
|
2018-02-09 13:27:25 +01:00
|
|
|
|
|
|
|
Map* map_lua_generator_single_room__run(unsigned int level, SDL_Renderer *renderer)
|
|
|
|
{
|
2018-02-23 19:32:01 +01:00
|
|
|
char file[] = "menumapgen.lua";
|
2018-10-26 18:37:50 +02:00
|
|
|
return generate_map(level, file, REGULAR, renderer);
|
2018-02-09 13:27:25 +01:00
|
|
|
}
|
|
|
|
|
2018-10-26 18:37:50 +02:00
|
|
|
Map* map_lua_generator_run(unsigned int level, GameMode gameMode, SDL_Renderer *renderer)
|
2018-02-09 13:27:25 +01:00
|
|
|
{
|
2018-02-23 19:32:01 +01:00
|
|
|
char file[] = "mapgen.lua";
|
2018-10-26 18:37:50 +02:00
|
|
|
return generate_map(level, file, gameMode, renderer);
|
2018-02-09 13:27:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|