diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua index 3023b7e9af1ea1170997cc7af49a875f14734179..0de153a3424232df28e75b5f2bcc72e6c062bf4f 100644 --- a/game/engine/Entity.lua +++ b/game/engine/Entity.lua @@ -9,6 +9,21 @@ local next_uid = 1 -- Setup the uids repository as a weak value table, when the entities are no more used anywhere else they disappear from there too setmetatable(__uids, {__mode="v"}) +local function copy_recurs(dst, src, deep) + for k, e in pairs(src) do + if not dst[k] then + if deep then + dst[k] = {} + copy_recurs(dst[k], e, deep) + else + dst[k] = e + end + elseif type(dst[k]) == "table" and type(e) == "table" then + copy_recurs(dst[k], e, deep) + end + end +end + --- Initialize an entity -- Any subclass MUST call this constructor -- @param t a table defining the basic properties of the entity @@ -18,7 +33,11 @@ function _M:init(t) self.uid = next_uid __uids[self.uid] = self - for k, e in pairs(t) do self[k] = e end + for k, e in pairs(t) do + local ee = e + if type(e) == "table" then ee = table.clone(e, true) end + self[k] = ee + end self.image = self.image or nil self.display = self.display or '.' @@ -62,6 +81,21 @@ function _M:changeUid(newuid) __uids[self.uid] = self end +--- Resolves an entity +-- This is called when generatingthe final clones of an entity for use in a level.<br/> +-- This can be used to make random enchants on objects, random properties on actors, ...<br/> +-- by default this only looks for properties with a table value containing a __resolver field +function _M:resolve(t) + t = t or self + for k, e in pairs(t) do + if type(e) == "table" and e.__resolver then + t[k] = resolvers.calc[e.__resolver](e, self) + elseif type(e) == "table" then + self:resolve(e) + end + end +end + --- Check for an entity's property -- If not a function it returns it directly, otherwise it calls the function -- with the extra parameters @@ -81,12 +115,40 @@ function _M:loadList(...) for i, file in ipairs{...} do local f, err = loadfile(file) if err then error(err) end - local data = f() - for i, a in ipairs(data) do - local e = self.new(a) - res[#res+1] = e - if a.define_as then res[a.define_as] = e end - end + + setfenv(f, setmetatable({ + resolvers = resolvers, + DamageType = require "engine.DamageType", + newEntity = function(t) + -- Do we inherit things ? + if t.base then + for k, e in pairs(res[t.base]) do + if not t[k] then + t[k] = e + elseif type(t[k]) == "table" and type(e) == "table" then + copy_recurs(t[k], e) + end + end + t.base = nil + end + + local e = self.new(t) + res[#res+1] = e + if t.define_as then res[t.define_as] = e end + print("new entity", t.name) + for k, ee in pairs(e) do + print("prop:", k, ee) + end + end, + load = function(f) + local ret = self:loadList(f) + for i, e in ipairs(ret) do res[#res+1] = e end + end, + loadList = function(f) + return self:loadList(f) + end, + }, {__index=_G})) + f() end return res end diff --git a/game/engine/Object.lua b/game/engine/Object.lua new file mode 100644 index 0000000000000000000000000000000000000000..56eaa2000c8737a698cb3cafa2a3c13a7702a1a6 --- /dev/null +++ b/game/engine/Object.lua @@ -0,0 +1,14 @@ +require "engine.class" +local Entity = require "engine.Entity" + +module(..., package.seeall, class.inherit(Entity)) + +function _M:init(t) + t = t or {} + Entity.init(self, t) +end + +--- Gets the full name of the object +function _M:getName() + return self.name +end diff --git a/game/engine/class.lua b/game/engine/class.lua index dd430c9b4810a8adf8ce5004f3ec1700d269a4fb..e7f10e3166a476c51a83e7bcebe0f119834eb1a2 100644 --- a/game/engine/class.lua +++ b/game/engine/class.lua @@ -32,7 +32,7 @@ function inherit(base, ...) for k, e in pairs(_if) do if k ~= "init" and k ~= "_NAME" and k ~= "_M" and k ~= "_PACKAGE" and k ~= "new" then c[k] = e - print(("caching interface value %s (%s) from %s to %s"):format(k, tostring(e), _if._NAME, c._NAME)) +-- print(("caching interface value %s (%s) from %s to %s"):format(k, tostring(e), _if._NAME, c._NAME)) end end end diff --git a/game/engine/generator/actor/Random.lua b/game/engine/generator/actor/Random.lua index 1719b5862a73952b176693f24eeeac6adb57c0f1..ea129e21505c949e7f8bca5cf398bd61e1eb45b0 100644 --- a/game/engine/generator/actor/Random.lua +++ b/game/engine/generator/actor/Random.lua @@ -17,6 +17,7 @@ end function _M:generate() for i = 1, rng.range(self.nb_npc[1], self.nb_npc[2]) do local m = self.npc_list[rng.range(1, #self.npc_list)]:clone() + m:resolve() local x, y = rng.range(0, self.map.w), rng.range(0, self.map.h) local tries = 0 while self.map:checkAllEntities(x, y, "block_move") and tries < 100 do diff --git a/game/engine/init.lua b/game/engine/init.lua index b0828d951b83e215930c18f5a98524d30cbeff40..17f1fdfe4be2237bacd30f2e949a76c5e2cec5eb 100644 --- a/game/engine/init.lua +++ b/game/engine/init.lua @@ -1,6 +1,9 @@ -- load some utility functions dofile("/engine/utils.lua") +-- load resolver functions for entities cloning +dofile("/engine/resolvers.lua") + require "config" require "engine.KeyCommand" require "engine.Savefile" diff --git a/game/engine/resolvers.lua b/game/engine/resolvers.lua new file mode 100644 index 0000000000000000000000000000000000000000..f2b3fb2881cc70be8a25d6853aa70ac3e245fa82 --- /dev/null +++ b/game/engine/resolvers.lua @@ -0,0 +1,17 @@ +resolvers = {} +resolvers.calc = {} + +--- Resolves a rng range +function resolvers.rngrange(x, y) + return {__resolver="rngrange", x, y} +end +function resolvers.calc.rngrange(t) + return rng.range(t[1], t[2]) +end + +function resolvers.rngavg(x, y) + return {__resolver="rngavg", x, y} +end +function resolvers.calc.rngavg(t) + return rng.avg(t[1], t[2]) +end diff --git a/game/engine/utils.lua b/game/engine/utils.lua index 8ae19e95bf5e67ac4909bd9c27cbfaa59a8a6082..e9930339d78a04ba77f72eba77d81750db6f924e 100644 --- a/game/engine/utils.lua +++ b/game/engine/utils.lua @@ -1,7 +1,8 @@ function table.clone(tbl, deep) local n = {} for k, e in pairs(tbl) do - if deep and type(e) == "table" then + -- Deep copy subtables, but not objects! + if deep and type(e) == "table" and not e.__CLASSNAME then n[k] = table.clone(e, true) else n[k] = e diff --git a/game/modules/tome/data/general/egos.lua b/game/modules/tome/data/general/egos.lua new file mode 100644 index 0000000000000000000000000000000000000000..4cd504528547d632743dc61c6ed96be4d5a03def --- /dev/null +++ b/game/modules/tome/data/general/egos.lua @@ -0,0 +1,16 @@ +newEntity{ + name = "flaming ", + level_range = {1, 10}, + rarity = 3, + wielder = { + melee_project={[DamageType.FIRE] = 4}, + }, +} +newEntity{ + name = " of accuracy", + level_range = {1, 10}, + rarity = 3, + wielder = { + hit = 4, + }, +} diff --git a/game/modules/tome/data/general/objects.lua b/game/modules/tome/data/general/objects.lua new file mode 100644 index 0000000000000000000000000000000000000000..6e11c0c1ef04fd0c3aa0d7f7c8a8ea96ec4fb5ac --- /dev/null +++ b/game/modules/tome/data/general/objects.lua @@ -0,0 +1,53 @@ +newEntity{ + define_as = "BASE_SWORD", + type = "weapon", + display = "\\", color_r=255, + encumber = 3, + egos_chance = { }, + egos = loadList("/data/general/egos.lua"), +} + +newEntity{ + base = "BASE_SWORD", + name = "& #1#longsword~#2#", + level_range = {1, 10}, + rarity = 3, + wielder = { + combat_dam=resolvers.rngavg(7,11), + }, +} + +newEntity{ + name = "& tower shield~", + display = "[", color_r=255, + level_range = {1, 10}, + encumber = 6, + wielder = { + combat_def=6, + }, +} + +newEntity{ + name = "& staff~ of fire", + type = "weapon", + display = "/", color_b=255, + level_range = {1, 10}, + encumber = 4, + wielder = { + combat_dam=3, + stats = {mag=3, wil=2}, + } +} + +newEntity{ + name = "& Staff of Olorin", + type = "weapon", + display = "/", color_r=255, color_b=255, + level_range = {10,10}, + encumber = 3, + unique = "STAFF_OLORIN", + wielder = { + combat_dam=3, + stats = {mag=3, wil=2}, + } +} diff --git a/game/modules/tome/data/zones/ancient_ruins/grids.lua b/game/modules/tome/data/zones/ancient_ruins/grids.lua index 9e09dda1b8a13243b9ee593f9c1da5340228df3d..e553fbe6062e771a627cb877edacde083d0aefe8 100644 --- a/game/modules/tome/data/zones/ancient_ruins/grids.lua +++ b/game/modules/tome/data/zones/ancient_ruins/grids.lua @@ -1,43 +1,44 @@ -return { - -{ +newEntity{ define_as = "UP", name = "previous level", display = '<', color_r=255, color_g=255, color_b=0, change_level = -1 -}, -{ +} + +newEntity{ define_as = "DOWN", name = "next level", display = '>', color_r=255, color_g=255, color_b=0, change_level = 1 -}, -{ +} + +newEntity{ define_as = "FLOOR", name = "floor", display = '.', color_r=255, color_g=255, color_b=255, -}, -{ +} + +newEntity{ define_as = "WALL", name = "wall", display = '#', color_r=255, color_g=255, color_b=255, block_move = true, block_sight = true, -}, -{ +} + +newEntity{ define_as = "DOOR", name = "door", display = '+', color_r=238, color_g=154, color_b=77, block_sight = true, door_opened = "DOOR_OPEN", -}, -{ +} + +newEntity{ define_as = "DOOR_OPEN", name = "open door", display = "'", color_r=238, color_g=154, color_b=77, block_move = false, block_sight = false, door_closed = "DOOR", -}, - } diff --git a/game/modules/tome/data/zones/ancient_ruins/npcs.lua b/game/modules/tome/data/zones/ancient_ruins/npcs.lua index 4fe00c8144479259da2a45a162360c90bd065507..82a98589ee87d7e6a3a26a560ae37acaeef6ca4b 100644 --- a/game/modules/tome/data/zones/ancient_ruins/npcs.lua +++ b/game/modules/tome/data/zones/ancient_ruins/npcs.lua @@ -1,6 +1,4 @@ -return { - -{ +newEntity{ name = "dragon of death", display = "D", color_r=255, level_range = {1, 10}, exp_worth = 100, @@ -13,20 +11,19 @@ return { has_blood = true, stats = { str=15, dex=8, mag=12, }, combat = { dam=8, atk=10, apr=2, def=4, armor=6}, -}, -{ +} + +newEntity{ name = "baby dragon", display = "d", color_r=128, -- faction = "poorsods", level_range = {1, 4}, exp_worth = 100, autolevel = "caster", ai = "simple", - max_life = 30, + max_life = resolvers.rngavg(1,100), max_mana = 1000, max_stamina = 1000, energy = { mod=0.3 }, has_blood = {nb=3, color={50,255,120}}, combat = { dam=5, atk=6, def=2, apr=1, armor=2}, -}, - -} \ No newline at end of file +} diff --git a/game/modules/tome/data/zones/ancient_ruins/objects.lua b/game/modules/tome/data/zones/ancient_ruins/objects.lua index 97aeaddb9693cea76493f6bab55c6c575b824967..6e9e5075c3bb87e916daec28104361c33b6006c6 100644 --- a/game/modules/tome/data/zones/ancient_ruins/objects.lua +++ b/game/modules/tome/data/zones/ancient_ruins/objects.lua @@ -1,2 +1 @@ -return { -} +load("/data/general/objects.lua")