From f327ac9d1f5775b290958e677cb1ed7404cc9147 Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Mon, 6 Jun 2011 18:14:33 +0000
Subject: [PATCH] New birth UI! All NPCs now have tiles!

git-svn-id: http://svn.net-core.org/repos/t-engine4@3598 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engines/default/engine/ui/Base.lua       |   3 +
 game/engines/default/engine/ui/Dialog.lua     |  61 ++++++++---
 game/engines/default/engine/ui/Dropdown.lua   |  96 ++++++++++++++++++
 game/engines/default/engine/ui/Textbox.lua    |   7 +-
 game/engines/default/engine/ui/TreeList.lua   |   4 +-
 game/modules/tome/class/Game.lua              |  15 ++-
 game/modules/tome/class/NPC.lua               |   2 +
 .../tome/class/interface/PlayerStats.lua      |   8 +-
 .../tome/data/birth/classes/afflicted.lua     |  10 +-
 .../tome/data/birth/classes/chronomancer.lua  |  10 +-
 .../tome/data/birth/classes/corrupted.lua     |  10 +-
 .../tome/data/birth/classes/divine.lua        |  10 +-
 game/modules/tome/data/birth/classes/mage.lua |   4 +-
 .../tome/data/birth/classes/psionic.lua       |   6 +-
 .../tome/data/birth/classes/warrior.lua       |   4 +-
 .../tome/data/birth/classes/wilder.lua        |  14 ++-
 game/modules/tome/data/birth/descriptors.lua  |   4 +-
 .../tome/data/birth/races/construct.lua       |   6 +-
 game/modules/tome/data/birth/races/undead.lua |  14 ++-
 game/modules/tome/data/birth/races/yeek.lua   |   4 +
 game/modules/tome/data/birth/worlds.lua       |  59 +++++------
 .../tome/data/chats/escort-quest-start.lua    |   2 +
 game/modules/tome/data/chats/escort-quest.lua |   2 +
 .../tome/data/general/npcs/sandworm.lua       |   1 +
 .../shockbolt/npc/dragon_sand_sand_drake.png  | Bin 0 -> 10287 bytes
 .../humanoid_shalore_archmage_tarelion.png    | Bin 0 -> 14977 bytes
 game/modules/tome/data/quests/escort-duty.lua |   3 +
 .../tome/data/zones/town-angolwen/npcs.lua    |   3 +-
 28 files changed, 285 insertions(+), 77 deletions(-)
 create mode 100644 game/engines/default/engine/ui/Dropdown.lua
 create mode 100644 game/modules/tome/data/gfx/shockbolt/npc/dragon_sand_sand_drake.png
 create mode 100644 game/modules/tome/data/gfx/shockbolt/npc/humanoid_shalore_archmage_tarelion.png

diff --git a/game/engines/default/engine/ui/Base.lua b/game/engines/default/engine/ui/Base.lua
index e23b2277fb..38c96c8482 100644
--- a/game/engines/default/engine/ui/Base.lua
+++ b/game/engines/default/engine/ui/Base.lua
@@ -157,3 +157,6 @@ end
 function _M:setTextShadow(v)
 	self.text_shadow = v
 end
+
+function _M:positioned(x, y)
+end
diff --git a/game/engines/default/engine/ui/Dialog.lua b/game/engines/default/engine/ui/Dialog.lua
index 24fa0240fd..92c67e7e7c 100644
--- a/game/engines/default/engine/ui/Dialog.lua
+++ b/game/engines/default/engine/ui/Dialog.lua
@@ -145,8 +145,8 @@ end
 
 title_shadow = true
 
-function _M:init(title, w, h, x, y, alpha, font, showup)
-	self.title = assert(title, "no dialog title")
+function _M:init(title, w, h, x, y, alpha, font, showup, skin)
+	self.title = title
 	self.alpha = self.alpha or 255
 	if showup ~= nil then
 		self.__showup = showup
@@ -154,6 +154,7 @@ function _M:init(title, w, h, x, y, alpha, font, showup)
 		self.__showup = 2
 	end
 	self.color = self.color or {r=255, g=255, b=255}
+	if skin then self.ui = skin end
 
 	local conf = self.ui_conf[self.ui]
 	self.frame = self.frame or {
@@ -175,6 +176,7 @@ function _M:init(title, w, h, x, y, alpha, font, showup)
 	self.frame.oy2 = self.frame.oy2 or conf.frame_oy2
 
 	self.uis = {}
+	self.ui_by_ui = {}
 	self.focus_ui = nil
 	self.focus_ui_id = 0
 
@@ -191,8 +193,13 @@ function _M:resize(w, h, nogen)
 	self.w, self.h = math.floor(w), math.floor(h)
 	self.display_x = math.floor(self.force_x or (gamew - self.w) / 2)
 	self.display_y = math.floor(self.force_y or (gameh - self.h) / 2)
-	self.ix, self.iy = 5, 8 + 3 + self.font_bold_h
-	self.iw, self.ih = w - 2 * 5, h - 8 - 8 - 3 - self.font_bold_h
+	if self.title then
+		self.ix, self.iy = 5, 8 + 3 + self.font_bold_h
+		self.iw, self.ih = w - 2 * 5, h - 8 - 8 - 3 - self.font_bold_h
+	else
+		self.ix, self.iy = 5, 8
+		self.iw, self.ih = w - 2 * 5, h - 8 - 8
+	end
 
 --	self.display_x = util.bound(self.display_x, 0, game.w - (self.w+self.frame.ox2))
 --	self.display_y = util.bound(self.display_y, 0, game.h - (self.h+self.frame.oy2))
@@ -248,6 +255,7 @@ function _M:generate()
 end
 
 function _M:updateTitle(title)
+	if not title then return end
 	local title = title
 	if type(title)=="function" then title = title() end
 	local tw, th = self.font_bold:size(title)
@@ -262,11 +270,13 @@ end
 function _M:loadUI(t)
 	if not t.no_reset then
 		self.uis = {}
+		self.ui_by_ui = {}
 		self.focus_ui = nil
 		self.focus_ui_id = 0
 	end
 	for i, ui in ipairs(t) do
 		self.uis[#self.uis+1] = ui
+		self.ui_by_ui[ui.ui] = ui
 
 		if not self.focus_ui and ui.ui.can_focus then
 			self:setFocus(i)
@@ -302,7 +312,8 @@ function _M:setupUI(resizex, resizey, on_resize, addmw, addmh)
 		mw = mw + addw + 5 * 2 + (addmw or 0)
 
 --		print("===", mw, addw)
-		local tw, th = self.font_bold:size(self.title)
+		local tw, th = 0, 0
+		if self.title then tw, th = self.font_bold:size(self.title) end
 		mw = math.max(tw + 6, mw)
 
 		mh = mh + addh + 5 + 22 + 3 + (addmh or 0) + th
@@ -320,13 +331,27 @@ function _M:setupUI(resizex, resizey, on_resize, addmw, addmh)
 		if not ui.absolute then
 			ux, uy = self.ix, self.iy
 
-			if ui.top then uy = uy + ui.top
-			elseif ui.bottom then uy = uy + self.ih - ui.bottom - ui.ui.h
-			elseif ui.vcenter then uy = uy + math.floor(self.ih / 2) + ui.vcenter - ui.ui.h / 2 end
+			if ui.top then
+				if type(ui.top) == "table" then ui.top = self.ui_by_ui[ui.top].y end
+				uy = uy + ui.top
+			elseif ui.bottom then
+				if type(ui.bottom) == "table" then ui.bottom = self.ui_by_ui[ui.bottom].y end
+				uy = uy + self.ih - ui.bottom - ui.ui.h
+			elseif ui.vcenter then
+				if type(ui.vcenter) == "table" then ui.vcenter = self.ui_by_ui[ui.vcenter].y + ui.vcenter.h end
+				uy = uy + math.floor(self.ih / 2) + ui.vcenter - ui.ui.h / 2
+			end
 
-			if ui.left then ux = ux + ui.left
-			elseif ui.right then ux = ux + self.iw - ui.right - ui.ui.w
-			elseif ui.hcenter then ux = ux + math.floor(self.iw / 2) + ui.hcenter - ui.ui.w / 2 end
+			if ui.left then
+				if type(ui.left) == "table" then ui.left = self.ui_by_ui[ui.left].x + ui.left.w end
+				ux = ux + ui.left
+			elseif ui.right then
+				if type(ui.right) == "table" then ui.right = self.ui_by_ui[ui.right].x end
+				ux = ux + self.iw - ui.right - ui.ui.w
+			elseif ui.hcenter then
+				if type(ui.hcenter) == "table" then ui.hcenter = self.ui_by_ui[ui.hcenter].x + ui.hcenter.w end
+				ux = ux + math.floor(self.iw / 2) + ui.hcenter - ui.ui.w / 2
+			end
 		else
 			ux, uy = 0, 0
 
@@ -346,6 +371,7 @@ function _M:setupUI(resizex, resizey, on_resize, addmw, addmh)
 		ui.y = uy
 		ui.ui.mouse.delegate_offset_x = ux
 		ui.ui.mouse.delegate_offset_y = uy
+		ui.ui:positioned(ux, uy, self.display_x + ux, self.display_y + uy)
 	end
 
 	self.setuped = true
@@ -394,6 +420,11 @@ function _M:getUIElement(id)
 	return self.uis[id]
 end
 
+function _M:toggleDisplay(ui, show)
+	if not self.ui_by_ui[ui] then return end
+	self.ui_by_ui[ui].hidden = not show
+end
+
 function _M:moveFocus(v)
 	local id = self.focus_ui_id
 	local start = id or 1
@@ -514,13 +545,15 @@ function _M:toScreen(x, y, nb_keyframes)
 	self:drawFrame(x, y, 1, 1, 1, self.frame.a)
 
 	-- Title
-	if self.title_shadow then self.title_tex[1]:toScreenFull(x + (self.w - self.title_tex.w) / 2 + 3, y + 3, self.title_tex.w, self.title_tex.h, self.title_tex[2], self.title_tex[3], 0, 0, 0, 0.5) end
-	self.title_tex[1]:toScreenFull(x + (self.w - self.title_tex.w) / 2, y, self.title_tex.w, self.title_tex.h, self.title_tex[2], self.title_tex[3])
+	if self.title then
+		if self.title_shadow then self.title_tex[1]:toScreenFull(x + (self.w - self.title_tex.w) / 2 + 3, y + 3, self.title_tex.w, self.title_tex.h, self.title_tex[2], self.title_tex[3], 0, 0, 0, 0.5) end
+		self.title_tex[1]:toScreenFull(x + (self.w - self.title_tex.w) / 2, y, self.title_tex.w, self.title_tex.h, self.title_tex[2], self.title_tex[3])
+	end
 
 	-- UI elements
 	for i = 1, #self.uis do
 		local ui = self.uis[i]
-		ui.ui:display(x + ui.x, y + ui.y, nb_keyframes, ox + ui.x, oy + ui.y)
+		if not ui.hidden then ui.ui:display(x + ui.x, y + ui.y, nb_keyframes, ox + ui.x, oy + ui.y) end
 	end
 
 	self:innerDisplay(x, y, nb_keyframes)
diff --git a/game/engines/default/engine/ui/Dropdown.lua b/game/engines/default/engine/ui/Dropdown.lua
new file mode 100644
index 0000000000..2982985e5c
--- /dev/null
+++ b/game/engines/default/engine/ui/Dropdown.lua
@@ -0,0 +1,96 @@
+-- TE4 - T-Engine 4
+-- Copyright (C) 2009, 2010, 2011 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+require "engine.class"
+local Base = require "engine.ui.Base"
+local Focusable = require "engine.ui.Focusable"
+local List = require "engine.ui.List"
+local Dialog = require "engine.ui.Dialog"
+
+--- A generic UI list dropdown box
+module(..., package.seeall, class.inherit(Base, Focusable))
+
+function _M:init(t)
+	self.text = t.text or ""
+	self.w = assert(t.width, "no dropdown width")
+	self.fct = assert(t.fct, "no dropdown fct")
+	self.list = assert(t.list, "no dropdown list")
+	self.nb_items = assert(t.nb_items, "no dropdown nb_items")
+	self.on_select = t.on_select
+	self.display_prop = t.display_prop or "name"
+	self.scrollbar = t.scrollbar
+
+	Base.init(self, t)
+end
+
+function _M:generate()
+	self.mouse:reset()
+	self.key:reset()
+
+	-- Draw UI
+	self.h = self.font_h + 6
+	self.height = self.h
+
+	self.frame = self:makeFrame("ui/textbox", self.w, self.h)
+	self.frame_sel = self:makeFrame("ui/textbox-sel", self.w, self.h)
+
+	-- Add UI controls
+	self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event)
+		if event == "button" and button == "left" then self:showSelect() end
+	end)
+	self.key:addBind("ACCEPT", function() self:showSelect() end)
+end
+
+function _M:positioned(x, y, sx, sy)
+	self.c_list = List.new{width=self.w, list=self.list, select=self.on_select, display_prop=self.display_prop, scrollbar=self.scrollbar, nb_items=self.nb_items, fct=function()
+		game:unregisterDialog(self.popup)
+		self.fct(self.c_list.list[self.c_list.sel])
+	end}
+	self.popup = Dialog.new(nil, self.w, self.c_list.h, sx, sy + self.h, nil, nil, false, "simple")
+	self.popup.frame.a = 0.7
+	self.popup:loadUI{{left=0, top=0, ui=self.c_list}}
+	self.popup:setupUI(true, true)
+	self.popup.key:addBind("EXIT", function()
+		game:unregisterDialog(self.popup)
+		self.c_list.sel = self.previous
+		self.fct(self.c_list.list[self.c_list.sel])
+	end)
+end
+
+function _M:showSelect()
+	self.previous = self.c_list.sel
+	game:registerDialog(self.popup)
+end
+
+function _M:display(x, y, nb_keyframes)
+	if self.focused then
+		self:drawFrame(self.frame_sel, x, y)
+	else
+		self:drawFrame(self.frame, x, y)
+		if self.focus_decay then
+			self:drawFrame(self.frame_sel, x, y, 1, 1, 1, self.focus_decay / self.focus_decay_max_d)
+			self.focus_decay = self.focus_decay - nb_keyframes
+			if self.focus_decay <= 0 then self.focus_decay = nil end
+		end
+	end
+
+	local item = self.c_list.list[self.c_list.sel]
+	if self.text_shadow then item._tex[1]:toScreenFull(x+1 + self.frame_sel.b4.w, y+1, self.c_list.fw, self.c_list.fh, item._tex[2], item._tex[3], 0, 0, 0, self.text_shadow) end
+	item._tex[1]:toScreenFull(x + self.frame_sel.b4.w, y, self.c_list.fw, self.c_list.fh, item._tex[2], item._tex[3])
+end
diff --git a/game/engines/default/engine/ui/Textbox.lua b/game/engines/default/engine/ui/Textbox.lua
index 9947f0dccf..20fbe9e845 100644
--- a/game/engines/default/engine/ui/Textbox.lua
+++ b/game/engines/default/engine/ui/Textbox.lua
@@ -27,7 +27,9 @@ module(..., package.seeall, class.inherit(Base, Focusable))
 function _M:init(t)
 	self.title = assert(t.title, "no textbox title")
 	self.text = t.text or ""
