From 9bf34c6ae0055fa0272f2ecf2386394bb12259fe Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Sat, 4 Sep 2010 12:28:17 +0000
Subject: [PATCH] Fix character sheet for controlled summmons

git-svn-id: http://svn.net-core.org/repos/t-engine4@1140 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/modules/tome/dialogs/CharacterSheet.lua | 341 ++++++++++---------
 ideas/worlds.ods                             | Bin 8198 -> 8438 bytes
 2 files changed, 172 insertions(+), 169 deletions(-)

diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua
index 5744d85b56..751c1ac6dd 100644
--- a/game/modules/tome/dialogs/CharacterSheet.lua
+++ b/game/modules/tome/dialogs/CharacterSheet.lua
@@ -43,135 +43,136 @@ function _M:init(actor)
 end
 
 function _M:drawDialog(s)
-	local cur_exp, max_exp = game.player.exp, game.player:getExpChart(game.player.level+1)
+	local player = self.actor
+	local cur_exp, max_exp = player.exp, player:getExpChart(player.level+1)
 
 	local h = 0
 	local w = 0
-	s:drawStringBlended(self.font, "Sex:   "..game.player.descriptor.sex, w, h, 0, 200, 255) h = h + self.font_h
-	s:drawStringBlended(self.font, "Race:  "..game.player.descriptor.subrace, w, h, 0, 200, 255) h = h + self.font_h
-	s:drawStringBlended(self.font, "Class: "..game.player.descriptor.subclass, w, h, 0, 200, 255) h = h + self.font_h
+	s:drawStringBlended(self.font, "Sex:   "..(player.descriptor.sex or (player.female and "Female" or "Male")), w, h, 0, 200, 255) h = h + self.font_h
+	s:drawStringBlended(self.font, "Race:  "..(player.descriptor.subrace or player.type:capitalize()), w, h, 0, 200, 255) h = h + self.font_h
+	s:drawStringBlended(self.font, "Class: "..(player.descriptor.subclass or player.subtype:capitalize()), w, h, 0, 200, 255) h = h + self.font_h
 	h = h + self.font_h
