diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua index 187bf033c228111e5b8cc860cfe4d8de25f10dc8..97d93b9e7cbaba2b6345e29e2c6d3bb60ed602c6 100644 --- a/game/engine/Entity.lua +++ b/game/engine/Entity.lua @@ -114,6 +114,37 @@ function _M:resolve(t) -- Finish resolving stuff if t == self then if self.resolveLevel then self:resolveLevel() end + + if self.unique and type(self.unique) == "boolean" then + self.unique = self.name + end + end +end + +--- Call when the entity is actually added to a level/whatever +-- This helps ensuring uniqueness of uniques +function _M:added() + if self.unique then + game.uniques[self.unique] = true + print("Added unique", self.unique) + end +end + +--- Call when the entity is actually removed from existance +-- This helps ensuring uniqueness of uniques. +-- This recursively remvoes inventories too, if you need anythign special, overload this +function _M:removed() + if self.inven then + for _, inven in pairs(self.inven) do + for i, o in ipairs(inven) do + o:removed() + end + end + end + + if self.unique then + game.uniques[self.unique] = nil + print("Removed unique", self.unique) end end diff --git a/game/engine/Game.lua b/game/engine/Game.lua index 90fb58e9dc1ce57ff8089c9266ddd2bb32c8dacd..35f76636b57539d6a68b8f7c345e369442d91180 100644 --- a/game/engine/Game.lua +++ b/game/engine/Game.lua @@ -21,6 +21,8 @@ function _M:init(keyhandler) self.mouse = engine.Mouse.new() self.mouse:setCurrent() + + self.uniques = {} end function _M:loaded() diff --git a/game/engine/Level.lua b/game/engine/Level.lua index 63730141f9d91fe7fe4cdf30e8bf7518408e5044..9fb0be9c2cb15c92b662dbb9a4b65fabbec0ba01 100644 --- a/game/engine/Level.lua +++ b/game/engine/Level.lua @@ -130,3 +130,15 @@ end function _M:getEntitiesList(type) return self.entities_list[type] end + +--- Removed, so we remove all entities +function _M:removed() + for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do + local z = i + j * self.map.w + if self.map.map[z] then + for _, e in pairs(self.map.map[z]) do + e:removed() + end + end + end end +end diff --git a/game/engine/Zone.lua b/game/engine/Zone.lua index 24468a241acca9e0094117891ce0142f0b0e992a..a09b12d822bd9a58985512a230d7d8a8deab6e5b 100644 --- a/game/engine/Zone.lua +++ b/game/engine/Zone.lua @@ -87,11 +87,16 @@ end --- Checks an entity against a filter function _M:checkFilter(e, filter) + if e.unique and game.uniques[e.unique] then print("refused unique", e.name, e.unique) return false end + if not filter then return true end if filter.type and filter.type ~= e.type then return false end if filter.subtype and filter.subtype ~= e.subtype then return false end if filter.name and filter.name ~= e.name then return false end + + if e.unique then print("accepted unique", e.name, e.unique) end + return true end @@ -210,20 +215,28 @@ function _M:getLevelData(lev) return res end ---- Asks the zone to generate a level of level "lev" --- @param lev the level (from 1 to zone.max_level) --- @return a Level object -function _M:getLevel(game, lev, old_lev, no_close) +--- Leave the level, forgetting uniques and such +function _M:leaveLevel(no_close) +print("leaving unique") -- Before doing anything else, close the current level if not no_close and game.level and game.level.map then if game.level.data.persistant then local save = Savefile.new(game.save_name) save:saveLevel(game.level) save:close() + else + game.level:removed() end game.level.map:close() end +end + +--- Asks the zone to generate a level of level "lev" +-- @param lev the level (from 1 to zone.max_level) +-- @return a Level object +function _M:getLevel(game, lev, old_lev, no_close) + self:leaveLevel(no_close) local level_data = self:getLevelData(lev) diff --git a/game/engine/generator/actor/Random.lua b/game/engine/generator/actor/Random.lua index 0ea98007fa702b7e98f674c91e54fa9a04fcbb4b..a75425912d590b312dc55bb994b600c4ecb5b9bd 100644 --- a/game/engine/generator/actor/Random.lua +++ b/game/engine/generator/actor/Random.lua @@ -34,6 +34,7 @@ function _M:generate() if tries < 100 then m:move(x, y, true) self.level:addEntity(m) + m:added() -- Levelup ? if self.adjust_level then @@ -58,6 +59,7 @@ function _M:generate() if tries < 100 then m:move(x, y, true) self.level:addEntity(m) + m:added() -- Levelup ? if self.adjust_level then diff --git a/game/engine/generator/object/Random.lua b/game/engine/generator/object/Random.lua index bdea35335931fddf112ff3448eca9c5ac8448be5..17cfd161f406e4462eee7d5e54363f25c1265f2c 100644 --- a/game/engine/generator/object/Random.lua +++ b/game/engine/generator/object/Random.lua @@ -33,6 +33,7 @@ function _M:generate() end if tries < 100 then self.map(x, y, Map.OBJECT, o) + o:added() end end end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index d9ab9a8734419639d392e1fb31a185b45fce80ac..66d9bd1adf364700abee2d83f7c955d5ed829485 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -137,7 +137,7 @@ end function _M:save() return class.save(self, {w=true, h=true, zone=true, player=true, level=true, entities=true, energy_to_act=true, energy_per_tick=true, turn=true, paused=true, save_name=true, - always_target=true, gfxmode=true; + always_target=true, gfxmode=true, uniques=true }, true) end @@ -150,6 +150,7 @@ end function _M:changeLevel(lev, zone) if zone then + if self.zone then self.zone:leaveLevel() end self.zone = Zone.new(zone) end self.zone:getLevel(self, lev, (self.level and not zone) and self.level.level or -1000) diff --git a/game/modules/tome/data/general/npcs/bear.lua b/game/modules/tome/data/general/npcs/bear.lua new file mode 100644 index 0000000000000000000000000000000000000000..7fcb95a77d025a6a4e09504ab2fc24129aac3660 --- /dev/null +++ b/game/modules/tome/data/general/npcs/bear.lua @@ -0,0 +1,75 @@ +local Talents = require("engine.interface.ActorTalents") + +newEntity{ + define_as = "BASE_NPC_BEAR", + type = "animal", subtype = "bear", + display = "q", color=colors.WHITE, + body = { INVEN = 10 }, + + max_stamina = 100, + + autolevel = "warrior", + ai = "dumb_talented_simple", ai_state = { talent_in=5, }, + energy = { mod=0.9 }, + stats = { str=18, dex=13, mag=5, con=15 }, + + combat_armor = 1, combat_def = 1, + combat = { dam=resolvers.rngavg(12,25), atk=10, apr=10, physspeed=2 }, + life_rating = 13, + tmasteries = resolvers.tmasteries{ ["physical/other"]=0.25 }, + + resists = { [DamageType.FIRE] = 20, [DamageType.COLD] = 20, [DamageType.POISON] = 20 }, +} + +newEntity{ base = "BASE_NPC_BEAR", + name = "brown bear", color=colors.UMBER, + desc = [[The weakest of bears, covered in brown shaggy fur.]], + level_range = {5, 50}, exp_worth = 1, + rarity = 7, + max_life = resolvers.rngavg(100,150), + combat_armor = 7, combat_def = 3, + talents = resolvers.talents{ [Talents.T_STUN]=1 }, +} + +newEntity{ base = "BASE_NPC_BEAR", + name = "black bear", color=colors.BLACK, + desc = [[Do you smell like honey, 'cause this bear wants honey.]], + level_range = {6, 50}, exp_worth = 1, + rarity = 7, + max_life = resolvers.rngavg(120,150), + combat_armor = 8, combat_def = 3, + talents = resolvers.talents{ [Talents.T_STUN]=1 }, +} + +newEntity{ base = "BASE_NPC_BEAR", + name = "cave bear", color=colors.DARK_SLATE_GRAY, + desc = [[It has come down from its cave foraging for food. Unfortunately, it found you.]], + level_range = {7, 50}, exp_worth = 1, + rarity = 8, + max_life = resolvers.rngavg(130,150), + combat_armor = 9, combat_def = 4, + combat = { dam=resolvers.rngavg(13,17), atk=7, apr=7, physspeed=2 }, + talents = resolvers.talents{ [Talents.T_STAMINA_POOL]=1, [Talents.T_STUN]=2, [Talents.T_KNOCKBACK]=1,}, +} + +newEntity{ base = "BASE_NPC_BEAR", + name = "war bear", color=colors.DARK_UMBER, + desc = [[Bears with tusks, trained to kill.]], + level_range = {8, 50}, exp_worth = 1, + rarity = 8, + max_life = resolvers.rngavg(140,150), + combat_armor = 9, combat_def = 4, + combat = { dam=resolvers.rngavg(13,17), atk=10, apr=7, physspeed=2 }, + talents = resolvers.talents{ [Talents.T_STAMINA_POOL]=1, [Talents.T_STUN]=2, [Talents.T_KNOCKBACK]=1,}, +} + +newEntity{ base = "BASE_NPC_BEAR", + name = "grizzly bear", color=colors.LIGHT_UMBER, + desc = [[A huge, beastly bear, more savage than most of its kind.]], + level_range = {10, 50}, exp_worth = 1, + rarity = 9, + max_life = resolvers.rngavg(150,170), + combat_armor = 10, combat_def = 5, + combat = { dam=resolvers.rngavg(15,20), atk=10, apr=7, physspeed=2 }, + talents = resolvers.talents{ [Talents.T_STAMINA_POOL]=1, [Talents.T_STUN]=3, [Talents.T_KNOCKBACK]=2,}, +} diff --git a/game/modules/tome/data/general/objects/world-artifacts.lua b/game/modules/tome/data/general/objects/world-artifacts.lua index 04d9ca15fb91273e69755a68c5a2f58610fd81bf..7983052843e3dc57532297c0b0f407aa077a56c9 100644 --- a/game/modules/tome/data/general/objects/world-artifacts.lua +++ b/game/modules/tome/data/general/objects/world-artifacts.lua @@ -31,7 +31,7 @@ newEntity{ level_range = {1, 10}, display = "~", color=colors.YELLOW, encumber = 1, - rarity = 100, + rarity = 1, desc = [[A small crystal phial, with the light of Earendil's Star contained inside. Its light is imperishable, and near it darkness cannot endure.]], cost = 2000, diff --git a/game/modules/tome/data/zones/tower-amon-sul/objects.lua b/game/modules/tome/data/zones/tower-amon-sul/objects.lua index e259bbcf4e9afb24af3827893e14671869619b27..fcb879de0b1f6237fc0fb4e6d557e91a5634ea58 100644 --- a/game/modules/tome/data/zones/tower-amon-sul/objects.lua +++ b/game/modules/tome/data/zones/tower-amon-sul/objects.lua @@ -2,7 +2,7 @@ load("/data/general/objects/objects.lua") -- Artifact, droped (and used!) by the Shade of Angmar newEntity{ base = "BASE_STAFF", - define_as = "STAFF_ANGMAR", + define_as = "STAFF_ANGMAR", rarity=false, name = "Angmar's Fall", unique=true, require = { stat = { mag=25 }, }, cost = 5, diff --git a/game/modules/tome/data/zones/tower-amon-sul/zone.lua b/game/modules/tome/data/zones/tower-amon-sul/zone.lua index 7eddaee077b5972878748c908ba332c5505052a4..0ba0656ded033d986bc987a0320bf7d2f82d547c 100644 --- a/game/modules/tome/data/zones/tower-amon-sul/zone.lua +++ b/game/modules/tome/data/zones/tower-amon-sul/zone.lua @@ -27,7 +27,7 @@ return { }, object = { class = "engine.generator.object.Random", - nb_object = {4, 6}, + nb_object = {40, 60}, filters = { {type="potion" }, {type="potion" }, {type="potion" }, {type="scroll" }, {}, {} } }, }, diff --git a/game/modules/tome/resolvers.lua b/game/modules/tome/resolvers.lua index 4ade719cdf6a89682084c194050219adf1c0850c..f7f5d9aa697bb75789d81a495921633cd4af10d9 100644 --- a/game/modules/tome/resolvers.lua +++ b/game/modules/tome/resolvers.lua @@ -19,7 +19,7 @@ function resolvers.calc.equip(t, e) -- Do not drop it unless it is an ego or better if not o.egoed and not o.unique then o.no_drop = true end - print(o.name, o.unique, o.no_drop) + o:added() end end -- Delete the origin field @@ -44,6 +44,7 @@ function resolvers.calc.inventory(t, e) if o then print("Zone made us an inventory according to filter!", o:getName()) e:addObject(e.INVEN_INVEN, o) + o:added() end end e:sortInven() @@ -73,6 +74,7 @@ function resolvers.calc.drops(t, e) if o then print("Zone made us an drop according to filter!", o:getName()) e:addObject(e.INVEN_INVEN, o) + o:added() end end -- Delete the origin field