+	self.old_text = self.text
 	self.hide = t.hide
+	self.on_change = t.on_change
 	self.max_len = t.max_len or 999
 	self.fct = assert(t.fct, "no textbox fct")
 	self.chars = assert(t.chars, "no textbox chars")
@@ -82,7 +84,8 @@ function _M:generate()
 		end
 	end)
 	self.key:addBind("ACCEPT", function() self.fct(self.text) end)
-	self.key:addIgnore("_ESCAPE", v)
+	self.key:addIgnore("_ESCAPE", true)
+	self.key:addIgnore("_TAV", true)
 	self.key:addCommands{
 		_LEFT = function() self.cursor = util.bound(self.cursor - 1, 1, #self.tmp+1) self.scroll = util.scroll(self.cursor, self.scroll, self.max_display) self:updateText() end,
 		_RIGHT = function() self.cursor = util.bound(self.cursor + 1, 1, #self.tmp+1) self.scroll = util.scroll(self.cursor, self.scroll, self.max_display) self:updateText() end,
@@ -135,6 +138,8 @@ function _M:updateText()
 	self.text_surf:erase(0, 0, 0, 0)
 	self.text_surf:drawStringBlended(self.font_mono, text, 0, 0, 255, 255, 255, true)
 	self.text_surf:updateTexture(self.text_tex)
+	if self.on_change and self.old_text ~= self.text then self.on_change(self.text) end
+	self.old_text = self.text
 end
 
 function _M:display(x, y, nb_keyframes)
diff --git a/game/engines/default/engine/ui/TreeList.lua b/game/engines/default/engine/ui/TreeList.lua
index 1eba2cf553..b466308832 100644
--- a/game/engines/default/engine/ui/TreeList.lua
+++ b/game/engines/default/engine/ui/TreeList.lua
@@ -268,8 +268,8 @@ function _M:outputList()
 	self.cur_col = self.cur_col or 1
 end
 
-function _M:treeExpand(v)
-	local item = self.list[self.sel]
+function _M:treeExpand(v, item)
+	local item = item or self.list[self.sel]
 	if not item then return end
 	if v == nil then
 		item.shown = not item.shown
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 17ce00e48c..9f79a1341c 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -29,7 +29,7 @@ local Zone = require "engine.Zone"
 local Tiles = require "engine.Tiles"
 local Map = require "engine.Map"
 local Level = require "engine.Level"
-local Birther = require "engine.Birther"
+local Birther = require "mod.dialogs.Birther"
 local Astar = require "engine.Astar"
 local DirectPath = require "engine.DirectPath"
 local Shader = require "engine.Shader"
@@ -164,6 +164,15 @@ function _M:isTainted()
 	return (game.player and game.player.__cheated) and true or false
 end
 
+--- Sets the player name
+function _M:setPlayerName(name)
+	self.save_name = name
+	self.player_name = name
+	if self.party and self.party:findMember{main=true} then
+		self.party:findMember{main=true}.name = name
+	end
+end
+
 function _M:newGame()
 	self.party = Party.new()
 	local player = Player.new{name=self.player_name, game_ender=true}
@@ -205,7 +214,7 @@ function _M:newGame()
 	local nb_unlocks, max_unlocks = self:countBirthUnlocks()
 
 	self.creating_player = true
-	local birth; birth = Birther.new("Character Creation: "..self.player.name.." ("..nb_unlocks.."/"..max_unlocks.." unlocked birth options)", self.player, {"base", "world", "difficulty", "race", "subrace", "sex", "class", "subclass" }, function()
+	local birth; birth = Birther.new("Character Creation ("..nb_unlocks.."/"..max_unlocks.." unlocked birth options)", self.player, {"base", "world", "difficulty", "race", "subrace", "sex", "class", "subclass" }, function()
 		self.calendar = Calendar.new("/data/calendar_"..(self.player.calendar or "allied")..".lua", "Today is the %s %s of the %s year of the Age of Ascendancy of Maj'Eyal.\nThe time is %02d:%02d.", 122, 167, 11)
 		self.player:check("make_tile")
 		self.player.make_tile = nil
@@ -267,7 +276,7 @@ function _M:newGame()
 
 		if self.player.no_birth_levelup or __module_extra_info.no_birth_popup then birthend()
 		else self.player:playerLevelup(birthend) end
-	end, quickbirth, 720, 500)
+	end, quickbirth, 800, 600)
 
 	-- Load a full player instead of a simpler quickbirthing, if possible
 	birth.quickBirth = function(b)
diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua
index dd73ee0f63..552bd1dda1 100644
--- a/game/modules/tome/class/NPC.lua
+++ b/game/modules/tome/class/NPC.lua
@@ -208,6 +208,8 @@ function _M:die(src)
 			game.state:allowRodRecall(false)
 		end
 	end
+	-- Ok the player managed to kill a boss dont bother him with tutorial anymore
+	if self.rank >= 3.5 and not profile.mod.allow_build.tutorial_done then game:setAllowedBuild("tutorial_done") end
 
 	return mod.class.Actor.die(self, src)
 end
diff --git a/game/modules/tome/class/interface/PlayerStats.lua b/game/modules/tome/class/interface/PlayerStats.lua
index e96f801477..2ebf2ad857 100644
--- a/game/modules/tome/class/interface/PlayerStats.lua
+++ b/game/modules/tome/class/interface/PlayerStats.lua
@@ -68,9 +68,13 @@ function _M:registerCharacterPlayed()
 end
 
 function _M:registerLoreFound(lore)
-	local pid = self:playerStatGetCharacterIdentifier(game.party:findMember{main=true})
-
 	profile.mod.lore = profile.mod.lore or { lore={} }
 	profile.mod.lore.lore[lore] = true
 	profile:saveModuleProfile("lore", profile.mod.lore)
 end
+
+function _M:registerEscorts(status)
+	profile.mod.escorts = profile.mod.escorts or { saved=0, lost=0, betrayed=0, zigur=0 }
+	profile.mod.escorts[status] = profile.mod.escorts[status] + 1
+	profile:saveModuleProfile("escorts", profile.mod.escorts)
+end
diff --git a/game/modules/tome/data/birth/classes/afflicted.lua b/game/modules/tome/data/birth/classes/afflicted.lua
index 1cf3372520..d249deb678 100644
--- a/game/modules/tome/data/birth/classes/afflicted.lua
+++ b/game/modules/tome/data/birth/classes/afflicted.lua
@@ -20,6 +20,8 @@
 newBirthDescriptor{
 	type = "class",
 	name = "Afflicted",
+	locked = function() return profile.mod.allow_build.afflicted end,
+	locked_desc = "Some walk in shadow, alone, unloved, unwanted. What powers they wield may be mighty, but their names are forever cursed.",
 	desc = {
 		"Afflicted classes have been twisted by their association with evil forces.",
 		"They can use these forces to their advantage, but at a cost...",
@@ -29,8 +31,8 @@ newBirthDescriptor{
 		subclass =
 		{
 			__ALL__ = "disallow",
-			Cursed = function() return profile.mod.allow_build.afflicted_cursed and "allow" or "disallow" end,
-			Doomed = function() return profile.mod.allow_build.afflicted_doomed and "allow" or "disallow" end,
+			Cursed = "allow",
+			Doomed = "allow",
 		},
 	},
 	copy = {
@@ -40,6 +42,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Cursed",
+	locked = function() return profile.mod.allow_build.afflicted_cursed end,
+	locked_desc = "Affliction can run to the soul, and hatred can fill one's entire being. Overcome someone else's hated curse to know its dreaded meaning.",
 	desc = {
 		"Through ignorance, greed or folly the Cursed served some dark design and are now doomed to pay for their sins.",
 		"Their only master now is the hatred they carry for every living thing.",
@@ -82,6 +86,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Doomed",
+	locked = function() return profile.mod.allow_build.afflicted_doomed end,
+	locked_desc = "In shaded places in unknown lands thou must overcome thyself and see thy doom.",
 	desc = {
 		"The Doomed are fallen mages who once wielded powerful magic wrought by ambition and dark bargains.",
 		"They now possess only a twisted shadow of that power as they struggle to keep it from consuming them.",
diff --git a/game/modules/tome/data/birth/classes/chronomancer.lua b/game/modules/tome/data/birth/classes/chronomancer.lua
index 3f40bc1b96..4272a6b717 100644
--- a/game/modules/tome/data/birth/classes/chronomancer.lua
+++ b/game/modules/tome/data/birth/classes/chronomancer.lua
@@ -20,6 +20,8 @@
 newBirthDescriptor{
 	type = "class",
 	name = "Chronomancer",
+	locked = function() return profile.mod.allow_build.chronomancer end,
+	locked_desc = "Some do not walk upon the straight road others follow. Seek the hidden paths outside the normal course of life.",
 	desc = {
 		"With one foot literally in the past and one in the future, Chronomancers manipulate the present at a whim and wield a power that only bows to nature's own need to keep the balance. The wake in spacetime they leave behind them makes their own Chronomantic abilites that much stronger and that much harder to control.  The wise Chronomancer learns to maintain the balance between his own thirst for cosmic power and the universe's need to flow undisturbed, for the hole he tears that amplifies his own abilities just may be the same hole that one day swallows him.",
 	},
@@ -28,8 +30,8 @@ newBirthDescriptor{
 		subclass =
 		{
 			__ALL__ = "disallow",
-			["Paradox Mage"] = function() return profile.mod.allow_build.chronomancer_paradox_mage and "allow" or "disallow" end,
-			["Temporal Warden"] = function() return profile.mod.allow_build.chronomancer_temporal_warden and "allow" or "disallow" end,
+			["Paradox Mage"] = "allow",
+			["Temporal Warden"] = "allow",
 		},
 	},
 	copy = {
@@ -39,6 +41,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Paradox Mage",
+	locked = function() return profile.mod.allow_build.chronomancer_paradox_mage end,
+	locked_desc = "A hand may clap alone if it returns to clap itself. Search for the power in the paradox.",
 	desc = {
 		"A Paradox Mage studies the very fabric of spacetime, learning not just to bend it but shape it and remake it.",
 		"Most Paradox Mages lack basic skills that others take for granted (like general fighting sense), but they make up for it through control of cosmic forces.",
@@ -85,6 +89,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Temporal Warden",
+	locked = function() return profile.mod.allow_build.chronomancer_temporal_warden end,
+	locked_desc = "We preserve the past to protect the future. The hands of time are guarded by the arms of war.",
 	desc = {
 		"The Temporal Wardens have learned to blend archery, dual-weapon fighting, and chronomancy into a fearsome whole.",
 		"Through their use of the chronomantic arts, the Temporal Wardens seek to control the battlefield while peppering their foes with arrows or engaging in hand-to-hand combat.",
diff --git a/game/modules/tome/data/birth/classes/corrupted.lua b/game/modules/tome/data/birth/classes/corrupted.lua
index 056be39b45..01ea7b9c6f 100644
--- a/game/modules/tome/data/birth/classes/corrupted.lua
+++ b/game/modules/tome/data/birth/classes/corrupted.lua
@@ -20,6 +20,8 @@
 newBirthDescriptor{
 	type = "class",
 	name = "Corrupter",
+	locked = function() return profile.mod.allow_build.corrupter end,
+	locked_desc = "Dark thoughts, black bloods, vile deeds... Those who spill their brethren's blood will find its power.",
 	desc = {
 		"Corrupters are touched by the mark of evil. They are a blight on the world. Working to promote the cause of evil, they serve their masters, or themselves become masters.",
 	},
@@ -28,8 +30,8 @@ newBirthDescriptor{
 		subclass =
 		{
 			__ALL__ = "disallow",
-			Reaver = function() return profile.mod.allow_build.corrupter_reaver and "allow" or "disallow" end,
-			Corruptor = function() return profile.mod.allow_build.corrupter_corruptor and "allow" or "disallow" end,
+			Reaver = "allow",
+			Corruptor = "allow",
 		},
 	},
 	copy = {
@@ -40,6 +42,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Reaver",
+	locked = function() return profile.mod.allow_build.corrupter_reaver end,
+	locked_desc = "Reap thee the souls of thine enemies, and the powers of darkness shall enter thine flesh.",
 	desc = {
 		"Reavers are terrible foes, charging their enemies with a weapon in each hand.",
 		"They can harness the blight of evil, infecting their foes with terrible contagious diseases while crushing their skulls with devastating combat techniques.",
@@ -81,6 +85,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Corruptor",
+	locked = function() return profile.mod.allow_build.corrupter_corruptor end,
+	locked_desc = "Blight and depravity hold the greatest powers. Accept temptation and become one with corruption.",
 	desc = {
 		"A corruptor is a terrible foe, wielding dark magics that can sap the very soul of her target.",
 		"They can harness the blight of evil, crushing souls, stealing life force to replenish themselves.",
diff --git a/game/modules/tome/data/birth/classes/divine.lua b/game/modules/tome/data/birth/classes/divine.lua
index 45c071b40a..32a2d05490 100644
--- a/game/modules/tome/data/birth/classes/divine.lua
+++ b/game/modules/tome/data/birth/classes/divine.lua
@@ -20,6 +20,8 @@
 newBirthDescriptor{
 	type = "class",
 	name = "Divine",
+	locked = function() return profile.mod.allow_build.divine end,
+	locked_desc = "The magic of the heavens is known to but a few, and that knowledge has long passed east, forgotten.",
 	desc = {
 		"Divine classes are worshippers of various gods and entities.",
 		"They include the worship of the Sun, the Moon, powerful spirits, ...",
@@ -29,8 +31,8 @@ newBirthDescriptor{
 		subclass =
 		{
 			__ALL__ = "disallow",
-			['Sun Paladin'] = function() return profile.mod.allow_build.divine_sun_paladin and "allow" or "disallow" end,
-			Anorithil = function() return profile.mod.allow_build.divine_anorithil and "allow" or "disallow" end,
+			['Sun Paladin'] = "allow",
+			Anorithil = "allow",
 		},
 	},
 	copy = {
@@ -42,6 +44,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Sun Paladin",
+	locked = function() return profile.mod.allow_build.divine_sun_paladin end,
+	locked_desc = "The sun rises in the east in full glory, but you must look for it first amidst the darkest places.",
 	desc = {
 		"Sun Paladins hail from the Gates of Morning, the last bastion of the free people in the Far East.",
 		"Their way of life is well represented by their motto 'The Sun is our giver, our purity, our essence. We carry the light into dark places, and against our strength none shall pass.'",
@@ -87,6 +91,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Anorithil",
+	locked = function() return profile.mod.allow_build.divine_anorithil end,
+	locked_desc = "The balance of the heavens' powers is a daunting task. Mighty are those that stand in the twilight places, wielding both light and darkness in their mind.",
 	desc = {
 		"Anorithils hail from the Gates of Morning, the last bastion of the free people in the Far East.",
 		"Their way of life is well represented by their motto 'We stand betwixt the Sun and Moon, where light and darkness meet. In the grey twilight we seek our destiny.'",
diff --git a/game/modules/tome/data/birth/classes/mage.lua b/game/modules/tome/data/birth/classes/mage.lua
index 477347d55d..1439d28ffb 100644
--- a/game/modules/tome/data/birth/classes/mage.lua
+++ b/game/modules/tome/data/birth/classes/mage.lua
@@ -29,7 +29,7 @@ newBirthDescriptor{
 		{
 			__ALL__ = "disallow",
 			Alchemist = "allow",
-			Archmage = function() return profile.mod.allow_build.mage and "allow" or "disallow" end,
+			Archmage = "allow",
 		},
 	},
 	copy = {
@@ -42,6 +42,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Archmage",
+	locked = function() return profile.mod.allow_build.mage end,
+	locked_desc = "Hated, harrowed, hunted, hidden... Our ways are forbidden, but our cause is just. In our veiled valley we find solace from the world's wrath, free to study our arts. Only through charity and friendship can you earn our trust.",
 	desc = {
 		"An Archmage devotes his whole life to the study of magic above anything else.",
 		"Most Archmagi lack basic skills that others take for granted (like general fighting sense), but they make up for it by their raw magical power.",
diff --git a/game/modules/tome/data/birth/classes/psionic.lua b/game/modules/tome/data/birth/classes/psionic.lua
index 4974f9db8e..890ff9d6a0 100644
--- a/game/modules/tome/data/birth/classes/psionic.lua
+++ b/game/modules/tome/data/birth/classes/psionic.lua
@@ -20,6 +20,8 @@
 newBirthDescriptor{
 	type = "class",
 	name = "Psionic",
+	locked = function() return profile.mod.allow_build.psionic end,
+	locked_desc = "Weakness of flesh can be overcome by mental prowess. Find the way and fight for the way to open the key to your mind.",
 	desc = {
 		"Psionics find their power within themselves. Their highly trained minds can harness energy from many different sources and manipulate it to produce physical effects.",
 	},
@@ -28,7 +30,7 @@ newBirthDescriptor{
 		subclass =
 		{
 			__ALL__ = "disallow",
-			Mindslayer = function() return profile.mod.allow_build.psionic_mindslayer and "allow" or "disallow" end,
+			Mindslayer = "allow",
 		},
 	},
 	copy = {
@@ -40,6 +42,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Mindslayer",
+	locked = function() return profile.mod.allow_build.psionic_mindslayer end,
+	locked_desc = "A thought can inspire, a thought can kill. After centuries of oppression, years of imprisonment, a thought shall break us free and vengeance will strike from our darkest dreams.",
 	desc = {
 		"Mindslayers specialize in direct and brutal application of mental forces to their immediate surroundings.",
 		"When Mindslayers do battle, they will most often be found in the thick of the fighting, vast energies churning around them and telekinetically-wielded weapons hewing nearby foes at the speed of thought.",
diff --git a/game/modules/tome/data/birth/classes/warrior.lua b/game/modules/tome/data/birth/classes/warrior.lua
index 15c289f278..e7aefda99d 100644
--- a/game/modules/tome/data/birth/classes/warrior.lua
+++ b/game/modules/tome/data/birth/classes/warrior.lua
@@ -30,7 +30,7 @@ newBirthDescriptor{
 			__ALL__ = "disallow",
 			Fighter = "allow",
 			Berserker = "allow",
-			Brawler = function() return profile.mod.allow_build.warrior_brawler and "allow" or "disallow" end,
+			Brawler = "allow",
 			["Arcane Blade"] = "allow",
 		},
 	},
@@ -179,6 +179,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Brawler",
+	locked = function() return profile.mod.allow_build.warrior_brawler end,
+	locked_desc = "Though you may fight alone against many, destined to fight till you die, still you do not relent. In a ring of blood you learn that a pair of fists can face the world.",
 	desc = {
 		"The ravages of the Spellblaze stretched armies thin and left many unprotected. Not everyone could afford the luxury of a weapon.",
 		"Without steel or iron, poor communities of all races turned to the strength of their own bodies for defense against the darkness.",
diff --git a/game/modules/tome/data/birth/classes/wilder.lua b/game/modules/tome/data/birth/classes/wilder.lua
index 8e6e910be6..5088d70c24 100644
--- a/game/modules/tome/data/birth/classes/wilder.lua
+++ b/game/modules/tome/data/birth/classes/wilder.lua
@@ -20,6 +20,8 @@
 newBirthDescriptor{
 	type = "class",
 	name = "Wilder",
+	locked = function() return profile.mod.allow_build.wilder_wyrmic or profile.mod.allow_build.wilder_summoner or profile.mod.allow_build.wilder_stone_warden end,
+	locked_desc = "Natural abilities can go beyond mere skill. Experience the true powers of nature to learn of its amazing gifts.",
 	desc = {
 		"Wilders are one with nature, in one manner or another. There are as many different Wilders as there are aspects of nature.",
 		"They can take on the aspects of creatures, summon creatures to them, feel the druidic call, ...",
@@ -29,9 +31,9 @@ newBirthDescriptor{
 		subclass =
 		{
 			__ALL__ = "disallow",
-			Summoner = function() return profile.mod.allow_build.wilder_summoner and "allow" or "disallow" end,
-			Wyrmic = function() return profile.mod.allow_build.wilder_wyrmic and "allow" or "disallow" end,
-			["Stone Warden"] = function(birth) return birth.descriptors_by_type.race and birth.descriptors_by_type.race.name == "Dwarf" and profile.mod.allow_build.wilder_stone_warden and "allow" or "disallow" end,
+			Summoner = "allow",
+			Wyrmic = "allow",
+			["Stone Warden"] = "allow",
 		},
 	},
 	copy = {
@@ -41,6 +43,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Summoner",
+	locked = function() return profile.mod.allow_build.wilder_summoner end,
+	locked_desc = "Not all might comes from within. Hear the invocations of nature, hear its calling power. See that from without we can find our true strengths.",
 	desc = {
 		"Summoners never fight alone. They are always ready to summon one of their many minions to fight at their side.",
 		"Summons can range from a combat hound to a fire drake.",
@@ -84,6 +88,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Wyrmic",
+	locked = function() return profile.mod.allow_build.wilder_wyrmic end,
+	locked_desc = "Sleek, majestic, powerful... In the path of dragons we walk, and their breath is our breath. See their beating hearts with your eyes and taste their majesty between your teeth.",
 	desc = {
 		"Wyrmics are fighters who have learnt how to mimic some of the aspects of the dragons.",
 		"They have access to talents normally belonging to the various kind of drakes.",
@@ -128,6 +134,8 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "subclass",
 	name = "Stone Warden",
+	locked = function() return profile.mod.allow_build.wilder_stone_warden and true or "hide" end,
+	locked_desc = "",
 	desc = {
 		"Stone Wardens are dwarves trained in both the eldritch arts and the worship of nature.",
 		"While other races are stuck in their belief that arcane forces and natural forces are meant to oppose, dwarves have found a way to combine them in harmony.",
diff --git a/game/modules/tome/data/birth/descriptors.lua b/game/modules/tome/data/birth/descriptors.lua
index ef1da42a0c..cdbd015df5 100644
--- a/game/modules/tome/data/birth/descriptors.lua
+++ b/game/modules/tome/data/birth/descriptors.lua
@@ -39,8 +39,8 @@ newBirthDescriptor{
 		{
 			Tutorial = "disallow",
 			["Maj'Eyal"] = "allow",
-			Infinite = function() return profile.mod.allow_build.campaign_infinite_dungeon and "allow" or "disallow" end,
-			Arena = function() return profile.mod.allow_build.campaign_arena and "allow" or "disallow" end,
+			Infinite = "allow",
+			Arena = "allow",
 			Ents = "disallow",
 			Spydre = "disallow",
 			Orcs = "disallow",
diff --git a/game/modules/tome/data/birth/races/construct.lua b/game/modules/tome/data/birth/races/construct.lua
index 0275d7e7b6..5e74962344 100644
--- a/game/modules/tome/data/birth/races/construct.lua
+++ b/game/modules/tome/data/birth/races/construct.lua
@@ -23,6 +23,8 @@
 newBirthDescriptor{
 	type = "race",
 	name = "Construct",
+	locked = function() return profile.mod.allow_build.construct and true or "hide" end,
+	locked_desc = "",
 	desc = {
 		"Constructs are not natural creatures.",
 		"The most usual contructs are golems, but they can vary in shape, form and abilities.",
@@ -32,7 +34,7 @@ newBirthDescriptor{
 		subrace =
 		{
 			__ALL__ = "disallow",
-			["Runic Golem"] = function() return profile.mod.allow_build.construct_runic_golem and "allow" or "disallow" end,
+			["Runic Golem"] = "allow",
 		},
 	},
 	random_escort_possibilities = { {"trollmire", 2, 3}, {"ruins-kor-pul", 1, 2}, {"daikara", 1, 5}, {"old-forest", 1, 5}, {"dreadfell", 1, 8}, {"reknor", 1, 1}, },
@@ -42,6 +44,8 @@ newBirthDescriptor
 {
 	type = "subrace",
 	name = "Runic Golem",
+	locked = function() return profile.mod.allow_build.construct_runic_golem and true or "hide" end,
+	locked_desc = "",
 	desc = {
 		"Runic Golems are creatures made of solid rock and animated using arcane forces.",
 		"They can not be of any class, but they have many intrinsinc abilities.",
diff --git a/game/modules/tome/data/birth/races/undead.lua b/game/modules/tome/data/birth/races/undead.lua
index 16e81bc90b..4b36b57302 100644
--- a/game/modules/tome/data/birth/races/undead.lua
+++ b/game/modules/tome/data/birth/races/undead.lua
@@ -23,6 +23,8 @@
 newBirthDescriptor{
 	type = "race",
 	name = "Undead",
+	locked = function() return profile.mod.allow_build.undead end,
+	locked_desc = "Grave strength, dread will, this flesh cannot stay still. Kings die, masters fall, we will outlast them all.",
 	desc = {
 		"Undead are humanoids (Humans, Elves, Dwarves, ...) that have been brought back to life by the corruption of dark magics.",
 		"Undead can take many forms, from ghouls to vampires and liches.",
@@ -32,10 +34,10 @@ newBirthDescriptor{
 		subrace =
 		{
 			__ALL__ = "disallow",
-			Ghoul = function() return profile.mod.allow_build.undead_ghoul and "allow" or "disallow" end,
-			Skeleton = function() return profile.mod.allow_build.undead_skeleton and "allow" or "disallow" end,
-			Vampire = function() return profile.mod.allow_build.undead_vampire and "allow" or "disallow" end,
-			Wight = function() return profile.mod.allow_build.undead_wight and "allow" or "disallow" end,
+			Ghoul = "allow",
+			Skeleton = "allow",
+			Vampire = "allow",
+			Wight = "allow",
 		},
 		class =
 		{
@@ -64,6 +66,8 @@ newBirthDescriptor
 {
 	type = "subrace",
 	name = "Ghoul",
+	locked = function() return profile.mod.allow_build.undead_ghoul end,
+	locked_desc = "Slow to shuffle, quick to bite, learn from master, rule the night!",
 	desc = {
 		"Ghouls are dumb, but resilient, rotting undead creatures, making good fighters.",
 		"They have access to #GOLD#special ghoul talents#WHITE# and a wide range of undead abilities:",
@@ -113,6 +117,8 @@ newBirthDescriptor
 {
 	type = "subrace",
 	name = "Skeleton",
+	locked = function() return profile.mod.allow_build.undead_skeleton end,
+	locked_desc = "The marching bones, each step we rattle, but servants no more, we march to battle!",
 	desc = {
 		"Skeletons are animated bones, undead creatures both strong and dexterous.",
 		"They have access to #GOLD#special skeleton talents#WHITE# and a wide range of undead abilities:",
diff --git a/game/modules/tome/data/birth/races/yeek.lua b/game/modules/tome/data/birth/races/yeek.lua
index b65617e639..1d3e756410 100644
--- a/game/modules/tome/data/birth/races/yeek.lua
+++ b/game/modules/tome/data/birth/races/yeek.lua
@@ -23,6 +23,8 @@
 newBirthDescriptor{
 	type = "race",
 	name = "Yeek",
+	locked = function() return profile.mod.allow_build.yeek end,
+	locked_desc = "One race, one mind, one way. Our oppression shall end, and we shall inherit Eyal. Do not presume we are weak - our way is true, and only those who help us shall see our strength.",
 	desc = {
 		"Yeeks are a mysterious race of small humanoids native to the tropical island of Rel.",
 		"Their body is covered with white fur and their disproportionate heads give them a ridiculous look.",
@@ -59,6 +61,8 @@ newBirthDescriptor
 {
 	type = "subrace",
 	name = "Yeek",
+	locked = function() return profile.mod.allow_build.yeek end,
+	locked_desc = "One race, one mind, one way. Our oppression shall end, and we shall inherit Eyal. Do not presume we are weak - our way is true, and only those who help us shall see our strength.",
 	desc = {
 		"Yeeks are a mysterious race native to the tropical island of Rel.",
 		"Although they are now nearly unheard of in Maj'Eyal, they spent many centuries as secret slaves to the Halfling nation of Nargol.",
diff --git a/game/modules/tome/data/birth/worlds.lua b/game/modules/tome/data/birth/worlds.lua
index 3645fb8028..6f50942fce 100644
--- a/game/modules/tome/data/birth/worlds.lua
+++ b/game/modules/tome/data/birth/worlds.lua
@@ -27,9 +27,9 @@ local default_eyal_descriptors = function(add)
 		Elf = "allow",
 		Dwarf = "allow",
 		Halfling = "allow",
-		Yeek = function() return profile.mod.allow_build.yeek and "allow" or "disallow" end,
-		Undead = function() return profile.mod.allow_build.undead and "allow" or "disallow" end,
-		Construct = function() return profile.mod.allow_build.construct and "allow" or "disallow" end,
+		Yeek = "allow",
+		Undead = "allow",
+		Construct = "allow",
 	},
 
 	class =
@@ -41,16 +41,12 @@ local default_eyal_descriptors = function(add)
 		Archer = "allow",
 		Rogue = "allow",
 		Mage = "allow",
-		Divine = function() return profile.mod.allow_build.divine and "allow" or "disallow" end,
-		Wilder = function() return (
-			profile.mod.allow_build.wilder_summoner or
-			profile.mod.allow_build.wilder_wyrmic
-			) and "allow" or "disallow"
-		end,
-		Corrupter = function() return profile.mod.allow_build.corrupter and "allow" or "disallow" end,
-		Afflicted = function() return profile.mod.allow_build.afflicted and "allow" or "disallow" end,
-		Chronomancer = function() return profile.mod.allow_build.chronomancer and "allow" or "disallow" end,
-		Psionic = function() return profile.mod.allow_build.psionic and "allow" or "disallow" end,
+		Divine = "allow",
+		Wilder = "allow",
+		Corrupter = "allow",
+		Afflicted = "allow",
+		Chronomancer = "allow",
+		Psionic = "allow",
 	},
 }
 	if add then table.merge(base, add) end
@@ -79,6 +75,8 @@ newBirthDescriptor{
 	type = "world",
 	name = "Infinite",
 	display_name = "Infinite Dungeon: The Neverending Descent",
+	locked = function() return profile.mod.allow_build.campaign_infinite_dungeon end,
+	locked_desc = "Ever deeper, never ending, no reprieve, keep descending. In ruins old, through barred gate, once riddle solved, find thy fate.",
 	desc =
 	{
 		"Play as your favorite race and class and venture into the infinite dungeon.",
@@ -105,6 +103,8 @@ newBirthDescriptor{
 	type = "world",
 	name = "Arena",
 	display_name = "The Arena: Challenge of the Master",
+	locked = function() return profile.mod.allow_build.campaign_arena end,
+	locked_desc = "Blood spilled on sand, only the strong survive. Prove yourself worthy to enter.",
 	desc =
 	{
 		"Play as a lone warrior facing the Arena's challenge!",
@@ -135,6 +135,8 @@ newBirthDescriptor{
 	type = "world",
 	name = "Orcs",
 	display_name = "Orcs: The Rise to Power",
+	locked = function() return profile.mod.allow_build.campaign_orc and true or "hide" end,
+	locked_desc = "",
 	desc =
 	{
 		"Baston!",
@@ -153,7 +155,9 @@ newBirthDescriptor{
 newBirthDescriptor{
 	type = "world",
 	name = "Spydre",
-	display_name = "Spydrë: Legacy of Ungoliant",
+	display_name = "Spydrë: Thouch of the Spider",
+	locked = function() return profile.mod.allow_build.campaign_spidre and true or "hide" end,
+	locked_desc = "",
 	desc =
 	{
 		"Spydrë is home to the essence of spiders. The mighty Ungoliant of Arda actually originated from this world.",
@@ -171,29 +175,12 @@ newBirthDescriptor{
 	},
 }
 
-newBirthDescriptor{
-	type = "world",
-	name = "Ents",
-	display_name = "Ents: The March of the Entwifes",
-	desc =
-	{
-		"",
-	},
-	descriptor_choices =
-	{
-		race =
-		{
-			__ALL__ = "disallow",
-			Human = "allow",
---			Spider = function() return profile.mod.allow_build.spider and "allow" or "disallow" end,
-		},
-	},
-}
-
 newBirthDescriptor{
 	type = "world",
 	name = "Trolls",
 	display_name = "Trolls: Pirates of the Kar'Haib",
+	locked = function() return profile.mod.allow_build.campaign_troll and true or "hide" end,
+	locked_desc = "",
 	desc =
 	{
 		"",
@@ -213,6 +200,8 @@ newBirthDescriptor{
 	type = "world",
 	name = "Nagas",
 	display_name = "Nagas: Guardians of the Tide",
+	locked = function() return profile.mod.allow_build.campaign_naga and true or "hide" end,
+	locked_desc = "",
 	desc =
 	{
 		"",
@@ -232,6 +221,8 @@ newBirthDescriptor{
 	type = "world",
 	name = "Faeros",
 	display_name = "Urthalath: Treason or the High Guards",
+	locked = function() return profile.mod.allow_build.campaign_faeros and true or "hide" end,
+	locked_desc = "",
 	desc =
 	{
 		"",
@@ -251,6 +242,8 @@ newBirthDescriptor{
 	type = "world",
 	name = "Undeads",
 	display_name = "Broken Oath: The Curse of Undeath",
+	locked = function() return profile.mod.allow_build.campaign_undead and true or "hide" end,
+	locked_desc = "",
 	desc =
 	{
 		"",
diff --git a/game/modules/tome/data/chats/escort-quest-start.lua b/game/modules/tome/data/chats/escort-quest-start.lua
index 1ce59e7840..86e8e4526f 100644
--- a/game/modules/tome/data/chats/escort-quest-start.lua
+++ b/game/modules/tome/data/chats/escort-quest-start.lua
@@ -35,6 +35,7 @@ newChat{ id="welcome",
 			})
 		end},
 		{"Go away; I do not help filthy arcane users!", action=function(npc, player)
+			game.player:registerEscorts("lost")
 			npc:disappear()
 			npc:removed()
 			player:hasQuest(npc.quest_id).abandoned = true
@@ -59,6 +60,7 @@ newChat{ id="welcome",
 			})
 		end},
 		{"Go away; I do not care for the weak.", action=function(npc, player)
+			game.player:registerEscorts("lost")
 			npc:disappear()
 			npc:removed()
 			player:hasQuest(npc.quest_id).abandoned = true
diff --git a/game/modules/tome/data/chats/escort-quest.lua b/game/modules/tome/data/chats/escort-quest.lua
index 9540236ee9..693d671047 100644
--- a/game/modules/tome/data/chats/escort-quest.lua
+++ b/game/modules/tome/data/chats/escort-quest.lua
@@ -182,6 +182,8 @@ local reward = reward_types[npc.reward_type]
 local quest = game.player:hasQuest(npc.quest_id)
 if quest.to_zigur and reward.antimagic then reward = reward.antimagic reward.is_antimagic = true end
 
+game.player:registerEscorts(quest.to_zigur and "zigur" or "saved")
+
 local saves_name = { mind="mental", spell="spell", phys="physical"}
 local saves_tooltips = { mind="MENTAL", spell="SPELL", phys="PHYS"}
 
diff --git a/game/modules/tome/data/general/npcs/sandworm.lua b/game/modules/tome/data/general/npcs/sandworm.lua
index 953cd21ac9..d5797bfe40 100644
--- a/game/modules/tome/data/general/npcs/sandworm.lua
+++ b/game/modules/tome/data/general/npcs/sandworm.lua
@@ -71,6 +71,7 @@ newEntity{ base = "BASE_NPC_SANDWORM",
 
 newEntity{ base = "BASE_NPC_SANDWORM",
 	name = "sand-drake", display = 'D',
+	type = "dragon", subtype = "sand",
 	color={r=204,g=255,b=95},
 	desc = [[This unholy creature looks like a wingless dragon in shape, but resembles a sandworm in color.]],
 	rarity = 5,
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/dragon_sand_sand_drake.png b/game/modules/tome/data/gfx/shockbolt/npc/dragon_sand_sand_drake.png
new file mode 100644
index 0000000000000000000000000000000000000000..5986724a1e20b0e63897854011c7e8dbc4272a9f
GIT binary patch
literal 10287
zcmV+~DA3o5P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00009a7bBm000d-
z000d-0Rti)g#Z8m1ZP1_K>z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA
zFaQARU;qF*m;eA5Z<1fdMgRaOrAb6VRCwCtdug;~$5q}}RcAiu&iBn@zt{8JYN@5R
zTCxTk&z3C*8=H`YZ7>etmDoVQ#7Q6!GC%@}1H=KAv2ko{jEM#Z4F*fHWJ#7<t?qt3
z_nYTC4`)87s`BH#Zgop7F9*Y~)LQlDopWEEy=&LE_x|=Sa%fjSevpxJfr*g<>P;UV
zHwL8ygh&WUKnWnE1fvv$0EMgp$F}gMx88>^;&|b^kAhKw;a&%n0+djI0Gvwz^15}T
zl+ZN=ewd=x^ziJ<OSm}K003wzLq4P9$KSONmZ8G+W6W2400c=CqumKetrd_cO2oGD
zB6<ooxR4NBAeBI?6Cg@B2zg~aMaow`fL#0J>IZ=eDgTj>2&I${axNi+1fc{3|8PS}
z2~A~q@0)hwxs%ICxxip=2BQO6Fh(IZzngObfFKou5JISsg7^10DCaH23E%ie0w@4%
zQ-z@^xc0*pRb`tiZtU_kLl;u&jMCA3#{7efsgmA;^)m{kj;aPMPSZaL!xaCJBS{1p
zA-L<v*i|ds*Z=_`UQrZd6sp3Qt}DD;bda@G)Y<{DbyZUOinO}QKs0il%_(;t9t9x;
zNy_ovmzR(v9E1?0T>cYXQ$DtDN1r;BXC(rGo}&Gy3eBi1^)Q%T4Y!_~u1*UfA0(7i
z{yqgyQx1g@vSVA{Z}5a)YPP&Ds46|AYwB*!({CBNdXuWD`6%vwrB?3%Ah1j=4Wkr=
zoCQJzX|w{=n(hs)`r4tWDtpaKoXg>?qknwsNam)!;~CVdEu5Qcf{?m>)2=@B<aMpT
zzxXSZ0JV1Tkya=Cgcroe8U5i*9v~ou*uA~QPc@pI)3@Bb=Tkyr{mCbfpDUMgAIoO#
zJI`HM+&4KobXWgCarfijda;}){J~1YTXp>;F61p_9RmasX)5FujJfuhzeWL99!e=U
z%}ajDvGot%esFMae~w^!p@tXF)ev(et{bXrtpsC(8SEHMuy1P~=jYi`$I}0NrP6t~
zAH?SvCI8QY6GEV>%6pR}JzL0U_a3|RmVf*Fb1y$>IXONsI557pT6?Hi$`^tlRuyIW
zm&dk@V%zpDm^!=gyW5-oCnm>AbF+)}r{YxpMXTjs=y;LTR0;|L!%(5A>g%r0j@>i@
zLI@}&@PkBg{rL0yw)O1VK3>LmUYNs+=j(6-{v}mY{<RQtjdOXR>qaUdF*cZk9}A=$
z#h#+GUkH4QbKcQZ3Qf~6xotPN0G1angA$3Xt$~nDuqA*Hl2J;I5Wv~Dck(Z#ln46;
zdT*Q9x^>I(<5MHGT2mK1A&q+5US6rPGiT>8w^WCa0=i0(u{D~t_0sO0qmwru+ICMI
zhVN1oBE29wL5bj$0QszmeAb3(s5hMK*i9oFnqah#F>;V8?7ki2`O=AVYdAGsPotQB
zMpM}@DvVwL@R;E8?w)dHLO?=iMCKh8mZ1{U(8g4S9*d&Xmr`alO?5`bwy0qcleLxE
zm=GZ6XqzsGfTtY&1La>jcIT1*(P?*@y}iY~OjQp>F&~fOgif8Ark##YE>ACFezAsn
zvx_)Qk<B_-TwKT6$~wX*#?W97wr!ihz5{!(xVV(BRhw_MO=X+s$H%#lEz{JXDk`Lu
zkP@$%$~Cr_Qc7>@$?2o5mW!#2Yv8H)f~v58f8_)*#z2Tzlu{y>&B<;|NyqERom=~{
zyw--HtGAT$=9kixdmwW4#qU1SZngb0hGBj@lhp&dvFp%Ox)VeW4h{Fc^^SY)Ei5do
z{`_~IIb$TLQ~-ffr>7ByF*Hp>7=~a9LoREBG6K#eXu*MQ=$M&ZN4xDo)eQ6v^nntJ
zAc)b|pZ_t-GIuVowmvMRc=`K+;1vKQgw)fNN4i4vt{2156@ZA-giru-^OyjH&}Td^
z{&30#X}LlujFRc)4ul{wNjMzaAd155Zr9)Hb_1xIsu+es@{S5Z$zUPt{Dk9}<E2vm
z9ka75?FYX8AWl!s3|4Dxs0xE+>0pdN*BGSa$XGh!l%ra0L(>?7D2A!)P#6Ih0t<^Z
zG+WPOb+rObp(vLeWE}&goO94J)jwXXcJ3nt%aq<2q1mkmh9HCl2(Yx)E+<Lyp<>=a
z+l?WFT<W;tLn-H=l!8(ULdYx#Ih-VXQdKD^A(AO7qLdTYi%6#%qU%KnLmo3#{YD{c
ze4>;$Yq^~LUdOh6tgpZLnRX`_tkt{2vvaGx)oKldQD_=N6viNoZ1{FcK?#K)#v6eb
zHg@0jLL><XqYPYdD2j@{{vs|-FT=4klu9`?S{@8Th37?sjh5dN#^RgxR={09M%TN3
zDvv*X37f$Z!Z=;oHdcss6&<~&6oOK6Z=CW0Lg=c>DB@HAKnuXnv^v4>hhg$IQ)i^n
z^pFY(*NYIR@`7oo4-fU_9_%d|Pfd>Zy=`Q4@b`y?2adgb;yiusd*`64+Mo~ugaBR;
zAq--~NeV(Jx(yFr5WzBZ*tUUcy#tX7a3P>542)7FRKT)1(wOsHMrT13LrMuJW8;oH
z4&zTg{}AfUE|N4s6vsavbNbE2)y`LM<e^x`(vYMANh%<u^!y-s&)9HJpKYn26ovl2
z{7XW})3&W+%Wxi)60|#EO9KBVh?3<bl_Ut$^_ClbTUFVAAMVZk%ZZWVH+F69b+>LA
z{LM@*`x^k+H8;CRmzJw!cD{m)V?omu1VM~?(?z4@qtlJx`Y~E9A6y7f0yH~5qF6{S
zB;j1b^CP4w2U7@4Q%AcK5JDvBc6_8MM=on)|AC!oHk$~75Spr>+4KlN%2LQbXOwVN
zp}2OE$>Hqvfj?uP-7!)A`NMlhP;UqD{pj1SAHUT!)Od2FfG|pM>cTprm?NJxaA~ft
z<ubZf&RcHA*05!yIM&-&es?~f`6%b<fwf8-)6<LKoWKtg_<jUX0?q|m?Es3xkft0w
z<-)erX@$|Vx~5&~$!l{`%Et6kS9pF*5AN>Qos2c|($w-BYW421@sX0lIfrFxFij1<
z8)AIC4|{fPLA&c=W@bfrp3mFeNUgU5Z+fwHY_-~b4InD?I<p`ULVRJh(*4NdYTNSt
z5IyD0-907eKg4nR=_pDfAp|CdbD)HxkTa>F(Kw8FeDnU1``X=T>-d)8j|~p?Y`<`E
z0Sk+3h!TO7^$y}>!-Rv7quKEQDPbF0BWtVYM*H(;-GG11kL46kc`aiZsc8^6riP_z
zh-Sx!rT{x9`>|a0jZ5>*oAd49Hw$^|jX{`zrvkaGxdDpvD~Py2B2r@6CWRzucSG9?
z;v-4=T92SeaebIbfER@%pFMeQ<(GR4Chj`63p=)tee$WNPYoCHnUy$>FVD`eeUWKY
z6pFcDogge}b%NaX9pgW@w%$_CUs}S#Vigx>R;BBPh~t#RTp$b+1W}4+D}ZgQYoq<y
z|49h`%2MUU-lFM8>j4mNBv(R8Z~=6~6otHrC{7?Hkfa<^A_U0O*{uCzxvcfK>(%zI
zBnpwunlKF=x8HsMC#PmnskVueH<@i}sJDE?3Ey=U?5<USqOj`~KnS=HzvTtVEkeqB
zzW35BR8@s#YCn40(L<<Jt8oy-9}J@;J$%dlqti1>>NC%t#_<!Ec)j7uR@WziAEVar
ziSLJ?jDbrDKS<6cDgSbk@XNMfQvjx<1Pnt(Z_&nTEkqP^5J(6q5pf2d2-uc}@sT3H
z6i95u5sJc)%b9B+<QD{?e<mbK^`?s>H}6ELT*N?M8^>RsfuX0ML_lt2l9?-6?{y$J
z(BptHdUX;)AcTkr!IM$M53N=@<5TAr5d<+L1g6eRGe1a2x?V6QgkUSHHC&!q6ZJ+{
zrV>m_isecN)mj%I3=tPoL74tpobXQ$mF>rl9U7SGDP<~8y|fJ7FmUY9DBgVAIQDJp
zfoZ6y)P2OMfTk%|U<pzJgi<g?ffO8rJsC(z(e=dTI87HrKYW*=tE`YWk;~ZdgAfag
z>rfPmIEf*-#KqbAnIsi|MF_#Qll2y@8wLo3kTxJ65d!5PO7?cWm|mJ)!_rC}T{n_R
zB5~^M9A@Sl1O%kk^l7sdB8*e4Rl5o2cuCWg{~{#$<oIyusbWsgAG>MfeTR1Te{Q87
zy#3VqweOY+PG`?#S=m0CCx))b?IU>{+Svm)NKkEsS1r=9G?==Eh1C|ySsnR|hK!{^
z*BF|eXsX`q-j>hk+e-xtmStdeVGWE>1VIEs2zrVRrWczRI&Sp!4JHd$r}Da48UV`Z
z8YA?hR8b!Z!u01{KRROSir(=OQpnn<*1G^9U=)awG?Ac}>kEy?+TG~kt)qpf3`2?A
z-RP5B#|n3sGs?D1#@Kmb*~bf~SHH)F)F~m50IAhGL`ZN*z|a_WjOI{jM~Gt%O{Fk(
z4RI<V0dTRI-V$Ql2Jt=Dmq{WXu}$S2g9BxByFL~cs&E_=x~`(x=%SFbp=m6>Vo}#&
zfVe@f{7P;P5DFm$z8b{*AwNj&=(x$-qa@u|X#^!k2~!xUN-3Z7{N$-r%I^s->nRtI
zf*&w6<=2iL8+^~Uu{`2fV7cny<qMU^mexBTri89sA%0vh0_PH{LNLD;V`{z&T~(kf
z3=;CH(3B8}4bJdwl(B<JlK!V%lO=xUB46$)=Wy`wKGZ68eDC<hjrVjNgt)jcvxZhD
zSb0UZYZS0n^KW4Pz}P?*Nh;un9EF^U;Y`jyad!35H06(O87WdfOp43v9ab(_sjjhi
z=5kg-DXAA6ZNDG!kL}*p`=Q}pr;s%jR2n|kYCh)X8_&$Gw11LOvU)8CLkWSR60Emk
zoLO)oH=+8<=1_`0Rb_{KKYGOIcMjcq?;E~w`SRRj7cR{4$+6N~D8Y~H+rJ&dBZHW}
zw195M$IxII{$}7*t$ET5(z7>AhHhj5kbtHth>{3N!T|v9d)omxjscPK@!qm?IGZsZ
zeD<ZeL<;;~A#eV(Qr28_!{lj&(tG>MR&Oz<V{9OY`IRnetq{wr&AEuGKb=UrDk*~`
z0t(#}o)N4yBb=V^LP+3BXd=W0|F?bn(5DB7`ak%>sfU024R;*<soU;)W6z1xmlQAL
zcigdO@=v!+j`uIG*74n^U%=e_B1+{96jgy`Nq9koW;aOUn12GmFo53y5M5QkjaeE%
z*AzImfm5{=Y8Zw0DvILgGR6z*weDBfYuzKZsr<%Bf2OD47#|P97=yj$2vKq$R5Tq_
zCU84G=2yFDx+z+1cTK99kGxoo&qYQa5FAnynDq$aBtei!oL%%Fgv6D=ObBT+M#cfs
zxb^6f_g5NjnG^Zzqhmu>ZG9Cp(<|?-*1cPbrD9JMbA0oWXL0H@LndQ_P=;2ki;fq<
z3sMLHb#x$mSOABY*E$!ukbiO24PLY0)ycWQ$UqK*eFYFI58bqP^r6f1)!jK;-`i6(
z-+f?P5x(o)wrw<j+rjN66mvG1ro#(j<QxNB(2eL#)6sPOhSv~3_5917N4sGMvfYBL
zHvzYcPOS~gvT*ux9gR+i-jWR|0nRzLZ5{cKliNl=<$Hd7>+QF`|D_jSCY^d+ZP%+<
zoW6{i#U|_eaUp9d^vu*H_+g5!m%tAa02@ix{6Y;(Vcaq_l5uom8Y&v?z)Vu{wJQ;U
zvVX?_T3sIm8?+eNKw4*PxcnIcIs1+`AH0btiB&3?lY1ue`*j|`woS|yOugeJIB}^7
zAt<6mpuabZYQ2L>y^HaYen>*Fu-v}%@|iUrC+Qt(#AgzY<!i02;SoG@d>XgxE@Ss(
z8EKM0*VUbO+<p7cUb;L#7bf(b-R3$9s*l5a266V{5*TF&{1}V?kN@q<&~yd5VL$@d
z2)-zIDiOt8#xa-WqC=86h3Chhgxn2aFMyK(pd8#ah~>2w_U;@6V-!g$AcZ{G+mrp}
zAWGywZ=T3FKwrry<!y#`gX1qAzlg<^2DktW(?CzzL2o&anYmTOF~@C3c4D>C#W%lw
z2D1x|BZi?oT*zl)*N-kY+rei6eD2B)=o*7%C{P%MloD~AVtBakT?4~I`pK71_d1%~
zvUvUsER7)JSjcBAEUmYpDhd+L5v2r?pTY}WWV03sB!VD<s%l)*R2c=4lFR5wQWZhM
zp{vYxf%~s0fW`^Gnrjn65JoA^U0xka(**Y%ogmvr9SEeTHGMq#)C_*>kDkHfPhUWk
zNbKA`h?@><LDsRbzFva_aMv3T!u3-;^28a`>Mr`q8B)wz&<#anl<sDfd>TNR5P}1H
zCUNJ{J@DNCQ52()&%AGPa`=Clj&pBqy#lvUE0`?NqHYTW92o=1WHb;;kR&M#T?O6r
z8M>|^iV`Ra1Lp!=H%N6&fn_l$3PU09U~DLlV$J}7cLB&;2ZC2f!$QuvXX|+SOZ#{9
zpxx-;_~`|lI=6@&Jp`)CvAR@;U9fQU)*VQb1hWe(Fbx}f_DrH!%%f6k<0}t5kFJ*@
zpSQpWL7H+zQ3}V_p{eY0rQvmT!^Ex~lgQ_7+<oU^luSw|wvPNllH%xvON;FbQ!is>
zc^xuMv1>~nm3EBjg$9z8!?8^Sv4=EDKqx`rM$k1ChRzT~DT0ur>qVNv2pJnHA)j}!
zk(hC887ZRP3HLTy!A$_3RIUNQa;@q9>hMtMXO7-9X)UibaN^`5F3hf@R&C=0Z@&d*
zvx-N{HufLc0gX{OmWAEBCty1cvKbqzD^&!3h*BYocDD*mGr$vZ)vqfGW+b6MzjgbB
zTwbaSL{YM;GD_}$=N)^Fzj*Hb{X>H{uddcGGrgEA+Z?9G&~!ccL5!7}k9s!-j}ydE
z3d_*p`Z3akZ<fk900nW9LemwLbd{uWjK1DH)J>NdryL{wDmrdKeXbR}4ZxF1nhKPQ
z&ZOg*Uo<V{4HF}IymV>~&wlR`KqQ6+iby!YAO6`zym5aY?t9k}6pI!#rXZ6suw}r6
zm!^m!7nRjjWNjU{>>YxsE9kgBs7{bb2`MC8H*&l%{Ko?An{PQVHkfzBvz&`FC(qA}
zPMtsd&qu~SM0H)q_+S<)qv$OfC^!lhmmBDI1sbgY{XH4P+()MsfHDP4p)gGyo*yHh
zvteoqT5bs2wve+`0200zKuQkBRAHGKc24x-^u_8iFGx(KuQ#I)^%wq#r|BCehDumj
zYvSqWE}&S-V05SqO;s?^UxE+<Nydhz>d<rx13fm1IR!(#COUqC^RsOX^ks2zp#@b}
zarE#w)+%j)Y?QTKHwJ)SDe<fMtPR6ZuvGPTdU5}K-R8LilfxPM^pnq_R;j|y*dPSR
zIu^<~9TLF#nFd}wTSJm?^p!Jct1<i_1|<}xLE(oISL)uOA0p)v#L?k-Av9G*v5<wT
zDiDH0Q55u+>>aa9twE)yXumNP;_h!e^gSHe*N<n8&tvzlQH+iCV{xep-w$Ev8sd~=
zdA*G|PM~WlKsGA3<$?(}<OoBKiLqV~rob{aNFgyYSb~%SQJliiG$aW}lq6`m5!&k^
zf>@khn|rbQ{&()Zb9#0eU;oR$K{jhbQ&sHR)(c&yXf!>5NJs*hhKiM{i+VdioJvpv
z<TDlsA<$F>wrv1XLT!2IxB>DR1C&TijO0=3DPpbCMyH(skQnT7%Ck$YL(104;kP{e
z*voinY8`PD;Lw3>n4B2I+4FNCl)|x1$W%f?B9k#dsRe}+czz5wh%vL+*<flQ(QNxr
zRR*4J6eY!GViCs)Tt5N_5GNbht7=TX>z*A$Sp%QG`N;kuFH8_dQ?ODUOaYeGx{%U=
zS~6iH!qQqBTyjvRpyS4ngrHjQV*9wdL5E3!(2t;N3Up0@nQ*8oL)KQYeY}La%Mthi
zG{zwm6$8ClXezx|X?KIn`SbI*??<-d;Jyho+7Z6<%oOr@3x;9A4^t3qurP|sAi2a^
zr4uEoh`1C<ln6k=a=pY1qXY_-h?4|Slp^IE1O%qB;krr%2ZgMTAc&#qD$xzS*NfA;
z7Uoxt)%7L{`3!7RMY$)BPNRu|{w-*G5f&RBYOaK$sK_}KLI@}-L&|M5+di@x1D37B
zPdNIsCXyrpqXbML=z0<2lp~5`7%BxL3~o$dTN)fo+p5%SZPMTC;P#{Yu(Z;^$<voX
zm;%aF%+6Ji%^2;L8$OYDjPpbN`P$54onM}>hbb3clJKzJ4j_aqrCi)m%9-~UbB0do
zMsc)YsUT87Qx#B3k+BU(DbY99gD^;NYHA4r(wtrV7K9KO8|z1ZZyqWG(i}sfm_el(
z;POHfm3ja_NFb#^sc0h%Q|y@NL8azGRVWHs3u_Gz*yz4N5T!_B0by-4R=92mjR9Ve
zB8&mk&|sTdPRZr$!MpD~0H!KfUa3JhbQqR#ZmHs(Rt@K`o9*_=Ctp}t1~3Sq2!P!n
ze`*4_-0X%eT~$7A8I0ueCi=_H#?fecDCBKWO5wTzLeB?L6hv_X(>Bm`LkPiP7$w-Y
z30<Wa8ZV$+G!Xe2%r6*dv^+>Dk<FMGA1+{au@1onGLDY68=;stk;DnAHE)CJB0v(S
zDCaGRG)247!cbopx@jP+d61Gr*A+#n)>?^fXgD*q(2f)SznP*ux?{ZbMBA^gKK8`v
z5`ZxP`(MkaUPm6ujm{47K)vnnaje{(imD(<C30B<x~5>Q(uSd{unZkx7=tnnL)Xw-
z%tE0O<zfbtlY>ap7|nVI?RE!m?C(c56Cm$sm`OQwgQ2e{i_tzC;1L$rJg5r8TGd4^
zV?t#VYqics`JDoa#*oGlx}7cvA?Uafh`Jf~aEUnPM0w_g%gbEI>dJci$A@~ej~8+#
zB!I`BnCb(t=XG{G*xdCNfcP4&m4s3HYhfb37DT)(MF7V!K?s8s5?wbyPbmv7IRpnX
zSqqd%1W^pj(xIsgrD6|4KSs6Mz<NiZ(IwylV2mQ~P!zKoR7N&B(kO-G0x6dOWw309
zTFV0yKooN%NrET}VHpazq@W4|WgEp_2?;+)V&#R?OV1aw=2NA-^>`Gg03`n1A3Ui5
z7=In%7Xi$^`>yR#CZpqt=jTyx`v{}-iaC5cN|Mj23i)-WFaR4KgAjsD#)2P42%{LL
zro!vEU=Zl<D<Dl%NJ)?@<gne)VVD}?D25*d;8H@T5<3Pg<ck`@Bt@&UL3pNd3eOAB
z?Rsz=3qlak&D}1C3HnO?C}d2eq6?yEh!c)Z+eM=lAc)ciO}YGPoba!Degw*{T6qpY
z_C}3c02Xe)X*9Y*WqDzYFiNkotN_qx1)pUE&x{Qfp{fLNnjo8VpeYJkO%Kgxfc07j
zrp`d503#BrO2Gxkr3*9gJs*x^V_|+7=g-fg)pkK-j9U-(p}(Ml5Q2f;EI<gdISaO9
zB8*dXyFTJL0izUgoT5^9kqQCHQ<MreIG1p24WJZ@t1ZMyx};D-q8ro;?AJN(-A(hq
zjy<}bP6wixH|LhyztmH-A7vDoT*iU~f!hfXL@5dd8?Ba$nfVIxc^j&xpj6Dj_X0HP
zP0Y<L!88r{euS~HK|K5188n(5XahF*Y=FLA2NF$~3LqE-g@mfANVtH+hB6g}q1lO0
zZTM()1MJ-~49Y0h*Xw9^LbzUxG!-wsUSF4ZoxcY^ao-_%g*X+PU6_m!D2!g6szR|=
zbDuqaX7yjGnkIK_?MHu477`LnVQ{?&{e49QvB3Od6YG@@R@a-DpI?EH8$95`;`+uK
zoFfQgWDFJc^$vuja6^HfVg}`c36&`j5(uIML6pEYG;l7UDilHjt2H0>P7I9^*c#Av
zLxfR+FcI?-_~z>=Ab1^R<o@h|6WR~b{Y5FkO2z%JC(f??i+0D44V|K|$HwSz8Mdjx
zwsrKBGRS3gbX_0It92Nf4k-X#(=jsK3r$nOc?zB;=mr9_r>i)1ZVlCji-Fz@m_o5$
zYa<L2G}{3Pq0n_@vy8sce^6<Km|kq6QLSLlmICrw6NC^%ae5KJ0<%mNy2hYu47R1g
zHZ`2SSWy5B0HB-a{t6gs0F1@ec4x<yQmShTF3i@EaPgX6!z2}olrmFq1@n!jmquZ9
zhzp_yVFJrk(ASd#7aWdbqL6n`t98(5cEK2hWooF@S_py|p6g*|b`AAz1Vy(1MT4zN
zh$uv*5#sE06<(Nv5}>DKBZ*_A5l7n%0ZQQq9HmkQ5CVODS)4qxf^*YV%q+FfMKS-1
z@_j78-(*dcO^CQ6VLt%p!Eaw&0?+^uQbzczgtr0g+5}U2d7=5O^|}`h^w=NMRn|W-
zT0*DmBS|<om&jx+WV1Fn7dU-x0mB1D<a0La%@(?@kFFm>VHC3~EgZ<%C}wo5Ry*KQ
zA{7KF7bsW;1Q+o92to)j#-L~#nw{`V7iR0@osM^`+D=f;>u9?n{4j|KfE!xCyWg}+
zeCLIE0-(Gp_^X2;4M1sA8AU1K2q8@&Bojia0Jd#Dzxum4;R~%!^g_pt&)3@FiDo+}
z1z}p0a-;G=h(x)RM-;|rG+gMqia1W;`60S)gfQY*sd&&-ioTMKgeYjb38v?2NKy&Q
zRKOTT;716;6pE@q*VMG*ML)S*>9lQAeFxoavYuaTLI6*3A-}17pJTkV=?z9+=Q-I_
zL~(Nh0N=!n8@6V0A(#9pUGghktW~<tGfKAWnzDQASn++s{SN8tDIlBKK>yjfDpZvs
zO%kXIL!}X5wH{)y8KTzkP%PyzG1`X{XV%aSx=<7aQb;7J1n5SW=z86K*bkzUevnpA
zU#j0cyWD+yxuExHj6!8>j&t$)#nHFiwO2m+#MGrtVScbn1shnwe!zDtT*!(aCasHe
zwfhw!h@~qi6&wr>6yOID78a}U{1}W801~Fb;5ZhjqQbEhfJ!9k#_2P44c)GfYAbju
ziUkS6q~-eYf8Jbc#SfE@`eFKTIj6pzX$);Qx)>+lM*#rv{`=p|zxIvCFKr6d^AFJy
zZyL&v4E1JdtsR2THDDMz(j<naY-Es{wvmEU0C`8-i2kUGQZb9!`3l-?50o-^L5#WO
z_IKCo?(a$|qfKkP645RLP|F2lz%do1k~IA&IYTIUeFZQ^0Yb55C=<>ucc(VZyab>C
z!1_MP(GNUqQ@wfTMES14o(z^N9ZX%SqSEk}`b%a;S7|PYQ^ZjUNC6=MRi!XAij1XV
zZhjrJ3w5M|pwaf-wQA=f&yW8SfOpLjSMaE;FuJ?1Xzp=L70b2YWSWTC8`cI1AutUU
z%~luFi(SmGy0A<&1yBJ{@q@$xFuHjx*xyz7Le>}>?6E&F(w{X-1qW%$v7GH-wdS2z
zultYKrt;RDqaRTe(kHk8BY+=q2*IV>@yI~g#Q110@)sJoywG?8z~^6QDTflWd+S)~
z7k5sSv?z?w>b9TTbnn+IKw%Uq7kJ{iSxjA6Mi9g>4HcfBm;m}V-I}pE|IWgz3N?35
zl>g~KZ)U(UG}-Qih*M6=c@y<km`%C3)b*1~T|XIA6?%YCGMJ=NXe!M+w)s}w&|sJb
zIzfP9&IEv)HshAnS1om~W9jedFPo*Elf`mAXJawsNwX9F?Q5#T3ZrPW15912VtKs-
zDZv2bQa|Yf(7TEFKlCW)&C!9f{gHvPbHuStcz%dxJ0Kl5LL%f#LdY*)^ZH7Xik0N5
zb<+DMCkDy(tpo78F4|rj%Em2?X#ky9S@OFlhVvioE7_)LFk~$QS;s*0{8}?k#kuPg
zz!*iV8)2>H!VeO2Q=8?@K#2Z5;azTQFn{l8fA&4SWxJm;CM&fL3FDNsJJG_-QsWC<
zFMdu)ncNU8b)~#-=fFMVBV}Z>4wjayAe5oeiKYPj?zLxMRp`z8cl7@Bft>?72$f5#
z4U*4WS9%H8H<P+oy2XPqL9-LW4-##&a+?1k!A;*XoZn}eS|4MqxnAoM*N@*f)MM|}
zH44v<rK+mL^CK*;bx*9;z26JMWc5b>D`RW<$<g9lh6i$Qo*XNWx~`AKr3zdx#O3)q
zpSrmAZvZ^I8L#9CA@<FC2Y%|n&OyD9H!(X`0Z#=+hkFo*5e!{fxK>$86sPcltND)c
zIy}G+2yCXkcYELA@!{Ot#(RxJj4`@Yk7Y4u#*jj{EnRLzg(+!uf@prF{lMaC=g;LU
zJ93?8**;#n>+rte5ANA9v?c49s5RR-b#@W0wvS5PU3hV7<+r^c`Nn4NP+8a5*2DXT
zJ~TO;n@|`~DrRwcu1eB4!s1dD1N}t=LDB$l^}3sqY-UZbqPj}gM0UaEG2oj&%wPMV
zln^r1pV>AxkiB)NKX+%wF~>y8K>?@=0VR@TEKQ?~N=7MB6audvq1g`pdSSKm$D9B2
zO2VZ9fMuxaUAIl%d;853pSb7t9V!UJh1m+e`{E_cE!N@s@mCkuI=|)x$@$G*B3jOy
zcieVx=vM}MbEAwBY~MDFdcBP>O3~Y!lWS{rqG=iy*E;84w^!J<w8Zn{v)3Gf@Kp-n
zo9@p7kPh@Xw~i0yKBZ~OzGB`q>J1mCE>uu&`kjf9LiXUU0dN7NT#!!3-?%XfiE7;i
zAvn5wqWtBvGqn={MjcDd5A<Y45APq@b#UkK(JkXWI|x%%Aps2`78ll|i_?`C{V4fd
z*NwjxCn92uVsf+q$I_fz_6`5+wu!#c=Z?=Ts0tg*=QGMnQ;UDPUh5X_xOLk*)>iB6
z`4e*w*W3QruTwypUeA5#ni2w7`#zSwd`$<}2mB~imMh)nh1vQ*vlE_);`AW^ORaAB
zW<N|OHI-@grcb>vHlmpK3L$GbM}M%l<n(1T>S`%(_4SvXpBw43ca9F`x4rS`b~R&b
zSgkbio#PAW%_^82bg;PGTwYl1d?4p2%barrVS+=u265Y=5u{vVY`9F9>h71%FSWli
zkT-vHb*=G%7fvkvvFR{73e)?dl$@KowDK`2ua`}U;=lXt&-I%3`<1%?-?$KO-SoxB
z0ki?6al%iYzOb%>5Fw@Hn^rUmV5RHDCp&HwY#l55<3risId<!|`-l1qc;@*t_{sy%
zC#qu3)fz#)(sJ`z13S0ge-L3H6w9{!jHSae2!;lGv449JLI_YoI?cBG$oxWZB5cQx
zpKW$$iUsS|R?}w<kIk(Qbk8iVd8Zql<TV?s{E)8g3V8iBfak7UJlULF0s>Ns%?$CX
zsr8j?l=3DtO~G(~ZYg7%@yV%$iwjHP%T#0^D5>RVyw<W82cff~lJ}gN>3nLie{_EI
zO~vjX{>$G&kJF1VaPgU6{5aN@Yha9Ft<w48Vn{OU!b`d<{@DlWXMc~Ul5r`gpL}8F
z{*KEzZqO0<!z$nk8yrY^Jz2Wxk3k7R!o|kDq*s#)3WcVS&(AG3PkMp9FxH=6YE?x<
z$VRgk1v>ex`3Fxvx9~UR!#m5J(m<+s0>Tk+az*Uie-vN(;-A2_9ax%rvKGaxt44wV
z2&43K08B;+52Ey9obt{6dDZoR?{}^A|A+B^2LN-x10*@G(AfY0002ovPDHLkV1j+1
BMLPfh

literal 0
HcmV?d00001

diff --git a/game/modules/tome/data/gfx/shockbolt/npc/humanoid_shalore_archmage_tarelion.png b/game/modules/tome/data/gfx/shockbolt/npc/humanoid_shalore_archmage_tarelion.png
new file mode 100644
index 0000000000000000000000000000000000000000..4bb3fd4e245582183150ad0476b6b5100f32eafb
GIT binary patch
literal 14977
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

literal 0
HcmV?d00001

diff --git a/game/modules/tome/data/quests/escort-duty.lua b/game/modules/tome/data/quests/escort-duty.lua
index bf9b3888ba..c07d733429 100644
--- a/game/modules/tome/data/quests/escort-duty.lua
+++ b/game/modules/tome/data/quests/escort-duty.lua
@@ -330,6 +330,9 @@ on_grant = function(self, who)
 		game.player:hasQuest(self.quest_id).killing_npc = who and who.name or "something"
 		if who.resolveSource and who:resolveSource().player then
 			world:gainAchievement("ESCORT_KILL", game.player)
+			game.player:registerEscorts("betrayed")
+		else
+			game.player:registerEscorts("lost")
 		end
 	end
 
diff --git a/game/modules/tome/data/zones/town-angolwen/npcs.lua b/game/modules/tome/data/zones/town-angolwen/npcs.lua
index 4e7558d5d5..867a79d2f3 100644
--- a/game/modules/tome/data/zones/town-angolwen/npcs.lua
+++ b/game/modules/tome/data/zones/town-angolwen/npcs.lua
@@ -89,7 +89,8 @@ newEntity{ define_as = "TARELION",
 	display = "p",
 	faction = "angolwen",
 	name = "Archmage Tarelion", color=colors.CRIMSON, unique = true,
-	desc = [[A tall shalore elf, in a flowing robe.]],
+	resolvers.nice_tile{image="invis.png", add_mos = {{image="npc/humanoid_shalore_archmage_tarelion.png", display_h=2, display_y=-1}}},
+	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,
 	size_category = 3,
-- 
GitLab