From 91bc65842090883c16f47aa9b1ef37d0458d9625 Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Tue, 22 Dec 2009 18:29:22 +0000
Subject: [PATCH] EGOS !

git-svn-id: http://svn.net-core.org/repos/t-engine4@139 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engine/Actor.lua                         |   4 +-
 game/engine/Entity.lua                        | 114 +++++++++---------
 game/engine/Grid.lua                          |   4 +-
 game/engine/Level.lua                         |  13 ++
 game/engine/Object.lua                        |   9 +-
 game/engine/Zone.lua                          |  43 ++++++-
 game/engine/generator/actor/Random.lua        |   9 +-
 game/engine/generator/object/Random.lua       |  11 +-
 game/modules/tome/class/Actor.lua             |   4 +-
 game/modules/tome/class/Game.lua              |   2 +-
 game/modules/tome/class/Grid.lua              |   4 +-
 game/modules/tome/class/NPC.lua               |   4 +-
 game/modules/tome/class/Object.lua            |   4 +-
 game/modules/tome/class/Player.lua            |   4 +-
 game/modules/tome/data/general/egos.lua       |   2 +-
 game/modules/tome/data/general/staves.lua     |   1 +
 game/modules/tome/data/general/swords.lua     |   1 +
 .../tome/data/zones/ancient_ruins/zone.lua    |   4 +-
 ideas/materials.ods                           | Bin 0 -> 9377 bytes
 19 files changed, 146 insertions(+), 91 deletions(-)
 create mode 100644 ideas/materials.ods

diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index 8223d00dcc..9d58fd9030 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -5,7 +5,7 @@ local Faction = require "engine.Faction"
 
 module(..., package.seeall, class.inherit(Entity))
 
-function _M:init(t)
+function _M:init(t, no_default)
 	t = t or {}
 
 	self.name = t.name or "unknown actor"
@@ -16,7 +16,7 @@ function _M:init(t)
 	self.energy.mod = self.energy.mod or 0
 	self.faction = t.faction or "enemies"
 	self.changed = true
-	Entity.init(self, t)
+	Entity.init(self, t, no_default)
 
 	self.compute_vals = {}
 end
diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua
index f7ac209c18..1d210d9167 100644
--- a/game/engine/Entity.lua
+++ b/game/engine/Entity.lua
@@ -11,14 +11,16 @@ setmetatable(__uids, {__mode="v"})
 
 local function copy_recurs(dst, src, deep)
 	for k, e in pairs(src) do
-		if not dst[k] then
+		if type(e) == "table" and e.__CLASSNAME then
+			dst[k] = e
+		elseif 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
+		elseif type(dst[k]) == "table" and type(e) == "table" and not e.__CLASSNAME then
 			copy_recurs(dst[k], e, deep)
 		end
 	end
@@ -28,7 +30,7 @@ end
 -- Any subclass MUST call this constructor
 -- @param t a table defining the basic properties of the entity
 -- @usage Entity.new{display='#', color_r=255, color_g=255, color_b=255}
-function _M:init(t)
+function _M:init(t, no_default)
 	t = t or {}
 	self.uid = next_uid
 	__uids[self.uid] = self
@@ -39,23 +41,25 @@ function _M:init(t)
 		self[k] = ee
 	end
 
-	self.image = self.image or nil
-	self.display = self.display or '.'
-	if self.color then
-		self.color_r = self.color.r
-		self.color_g = self.color.g
-		self.color_b = self.color.b
-		self.color_br = self.color.br
-		self.color_bg = self.color.bg
-		self.color_bb = self.color.bb
-		self.color = nil
+	if not no_default then
+		self.image = self.image or nil
+		self.display = self.display or '.'
+		if self.color then
+			self.color_r = self.color.r
+			self.color_g = self.color.g
+			self.color_b = self.color.b
+			self.color_br = self.color.br
+			self.color_bg = self.color.bg
+			self.color_bb = self.color.bb
+			self.color = nil
+		end
+		self.color_r = self.color_r or 0
+		self.color_g = self.color_g or 0
+		self.color_b = self.color_b or 0
+		self.color_br = self.color_br or -1
+		self.color_bg = self.color_bg or -1
+		self.color_bb = self.color_bb or -1
 	end
-	self.color_r = self.color_r or 0
-	self.color_g = self.color_g or 0
-	self.color_b = self.color_b or 0
-	self.color_br = self.color_br or -1
-	self.color_bg = self.color_bg or -1
-	self.color_bb = self.color_bb or -1
 
 	next_uid = next_uid + 1
 
@@ -121,48 +125,46 @@ function _M:check(prop, ...)
 end
 
 --- Loads a list of entities from a definition file
--- @param ... the files to load from
+-- @param file the file to load from
+-- @param no_default if true then no default values will be assigned
 -- @usage MyEntityClass:loadList("/data/my_entities_def.lua")
