From a6a62c80746fd8eb7cbea5162aa15021a794c9ff Mon Sep 17 00:00:00 2001
From: DarkGod <darkgod@net-core.org>
Date: Fri, 26 Jul 2013 19:30:26 +0200
Subject: [PATCH] Attachement spots for particles can be read from a file per
 tileset

---
 game/engines/default/engine/ui/Image.lua      | 10 +-
 game/engines/default/engine/ui/List.lua       | 17 ++--
 game/modules/tome/class/Actor.lua             |  7 +-
 game/modules/tome/class/Game.lua              | 48 +++++++++
 game/modules/tome/data/birth/races/dwarf.lua  | 15 +--
 game/modules/tome/data/birth/races/elf.lua    |  1 +
 game/modules/tome/data/birth/races/human.lua  | 15 +--
 .../tome/data/gfx/shockbolt/attachements.lua  | 99 +++++++++++++++++++
 .../tome/data/zones/town-angolwen/npcs.lua    |  3 +-
 game/modules/tome/dialogs/Birther.lua         | 17 ++--
 game/modules/tome/resolvers.lua               |  1 +
 11 files changed, 184 insertions(+), 49 deletions(-)
 create mode 100644 game/modules/tome/data/gfx/shockbolt/attachements.lua

diff --git a/game/engines/default/engine/ui/Image.lua b/game/engines/default/engine/ui/Image.lua
index 353f8d6816..7b3a9b1777 100644
--- a/game/engines/default/engine/ui/Image.lua
+++ b/game/engines/default/engine/ui/Image.lua
@@ -36,8 +36,9 @@ function _M:init(t)
 		if t.auto_width then t.width = iw end
 		if t.auto_height then t.height = ih end
 	end
-	self.w = assert(t.width, "no image width")
-	self.h = assert(t.height, "no image height")
+	self.w = assert(t.width, "no image width") * (t.zoom or 1)
+	self.h = assert(t.height, "no image height") * (t.zoom or 1)
+	self.back_color = t.back_color
 
 	self.shadow = t.shadow
 
@@ -53,6 +54,11 @@ end
 
 function _M:display(x, y)
 	if not self.item then return end
+
+	if self.back_color then
+		core.display.drawQuad(x, y, self.w, self.h, unpack(self.back_color))
+	end
+
 	if self.shadow then
 		self.item[1]:toScreenFull(x + 5, y + 5, self.w, self.h, self.item[2], self.item[3], 0, 0, 0, 0.5)
 	end
diff --git a/game/engines/default/engine/ui/List.lua b/game/engines/default/engine/ui/List.lua
index 8b139320a4..cf7169bad2 100644
--- a/game/engines/default/engine/ui/List.lua
+++ b/game/engines/default/engine/ui/List.lua
@@ -69,12 +69,7 @@ function _M:generate()
 
 	-- Draw the list items
 	for i, item in ipairs(self.list) do
-		local color = item.color or {255,255,255}
-		local text = item[self.display_prop]
-
-		s:erase(0, 0, 0, 0)
-		s:drawColorStringBlended(self.font, text, 0, (self.fh - self.font_h) / 2, color[1], color[2], color[3], true, fw)
-		item._tex = {s:glTexture()}
+		self:drawItem(item)
 	end
 
 	-- Add UI controls
@@ -132,6 +127,16 @@ function _M:generate()
 	self:onSelect()
 end
 
