diff --git a/data/mapgen.lua b/data/mapgen.lua index 672ebe9..902c077 100644 --- a/data/mapgen.lua +++ b/data/mapgen.lua @@ -49,7 +49,11 @@ local function generate_path () local direction = 0 local lastDirection = 0 local coridoor_count = 0 + local bossLevel = CURRENT_LEVEL % 5 == 0 local coverage = 9 + CURRENT_LEVEL + if bossLevel then + coverage = 5 + end -- Create the first room map_matrix[cx][cy] = room_builder.create_empty_room() @@ -110,15 +114,23 @@ local function generate_path () map_matrix[cx][cy].goal = true map_matrix[cx][cy].type = "room" + local roomCount = 0 + local bossAdded = false + -- Build all the rooms for i=1,10 do for j=1,10 do room = map_matrix[i][j] if room then + roomCount = roomCount + 1 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) chest_gen.add_chests_to_room(room, i-1, j-1) + if roomCount > 3 and bossLevel and not bossAdded then + bossAdded = true + monster_gen.add_boss_to_room(room, i-1, j-1) + end end end end diff --git a/data/maproombuilder.lua b/data/maproombuilder.lua index ff23c84..6889487 100644 --- a/data/maproombuilder.lua +++ b/data/maproombuilder.lua @@ -405,6 +405,7 @@ local function room_tile_available(room, rx, ry) and not room.decor[rx][ry] and (room.tiles[rx][ry] and not room.tiles[rx][ry][5] + and not room.tiles[rx][ry][7] and not room.tiles[rx][ry][8]) end diff --git a/data/monstergen.lua b/data/monstergen.lua index e9c5ee3..de98692 100644 --- a/data/monstergen.lua +++ b/data/monstergen.lua @@ -44,7 +44,8 @@ local behaviour = { hostile = 2, guerilla = 3, coward = 4, - sentinel = 5 + sentinel = 5, + fire_demon = 6 } local stats = { @@ -83,6 +84,13 @@ local stats = { def = 0, speed = 1 }, + boss = { + hp = 60, + dmg = 4, + atk = 1, + def = 0, + speed = 1 + }, platino = { hp = 60, dmg = 60, @@ -137,49 +145,54 @@ end local undead = { -- UNDEAD - { stats.undead, 0, 32, "A Skeleton", behaviour.normal }; - { stats.undead, 48, 32, "A Black Skeleton", behaviour.normal }; - { stats.undead, 64, 32, "A Zombie", behaviour.normal }; - { stats.undead, 80, 32, "A Zombie", behaviour.normal }; + { stats.undead, 0, 32, "A Skeleton", behaviour.normal }, + { stats.undead, 48, 32, "A Black Skeleton", behaviour.normal }, + { stats.undead, 64, 32, "A Zombie", behaviour.normal }, + { stats.undead, 80, 32, "A Zombie", behaviour.normal } } for i=1,#undead do undead[i] = concat({ texturePaths.undead0, texturePaths.undead1 }, undead[i]) end local dogs = { - { stats.dog, 0, 16, "A Rabid Dog", behaviour.normal }; - { stats.dog, 16, 16, "An Angry Rabid Dog", behaviour.hostile }; + { stats.dog, 0, 16, "A Rabid Dog", behaviour.normal }, + { stats.dog, 16, 16, "An Angry Rabid Dog", behaviour.hostile } } for i=1,#dogs do dogs[i] = concat({ texturePaths.dog0, texturePaths.dog1 }, dogs[i]) end local reptile = { - { stats.default, 0, 64, "A Small Brown Snake", behaviour.coward }; - { stats.default, 16, 64, "A Medium Brown Snake", behaviour.guerilla }; - { stats.default, 32, 64, "A Large Brown Snake", behaviour.hostile }; - { stats.default, 48, 64, "A Small Black Snake", behaviour.coward }; - { stats.default, 64, 64, "A Medium Black Snake", behaviour.guerilla }; - { stats.default, 80, 64, "A Large Black Snake", behaviour.hostile }; + { stats.default, 0, 64, "A Small Brown Snake", behaviour.coward }, + { stats.default, 16, 64, "A Medium Brown Snake", behaviour.guerilla }, + { stats.default, 32, 64, "A Large Brown Snake", behaviour.hostile }, + { stats.default, 48, 64, "A Small Black Snake", behaviour.coward }, + { stats.default, 64, 64, "A Medium Black Snake", behaviour.guerilla }, + { stats.default, 80, 64, "A Large Black Snake", behaviour.hostile }, } for i=1,#reptile do reptile[i] = concat({ texturePaths.reptile0, texturePaths.reptile1 }, reptile[i]) end local demon = { - { stats.default, 0, 0, "A Demon", behaviour.hostile }; - { stats.default, 16, 0, "A Demon", behaviour.hostile }; - { stats.default, 32, 0, "A Demon", behaviour.hostile }; - { stats.default, 48, 0, "A Demon", behaviour.hostile }; - { stats.default, 64, 0, "A Demon", behaviour.hostile }; - { stats.default, 80, 0, "A Demon", behaviour.hostile }; - { stats.default, 96, 0, "A Demon", behaviour.hostile }; - { stats.default, 112, 0, "A Demon", behaviour.hostile }; + { stats.default, 0, 0, "A Demon", behaviour.hostile }, + { stats.default, 16, 0, "A Demon", behaviour.hostile }, + { stats.default, 32, 0, "A Demon", behaviour.hostile }, + { stats.default, 48, 0, "A Demon", behaviour.hostile }, + { stats.default, 64, 0, "A Demon", behaviour.hostile }, + { stats.default, 80, 0, "A Demon", behaviour.hostile }, + { stats.default, 96, 0, "A Demon", behaviour.hostile }, + { stats.default, 112, 0, "A Demon", behaviour.hostile }, } for i=1,#demon do demon[i] = concat({ texturePaths.demon0, texturePaths.demon1 }, demon[i]) end +local bosses = { + { stats.boss, 16, 5*16, "The Hell Hound", behaviour.fire_demon, true } +} +bosses[1] = concat({ texturePaths.dog0, texturePaths.dog1 }, bosses[1]) + local platino = { { texturePaths.reptile0, @@ -201,6 +214,7 @@ local function repack(data) clipY = data[5], label = data[6] or "", behaviour = data[7] or behaviour.normal, + boss = data[8] or false, } end @@ -239,7 +253,7 @@ if(CURRENT_LEVEL > 0 and CURRENT_LEVEL < 10) then end if random(100) == 1 then - enemies = concat(enemies, platino); + enemies = concat(enemies, platino) end function module.add_monsters_to_room(room, roomx, roomy) @@ -264,6 +278,25 @@ function module.add_monsters_to_room(room, roomx, roomy) end end +function module.add_boss_to_room(room, roomx, roomy) + local boss = bosses[1] + local success = false + while not success do + local rx = random(13) + 1 + local ry = random(9) + 1 + if room_builder.is_tile_avilable(room, rx, ry) then + local x = (roomx * 512) + rx * 32 + local y = (roomy * 384) + ry * 32 + room.monsters[rx][ry] = { + x, + y, + boss + } + success = true + end + end +end + function module.load_monsters(map, monsters) for i=0,15 do for j=0,11 do diff --git a/src/main.c b/src/main.c index 5b6839f..7291ef5 100644 --- a/src/main.c +++ b/src/main.c @@ -216,6 +216,14 @@ startGame(void *unused) player_destroy(gPlayer); gPlayer = player_create(WARRIOR, gRenderer); mixer_play_music(GAME_MUSIC0 + get_random(2)); +#ifdef DEBUG + // This block is for testing + cLevel = 1; + if (cLevel % 5 == 0) + mixer_play_music(BOSS_MUSIC0); + for (size_t i = 1; i < cLevel; ++i) + player_levelup(gPlayer); +#endif // DEBUG resetGame(); gui_clear_message_log(); gui_log("The Dungeon Crawl begins!"); diff --git a/src/map_lua.c b/src/map_lua.c index 5719434..cf3dc95 100644 --- a/src/map_lua.c +++ b/src/map_lua.c @@ -358,6 +358,7 @@ l_add_monster(lua_State *L) int x, y, clip_x, clip_y, behaviour; const char *texture_path_1, *texture_path_2, *tmp_label; char *label; + bool boss; Texture *texture1, *texture2; Stats stats; @@ -376,14 +377,16 @@ l_add_monster(lua_State *L) lua_getfield(L, 4, "clipX"); lua_getfield(L, 4, "clipY"); lua_getfield(L, 4, "behaviour"); + lua_getfield(L, 4, "boss"); - tmp_label = luaL_checkstring(L, -7); - texture_path_1 = luaL_checkstring(L, -6); - texture_path_2 = luaL_checkstring(L, -5); - stats = lua_checkstats(L, -4); - clip_x = (int) luaL_checkinteger(L, -3); - clip_y = (int) luaL_checkinteger(L, -2); - behaviour = (int) luaL_checkinteger(L, -1); + 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); texture1 = texturecache_add(texture_path_1); texture2 = texturecache_add(texture_path_2); @@ -404,6 +407,7 @@ l_add_monster(lua_State *L) } monster->stats = stats; + monster->boss = boss; map_add_monster(map, monster); diff --git a/src/monster.c b/src/monster.c index bc1a774..a46bd2a 100644 --- a/src/monster.c +++ b/src/monster.c @@ -199,6 +199,7 @@ monster_create(void) m->stateIndicator.displayCount = 0; m->stateIndicator.shownOnPlayerRoomEnter = false; m->state.forceCount = 0; + m->boss = false; monster_set_behaviour(m, NORMAL); return m; @@ -532,6 +533,15 @@ monster_drop_loot(Monster *monster, Map *map, Player *player) unsigned int item_count = 0; bool player_full_health = player->stats.hp >= player->stats.maxhp; + if (monster->boss) { + Artifact *a = artifact_create_random(player, 2); + a->sprite->pos = monster->sprite->pos; + linkedlist_append(&map->artifacts, a); + Item *treasure = item_builder_build_item(TREASURE, map->level*2); + treasure->sprite->pos = monster->sprite->pos; + linkedlist_append(&map->items, treasure); + } + if (get_random(19) == 0) { Artifact *a = artifact_create_random(player, 1); a->sprite->pos = monster->sprite->pos; diff --git a/src/monster.h b/src/monster.h index d61078c..91ebd1b 100644 --- a/src/monster.h +++ b/src/monster.h @@ -70,6 +70,7 @@ typedef struct Monster { MonsterStateIndicator stateIndicator; MonsterBehaviour behaviour; unsigned int steps; + bool boss; } Monster; Monster* monster_create(void); diff --git a/src/roommatrix.c b/src/roommatrix.c index 519b37e..7c5f9d0 100644 --- a/src/roommatrix.c +++ b/src/roommatrix.c @@ -295,8 +295,6 @@ void roommatrix_destroy(RoomMatrix *m) linkedlist_pop(&space->items); while (space->artifacts) linkedlist_pop(&space->artifacts); - while (space->objects) - linkedlist_pop(&space->objects); } } diff --git a/src/util.h b/src/util.h index b2b92c4..5e0fcd3 100644 --- a/src/util.h +++ b/src/util.h @@ -35,11 +35,22 @@ #define info(...) do {} while(0) #endif // DEBUG #define error(...) log_print(stderr, "ERROR", __FNAME__, __LINE__, __func__, __VA_ARGS__) + +#ifdef DEBUG +#define fatal(...) \ +{ \ + log_print(stderr, "FATAL", __FNAME__, __LINE__, __func__, __VA_ARGS__); \ + printf("\n- Press any key to close -\n"); \ + getchar(); \ + exit(-1); \ +} +#else #define fatal(...) \ { \ log_print(stderr, "FATAL", __FNAME__, __LINE__, __func__, __VA_ARGS__); \ exit(-1); \ } +#endif // DEBUG void log_print(FILE *out,