-function _M:loadList(...)
+function _M:loadList(file, no_default)
 	local res = {}
 
-	for i, file in ipairs{...} do
-		local f, err = loadfile(file)
-		if err then error(err) 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
+	print("Loading entities file", file)
+	local f, err = loadfile(file)
+	if err then error(err) 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
-					t.base = nil
 				end
+				t.base = nil
+			end
+
+			local e = self.new(t, no_default)
+			print("loaded", e.name, no_default)
+			res[#res+1] = e
+			if t.define_as then res[t.define_as] = e 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()
 
-				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/Grid.lua b/game/engine/Grid.lua
index d7647275b2..21bd36f2e1 100644
--- a/game/engine/Grid.lua
+++ b/game/engine/Grid.lua
@@ -3,8 +3,8 @@ local Entity = require "engine.Entity"
 
 module(..., package.seeall, class.inherit(Entity))
 
-function _M:init(t)
+function _M:init(t, no_default)
 	t = t or {}
 	self.name = t.name
-	Entity.init(self, t)
+	Entity.init(self, t, no_default)
 end
diff --git a/game/engine/Level.lua b/game/engine/Level.lua
index b1a269f70b..d631223a8d 100644
--- a/game/engine/Level.lua
+++ b/game/engine/Level.lua
@@ -16,6 +16,8 @@ function _M:init(level, map)
 	self.e_distances = {}
 
 	self.distancer_co = self:createDistancer()
+
+	self.entities_list = {}
 end
 
 --- Adds an entity to the level
@@ -115,3 +117,14 @@ end
 function _M:idleProcessActor(act)
 	table.insert(self.e_toprocess, 1, act)
 end
+
+--- Setup an entity list for the level, this allwos the Zone to pick objects/actors/...
+function _M:setEntitiesList(type, list)
+	self.entities_list[type] = list
+	print("Stored entities list", type, list)
+end
+
+--- Gets an entity list for the level, this allows the Zone to pick objects/actors/...
+function _M:getEntitiesList(type)
+	return self.entities_list[type]
+end
diff --git a/game/engine/Object.lua b/game/engine/Object.lua
index ac3170d4b4..9bfb78f8ad 100644
--- a/game/engine/Object.lua
+++ b/game/engine/Object.lua
@@ -3,14 +3,9 @@ local Entity = require "engine.Entity"
 
 module(..., package.seeall, class.inherit(Entity))
 
-function _M:init(t)
+function _M:init(t, no_default)
 	t = t or {}
-	Entity.init(self, t)
-end
-
-function _M:resolve(t)
-	Entity.resolve(self, t)
-	self.egos = nil
+	Entity.init(self, t, no_default)
 end
 
 --- Gets the full name of the object
diff --git a/game/engine/Zone.lua b/game/engine/Zone.lua
index 4dbc53f713..d2d234992b 100644
--- a/game/engine/Zone.lua
+++ b/game/engine/Zone.lua
@@ -52,7 +52,7 @@ function _M:computeRarities(list, level, ood, filter)
 			elseif lev > e.level_range[2] then max = 100 / (lev - e.level_range[2])
 			end
 			local genprob = max / e.rarity
-			print("prob", e.name, math.floor(genprob), "max", math.floor(max), e.level_range[1], e.level_range[2], lev)
+			print("prob", e.name, math.floor(genprob), "max", math.floor(max), e.level_range[1], e.level_range[2], lev, "egoable", e.egos and #e.egos)
 
 			r.total = r.total + genprob
 			r[#r+1] = { e=e, genprob=r.total + genprob, level_diff = lev - level }
@@ -76,6 +76,47 @@ function _M:pickEntity(list)
 	return nil
 end
 
+function _M:getEgosList(level, type, group, class)
+	-- Already loaded ? use it
+	local list = level:getEntitiesList(type.."/"..group)
+	if list then return list end
+
+	-- otehrwise loads it and store it
+	list = require(class):loadList(group, true)
+	level:setEntitiesList(type.."/"..group, list)
+
+	return list
+end
+
+function _M:makeEntity(level, type)
+	local list = level:getEntitiesList(type)
+	local e = self:pickEntity(list)
+	e = e:clone()
+	e:resolve()
+
+	-- Add "ego" properties
+	if e.egos then
+		local egos = self:getEgosList(level, type, e.egos, e.__CLASSNAME)
+		local ego = egos[rng.range(1, #egos)]
+		if ego then
+			print("ego", ego.__CLASSNAME, ego.name, getmetatable(ego))
+			ego = ego:clone()
+			ego:resolve()
+			local newname
+			if ego.prefix then
+				newname = ego.name .. e.name
+			else
+				newname = e.name .. ego.name
+			end
+			print("applying ego", ego.name, "to ", e.name, "::", newname)
+			table.merge(e, ego, true)
+			e.name = newname
+		end
+	end
+
+	return e
+end
+
 function _M:load()
 	local f, err = loadfile("/data/zones/"..self.short_name.."/zone.lua")
 	if err then error(err) end
diff --git a/game/engine/generator/actor/Random.lua b/game/engine/generator/actor/Random.lua
index a6950e2b51..11f48b780b 100644
--- a/game/engine/generator/actor/Random.lua
+++ b/game/engine/generator/actor/Random.lua
@@ -7,7 +7,10 @@ function _M:init(zone, map, level)
 	engine.Generator.init(self, zone, map)
 	self.level = level
 	local data = level.data.generator.actor
-	self.npc_list = zone:computeRarities(zone.npc_list, level.level, data.ood, nil)
+
+	-- Setup the entities list
+	level:setEntitiesList("actor", zone:computeRarities(zone.npc_list, level.level, data.ood, nil))
+
 	if data.adjust_level_to_player and game:getPlayer() then
 		self.adjust_level_to_player = {base=game:getPlayer().level, min=data.adjust_level_to_player[1], max=data.adjust_level_to_player[2]}
 	end
@@ -17,10 +20,8 @@ end
 
 function _M:generate()
 	for i = 1, rng.range(self.nb_npc[1], self.nb_npc[2]) do
-		local m = self.zone:pickEntity(self.npc_list)
+		local m = self.zone:makeEntity(self.level, "actor")
 		if m then
-			m = m:clone()
-			m:resolve()
 			local x, y = rng.range(0, self.map.w), rng.range(0, self.map.h)
 			local tries = 0
 			while not m:canMove(x, y) and tries < 100 do
diff --git a/game/engine/generator/object/Random.lua b/game/engine/generator/object/Random.lua
index 6ff3c45e73..4dc974907f 100644
--- a/game/engine/generator/object/Random.lua
+++ b/game/engine/generator/object/Random.lua
@@ -6,8 +6,11 @@ module(..., package.seeall, class.inherit(engine.Generator))
 function _M:init(zone, map, level)
 	engine.Generator.init(self, zone, map)
 	self.level = level
-	local data = level.data
-	self.object_list = zone:computeRarities(zone.object_list, level.level, data.generator and data.generator.actor and data.generator.actor.ood, nil)
+	local data = level.data.generator.object
+
+	-- Setup the entities list
+	level:setEntitiesList("object", zone:computeRarities(zone.object_list, level.level, data.ood, nil))
+
 	if data.adjust_level_to_player and game:getPlayer() then
 		self.adjust_level_to_player = {base=game:getPlayer().level, min=data.adjust_level_to_player[1], max=data.adjust_level_to_player[2]}
 	end
@@ -17,10 +20,8 @@ end
 
 function _M:generate()
 	for i = 1, rng.range(self.nb_object[1], self.nb_object[2]) do
-		local o = self.zone:pickEntity(self.object_list)
+		local o = self.zone:makeEntity(self.level, "object")
 		if o then
-			o = o:clone()
-			o:resolve()
 			local x, y = rng.range(0, self.map.w), rng.range(0, self.map.h)
 			local tries = 0
 			while (self.map:checkEntity(x, y, Map.TERRAIN, "block_move") or self.map(x, y, Map.OBJECT)) and tries < 100 do
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 27007f214f..27646543ce 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -25,7 +25,7 @@ module(..., package.seeall, class.inherit(
 	mod.class.interface.Combat
 ))
 
-function _M:init(t)
+function _M:init(t, no_default)
 	-- Define some basic combat stats
 	self.combat_def = 0
 	self.combat_armor = 0
@@ -54,7 +54,7 @@ function _M:init(t)
 	-- Default melee barehanded damage
 	self.combat = { dam=1, atk=1, apr=0, dammod={str=1} }
 
-	engine.Actor.init(self, t)
+	engine.Actor.init(self, t, no_default)
 	engine.interface.ActorInventory.init(self, t)
 	engine.interface.ActorTemporaryEffects.init(self, t)
 	engine.interface.ActorLife.init(self, t)
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index d7ae87c3bb..fd21bafb4c 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -75,7 +75,7 @@ function _M:newGame()
 	self.player = Player.new{name=self.player_name}
 
 	local birth = Birther.new(self.player, {"base", "race", "subrace", "sex", "class", "subclass" }, function()
-		self.player.wild_x, self.player.wild_y = 38, 15
+		self.player.wild_x, self.player.wild_y = 39, 17
 		self:changeLevel(1)
 
 		local ds = LevelupStatsDialog.new(self.player)
diff --git a/game/modules/tome/class/Grid.lua b/game/modules/tome/class/Grid.lua
index 8c9a2029e0..3d224a2ae3 100644
--- a/game/modules/tome/class/Grid.lua
+++ b/game/modules/tome/class/Grid.lua
@@ -3,8 +3,8 @@ require "engine.Grid"
 
 module(..., package.seeall, class.inherit(engine.Grid))
 
-function _M:init(t)
-	engine.Grid.init(self, t)
+function _M:init(t, no_default)
+	engine.Grid.init(self, t, no_default)
 end
 
 function _M:block_move(x, y, e)
diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua
index 7a1372162c..47530eec3c 100644
--- a/game/modules/tome/class/NPC.lua
+++ b/game/modules/tome/class/NPC.lua
@@ -4,8 +4,8 @@ require "mod.class.Actor"
 
 module(..., package.seeall, class.inherit(mod.class.Actor, engine.interface.ActorAI))
 
-function _M:init(t)
-	mod.class.Actor.init(self, t)
+function _M:init(t, no_default)
+	mod.class.Actor.init(self, t, no_default)
 	ActorAI.init(self, t)
 end
 
diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua
index 07909cbab9..85d2987786 100644
--- a/game/modules/tome/class/Object.lua
+++ b/game/modules/tome/class/Object.lua
@@ -3,8 +3,8 @@ require "engine.Object"
 
 module(..., package.seeall, class.inherit(engine.Object))
 
-function _M:init(t)
-	engine.Object.init(self, t)
+function _M:init(t, no_default)
+	engine.Object.init(self, t, no_default)
 end
 
 function _M:tooltip()
diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 5fcd44fa63..c739697f3f 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -6,7 +6,7 @@ local ActorTalents = require "engine.interface.ActorTalents"
 
 module(..., package.seeall, class.inherit(mod.class.Actor))
 
-function _M:init(t)
+function _M:init(t, no_default)
 	t.body = {
 		INVEN = 1000,
 		MAINHAND = 1,
@@ -20,7 +20,7 @@ function _M:init(t)
 		FEET = 1,
 		TOOL = 1,
 	}
-	mod.class.Actor.init(self, t)
+	mod.class.Actor.init(self, t, no_default)
 	self.player = true
 	self.faction = "players"
 
diff --git a/game/modules/tome/data/general/egos.lua b/game/modules/tome/data/general/egos.lua
index 26bb20e48c..7d456d30dd 100644
--- a/game/modules/tome/data/general/egos.lua
+++ b/game/modules/tome/data/general/egos.lua
@@ -1,5 +1,5 @@
 newEntity{
-	name = "flaming ",
+	name = "flaming ", prefix=true,
 	level_range = {1, 10},
 	rarity = 3,
 	wielder = {
diff --git a/game/modules/tome/data/general/staves.lua b/game/modules/tome/data/general/staves.lua
index e0837b4612..c512986606 100644
--- a/game/modules/tome/data/general/staves.lua
+++ b/game/modules/tome/data/general/staves.lua
@@ -6,6 +6,7 @@ newEntity{
 	encumber = 5,
 	rarity = 3,
 	desc = [[Staves designed for wielders of magic, by the greats of the art.]],
+	egos = "/data/general/egos.lua",
 }
 
 newEntity{ base = "BASE_STAFF",
diff --git a/game/modules/tome/data/general/swords.lua b/game/modules/tome/data/general/swords.lua
index c33bc3c818..05fa636662 100644
--- a/game/modules/tome/data/general/swords.lua
+++ b/game/modules/tome/data/general/swords.lua
@@ -6,6 +6,7 @@ newEntity{
 	encumber = 3,
 	rarity = 3,
 	desc = [[Sharp, long, and deadly.]],
+	egos = "/data/general/egos.lua",
 }
 
 newEntity{ base = "BASE_LONGSWORD",
diff --git a/game/modules/tome/data/zones/ancient_ruins/zone.lua b/game/modules/tome/data/zones/ancient_ruins/zone.lua
index e4b45e529d..7d243d86d9 100644
--- a/game/modules/tome/data/zones/ancient_ruins/zone.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/zone.lua
@@ -19,13 +19,13 @@ return {
 		},
 		actor = {
 			class = "engine.generator.actor.Random",
-			nb_npc = {20, 30},
+			nb_npc = {2, 3},
 			ood = {chance=5, range={1, 10}},
 			adjust_level_to_player = {-1, 2},
 		},
 		object = {
 			class = "engine.generator.object.Random",
-			nb_object = {3, 6},
+			nb_object = {100, 100},
 			ood = {chance=5, range={1, 10}},
 		},
 	},
diff --git a/ideas/materials.ods b/ideas/materials.ods
new file mode 100644
index 0000000000000000000000000000000000000000..9feec2ad97bd9d6641714ab878670287619deaae
GIT binary patch
literal 9377
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
a@JIh?s6&V`1P%^0=Cg{qLr7=GKK&nc;eW0G

literal 0
HcmV?d00001

-- 
GitLab