+function _M:drawItem(item)
+	local s = self.surf
+	local color = item.color or {255,255,255}
+	local text = item[self.display_prop]
+
+	s:erase(0, 0, 0, 0)
+	s:drawColorStringBlended(self.font, text, 0, (self.fh - self.font_h) / 2, color[1], color[2], color[3], true, fw)
+	item._tex = {s:glTexture()}
+end
+
 function _M:select(i)
 	if self.sel and self.list[self.sel] then self.list[self.sel].focus_decay = self.focus_decay_max end
 	self.sel = util.bound(i, 1, #self.list)
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index e9fc8a31e1..7b0ed16211 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -2780,10 +2780,13 @@ end
 
 --- Return attachement coords
 function _M:attachementSpot(kind, particle)
-	if not self.attachement_spots or not self.attachement_spots[kind] then return end
+	local as = self.attachement_spots or self.image
+	if not as then return end
+	if not game.tiles_attachements or not game.tiles_attachements[as] or not game.tiles_attachements[as][kind] then return end
 	local x, y = 0, 0
 	if particle then x, y = -0.5, -0.5 end
-	return self.attachement_spots[kind].x + x, self.attachement_spots[kind].y + y
+	print(kind,"=========", game.tiles_attachements[as][kind].x, game.tiles_attachements[as][kind].y)
+	return game.tiles_attachements[as][kind].x + x, game.tiles_attachements[as][kind].y + y
 end
 
 --- Update tile for races that can handle it
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 2e45b48762..1770cf9c63 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -83,6 +83,7 @@ function _M:init()
 	self:loaded()
 
 	self.visited_zones = {}
+	self.tiles_attachements = {}
 end
 
 function _M:run()
@@ -371,6 +372,50 @@ function _M:loaded()
 	self:updateCurrentChar()
 end
 
+function _M:computeAttachementSpotsFromTable(ta)
+	local base = ta.default_base or 64
+	local res = { }
+
+	for tile, data in pairs(ta.tiles or {}) do
+		local base = data.base or base
+		local yoff = data.yoff or 0
+		local t = {}
+		res[tile] = t
+		for kind, d in pairs(data) do if kind ~= "base" and kind ~= "yoff" then
+			t[kind] = { x=d.x / base, y=(d.y + yoff) / base }
+		end end
+	end
+
+	for race, data in pairs(ta.dolls or {}) do
+		local base = data.base or base
+		for sex, d in pairs(data) do if sex ~= "base" then
+			local t = {}
+			res["dolls_"..race.."_"..sex] = t
+			local yoff = d.yoff or 0
+			local base = d.base or base
+			for kind, d in pairs(d) do if kind ~= "yoff" and kind ~= "base" then
+				t[kind] = { x=d.x / base, y=(d.y + yoff) / base }
+			end end
+		end end
+	end
+
+	self.tiles_attachements = res
+end
+
+function _M:computeAttachementSpots()
+	if fs.exists(Tiles.prefix.."attachements.lua") then
+		local f, err = loadfile(Tiles.prefix.."attachements.lua")
+		if not f then print("Loading tileset attachements error", err)
+		else
+			local t = {}
+			setfenv(f, t)
+			local ok, err = pcall(f)
+			if not ok then print("Loading tileset attachements error", err) end
+			self:computeAttachementSpotsFromTable(t)
+		end
+	end
+end
+
 function _M:setupDisplayMode(reboot, mode)
 	if not mode or mode == "init" then
 		local gfx = config.settings.tome.gfx
@@ -396,6 +441,9 @@ function _M:setupDisplayMode(reboot, mode)
 		print("[DISPLAY MODE] Tileset: "..gfx.tiles)
 		print("[DISPLAY MODE] Size: "..gfx.size)
 
+		-- Load attachement spots for this tileset
+		self:computeAttachementSpots()
+
 		local do_bg = gfx.tiles == "ascii_full"
 		local _, _, tw, th = gfx.size:find("^([0-9]+)x([0-9]+)$")
 		tw, th = tonumber(tw), tonumber(th)
diff --git a/game/modules/tome/data/birth/races/dwarf.lua b/game/modules/tome/data/birth/races/dwarf.lua
index d881297601..484a53eebd 100644
--- a/game/modules/tome/data/birth/races/dwarf.lua
+++ b/game/modules/tome/data/birth/races/dwarf.lua
@@ -50,20 +50,7 @@ newBirthDescriptor{
 	},
 	random_escort_possibilities = { {"tier1.1", 1, 2}, {"tier1.2", 1, 2}, {"daikara", 1, 2}, {"old-forest", 1, 4}, {"dreadfell", 1, 8}, {"reknor", 1, 2}, },
 
-	moddable_attachement_spots = { base=128,
-		female = {
-			head = {x=66, y=19},
-			back = {x=66, y=51},
-			hand1 = {x=19, y=78},
-			hand2 = {x=110, y=78},
-		},
-		male = {
-			head = {x=65, y=20},
-			back = {x=65, y=51},
-			hand1 = {x=20, y=78},
-			hand2 = {x=110, y=78},
-		},
-	},
+	moddable_attachement_spots = "race_dwarf",
 	cosmetic_unlock = {
 		cosmetic_race_human_redhead = {
 			{name="Redhead [donator only]", donator=true, on_actor=function(actor) if actor.moddable_tile then actor.moddable_tile_base = "base_redhead_01.png" actor.moddable_tile_ornament={male="beard_redhead_02"} end end, check=function(birth) return birth.descriptors_by_type.sex == "Male" end},
diff --git a/game/modules/tome/data/birth/races/elf.lua b/game/modules/tome/data/birth/races/elf.lua
index 5c7b99561b..10c92f72ac 100644
--- a/game/modules/tome/data/birth/races/elf.lua
+++ b/game/modules/tome/data/birth/races/elf.lua
@@ -53,6 +53,7 @@ newBirthDescriptor{
 		resolvers.inventory{ id=true, {defined="ORB_SCRYING"} },
 	},
 
+	moddable_attachement_spots = "race_elf",
 	cosmetic_unlock = {
 		cosmetic_race_human_redhead = {
 			{name="Redhead [donator only]", donator=true, on_actor=function(actor) if actor.moddable_tile then actor.moddable_tile_base = "base_redhead_01.png" end end, check=function(birth) return birth.descriptors_by_type.sex == "Male" end},
diff --git a/game/modules/tome/data/birth/races/human.lua b/game/modules/tome/data/birth/races/human.lua
index 20f1dded9f..2284a09c2e 100644
--- a/game/modules/tome/data/birth/races/human.lua
+++ b/game/modules/tome/data/birth/races/human.lua
@@ -56,20 +56,7 @@ newBirthDescriptor{
 	},
 	random_escort_possibilities = { {"tier1.1", 1, 2}, {"tier1.2", 1, 2}, {"daikara", 1, 2}, {"old-forest", 1, 4}, {"dreadfell", 1, 8}, {"reknor", 1, 2}, },
 
-	moddable_attachement_spots = { base=128,
-		female = {
-			head = {x=64, y=6},
-			back = {x=66, y=34},
-			hand1 = {x=38, y=66},
-			hand2 = {x=90, y=66},
-		},
-		male = {
-			head = {x=60, y=6},
-			back = {x=64, y=31},
-			hand1 = {x=31, y=66},
-			hand2 = {x=95, y=66},
-		},
-	},
+	moddable_attachement_spots = "race_human",
 	cosmetic_unlock = {
 		cosmetic_race_human_redhead = {
 			{name="Redhead [donator only]", donator=true, on_actor=function(actor) if actor.moddable_tile then actor.moddable_tile_base = "base_redhead_01.png" end end},
diff --git a/game/modules/tome/data/gfx/shockbolt/attachements.lua b/game/modules/tome/data/gfx/shockbolt/attachements.lua
new file mode 100644
index 0000000000..2aae5e4bd6
--- /dev/null
+++ b/game/modules/tome/data/gfx/shockbolt/attachements.lua
@@ -0,0 +1,99 @@
+tiles={} dolls={}
+
+dolls.race_elf = dolls.race_elf or {}
+dolls.race_elf.male = { base=64,
+	feet = {x=32, y=61},
+	hand1 = {x=19, y=32},
+	hand2 = {x=44, y=34},
+	back = {x=32, y=15},
+	belly = {x=33, y=27},
+	head = {x=30, y=4},
+}
+dolls.race_elf = dolls.race_elf or {}
+dolls.race_elf.female = { base=64,
+	feet = {x=34, y=61},
+	hand1 = {x=19, y=33},
+	hand2 = {x=46, y=33},
+	back = {x=33, y=14},
+	belly = {x=34, y=27},
+	head = {x=31, y=3},
+}
+dolls.race_ghoul = dolls.race_ghoul or {}
+dolls.race_ghoul.all = { base=64,
+	feet = {x=33, y=61},
+	hand1 = {x=20, y=37},
+	hand2 = {x=48, y=38},
+	back = {x=34, y=20},
+	belly = {x=33, y=38},
+	head = {x=33, y=8},
+}
+dolls.race_runic_golem = dolls.race_runic_golem or {}
+dolls.race_runic_golem.all = { base=64,
+	feet = {x=54, y=43},
+	hand1 = {x=29, y=18},
+	hand2 = {x=22, y=28},
+	back = {x=28, y=48},
+	belly = {x=43, y=49},
+	head = {x=39, y=29},
+}
+tiles["npc/animal_feline_snow_cat.png"] = { base=64,
+	head = {x=17, y=18},
+}
+dolls.race_dwarf = dolls.race_dwarf or {}
+dolls.race_dwarf.female = { base=64,
+	feet = {x=33, y=59},
+	back = {x=33, y=25},
+	hand2 = {x=55, y=39},
+	belly = {x=33, y=37},
+	hand1 = {x=9, y=39},
+	head = {x=33, y=9},
+}
+tiles["npc/humanoid_human_linaniil_supreme_archmage.png"] = { base=64,
+	feet = {x=38, y=60},
+	hand1 = {x=10, y=7},
+	hand2 = {x=49, y=29},
+	belly = {x=37, y=19},
+	back = {x=35, y=1},
+	head = {x=31, y=-13},
+}
+tiles["npc/canine_warg.png"] = { base=64,
+	feet = {x=15, y=18},
+	hand1 = {x=48, y=22},
+	hand2 = {x=46, y=48},
+	back = {x=26, y=51},
+	belly = {x=12, y=32},
+	head = {x=33, y=13},
+}
+tiles["npc/acid_ant.png"] = { base=64,
+	feet = {x=36, y=57},
+	back = {x=45, y=37},
+	hand2 = {x=51, y=17},
+	belly = {x=11, y=33},
+	hand1 = {x=32, y=22},
+	head = {x=15, y=13},
+}
+dolls.race_human = dolls.race_human or {}
+dolls.race_human.female = { base=64,
+	feet = {x=33, y=60},
+	hand1 = {x=0, y=0},
+	hand2 = {x=0, y=0},
+	belly = {x=34, y=28},
+	back = {x=33, y=17},
+	head = {x=32, y=3},
+}
+dolls.race_human = dolls.race_human or {}
+dolls.race_human.male = { base=128,
+	back = {x=64, y=30},
+	hand2 = {x=114, y=11},
+	hand1 = {x=16, y=10},
+	head = {x=60, y=6},
+}
+dolls.race_dwarf = dolls.race_dwarf or {}
+dolls.race_dwarf.male = { base=64,
+	feet = {x=34, y=61},
+	back = {x=32, y=25},
+	hand2 = {x=55, y=39},
+	belly = {x=34, y=34},
+	hand1 = {x=10, y=39},
+	head = {x=32, y=10},
+}
diff --git a/game/modules/tome/data/zones/town-angolwen/npcs.lua b/game/modules/tome/data/zones/town-angolwen/npcs.lua
index 91ca2abca2..06c414aaac 100644
--- a/game/modules/tome/data/zones/town-angolwen/npcs.lua
+++ b/game/modules/tome/data/zones/town-angolwen/npcs.lua
@@ -94,7 +94,6 @@ newEntity{ define_as = "SUPREME_ARCHMAGE_LINANIIL",
 		[Talents.T_KEEN_SENSES]=5,
 		[Talents.T_PREMONITION]=5,
 	},
-	attachement_spots = { back={x=35/64, y=1/64} },
 	resolvers.sustains_at_birth(),
 
 	can_talk = "angolwen-leader",
@@ -116,7 +115,7 @@ newEntity{ define_as = "TARELION",
 	display = "p",
 	faction = "angolwen",
 	name = "Archmage Tarelion", color=colors.CRIMSON, unique = true,
-	resolvers.nice_tile{image="invis.png", add_mos = {{image="npc/humanoid_shalore_archmage_tarelion.png", display_h=2, display_y=-1}}},
+	resolvers.nice_tile{tall=true},
 	desc = [[A tall shalore elf, in a flowing robe, he looks calm and at peace but you can feel his tremendous power.]],
 	level_range = {30, nil}, exp_worth = 2,
 	rank = 4,
diff --git a/game/modules/tome/dialogs/Birther.lua b/game/modules/tome/dialogs/Birther.lua
index bc9155dec4..7835314af0 100644
--- a/game/modules/tome/dialogs/Birther.lua
+++ b/game/modules/tome/dialogs/Birther.lua
@@ -1034,22 +1034,21 @@ end
 
 function _M:resetAttachementSpots()
 	self.actor.attachement_spots = nil
-	if self.has_custom_tile then return end
+	if self.has_custom_tile then 
+		self.actor.attachement_spots = self.has_custom_tile.f
+		return
+	end
 
 	local dbr = self.birth_descriptor_def.race[self.descriptors_by_type.race or "Human"]
 	local dr = self.birth_descriptor_def.subrace[self.descriptors_by_type.subrace or "Cornac"]
 	local ds = self.birth_descriptor_def.sex[self.descriptors_by_type.sex or "Female"]
 
 	local moddable_attachement_spots = dr.moddable_attachement_spots or dbr.moddable_attachement_spots
+	local moddable_attachement_spots_sexless = dr.moddable_attachement_spots_sexless or dbr.moddable_attachement_spots_sexless
 	if moddable_attachement_spots then
-		local base = moddable_attachement_spots.base
-		local b = moddable_attachement_spots.all
-		if not b then b = self.actor.female and moddable_attachement_spots.female or moddable_attachement_spots.male end
-		local t = {}
-		self.actor.attachement_spots = t
-		for kind, d in pairs(b) do
-			t[kind] = {}
-			for o, p in pairs(d) do t[kind][o] = p / base end
+		if moddable_attachement_spots_sexless then self.actor.attachement_spots = "dolls_"..moddable_attachement_spots.."_all"
+		elseif self.descriptors_by_type.sex == "Female" then self.actor.attachement_spots = "dolls_"..moddable_attachement_spots.."_female"
+		else self.actor.attachement_spots = "dolls_"..moddable_attachement_spots.."_male"
 		end
 	end
 end
diff --git a/game/modules/tome/resolvers.lua b/game/modules/tome/resolvers.lua
index 1b34b38dac..e8616fc77e 100644
--- a/game/modules/tome/resolvers.lua
+++ b/game/modules/tome/resolvers.lua
@@ -697,6 +697,7 @@ function resolvers.calc.nice_tile(t, e)
 	if engine.Map.tiles.nicer_tiles then
 		if t[1].tall then t[1] = {image="invis.png", add_mos = {{image="=BASE=TILE=", display_h=2, display_y=-1}}} end
 		if t[1].add_mos and t[1].add_mos[1] and t[1].add_mos[1].image == "=BASE=TILE=" then t[1].add_mos[1].image = e.image end
+		if t[1].add_mos and t[1].add_mos[1] and t[1].add_mos[1].image then t[1].attachement_spots = t[1].add_mos[1].image end
 		table.merge(e, t[1])
 	end
 	return nil
-- 
GitLab