-	s:drawColorStringBlended(self.font, "Level: #00ff00#"..game.player.level, w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, "Level: #00ff00#"..player.level, w, h, 255, 255, 255) h = h + self.font_h
 	s:drawColorStringBlended(self.font, ("Exp:  #00ff00#%2d%%"):format(100 * cur_exp / max_exp), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Gold: #00ff00#%0.2f"):format(game.player.money), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Gold: #00ff00#%0.2f"):format(player.money), w, h, 255, 255, 255) h = h + self.font_h
 
 	h = h + self.font_h
 
-	s:drawColorStringBlended(self.font, ("#c00000#Life:    #00ff00#%d/%d"):format(game.player.life, game.player.max_life), w, h, 255, 255, 255) h = h + self.font_h
-	if game.player:knowTalent(game.player.T_STAMINA_POOL) then
-		s:drawColorStringBlended(self.font, ("#ffcc80#Stamina: #00ff00#%d/%d"):format(game.player:getStamina(), game.player.max_stamina), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("#c00000#Life:    #00ff00#%d/%d"):format(player.life, player.max_life), w, h, 255, 255, 255) h = h + self.font_h
+	if player:knowTalent(player.T_STAMINA_POOL) then
+		s:drawColorStringBlended(self.font, ("#ffcc80#Stamina: #00ff00#%d/%d"):format(player:getStamina(), player.max_stamina), w, h, 255, 255, 255) h = h + self.font_h
 	end
-	if game.player:knowTalent(game.player.T_MANA_POOL) then
-		s:drawColorStringBlended(self.font, ("#7fffd4#Mana:    #00ff00#%d/%d"):format(game.player:getMana(), game.player.max_mana), w, h, 255, 255, 255) h = h + self.font_h
+	if player:knowTalent(player.T_MANA_POOL) then
+		s:drawColorStringBlended(self.font, ("#7fffd4#Mana:    #00ff00#%d/%d"):format(player:getMana(), player.max_mana), w, h, 255, 255, 255) h = h + self.font_h
 	end
-	if game.player:knowTalent(game.player.T_POSITIVE_POOL) then
-		s:drawColorStringBlended(self.font, ("#7fffd4#Positive:#00ff00#%d/%d"):format(game.player:getPositive(), game.player.max_positive), w, h, 255, 255, 255) h = h + self.font_h
+	if player:knowTalent(player.T_POSITIVE_POOL) then
+		s:drawColorStringBlended(self.font, ("#7fffd4#Positive:#00ff00#%d/%d"):format(player:getPositive(), player.max_positive), w, h, 255, 255, 255) h = h + self.font_h
 	end
-	if game.player:knowTalent(game.player.T_NEGATIVE_POOL) then
-		s:drawColorStringBlended(self.font, ("#7fffd4#Negative:#00ff00#%d/%d"):format(game.player:getNegative(), game.player.max_negative), w, h, 255, 255, 255) h = h + self.font_h
+	if player:knowTalent(player.T_NEGATIVE_POOL) then
+		s:drawColorStringBlended(self.font, ("#7fffd4#Negative:#00ff00#%d/%d"):format(player:getNegative(), player.max_negative), w, h, 255, 255, 255) h = h + self.font_h
 	end
-	if game.player:knowTalent(game.player.T_VIM_POOL) then
-		s:drawColorStringBlended(self.font, ("#904010#Vim:     #00ff00#%d/%d"):format(game.player:getVim(), game.player.max_vim), w, h, 255, 255, 255) h = h + self.font_h
+	if player:knowTalent(player.T_VIM_POOL) then
+		s:drawColorStringBlended(self.font, ("#904010#Vim:     #00ff00#%d/%d"):format(player:getVim(), player.max_vim), w, h, 255, 255, 255) h = h + self.font_h
 	end
-	if game.player:knowTalent(game.player.T_EQUILIBRIUM_POOL) then
-		s:drawColorStringBlended(self.font, ("#00ff74#Equi:    #00ff00#%d"):format(game.player:getEquilibrium()), w, h, 255, 255, 255) h = h + self.font_h
+	if player:knowTalent(player.T_EQUILIBRIUM_POOL) then
+		s:drawColorStringBlended(self.font, ("#00ff74#Equi:    #00ff00#%d"):format(player:getEquilibrium()), w, h, 255, 255, 255) h = h + self.font_h
 	end
 
 	h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("STR: #00ff00#%3d"):format(game.player:getStr()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("DEX: #00ff00#%3d"):format(game.player:getDex()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("MAG: #00ff00#%3d"):format(game.player:getMag()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("WIL: #00ff00#%3d"):format(game.player:getWil()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("CUN: #00ff00#%3d"):format(game.player:getCun()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("CON: #00ff00#%3d"):format(game.player:getCon()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("STR: #00ff00#%3d"):format(player:getStr()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("DEX: #00ff00#%3d"):format(player:getDex()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("MAG: #00ff00#%3d"):format(player:getMag()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("WIL: #00ff00#%3d"):format(player:getWil()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("CUN: #00ff00#%3d"):format(player:getCun()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("CON: #00ff00#%3d"):format(player:getCon()), w, h, 255, 255, 255) h = h + self.font_h
 
 	h = 0
 	w = 200
 	-- All weapons in main hands
-	if self.actor:getInven(self.actor.INVEN_MAINHAND) then
-		for i, o in ipairs(self.actor:getInven(self.actor.INVEN_MAINHAND)) do
+	if player:getInven(player.INVEN_MAINHAND) then
+		for i, o in ipairs(player:getInven(player.INVEN_MAINHAND)) do
 			if o.combat then
-				s:drawColorStringBlended(self.font, ("Attack(Main Hand): #00ff00#%3d"):format(game.player:combatAttack(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("Damage(Main Hand): #00ff00#%3d"):format(game.player:combatDamage(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("APR   (Main Hand): #00ff00#%3d"):format(game.player:combatAPR(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("Crit  (Main Hand): #00ff00#%3d%%"):format(game.player:combatCrit(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("Speed (Main Hand): #00ff00#%0.2f"):format(game.player:combatSpeed(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Attack(Main Hand): #00ff00#%3d"):format(player:combatAttack(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Damage(Main Hand): #00ff00#%3d"):format(player:combatDamage(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("APR   (Main Hand): #00ff00#%3d"):format(player:combatAPR(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Crit  (Main Hand): #00ff00#%3d%%"):format(player:combatCrit(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Speed (Main Hand): #00ff00#%0.2f"):format(player:combatSpeed(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
 			end
 		end
 	end
 	h = h + self.font_h
 	-- All wpeaons in off hands
 	-- Offhand atatcks are with a damage penality, taht can be reduced by talents
-	if self.actor:getInven(self.actor.INVEN_OFFHAND) then
+	if player:getInven(player.INVEN_OFFHAND) then
 		local offmult = (mult or 1) / 2
-		if self.actor:knowTalent(Talents.T_DUAL_WEAPON_TRAINING) then
-			offmult = (mult or 1) / (2 - (self.actor:getTalentLevel(Talents.T_DUAL_WEAPON_TRAINING) / 6))
+		if player:knowTalent(Talents.T_DUAL_WEAPON_TRAINING) then
+			offmult = (mult or 1) / (2 - (player:getTalentLevel(Talents.T_DUAL_WEAPON_TRAINING) / 6))
 		end
-		for i, o in ipairs(self.actor:getInven(self.actor.INVEN_OFFHAND)) do
+		for i, o in ipairs(player:getInven(player.INVEN_OFFHAND)) do
 			if o.combat then
-				s:drawColorStringBlended(self.font, ("Attack (Off Hand): #00ff00#%3d"):format(game.player:combatAttack(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("Damage (Off Hand): #00ff00#%3d"):format(game.player:combatDamage(o.combat) * offmult), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("APR    (Off Hand): #00ff00#%3d"):format(game.player:combatAPR(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("Crit   (Off Hand): #00ff00#%3d%%"):format(game.player:combatCrit(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
-				s:drawColorStringBlended(self.font, ("Speed  (Off Hand): #00ff00#%0.2f"):format(game.player:combatSpeed(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Attack (Off Hand): #00ff00#%3d"):format(player:combatAttack(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Damage (Off Hand): #00ff00#%3d"):format(player:combatDamage(o.combat) * offmult), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("APR    (Off Hand): #00ff00#%3d"):format(player:combatAPR(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Crit   (Off Hand): #00ff00#%3d%%"):format(player:combatCrit(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
+				s:drawColorStringBlended(self.font, ("Speed  (Off Hand): #00ff00#%0.2f"):format(player:combatSpeed(o.combat)), w, h, 255, 255, 255) h = h + self.font_h
 			end
 		end
 	end
 	h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Spellpower:  #00ff00#%3d"):format(game.player:combatSpellpower()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Spell Crit:  #00ff00#%3d%%"):format(game.player:combatSpellCrit()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Spell Speed: #00ff00#%3d"):format(game.player:combatSpellSpeed()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Spellpower:  #00ff00#%3d"):format(player:combatSpellpower()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Spell Crit:  #00ff00#%3d%%"):format(player:combatSpellCrit()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Spell Speed: #00ff00#%3d"):format(player:combatSpellSpeed()), w, h, 255, 255, 255) h = h + self.font_h
 
 	h = h + self.font_h
-	if self.actor.inc_damage.all then s:drawColorStringBlended(self.font, ("All damage: #00ff00#%3d%%"):format(self.actor.inc_damage.all), w, h, 255, 255, 255) h = h + self.font_h end
+	if player.inc_damage.all then s:drawColorStringBlended(self.font, ("All damage: #00ff00#%3d%%"):format(player.inc_damage.all), w, h, 255, 255, 255) h = h + self.font_h end
 	for i, t in ipairs(DamageType.dam_def) do
-		if self.actor.inc_damage[DamageType[t.type]] and self.actor.inc_damage[DamageType[t.type]] ~= 0 then
-			s:drawColorStringBlended(self.font, ("%s damage: #00ff00#%3d%%"):format(t.name:capitalize(), self.actor.inc_damage[DamageType[t.type]]), w, h, 255, 255, 255) h = h + self.font_h
+		if player.inc_damage[DamageType[t.type]] and player.inc_damage[DamageType[t.type]] ~= 0 then
+			s:drawColorStringBlended(self.font, ("%s damage: #00ff00#%3d%%"):format(t.name:capitalize(), player.inc_damage[DamageType[t.type]]), w, h, 255, 255, 255) h = h + self.font_h
 		end
 	end
 
 	h = 0
 	w = 400
-	s:drawColorStringBlended(self.font, ("Fatigue:        #00ff00#%3d%%"):format(game.player.fatigue), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Armor:          #00ff00#%3d"):format(game.player:combatArmor()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Defense:        #00ff00#%3d"):format(game.player:combatDefense()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Ranged Defense: #00ff00#%3d"):format(game.player:combatDefenseRanged()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Fatigue:        #00ff00#%3d%%"):format(player.fatigue), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Armor:          #00ff00#%3d"):format(player:combatArmor()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Defense:        #00ff00#%3d"):format(player:combatDefense()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Ranged Defense: #00ff00#%3d"):format(player:combatDefenseRanged()), w, h, 255, 255, 255) h = h + self.font_h
 
 	h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Physical Save: #00ff00#%3d"):format(game.player:combatPhysicalResist()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Spell Save:    #00ff00#%3d"):format(game.player:combatSpellResist()), w, h, 255, 255, 255) h = h + self.font_h
-	s:drawColorStringBlended(self.font, ("Mental Save:   #00ff00#%3d"):format(game.player:combatMentalResist()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Physical Save: #00ff00#%3d"):format(player:combatPhysicalResist()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Spell Save:    #00ff00#%3d"):format(player:combatSpellResist()), w, h, 255, 255, 255) h = h + self.font_h
+	s:drawColorStringBlended(self.font, ("Mental Save:   #00ff00#%3d"):format(player:combatMentalResist()), w, h, 255, 255, 255) h = h + self.font_h
 
 	h = h + self.font_h
-	if self.actor.resists.all then s:drawColorStringBlended(self.font, ("All Resists: #00ff00#%3d%%"):format(self.actor.resists.all), w, h, 255, 255, 255) h = h + self.font_h end
+	if player.resists.all then s:drawColorStringBlended(self.font, ("All Resists: #00ff00#%3d%%"):format(player.resists.all), w, h, 255, 255, 255) h = h + self.font_h end
 	for i, t in ipairs(DamageType.dam_def) do
-		if self.actor.resists[DamageType[t.type]] and self.actor.resists[DamageType[t.type]] ~= 0 then
-			s:drawColorStringBlended(self.font, ("%s Resist: #00ff00#%3d%%"):format(t.name:capitalize(), self.actor.resists[DamageType[t.type]]), w, h, 255, 255, 255) h = h + self.font_h
+		if player.resists[DamageType[t.type]] and player.resists[DamageType[t.type]] ~= 0 then
+			s:drawColorStringBlended(self.font, ("%s Resist: #00ff00#%3d%%"):format(t.name:capitalize(), player.resists[DamageType[t.type]]), w, h, 255, 255, 255) h = h + self.font_h
 		end
 	end
 
-	immune_type = "poison_immune" immune_name = "Poison Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "cut_immune" immune_name = "Bleed Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "confusion_immune" immune_name = "Confusion Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "blind_immune" immune_name = "Blind Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "silence_immune" immune_name = "Silence Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "disarm_immune" immune_name = "Disarm Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "pin_immune" immune_name = "Pinning Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "stun_immune" immune_name = "Stun Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "fear_immune" immune_name = "Fear Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "knockback_immune" immune_name = "Knockback Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "stone_immune" immune_name = "Stoning Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
-	immune_type = "teleport_immune" immune_name = "Teleport Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "poison_immune" immune_name = "Poison Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "cut_immune" immune_name = "Bleed Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "confusion_immune" immune_name = "Confusion Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "blind_immune" immune_name = "Blind Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "silence_immune" immune_name = "Silence Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "disarm_immune" immune_name = "Disarm Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "pin_immune" immune_name = "Pinning Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "stun_immune" immune_name = "Stun Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "fear_immune" immune_name = "Fear Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "knockback_immune" immune_name = "Knockback Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "stone_immune" immune_name = "Stoning Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
+	immune_type = "teleport_immune" immune_name = "Teleport Resistance" if player:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end
 
 	h = 0
 	w = 600
 	s:drawColorStringBlended(self.font, "#LIGHT_BLUE#Current effects:", w, h, 255, 255, 255) h = h + self.font_h
-	for tid, act in pairs(game.player.sustain_talents) do
-		if act then s:drawColorStringBlended(self.font, ("#LIGHT_GREEN#%s"):format(game.player:getTalentFromId(tid).name), w, h, 255, 255, 255) h = h + self.font_h end
+	for tid, act in pairs(player.sustain_talents) do
+		if act then s:drawColorStringBlended(self.font, ("#LIGHT_GREEN#%s"):format(player:getTalentFromId(tid).name), w, h, 255, 255, 255) h = h + self.font_h end
 	end
-	for eff_id, p in pairs(game.player.tmp) do
-		local e = game.player.tempeffect_def[eff_id]
+	for eff_id, p in pairs(player.tmp) do
+		local e = player.tempeffect_def[eff_id]
 		if e.status == "detrimental" then
 			s:drawColorStringBlended(self.font, ("#LIGHT_RED#%s"):format(e.desc), w, h, 255, 255, 255) h = h + self.font_h
 		else
@@ -183,8 +184,10 @@ function _M:drawDialog(s)
 end
 
 function _M:dump()
+	local player = self.actor
+
 	fs.mkdir("/character-dumps")
-	local file = "/character-dumps/"..(game.player.name:gsub("[^a-zA-Z0-9_-.]", "_")).."-"..os.date("%Y%m%d-%H%M%S")..".txt"
+	local file = "/character-dumps/"..(player.name:gsub("[^a-zA-Z0-9_-.]", "_")).."-"..os.date("%Y%m%d-%H%M%S")..".txt"
 	local fff = fs.open(file, "w")
 	local labelwidth = 17
 	local nl = function(s) s = s or "" fff:write(s:removeColorCodes()) fff:write("\n") end
@@ -192,169 +195,169 @@ function _M:dump()
 	--prepare label and value
 	local makelabel = function(s,r) while s:len() < labelwidth do s = s.." " end return ("%s: %s"):format(s, r) end
 
-	local cur_exp, max_exp = game.player.exp, game.player:getExpChart(game.player.level+1)
+	local cur_exp, max_exp = player.exp, player:getExpChart(player.level+1)
 	nl("  [Tome 4.00 @ www.te4.org Character Dump]")
 	nl()
 
-	nnl(("%-32s"):format(makelabel("Sex", game.player.descriptor.sex)))
-	nl(("STR:  %d"):format(game.player:getStr()))
+	nnl(("%-32s"):format(makelabel("Sex", player.descriptor.sex or (player.female and "Female" or "Male"))))
+	nl(("STR:  %d"):format(player:getStr()))
 
-	nnl(("%-32s"):format(makelabel("Race", game.player.descriptor.subrace)))
-	nl(("DEX:  %d"):format(game.player:getDex()))
+	nnl(("%-32s"):format(makelabel("Race", player.descriptor.subrace or player.type:capitalize())))
+	nl(("DEX:  %d"):format(player:getDex()))
 
-	nnl(("%-32s"):format(makelabel("Class", game.player.descriptor.subclass)))
-	nl(("MAG:  %d"):format(game.player:getMag()))
+	nnl(("%-32s"):format(makelabel("Class", player.descriptor.subclass or player.subtype:capitalize())))
+	nl(("MAG:  %d"):format(player:getMag()))
 
-	nnl(("%-32s"):format(makelabel("Level", ("%d"):format(game.player.level))))
-	nl(("WIL:  %d"):format(game.player:getWil()))
+	nnl(("%-32s"):format(makelabel("Level", ("%d"):format(player.level))))
+	nl(("WIL:  %d"):format(player:getWil()))
 
 	nnl(("%-32s"):format(makelabel("Exp", ("%d%%"):format(100 * cur_exp / max_exp))))
-	nl(("CUN:  %d"):format(game.player:getCun()))
+	nl(("CUN:  %d"):format(player:getCun()))
 
-	nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(game.player.money))))
-	nl(("CON:  %d"):format(game.player:getCon()))
+	nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(player.money))))
+	nl(("CON:  %d"):format(player:getCon()))
 
 	 -- All weapons in main hands
 
 	local strings = {}
 	for i = 1, 5 do strings[i]="" end
-	if self.actor:getInven(self.actor.INVEN_MAINHAND) then
-		for i, o in ipairs(self.actor:getInven(self.actor.INVEN_MAINHAND)) do
+	if player:getInven(player.INVEN_MAINHAND) then
+		for i, o in ipairs(player:getInven(player.INVEN_MAINHAND)) do
 			if o.combat then
-				strings[1] = ("Attack(Main Hand): %3d"):format(game.player:combatAttack(o.combat))
-				strings[2] = ("Damage(Main Hand): %3d"):format(game.player:combatDamage(o.combat))
-				strings[3] = ("APR   (Main Hand): %3d"):format(game.player:combatAPR(o.combat))
-				strings[4] = ("Crit  (Main Hand): %3d%%"):format(game.player:combatCrit(o.combat))
-				strings[5] = ("Speed (Main Hand): %0.2f"):format(game.player:combatSpeed(o.combat))
+				strings[1] = ("Attack(Main Hand): %3d"):format(player:combatAttack(o.combat))
+				strings[2] = ("Damage(Main Hand): %3d"):format(player:combatDamage(o.combat))
+				strings[3] = ("APR   (Main Hand): %3d"):format(player:combatAPR(o.combat))
+				strings[4] = ("Crit  (Main Hand): %3d%%"):format(player:combatCrit(o.combat))
+				strings[5] = ("Speed (Main Hand): %0.2f"):format(player:combatSpeed(o.combat))
 			end
 		end
 	end
 
-	local enc, max = game.player:getEncumbrance(), game.player:getMaxEncumbrance()
+	local enc, max = player:getEncumbrance(), player:getMaxEncumbrance()
 
 	nl()
 	nnl(("%-32s"):format(strings[1]))
-	nnl(("%-32s"):format(makelabel("Life", ("    %d/%d"):format(game.player.life, game.player.max_life))))
+	nnl(("%-32s"):format(makelabel("Life", ("    %d/%d"):format(player.life, player.max_life))))
 	nl(makelabel("Encumbrance", enc .. "/" .. max))
 
 	nnl(("%-32s"):format(strings[2]))
-	if game.player:knowTalent(game.player.T_STAMINA_POOL) then
-		nnl(("%-32s"):format(makelabel("Stamina", ("    %d/%d"):format(game.player:getStamina(), game.player.max_stamina))))
+	if player:knowTalent(player.T_STAMINA_POOL) then
+		nnl(("%-32s"):format(makelabel("Stamina", ("    %d/%d"):format(player:getStamina(), player.max_stamina))))
 	else
 		 nnl(("%-32s"):format(" "))
 	end
-	nl(makelabel("Difficulty", game.player.descriptor.difficulty))
+	nl(makelabel("Difficulty", player.descriptor.difficulty))
 
 	nnl(("%-32s"):format(strings[3]))
-	if game.player:knowTalent(game.player.T_MANA_POOL) then
-		nl(makelabel("Mana", ("    %d/%d"):format(game.player:getMana(), game.player.max_mana)))
+	if player:knowTalent(player.T_MANA_POOL) then
+		nl(makelabel("Mana", ("    %d/%d"):format(player:getMana(), player.max_mana)))
 	else
 		nl()
 	end
 	nnl(("%-32s"):format(strings[4]))
-	if game.player:knowTalent(game.player.T_POSITIVE_POOL) then
-		nl(makelabel("Positive", ("    %d/%d"):format(game.player:getPositive(), game.player.max_positive)))
+	if player:knowTalent(player.T_POSITIVE_POOL) then
+		nl(makelabel("Positive", ("    %d/%d"):format(player:getPositive(), player.max_positive)))
 	else
 		nl()
 	end
 	nnl(("%-32s"):format(strings[4]))
-	if game.player:knowTalent(game.player.T_NEGATIVE_POOL) then
-		nl(makelabel("Negative", ("    %d/%d"):format(game.player:getNegative(), game.player.max_negative)))
+	if player:knowTalent(player.T_NEGATIVE_POOL) then
+		nl(makelabel("Negative", ("    %d/%d"):format(player:getNegative(), player.max_negative)))
 	else
 		nl()
 	end
 	nnl(("%-32s"):format(strings[4]))
-	if game.player:knowTalent(game.player.T_VIM_POOL) then
-		nl(makelabel("Vim", ("    %d/%d"):format(game.player:getVim(), game.player.max_vim)))
+	if player:knowTalent(player.T_VIM_POOL) then
+		nl(makelabel("Vim", ("    %d/%d"):format(player:getVim(), player.max_vim)))
 	else
 		nl()
 	end
 	nnl(("%-32s"):format(strings[5]))
-	if game.player:knowTalent(game.player.T_EQUILIBRIUM_POOL) then
-		nl((makelabel("Equilibrium", ("    %d"):format(game.player:getEquilibrium()))))
+	if player:knowTalent(player.T_EQUILIBRIUM_POOL) then
+		nl((makelabel("Equilibrium", ("    %d"):format(player:getEquilibrium()))))
 	else
 		nl()
 	end
 
 	-- All wpeaons in off hands
 	-- Offhand atatcks are with a damage penality, taht can be reduced by talents
-	if self.actor:getInven(self.actor.INVEN_OFFHAND) then
+	if player:getInven(player.INVEN_OFFHAND) then
 		local offmult = (mult or 1) / 2
-		if self.actor:knowTalent(Talents.T_DUAL_WEAPON_TRAINING) then
-			offmult = (mult or 1) / (2 - (self.actor:getTalentLevel(Talents.T_DUAL_WEAPON_TRAINING) / 6))
+		if player:knowTalent(Talents.T_DUAL_WEAPON_TRAINING) then
+			offmult = (mult or 1) / (2 - (player:getTalentLevel(Talents.T_DUAL_WEAPON_TRAINING) / 6))
 		end
-		for i, o in ipairs(self.actor:getInven(self.actor.INVEN_OFFHAND)) do
+		for i, o in ipairs(player:getInven(player.INVEN_OFFHAND)) do
 			if o.combat then
 				nl()
-				nl(("Attack (Off Hand): %3d"):format(game.player:combatAttack(o.combat)))
-				nl(("Damage (Off Hand): %3d"):format(game.player:combatDamage(o.combat) * offmult))
-				nl(("APR    (Off Hand): %3d"):format(game.player:combatAPR(o.combat)))
-				nl(("Crit   (Off Hand): %3d%%"):format(game.player:combatCrit(o.combat)))
-				nl(("Speed  (Off Hand): %0.2f"):format(game.player:combatSpeed(o.combat)))
+				nl(("Attack (Off Hand): %3d"):format(player:combatAttack(o.combat)))
+				nl(("Damage (Off Hand): %3d"):format(player:combatDamage(o.combat) * offmult))
+				nl(("APR    (Off Hand): %3d"):format(player:combatAPR(o.combat)))
+				nl(("Crit   (Off Hand): %3d%%"):format(player:combatCrit(o.combat)))
+				nl(("Speed  (Off Hand): %0.2f"):format(player:combatSpeed(o.combat)))
 			end
 		end
 	end
 
 	nl()
-	nnl(("%-32s"):format(makelabel("Fatigue", game.player.fatigue .. "%")))
-	nl(makelabel("Spellpower", game.player:combatSpellpower() ..""))
-	nnl(("%-32s"):format(makelabel("Armor", game.player:combatArmor() .. "")))
-	nl(makelabel("Spell Crit", game.player:combatSpellCrit() .."%"))
-	nnl(("%-32s"):format(makelabel("Defense", game.player:combatDefense() .. "")))
-	nl(makelabel("Spell Speed", game.player:combatSpellSpeed() ..""))
-	nnl(("%-32s"):format(makelabel("Ranged Defense", game.player:combatDefenseRanged() .. "")))
+	nnl(("%-32s"):format(makelabel("Fatigue", player.fatigue .. "%")))
+	nl(makelabel("Spellpower", player:combatSpellpower() ..""))
+	nnl(("%-32s"):format(makelabel("Armor", player:combatArmor() .. "")))
+	nl(makelabel("Spell Crit", player:combatSpellCrit() .."%"))
+	nnl(("%-32s"):format(makelabel("Defense", player:combatDefense() .. "")))
+	nl(makelabel("Spell Speed", player:combatSpellSpeed() ..""))
+	nnl(("%-32s"):format(makelabel("Ranged Defense", player:combatDefenseRanged() .. "")))
 	nl()
 
 	nl()
-	if self.actor.inc_damage.all then nl(makelabel("All damage", self.actor.inc_damage.all.."%")) end
+	if player.inc_damage.all then nl(makelabel("All damage", player.inc_damage.all.."%")) end
 	for i, t in ipairs(DamageType.dam_def) do
-		if self.actor.inc_damage[DamageType[t.type]] and self.actor.inc_damage[DamageType[t.type]] ~= 0 then
-			nl(makelabel(t.name:capitalize().." damage", self.actor.inc_damage[DamageType[t.type]].."%"))
+		if player.inc_damage[DamageType[t.type]] and player.inc_damage[DamageType[t.type]] ~= 0 then
+			nl(makelabel(t.name:capitalize().." damage", player.inc_damage[DamageType[t.type]].."%"))
 		end
 	end
 
 	nl()
-	nl(makelabel("Physical Save",game.player:combatPhysicalResist() ..""))
-	nl(makelabel("Spell Save",game.player:combatSpellResist() ..""))
-	nl(makelabel("Mental Save",game.player:combatMentalResist() ..""))
+	nl(makelabel("Physical Save",player:combatPhysicalResist() ..""))
+	nl(makelabel("Spell Save",player:combatSpellResist() ..""))
+	nl(makelabel("Mental Save",player:combatMentalResist() ..""))
 
 	nl()
-	if self.actor.resists.all then nl(("All Resists: %3d%%"):format(self.actor.resists.all)) end
+	if player.resists.all then nl(("All Resists: %3d%%"):format(player.resists.all)) end
 	for i, t in ipairs(DamageType.dam_def) do
-		if self.actor.resists[DamageType[t.type]] and self.actor.resists[DamageType[t.type]] ~= 0 then
-			nl(("%s Resist: %3d%%"):format(t.name:capitalize(), self.actor.resists[DamageType[t.type]]))
+		if player.resists[DamageType[t.type]] and player.resists[DamageType[t.type]] ~= 0 then
+			nl(("%s Resist: %3d%%"):format(t.name:capitalize(), player.resists[DamageType[t.type]]))
 		end
 	end
 
-	immune_type = "poison_immune" immune_name = "Poison Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "cut_immune" immune_name = "Bleed Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "confusion_immune" immune_name = "Confusion Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "blind_immune" immune_name = "Blind Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "silence_immune" immune_name = "Silence Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "disarm_immune" immune_name = "Disarm Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "pin_immune" immune_name = "Pinning Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "stun_immune" immune_name = "Stun Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "fear_immune" immune_name = "Fear Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "knockback_immune" immune_name = "Knockback Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "stone_immune" immune_name = "Stoning Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
-	immune_type = "teleport_immune" immune_name = "Teleport Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "poison_immune" immune_name = "Poison Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "cut_immune" immune_name = "Bleed Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "confusion_immune" immune_name = "Confusion Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "blind_immune" immune_name = "Blind Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "silence_immune" immune_name = "Silence Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "disarm_immune" immune_name = "Disarm Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "pin_immune" immune_name = "Pinning Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "stun_immune" immune_name = "Stun Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "fear_immune" immune_name = "Fear Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "knockback_immune" immune_name = "Knockback Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "stone_immune" immune_name = "Stoning Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
+	immune_type = "teleport_immune" immune_name = "Teleport Resistance" if player:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(player:attr(immune_type) * 100, 0, 100))) end
 
 	nl()
 	local most_kill, most_kill_max = "none", 0
 	local total_kill = 0
-	for name, nb in pairs(game.player.all_kills or {}) do
+	for name, nb in pairs(player.all_kills or {}) do
 		if nb > most_kill_max then most_kill_max = nb most_kill = name end
 		total_kill = total_kill + nb
 	end
 	nl(("Number of NPC killed: %s"):format(total_kill))
 	nl(("Most killed NPC: %s (%d)"):format(most_kill, most_kill_max))
 
-	if self.actor.winner then
+	if player.winner then
 		nl()
 		nl("  [Winner!]")
 		nl()
-		for i, line in ipairs(self.actor.winner_text) do
+		for i, line in ipairs(player.winner_text) do
 			nl(("%s"):format(line:removeColorCodes()))
 		end
 	end
@@ -364,12 +367,12 @@ function _M:dump()
 	nl("  [Talents Chart]")
 	nl()
 
-	for i, tt in ipairs(self.actor.talents_types_def) do
-		 local ttknown = self.actor:knowTalentType(tt.type)
-		if not (self.actor.talents_types[tt.type] == nil) and ttknown then
+	for i, tt in ipairs(player.talents_types_def) do
+		 local ttknown = player:knowTalentType(tt.type)
+		if not (player.talents_types[tt.type] == nil) and ttknown then
 			local cat = tt.type:gsub("/.*", "")
 			local catname = ("%s / %s"):format(cat:capitalize(), tt.name:capitalize())
-			nl((" - %-35s(mastery %.02f)"):format(catname, self.actor:getTalentTypeMastery(tt.type)))
+			nl((" - %-35s(mastery %.02f)"):format(catname, player:getTalentTypeMastery(tt.type)))
 
 			-- Find all talents of this school
 			if (ttknown) then
@@ -378,7 +381,7 @@ function _M:dump()
 						local typename = "class"
 						if t.generic then typename = "generic" end
 						local skillname = ("    %s (%s)"):format(t.name, typename)
-						nl(("%-37s %d/%d"):format(skillname, self.actor:getTalentLevelRaw(t.id), t.points))
+						nl(("%-37s %d/%d"):format(skillname, player:getTalentLevelRaw(t.id), t.points))
 					end
 				end
 			end
@@ -391,11 +394,11 @@ function _M:dump()
 	 nl("  [Current Effects]")
 	 nl()
 
-	for tid, act in pairs(game.player.sustain_talents) do
-		if act then nl("- "..game.player:getTalentFromId(tid).name)	end
+	for tid, act in pairs(player.sustain_talents) do
+		if act then nl("- "..player:getTalentFromId(tid).name)	end
 	end
-	for eff_id, p in pairs(game.player.tmp) do
-		local e = game.player.tempeffect_def[eff_id]
+	for eff_id, p in pairs(player.tmp) do
+		local e = player.tempeffect_def[eff_id]
 		if e.status == "detrimental" then
 			 nl("+ "..e.desc)
 		else
@@ -406,7 +409,7 @@ function _M:dump()
 	-- Quests, Active and Completed
 
 	local first = true
-	for id, q in pairs(self.actor.quests or {}) do
+	for id, q in pairs(player.quests or {}) do
 		if q:isEnded() then
 			if first then
 					nl()
@@ -415,12 +418,12 @@ function _M:dump()
 					first=false
 			end
 			nl(" -- ".. q.name)
-			nl(q:desc(self.actor):gsub("#.-#", "   "))
+			nl(q:desc(player):gsub("#.-#", "   "))
 		end
 	end
 
 	 first=true
-	for id, q in pairs(self.actor.quests or {}) do
+	for id, q in pairs(player.quests or {}) do
 		if not q:isEnded() then
 			if first then
 					first=false
@@ -429,7 +432,7 @@ function _M:dump()
 					nl()
 				end
 			nl(" -- ".. q.name)
-			nl(q:desc(self.actor):gsub("#.-#", "   "))
+			nl(q:desc(player):gsub("#.-#", "   "))
 		end
 	end
 
@@ -439,11 +442,11 @@ function _M:dump()
 	nl("  [Character Equipment]")
 	nl()
 	local index = 0
-	for inven_id =  1, #self.actor.inven_def do
-		if self.actor.inven[inven_id] and self.actor.inven_def[inven_id].is_worn then
-			nl((" %s"):format(self.actor.inven_def[inven_id].name))
+	for inven_id =  1, #player.inven_def do
+		if player.inven[inven_id] and player.inven_def[inven_id].is_worn then
+			nl((" %s"):format(player.inven_def[inven_id].name))
 
-			for item, o in ipairs(self.actor.inven[inven_id]) do
+			for item, o in ipairs(player.inven[inven_id]) do
 				if not self.filter or self.filter(o) then
 					local char = string.char(string.byte('a') + index)
 					nl(("%s) %s"):format(char, o:getName{force_id=true}))
@@ -461,7 +464,7 @@ function _M:dump()
 	nl("  [Player Achievements]")
 	nl()
 	local achs = {}
-	for id, data in pairs(self.actor.achievements or {}) do
+	for id, data in pairs(player.achievements or {}) do
 		local a = world:getAchievementFromId(id)
 		achs[#achs+1] = {id=id, data=data, name=a.name}
 	end
@@ -474,7 +477,7 @@ function _M:dump()
 	nl()
 	nl("  [Character Inventory]")
 	nl()
-	for item, o in ipairs(self.actor:getInven("INVEN")) do
+	for item, o in ipairs(player:getInven("INVEN")) do
 		if not self.filter or self.filter(o) then
 			local char = string.char(string.byte('a') + item - 1)
 			nl(("%s) %s"):format(char, o:getName{force_id=true}))
diff --git a/ideas/worlds.ods b/ideas/worlds.ods
index e194fa6fd38d279a3374a38cba265b773d3ccf28..254265917247eab4bfd33bbfc1bbea9c80c2a1c7 100644
GIT binary patch
delta 6700
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

delta 6570
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
M1z{t>k^Rd44`J1tBLDyZ

-- 
GitLab