From 07924bdd6461d347a737dc45b3df05d125ecfb1a Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Mon, 9 May 2011 18:57:07 +0000 Subject: [PATCH] New "Building" map generator git-svn-id: http://svn.net-core.org/repos/t-engine4@3327 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/engines/default/engine/BSP.lua | 4 +- .../default/engine/generator/map/Building.lua | 211 ++++++++++++++++++ game/engines/default/modules/boot/load.lua | 3 + game/modules/tome/class/Game.lua | 4 +- game/modules/tome/class/GameState.lua | 33 ++- game/modules/tome/data/zones/test/zone.lua | 1 + 6 files changed, 242 insertions(+), 14 deletions(-) create mode 100644 game/engines/default/engine/generator/map/Building.lua diff --git a/game/engines/default/engine/BSP.lua b/game/engines/default/engine/BSP.lua index 26aab303f9..d676602cf0 100644 --- a/game/engines/default/engine/BSP.lua +++ b/game/engines/default/engine/BSP.lua @@ -53,7 +53,7 @@ function _M:partition(store) -- print("[BSP] vertical split", s) store.nodes[1] = {depth=store.depth+1, x=0, y=0, rx=store.rx, ry=store.ry, w=store.w, h=s, nodes={}, id=self.node_id} self.node_id = self.node_id + 1 store.nodes[2] = {depth=store.depth+1, x=0, y=s, rx=store.rx, ry=store.ry + s, w=store.w, h=store.h - s, nodes={}, id=self.node_id} self.node_id = self.node_id + 1 - self.splits.vert[store.ry + s] = true + self.splits.vert[store.ry + s] = {min=store.rx, max=store.rx+store.w} self:partition(store.nodes[1]) self:partition(store.nodes[2]) @@ -62,7 +62,7 @@ function _M:partition(store) -- print("[BSP] horizontal split", s) store.nodes[1] = {depth=store.depth+1, x=0, y=0, rx=store.rx, ry=store.ry, w=s, h=store.h, nodes={}, id=self.node_id} self.node_id = self.node_id + 1 store.nodes[2] = {depth=store.depth+1, x=s, y=0, rx=store.rx + s, ry=store.ry, w=store.w -s , h=store.h, nodes={}, id=self.node_id} self.node_id = self.node_id + 1 - self.splits.hor[store.rx + s] = true + self.splits.hor[store.rx + s] = {min=store.ry, max=store.ry+store.h} self:partition(store.nodes[1]) self:partition(store.nodes[2]) end diff --git a/game/engines/default/engine/generator/map/Building.lua b/game/engines/default/engine/generator/map/Building.lua new file mode 100644 index 0000000000..cb728cf276 --- /dev/null +++ b/game/engines/default/engine/generator/map/Building.lua @@ -0,0 +1,211 @@ +-- TE4 - T-Engine 4 +-- Copyright (C) 2009, 2010, 2011 Nicolas Casalini +-- +-- 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/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +require "engine.class" +local Map = require "engine.Map" +local BSP = require "engine.BSP" +require "engine.Generator" +local RoomsLoader = require "engine.generator.map.RoomsLoader" +module(..., package.seeall, class.inherit(engine.Generator, RoomsLoader)) + +function _M:init(zone, map, level, data) + engine.Generator.init(self, zone, map, level) + self.data = data + self.grid_list = self.zone.grid_list + self.max_block_w = data.max_block_w or 20 + self.max_block_h = data.max_block_h or 20 + self.max_building_w = data.max_building_w or 7 + self.max_building_h = data.max_building_h or 7 + + RoomsLoader.init(self, data) +end + +function _M:building(leaf, spots) +-- local x1, x2 = leaf.rx + rng.range(2, math.max(2, math.floor(leaf.w / 2 - 3))), leaf.rx + leaf.w - rng.range(2, math.max(2, math.floor(leaf.w / 2 - 3))) +-- local y1, y2 = leaf.ry + rng.range(2, math.max(2, math.floor(leaf.h / 2 - 3))), leaf.ry + leaf.h - rng.range(2, math.max(2, math.floor(leaf.h / 2 - 3))) + local x1, x2 = leaf.rx, leaf.rx + leaf.w + local y1, y2 = leaf.ry, leaf.ry + leaf.h + local ix1, ix2, iy1, iy2 = x1 + 2, x2 - 1, y1 + 2, y2 - 1 + local inner_grids = {} + local door_grids = {} + local is_lit = rng.percent(self.data.lite_room_chance or 70) + + for i = leaf.rx, leaf.rx + leaf.w do for j = leaf.ry, leaf.ry + leaf.h do + -- Abort if there is something already + if self.map:isBound(i, j) and self.map.room_map[i][j].room then return end + end end + + for i = x1, x2 do for j = y1, y2 do + if i == x1 or i == x2 or j == y1 or j == y2 then + if not self.map.room_map[i][j].walled then self.map(i, j, Map.TERRAIN, self:resolve("wall")) end + self.map.room_map[i][j].walled = true + if not (i == x1 and j == y1) and not (i == x1 and j == y2) and not (i == x2 and j == y1) and not (i == x2 and j == y2) then + door_grids[#door_grids+1] = {x=i,y=j} + end + else + self.map(i, j, Map.TERRAIN, self:resolve("floor")) + if is_lit then self.map.lites(i, j, true) end + if i >= ix1 and i <= ix2 and j >= iy1 and j <= iy2 then + inner_grids[#inner_grids+1] = {x=i,y=j} + end + end + end end + + -- Door + local door = rng.table(door_grids) + self.map(door.x, door.y, Map.TERRAIN, self:resolve("door")) + -- Eliminate inner grids that face the door + for i = #inner_grids, 1, -1 do + local g = inner_grids[i] + if g.x == door.x or g.y == door.y then table.remove(inner_grids, i) end + end + + spots[#spots+1] = {x=math.floor((x1+x2)/2), y=math.floor((y1+y2)/2), type="building", subtype="building"} +end + +function _M:block(leaf, spots) + local x1, x2 = leaf.rx, leaf.rx + leaf.w + local y1, y2 = leaf.ry, leaf.ry + leaf.h + local ix1, ix2, iy1, iy2 = x1 + 2, x2 - 1, y1 + 2, y2 - 1 + local inner_grids = {} + local door_grids = {} + + for i = leaf.rx, leaf.rx + leaf.w do for j = leaf.ry, leaf.ry + leaf.h do + -- Abort if there is something already + if self.map:isBound(i, j) and self.map.room_map[i][j].room then return end + end end + + local door_grids = {} + for i = x1, x2 do for j = y1, y2 do + if i == x1 or i == x2 or j == y1 or j == y2 then + self.map(i, j, Map.TERRAIN, self:resolve("floor")) + elseif (i == x1+1 or i == x2-1 or j == y1+1 or j == y2-1) and + not (i == x1+1 and j == y1+1) and not (i == x1+1 and j == y2-1) and not (i == x2-1 and j == y1+1) and not (i == x2-1 and j == y2-1) then + door_grids[#door_grids+1] = {x=i,y=j} + end + end end + + -- Door + local door = rng.table(door_grids) + self.map(door.x, door.y, Map.TERRAIN, self:resolve("door")) + + local bsp = BSP.new(leaf.w-2, leaf.h-2, self.max_building_w, self.max_building_h) + bsp:partition() + + print("Building gen made ", #bsp.leafs, "building BSP leafs") + for z, sleaf in ipairs(bsp.leafs) do + sleaf.rx = sleaf.rx + leaf.rx + 1 + sleaf.ry = sleaf.ry + leaf.ry + 1 + self:building(sleaf, spots) + end +end + +function _M:generate(lev, old_lev) + for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do + self.map(i, j, Map.TERRAIN, self:resolve("wall")) + end end + + local spots = {} + self.spots = spots + + local bsp = BSP.new(self.map.w, self.map.h, self.max_block_w, self.max_block_h) + bsp:partition() + + print("Building gen made ", #bsp.leafs, "blocks BSP leafs") + for z, leaf in ipairs(bsp.leafs) do + self:block(leaf, spots) + end + + local ux, uy, dx, dy + if self.data.edge_entrances then + ux, uy, dx, dy, spots = self:makeStairsSides(lev, old_lev, self.data.edge_entrances, spots) + else + ux, uy, dx, dy, spots = self:makeStairsInside(lev, old_lev, spots) + end + + return ux, uy, dx, dy, spots +end + +--- Create the stairs inside the level +function _M:makeStairsInside(lev, old_lev, spots) + -- Put down stairs + local dx, dy + if lev < self.zone.max_level or self.data.force_last_stair then + while true do + dx, dy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1) + if not self.map:checkEntity(dx, dy, Map.TERRAIN, "block_move") and not self.map.room_map[dx][dy].special then + self.map(dx, dy, Map.TERRAIN, self:resolve("down")) + self.map.room_map[dx][dy].special = "exit" + break + end + end + end + + -- Put up stairs + local ux, uy + while true do + ux, uy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1) + if not self.map:checkEntity(ux, uy, Map.TERRAIN, "block_move") and not self.map.room_map[ux][uy].special then + self.map(ux, uy, Map.TERRAIN, self:resolve("up")) + self.map.room_map[ux][uy].special = "exit" + break + end + end + + return ux, uy, dx, dy, spots +end + +--- Create the stairs on the sides +function _M:makeStairsSides(lev, old_lev, sides, spots) + -- Put down stairs + local dx, dy + if lev < self.zone.max_level or self.data.force_last_stair then + while true do + if sides[2] == 4 then dx, dy = 0, rng.range(0, self.map.h - 1) + elseif sides[2] == 6 then dx, dy = self.map.w - 1, rng.range(0, self.map.h - 1) + elseif sides[2] == 8 then dx, dy = rng.range(0, self.map.w - 1), 0 + elseif sides[2] == 2 then dx, dy = rng.range(0, self.map.w - 1), self.map.h - 1 + end + + if not self.map.room_map[dx][dy].special then + self.map(dx, dy, Map.TERRAIN, self:resolve("down")) + self.map.room_map[dx][dy].special = "exit" + break + end + end + end + + -- Put up stairs + local ux, uy + while true do + if sides[1] == 4 then ux, uy = 0, rng.range(0, self.map.h - 1) + elseif sides[1] == 6 then ux, uy = self.map.w - 1, rng.range(0, self.map.h - 1) + elseif sides[1] == 8 then ux, uy = rng.range(0, self.map.w - 1), 0 + elseif sides[1] == 2 then ux, uy = rng.range(0, self.map.w - 1), self.map.h - 1 + end + + if not self.map.room_map[ux][uy].special then + self.map(ux, uy, Map.TERRAIN, self:resolve("up")) + self.map.room_map[ux][uy].special = "exit" + break + end + end + + return ux, uy, dx, dy, spots +end diff --git a/game/engines/default/modules/boot/load.lua b/game/engines/default/modules/boot/load.lua index 888977c784..f35cdbdbb7 100644 --- a/game/engines/default/modules/boot/load.lua +++ b/game/engines/default/modules/boot/load.lua @@ -27,10 +27,13 @@ local ActorAI = require "engine.interface.ActorAI" local ActorLevel = require "engine.interface.ActorLevel" local ActorTemporaryEffects = require "engine.interface.ActorTemporaryEffects" local Birther = require "engine.Birther" +local UIBase = require "engine.ui.Base" local n = core.noise.new(2) _2DNoise = n:makeTexture2D(64, 64) +UIBase:setTextShadow(0.6) + -- Usefull keybinds KeyBind:load("move,hotkeys,inventory,actions,interface,debug") diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 5584be2605..bdad77785d 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -934,10 +934,10 @@ function _M:setupCommands() print((" [ [[\n%d%d%d\n%d %d\n%d%d%d]] ] = '',"):format(g7,g8,g9,g4,g6,g1,g2,g3)) end end, [{"_g","ctrl"}] = function() if config.settings.cheat then --- self.state:debugRandomZone() + self.state:debugRandomZone() -- local m = game.zone:makeEntity(game.level, "actor", {random_boss=true}, nil, true) -- if m then game.zone:addEntity(game.level, m, "actor", game.player.x, game.player.y + 1) end - self:changeLevel(1, "test") +-- self:changeLevel(1, "test") end end, } diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index c593a912e5..1e6283390c 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -1049,6 +1049,19 @@ local random_zone_layouts = { door = data:getDoor(), ["'"] = data:getDoor(), } end }, + -- Building + { name="building", rarity=1, gen=function(data) + return { + class = "engine.generator.map.Building", + lite_room_chance = rng.range(0, 100), + max_block_w = rng.range(14, 20), max_block_h = rng.range(14, 20), + max_building_w = rng.range(4, 8), max_building_h = rng.range(4, 8), + floor = data:getFloor(), + wall = data:getWall(), + up = data:getUp(), + down = data:getDown(), + door = data:getDoor(), + } end }, } local random_zone_themes = { @@ -1169,7 +1182,7 @@ function _M:createRandomZone(zbase) end end local base = rng.table(list) - local boss, boss_id = self:createRandomBoss(base, data.min_lev + data.depth + rng.range(2, 4)) + local boss, boss_id = self:createRandomBoss(base, {level=data.min_lev + data.depth + rng.range(2, 4)}) npcs[boss_id] = boss ------------------------------------------------------------ @@ -1379,15 +1392,15 @@ function _M:debugRandomZone() local zone = self:createRandomZone() game:changeLevel(zone.max_level, zone) - game.level.map:liteAll(0, 0, game.level.map.w, game.level.map.h) - game.level.map:rememberAll(0, 0, game.level.map.w, game.level.map.h) - for i = 0, game.level.map.w - 1 do - for j = 0, game.level.map.h - 1 do - local trap = game.level.map(i, j, game.level.map.TRAP) - if trap then - trap:setKnown(game.player, true) - game.level.map:updateMap(i, j) - end + game.level.map:liteAll(0, 0, game.level.map.w, game.level.map.h) + game.level.map:rememberAll(0, 0, game.level.map.w, game.level.map.h) + for i = 0, game.level.map.w - 1 do + for j = 0, game.level.map.h - 1 do + local trap = game.level.map(i, j, game.level.map.TRAP) + if trap then + trap:setKnown(game.player, true) + game.level.map:updateMap(i, j) end end + end end diff --git a/game/modules/tome/data/zones/test/zone.lua b/game/modules/tome/data/zones/test/zone.lua index ce8b074921..c199081a41 100644 --- a/game/modules/tome/data/zones/test/zone.lua +++ b/game/modules/tome/data/zones/test/zone.lua @@ -32,6 +32,7 @@ return { generator = { map = { class = "engine.generator.map.Building", + max_block_w = 15, max_block_h = 15, max_building_w = 5, max_building_h = 5, floor = "FLOOR", external_floor = "FLOOR", -- GitLab