diff --git a/game/engines/default/engine/generator/map/Forest.lua b/game/engines/default/engine/generator/map/Forest.lua index ccf16d1d75f3ae46658e5df964a72dfedc198218..320c66c36b5273692e349b55ffa08bc723d177e8 100644 --- a/game/engines/default/engine/generator/map/Forest.lua +++ b/game/engines/default/engine/generator/map/Forest.lua @@ -227,6 +227,26 @@ function _M:generate(lev, old_lev) rooms[#rooms+1] = r end_room = r print("Successfully loaded the end room") + else + self.force_recreate = true return + end + end + + -- Those we are required to have + if #self.required_rooms > 0 then + for i, rroom in ipairs(self.required_rooms) do + local ok = false + if type(rroom) == "table" and rroom.chance_room then + if rng.percent(rroom.chance_room) then rroom = rroom[1] ok = true end + else ok = true + end + + if ok then + local r = self:roomAlloc(rroom, #rooms+1, lev, old_lev) + if r then rooms[#rooms+1] = r + else self.force_recreate = true return end + nb_room = nb_room - 1 + end end end diff --git a/game/engines/default/engine/generator/map/RoomsLoader.lua b/game/engines/default/engine/generator/map/RoomsLoader.lua index 6f254ac618de538eefe9897894c2fe45f9fd6cfd..a3e0a480bf749a69be8140565687ea09271e1d94 100644 --- a/game/engines/default/engine/generator/map/RoomsLoader.lua +++ b/game/engines/default/engine/generator/map/RoomsLoader.lua @@ -50,12 +50,232 @@ end local rooms_cache = {} +function _M:tmxLoadRoom(file) + file = file:gsub("%.lua$", ".tmx") + if not fs.exists(file) then return end + print("Static generator using file", file) + local f = fs.open(file, "r") + local data = f:read(10485760) + f:close() + + local t = {} + local g = self:getLoader(t) + local map = lom.parse(data) + local mapprops = {} + if map:findOne("properties") then mapprops = map:findOne("properties"):findAllAttrs("property", "name", "value") end + local w, h = tonumber(map.attr.width), tonumber(map.attr.height) + local tw, th = tonumber(map.attr.tilewidth), tonumber(map.attr.tileheight) + local chars = {} + local start_tid, end_tid = nil, nil + for _, tileset in ipairs(map:findAll("tileset")) do + if tileset:findOne("properties") then for name, value in pairs(tileset:findOne("properties"):findAllAttrs("property", "name", "value")) do + if name == "load_terrains" then + local list = self:loadLuaInEnv(g, nil, "return "..value) or {} + self.zone.grid_class:loadList(list, nil, self.grid_list, nil, self.grid_list.__loaded_files) + elseif name == "load_traps" then + local list = self:loadLuaInEnv(g, nil, "return "..value) or {} + self.zone.trap_class:loadList(list, nil, self.trap_list, nil, self.trap_list.__loaded_files) + elseif name == "load_objects" then + local list = self:loadLuaInEnv(g, nil, "return "..value) or {} + self.zone.object_class:loadList(list, nil, self.object_list, nil, self.object_list.__loaded_files) + elseif name == "load_actors" then + local list = self:loadLuaInEnv(g, nil, "return "..value) or {} + self.zone.npc_class:loadList(list, nil, self.npc_list, nil, self.npc_list.__loaded_files) + end + end end + + local firstgid = tonumber(tileset.attr.firstgid) + for _, tile in ipairs(tileset:findAll("tile")) do + local tid = tonumber(tile.attr.id + firstgid) + local display = tile:findOne("property", "name", "display") + local id = tile:findOne("property", "name", "id") + local data_id = tile:findOne("property", "name", "data_id") + local custom = tile:findOne("property", "name", "custom") + local is_start = tile:findOne("property", "name", "start") + local is_end = tile:findOne("property", "name", "end") or tile:findOne("property", "name", "stop") + if display then + chars[tid] = display.attr.value + elseif id then + t[tid] = id.attr.value + elseif data_id then + t[tid] = self.data[data_id.attr.value] + elseif custom then + local ret = self:loadLuaInEnv(g, nil, "return "..custom.attr.value) + t[tid] = ret + end + if is_start then start_tid = tid end + if is_end then end_tid = tid end + end + end + + local rotate = "default" + if mapprops.rotate then + rotate = self:loadLuaInEnv(g, nil, "return "..mapprops.rotate) or mapprops.rotate + end + + if mapprops.status_all then + self.status_all = self:loadLuaInEnv(g, nil, "return "..mapprops.status_all) or {} + end + + if mapprops.add_data then + table.merge(self.level.data, self:loadLuaInEnv(g, nil, "return "..mapprops.add_data) or {}, true) + end + + if mapprops.lua then + self:loadLuaInEnv(g, nil, "return "..mapprops.lua) + end + + local m = { w=w, h=h } + + local function rotate_coords(i, j) + local ii, jj = i, j + if rotate == "flipx" then ii, jj = m.w - i + 1, j + elseif rotate == "flipy" then ii, jj = i, m.h - j + 1 + elseif rotate == "90" then ii, jj = j, m.w - i + 1 + elseif rotate == "180" then ii, jj = m.w - i + 1, m.h - j + 1 + elseif rotate == "270" then ii, jj = m.h - j + 1, i + end + return ii, jj + end + local function populate(i, j, c, tid) + local ii, jj = rotate_coords(i, j) + + m[ii] = m[ii] or {} + if type(c) == "string" then + m[ii][jj] = c + else + m[ii][jj] = m[ii][jj] or {} + table.update(m[ii][jj], c) + end + if tid == start_tid then m.startx = ii - 1 m.starty = jj - 1 m.start_rotated = true end + if tid == end_tid then m.endx = ii - 1 m.endy = jj - 1 m.end_rotated = true end + end + + self.gen_map = m + self.tiles = t + + self.map.w = m.w + self.map.h = m.h + + for _, layer in ipairs(map:findAll("layer")) do + local mapdata = layer:findOne("data") + local layername = layer.attr.name:lower() + if layername == "terrain" then layername = "grid" end + + if mapdata.attr.encoding == "base64" then + local b64 = mime.unb64(mapdata[1]:trim()) + local data + if mapdata.attr.compression == "zlib" then data = zlib.decompress(b64) + elseif not mapdata.attr.compression then data = b64 + else error("tmx map compression unsupported: "..mapdata.attr.compression) + end + local gid, i = nil, 1 + local x, y = 1, 1 + while i <= #data do + gid, i = struct.unpack("<I4", data, i) + if chars[gid] then populate(x, y, chars[id]) + else populate(x, y, {[layername] = gid}, gid) + end + x = x + 1 + if x > w then x = 1 y = y + 1 end + end + elseif mapdata.attr.encoding == "csv" then + local data = mapdata[1]:gsub("[^,0-9]", ""):split(",") + local x, y = 1, 1 + for i, gid in ipairs(data) do + gid = tonumber(gid) + if chars[gid] then populate(x, y, chars[id]) + else populate(x, y, {[layername] = gid}, gid) + end + x = x + 1 + if x > w then x = 1 y = y + 1 end + end + elseif not mapdata.attr.encoding then + local data = mapdata:findAll("tile") + local x, y = 1, 1 + for i, tile in ipairs(data) do + local gid = tonumber(tile.attr.gid) + if chars[gid] then populate(x, y, chars[id]) + else populate(x, y, {[layername] = gid}, gid) + end + x = x + 1 + if x > w then x = 1 y = y + 1 end + end + end + end + + self.add_attrs_later = {} + + for _, og in ipairs(map:findAll("objectgroup")) do + for _, o in ipairs(map:findAll("object")) do + local props = o:findOne("properties"):findAllAttrs("property", "name", "value") + + if og.attr.name:find("^addSpot") then + local x, y, w, h = math.floor(tonumber(o.attr.x) / tw), math.floor(tonumber(o.attr.y) / th), math.floor(tonumber(o.attr.width) / tw), math.floor(tonumber(o.attr.height) / th) + if props.start then m.startx = x m.starty = y end + if props['end'] then m.endx = x m.endy = y end + if props.type and props.subtype then + for i = x, x + w do for j = y, y + h do + local i, j = rotate_coords(i, j) + g.addSpot({i, j}, props.type, props.subtype) + end end + end + elseif og.attr.name:find("^addZone") then + local x, y, w, h = math.floor(tonumber(o.attr.x) / tw), math.floor(tonumber(o.attr.y) / th), math.floor(tonumber(o.attr.width) / tw), math.floor(tonumber(o.attr.height) / th) + if props.type and props.subtype then + local i1, j2 = rotate_coords(x, y) + local i2, j2 = rotate_coords(x + w, y + h) + g.addZone({x, y, x + w, y + h}, props.type, props.subtype) + end + elseif og.attr.name:find("^attrs") then + local x, y, w, h = math.floor(tonumber(o.attr.x) / tw), math.floor(tonumber(o.attr.y) / th), math.floor(tonumber(o.attr.width) / tw), math.floor(tonumber(o.attr.height) / th) + for k, v in pairs(props) do + for i = x, x + w do for j = y, y + h do + local i, j = rotate_coords(i, j) + self.add_attrs_later[#self.add_attrs_later+1] = {x=i, y=j, key=k, value=self:loadLuaInEnv(g, nil, "return "..v)} + print("====", i, j, k) + end end + end + end + end + end + + m.startx = m.startx or math.floor(m.w / 2) + m.starty = m.starty or math.floor(m.h / 2) + m.endx = m.endx or math.floor(m.w / 2) + m.endy = m.endy or math.floor(m.h / 2) + if rotate == "flipx" then + if not m.start_rotated then m.startx = m.w - m.startx - 1 end + if not m.end_rotated then m.endx = m.w - m.endx - 1 end + elseif rotate == "flipy" then + if not m.start_rotated then m.starty = m.h - m.starty - 1 end + if not m.end_rotated then m.endy = m.h - m.endy - 1 end + elseif rotate == "90" then + if not m.start_rotated then m.startx, m.starty = m.starty, m.w - m.startx - 1 end + if not m.end_rotated then m.endx, m.endy = m.endy, m.w - m.endx - 1 end + m.w, m.h = m.h, m.w + elseif rotate == "180" then + if not m.start_rotated then m.startx, m.starty = m.w - m.startx - 1, m.h - m.starty - 1 end + if not m.end_rotated then m.endx, m.endy = m.w - m.endx - 1, m.h - m.endy - 1 end + elseif rotate == "270" then + if not m.start_rotated then m.startx, m.starty = m.h - m.starty - 1, m.startx end + if not m.end_rotated then m.endx, m.endy = m.h - m.endy - 1, m.endx end + m.w, m.h = m.h, m.w + end + + print("[STATIC TMX MAP] size", m.w, m.h) + return true +end + function _M:loadRoom(file) if rooms_cache[file] then return rooms_cache[file] end local filename = "/data/rooms/"..file..".lua" -- Found in the zone itself ? if file:find("^!") then filename = self.zone:getBaseName().."/rooms/"..file:sub(2)..".lua" end + local tmxed = self:tmxLoadRoom(filename) + if tmxed then return tmxed end + local f, err = loadfile(filename) if not f and err then error(err) end setfenv(f, setmetatable({ diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 001d29e41c48dae16425a3dc6bc987d9efee608d..a4279352fe2c4a2bc439757b59aac502bf335543 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -1694,7 +1694,7 @@ function _M:setupCommands() print("===============") end end, [{"_g","ctrl"}] = function() if config.settings.cheat then - self:changeLevel(5, "orcs+slumbering-caves") + self:changeLevel(1, "orcs+lost-city") -- self:changeLevel(6, "orcs+palace-fumes") do return end local o = game.zone:makeEntity(game.level, "object", {subtype="steamsaw", random_object=true}, nil, true) diff --git a/game/modules/tome/data/gfx/dark-ui/inven_tabs/tinkers.png b/game/modules/tome/data/gfx/dark-ui/inven_tabs/tinkers.png new file mode 100644 index 0000000000000000000000000000000000000000..92c7005e513c50ca7a40553648bb010898d101e4 Binary files /dev/null and b/game/modules/tome/data/gfx/dark-ui/inven_tabs/tinkers.png differ diff --git a/game/modules/tome/data/gfx/metal-ui/inven_tabs/tinkers.png b/game/modules/tome/data/gfx/metal-ui/inven_tabs/tinkers.png new file mode 100644 index 0000000000000000000000000000000000000000..af792fbb58f05240f141fc28d9e92aa577415c93 Binary files /dev/null and b/game/modules/tome/data/gfx/metal-ui/inven_tabs/tinkers.png differ diff --git a/game/modules/tome/load.lua b/game/modules/tome/load.lua index 0bb29e9853041dea2c3e61c3c89ff29048564280..11e06b29eb6234c1614484de974c74bd005384ee 100644 --- a/game/modules/tome/load.lua +++ b/game/modules/tome/load.lua @@ -251,7 +251,7 @@ InventoryUI.default_tabslist = function(self) tabslist[#tabslist+1] = {image="inven_tabs/jewelry.png", kind="jewelry", desc="Rings and Amulets", filter=function(o) return not o.__transmo and (o.type == "jewelry") end} tabslist[#tabslist+1] = {image="inven_tabs/gems.png", kind="gems", desc="Gems" , filter=function(o) return not o.__transmo and (o.type == "gem" or o.type == "alchemist-gem") end} tabslist[#tabslist+1] = {image="inven_tabs/inscriptions.png", kind="inscriptions", desc="Infusions, Runes, ...", filter=function(o) return not o.__transmo and (o.type == "scroll") end} - if self.actor.can_tinker then tabslist[#tabslist+1] = {image="inven_tabs/chest.png", kind="tinker", desc="Tinkers", filter=function(o) return o.is_tinker end} end + if self.actor.can_tinker then tabslist[#tabslist+1] = {image="inven_tabs/tinkers.png", kind="tinker", desc="Tinkers", filter=function(o) return o.is_tinker end} end tabslist[#tabslist+1] = {image="inven_tabs/misc.png", kind="misc", desc="Miscellaneous", filter="others"} tabslist[#tabslist+1] = {image="inven_tabs/quests.png", kind="quests", desc="Quest and plot related items", filter=function(o) return not o.__transmo and (o.plot or o.quest) end} if self.actor:attr("has_transmo") then tabslist[#tabslist+1] = {image="inven_tabs/chest.png", kind="transmo", desc="Transmogrification Chest", filter=function(o) return o.__transmo end} end