Page 1 of 2

Character dump code

Posted: Thu Jul 01, 2010 5:24 pm
by shani
Charactger textual dump version 1.0 :D

/tome/dialogs/CharacterSheet.lua

Code: Select all

function _M:dump()
	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 fff = fs.open(file, "w")
	local labelwidth = 17
	local nl = function(s) fff:write(s or "") fff:write("\n") end
	local nnl = function(s) fff:write(s or "") end
	--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)
	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("Race", game.player.descriptor.subrace)))	
	nl(("DEX:  %d"):format(game.player:getDex()))
	
	nnl(("%-32s"):format(makelabel("Class", game.player.descriptor.subclass)))	
	nl(("MAG:  %d"):format(game.player:getMag()))
	
	nnl(("%-32s"):format(makelabel("Level", ("%d"):format(game.player.level))))
	nl(("WIL:  %d"):format(game.player:getWil()))

	nnl(("%-32s"):format(makelabel("Exp", ("%d%%"):format(100 * cur_exp / max_exp))))	
	nl(("CUN:  %d"):format(game.player:getCun()))
	
    nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(game.player.money))))	
	nl(("CON:  %d"):format(game.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 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))
			end
		end
	end
	
	nl()
	nnl(("%-32s"):format(strings[1]))
	nl(makelabel("Life", ("    %d/%d"):format(game.player.life, game.player.max_life)))
	
	nnl(("%-32s"):format(strings[2]))
	if game.player:knowTalent(game.player.T_STAMINA_POOL) then
		nl(makelabel("Stamina", ("    %d/%d"):format(game.player:getStamina(), game.player.max_stamina)))
	else
	    nl()	
	end
	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)))
	else
		nl()
	end
	nnl(("%-32s"):format(strings[4]))
	if game.player:knowTalent(game.player.T_SOUL_POOL) then
		nl(makelabel("Soul", ("    %d/%d"):format(game.player:getSoul(), game.player.max_soul)))
    else
		nl()
	end
	nnl(("%-32s"):format(strings[5]))
	if game.player:knowTalent(game.player.T_EQUILIBRIUM_POOL) then
		nl((makelabel("Equi", ("    %d/%d"):format(game.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
		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))
		end
		for i, o in ipairs(self.actor:getInven(self.actor.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)))
			end
		end
	end

	nl()
	nnl(("%-32s"):format(makelabel("Fatigue", game.player.fatigue .. "%")))
	nl(("Spellpower:  %3d"):format(game.player:combatSpellpower()))
	nnl(("%-32s"):format(makelabel("Armor", game.player:combatArmor() .. "")))
	nl(("Spell Crit:  %3d%%"):format(game.player:combatSpellCrit()))
	nnl(("%-32s"):format(makelabel("Class", game.player:combatDefense() .. "")))
	nl(("Spell Speed: %3d"):format(game.player:combatSpellSpeed()))
	nnl(("%-32s"):format(makelabel("Class", game.player:combatDefenseRanged() .. "")))
	nl()

	nl()
	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(("%s damage: %3d%%"):format(t.name:capitalize(), self.actor.inc_damage[DamageType[t.type]]))
		end
	end	

	nl()
	nl(("Physical Resist: %3d"):format(game.player:combatPhysicalResist()))
	nl(("Spell Resist:    %3d"):format(game.player:combatSpellResist()))
	nl(("Mental Resist:   %3d"):format(game.player:combatMentalResist()))

	nl()
	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]]))
		end
	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
		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))
	
	--All Equipment
	nl()
	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 item, o in ipairs(self.actor.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}))					
					index = index + 1
				end
			end
		end
	end
	
	nl()
	nl("  [Character Inventory]")
	nl()
	for item, o in ipairs(self.actor: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}))			
		end
	end

	fff:close()

	Dialog:simplePopup("Character dump complete", "File: "..fs.getRealPath(file))
end

Re: Character dump code

Posted: Thu Jul 01, 2010 6:23 pm
by darkgod
Imported! :)

Now you could add talents too ? ;)

Re: Character dump code

Posted: Thu Jul 01, 2010 6:29 pm
by shani
:D

I'm working on item descriptions in the dump (It adds flavor to the dump IMHO)
It will require a new function in object.lua (Working on it also)
And when i'm done i'll do talents.

Deal? :lol:

Re: Character dump code

Posted: Thu Jul 01, 2010 6:35 pm
by darkgod
Deal ;)

Re: Character dump code

Posted: Thu Jul 01, 2010 8:19 pm
by shani
Ok. Version 2 is out :lol:
Added talents, and item description.

This one supposed to go to into /tome/class/Object.lua

Code: Select all

--- Gets the full textual desc of the object without the name for the character dump
function _M:getTextualDesc()
	local desc
		
	desc = { }
			
	if self.encumber then
		desc[#desc+1] = ("%0.2f Encumbrance."):format(self.encumber)
	end

	desc[#desc+1] = ("Type: %s / %s"):format(self.type, self.subtype)

	-- Stop here if unided
	if not self:isIdentified() then return table.concat(desc, "\n") end


	if self.combat then
		local dm = {}
		for stat, i in pairs(self.combat.dammod or {}) do
			dm[#dm+1] = ("+%d%% %s"):format(i * 100, Stats.stats_def[stat].name)
		end
		desc[#desc+1] = ("%d Power [Range %0.2f] (%s), %d Attack, %d Armor Penetration, Crit %d%%"):format(self.combat.dam or 0, self.combat.damrange or 1.1, table.concat(dm, ','), self.combat.atk or 0, self.combat.apr or 0, self.combat.physcrit or 0)
		if self.combat.range then desc[#desc+1] = "Firing range: "..self.combat.range end
		desc[#desc+1] = ""
	end

	local w = self.wielder or {}
	if w.combat_atk or w.combat_dam or w.combat_apr then desc[#desc+1] = ("Attack %d, Armor Penetration %d, Physical Crit %d%%, Physical power %d"):format(w.combat_atk or 0, w.combat_apr or 0, w.combat_physcrit or 0, w.combat_dam or 0) end
	if w.combat_armor or w.combat_def then desc[#desc+1] = ("Armor %d, Defense %d"):format(w.combat_armor or 0, w.combat_def or 0) end
	if w.fatigue then desc[#desc+1] = ("Fatigue %d%%"):format(w.fatigue) end

	if w.inc_stats then
		local dm = {}
		for stat, i in pairs(w.inc_stats) do
			dm[#dm+1] = ("%d %s"):format(i, Stats.stats_def[stat].name)
		end
		desc[#desc+1] = ("Increases stats: %s."):format(table.concat(dm, ','))
	end

	if w.melee_project then
		local rs = {}
		for typ, dam in pairs(w.melee_project) do
			rs[#rs+1] = ("%d %s"):format(dam, DamageType.dam_def[typ].name)
		end
		desc[#desc+1] = ("Damage on hit: %s."):format(table.concat(rs, ','))
	end

	if w.on_melee_hit then
		local rs = {}
		for typ, dam in pairs(w.on_melee_hit) do
			rs[#rs+1] = ("%d %s"):format(dam, DamageType.dam_def[typ].name)
		end
		desc[#desc+1] = ("Damage when hit: %s."):format(table.concat(rs, ','))
	end

	if w.resists then
		local rs = {}
		for res, i in pairs(w.resists) do
			rs[#rs+1] = ("%d%% %s"):format(i, DamageType.dam_def[res].name)
		end
		desc[#desc+1] = ("Increases resistances: %s."):format(table.concat(rs, ','))
	end

	if w.inc_damage then
		local rs = {}
		for res, i in pairs(w.inc_damage) do
			rs[#rs+1] = ("%d%% %s"):format(i, DamageType.dam_def[res].name)
		end
		desc[#desc+1] = ("Increases damage type: %s."):format(table.concat(rs, ','))
	end

	if w.esp then
		local rs = {}
		for type, i in pairs(w.esp) do
			if type == "all" then rs[#rs+1] = "all"
			elseif type == "range" then rs[#rs+1] = "increase range by "..i
			else
				local _, _, t, st = type:find("^([^/]+)/?(.*)$")
				if st then
					rs[#rs+1] = st
				else
					rs[#rs+1] = t
				end
			end
		end
		desc[#desc+1] = ("Grants telepathy: %s."):format(table.concat(rs, ','))
	end

	if w.talents_types_mastery then
		local tms = {}
		for ttn, i in pairs(w.talents_types_mastery) do
			local tt = Talents.talents_types_def[ttn]
			local cat = tt.type:gsub("/.*", "")
			local name = cat:capitalize().." / "..tt.name:capitalize()
			tms[#tms+1] = ("%0.2f %s"):format(i, name)
		end
		desc[#desc+1] = ("Increases talent masteries: %s."):format(table.concat(tms, ','))
	end

	if w.combat_physresist then desc[#desc+1] = ("Increases physical resistance: %s."):format(w.combat_physresist) end
	if w.combat_spellresist then desc[#desc+1] = ("Increases spell resistance: %s."):format(w.combat_spellresist) end
	if w.combat_mentalresist then desc[#desc+1] = ("Increases mental resistance: %s."):format(w.combat_mentalresist) end

	if w.blind_immune then desc[#desc+1] = ("Increases blindness immunity: %d%%."):format(w.blind_immune * 100) end
	if w.poison_immune then desc[#desc+1] = ("Increases poison immunity: %d%%."):format(w.poison_immune * 100) end
	if w.cut_immune then desc[#desc+1] = ("Increases cut immunity: %d%%."):format(w.cut_immune * 100) end
	if w.confusion_immune then desc[#desc+1] = ("Increases confusion immunity: %d%%."):format(w.confusion_immune * 100) end
	if w.stun_immune then desc[#desc+1] = ("Increases stun immunity: %d%%."):format(w.stun_immune * 100) end
	if w.fear_immune then desc[#desc+1] = ("Increases fear immunity: %d%%."):format(w.fear_immune * 100) end
	if w.knockback_immune then desc[#desc+1] = ("Increases knockback immunity: %d%%."):format(w.knockback_immune * 100) end
	if w.instakill_immune then desc[#desc+1] = ("Increases instant-death immunity: %d%%."):format(w.instakill_immune * 100) end

	if w.life_regen then desc[#desc+1] = ("Regenerates %0.2f hitpoints each turn."):format(w.life_regen) end
	if w.mana_regen then desc[#desc+1] = ("Regenerates %0.2f mana each turn."):format(w.mana_regen) end

	if w.max_life then desc[#desc+1] = ("Maximum life %d"):format(w.max_life) end
	if w.max_mana then desc[#desc+1] = ("Maximum mana %d"):format(w.max_mana) end
	if w.max_stamina then desc[#desc+1] = ("Maximum stamina %d"):format(w.max_stamina) end

	if w.combat_spellpower or w.combat_spellcrit then desc[#desc+1] = ("Spellpower %d, Spell Crit %d%%"):format(w.combat_spellpower or 0, w.combat_spellcrit or 0) end

	if w.lite then desc[#desc+1] = ("Light radius %d"):format(w.lite) end

	if w.see_invisible then desc[#desc+1] = ("See invisible: %d"):format(w.see_invisible) end
	if w.invisible then desc[#desc+1] = ("Invisibility: %d"):format(w.invisible) end

	local use_desc = self:getUseDesc()
	if use_desc then desc[#desc+1] = use_desc end

	return table.concat(desc, "\n    ")
end
And this one replace existing function in /tome/dialogs/CharacterSheet.lua

Code: Select all

function _M:dump()
	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 fff = fs.open(file, "w")
	local labelwidth = 17
	local nl = function(s) fff:write(s or "") fff:write("\n") end
	local nnl = function(s) fff:write(s or "") end
	--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)
	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("Race", game.player.descriptor.subrace)))	
	nl(("DEX:  %d"):format(game.player:getDex()))
	
	nnl(("%-32s"):format(makelabel("Class", game.player.descriptor.subclass)))	
	nl(("MAG:  %d"):format(game.player:getMag()))
	
	nnl(("%-32s"):format(makelabel("Level", ("%d"):format(game.player.level))))
	nl(("WIL:  %d"):format(game.player:getWil()))

	nnl(("%-32s"):format(makelabel("Exp", ("%d%%"):format(100 * cur_exp / max_exp))))	
	nl(("CUN:  %d"):format(game.player:getCun()))
	
    nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(game.player.money))))	
	nl(("CON:  %d"):format(game.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 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))
			end
		end
	end
	
	nl()
	nnl(("%-32s"):format(strings[1]))
	nl(makelabel("Life", ("    %d/%d"):format(game.player.life, game.player.max_life)))
	
	nnl(("%-32s"):format(strings[2]))
	if game.player:knowTalent(game.player.T_STAMINA_POOL) then
		nl(makelabel("Stamina", ("    %d/%d"):format(game.player:getStamina(), game.player.max_stamina)))
	else
	    nl()	
	end
	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)))
	else
		nl()
	end
	nnl(("%-32s"):format(strings[4]))
	if game.player:knowTalent(game.player.T_SOUL_POOL) then
		nl(makelabel("Soul", ("    %d/%d"):format(game.player:getSoul(), game.player.max_soul)))
    else
		nl()
	end
	nnl(("%-32s"):format(strings[5]))
	if game.player:knowTalent(game.player.T_EQUILIBRIUM_POOL) then
		nl((makelabel("Equi", ("    %d/%d"):format(game.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
		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))
		end
		for i, o in ipairs(self.actor:getInven(self.actor.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)))
			end
		end
	end

	nl()
	nnl(("%-32s"):format(makelabel("Fatigue", game.player.fatigue .. "%")))
	nl(("Spellpower:  %3d"):format(game.player:combatSpellpower()))
	nnl(("%-32s"):format(makelabel("Armor", game.player:combatArmor() .. "")))
	nl(("Spell Crit:  %3d%%"):format(game.player:combatSpellCrit()))
	nnl(("%-32s"):format(makelabel("Class", game.player:combatDefense() .. "")))
	nl(("Spell Speed: %3d"):format(game.player:combatSpellSpeed()))
	nnl(("%-32s"):format(makelabel("Class", game.player:combatDefenseRanged() .. "")))
	nl()

	nl()
	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(("%s damage: %3d%%"):format(t.name:capitalize(), self.actor.inc_damage[DamageType[t.type]]))
		end
	end	

	nl()
	nl(("Physical Resist: %3d"):format(game.player:combatPhysicalResist()))
	nl(("Spell Resist   : %3d"):format(game.player:combatSpellResist()))
	nl(("Mental Resist  : %3d"):format(game.player:combatMentalResist()))

	nl()
	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]]))
		end
	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
		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))
	
	--Talents and skills
	nl()
	nl("  [Talents/Skills Chart]")
	nl()
	
	for i, tt in ipairs(self.actor.talents_types_def) do
	    local ttknown = self.actor:knowTalentType(tt.type)
		if not tt.hide and not (self.actor.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)))			

			-- Find all talents of this school
			if (self.actor.__hidden_talent_types[tt.type] == nil and ttknown) or (self.actor.__hidden_talent_types[tt.type] ~= nil and not self.actor.__hidden_talent_types[tt.type]) then
				for j, t in ipairs(tt.talents) do
					if not t.hide then
						local typename = "talent"
						if t.skill then typename = "skill" end
						local skillname = ("    %s (%s)"):format(t.name, typename)
						nl(("%-37s %d/%d"):format(skillname, self.actor:getTalentLevelRaw(t.id), t.points))						
					end
				end
			end
		end
	end
	
	--All Equipment
	nl()
	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 item, o in ipairs(self.actor.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}))					
					nl(("   %s"):format(o:getTextualDesc()))
					index = index + 1
				end
			end
		end
	end
	
	nl()
	nl("  [Character Inventory]")
	nl()
	for item, o in ipairs(self.actor: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}))			
			nl(("   %s"):format(o:getTextualDesc()))
		end
	end

	fff:close()

	Dialog:simplePopup("Character dump complete", "File: "..fs.getRealPath(file))
end

Re: Character dump code

Posted: Thu Jul 01, 2010 8:31 pm
by Shoob
oh and active and completed quests in there too would be nice :P

and change the equillibrium line, you have an extra /%d in there that you dont need.

Re: Character dump code

Posted: Thu Jul 01, 2010 8:43 pm
by shani
No problems!

Just not today. :D

Re: Character dump code

Posted: Fri Jul 02, 2010 3:37 am
by Shoob
Other stuff to add/fix:

- difficulty level
- if the character minimizes a talent group in game, the sub-talents are not printed in the character dump (they still should print in the dump)
- encumbrance levels
- sustained/active talents and effects (including scrolls (like shielding) and potions (like invis))

Good job; after I fixed the equilibrium line, this is a lot better :) just a few more tweaks and it will be purrrrrrfect (well until next beta) ;)

Re: Character dump code

Posted: Fri Jul 02, 2010 1:36 pm
by shani
Version 3 of /tome/dialogs/Characterdump.lua/dump
All of Shoob's ideas have been implemented

It's getting quite long.... :D

Code: Select all

function _M:dump()
	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 fff = fs.open(file, "w")
	local labelwidth = 17
	local nl = function(s) fff:write(s or "") fff:write("\n") end
	local nnl = function(s) fff:write(s or "") end
	--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)
	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("Race", game.player.descriptor.subrace)))	
	nl(("DEX:  %d"):format(game.player:getDex()))
	
	nnl(("%-32s"):format(makelabel("Class", game.player.descriptor.subclass)))	
	nl(("MAG:  %d"):format(game.player:getMag()))
	
	nnl(("%-32s"):format(makelabel("Level", ("%d"):format(game.player.level))))
	nl(("WIL:  %d"):format(game.player:getWil()))

	nnl(("%-32s"):format(makelabel("Exp", ("%d%%"):format(100 * cur_exp / max_exp))))	
	nl(("CUN:  %d"):format(game.player:getCun()))
	
    nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(game.player.money))))	
	nl(("CON:  %d"):format(game.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 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))
			end
		end
	end
	
	local enc, max = game.player:getEncumbrance(), game.player:getMaxEncumbrance()
	
	nl()
	nnl(("%-32s"):format(strings[1]))
	nnl(("%-32s"):format(makelabel("Life", ("    %d/%d"):format(game.player.life, game.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))))
	else
	    nnl(("%-32s"):format(" "))
	end
	nl(makelabel("Difficulty", game.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)))
	else
		nl()
	end
	nnl(("%-32s"):format(strings[4]))
	if game.player:knowTalent(game.player.T_SOUL_POOL) then
		nl(makelabel("Soul", ("    %d/%d"):format(game.player:getSoul(), game.player.max_soul)))
    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()))))
	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
		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))
		end
		for i, o in ipairs(self.actor:getInven(self.actor.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)))
			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("Class", game.player:combatDefense() .. "")))
	nl(makelabel("Spell Speed", game.player:combatSpellSpeed() ..""))			
	nnl(("%-32s"):format(makelabel("Class", game.player:combatDefenseRanged() .. "")))
	nl()

	nl()
	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]].."%"))			
		end
	end	

	nl()
	nl(makelabel("Physical Resist",game.player:combatPhysicalResist() ..""))
	nl(makelabel("Spell Resist",game.player:combatSpellResist() ..""))
	nl(makelabel("Mental Resist",game.player:combatMentalResist() ..""))	

	nl()
	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]]))
		end
	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
		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))
			
	--Talents and skills
	nl()
	nl("  [Talents/Skills 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		
			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)))			

			-- Find all talents of this school			
			if (ttknown) then			
				for j, t in ipairs(tt.talents) do
					if not t.hide then
						local typename = "talent"
						if t.skill then typename = "skill" end
						local skillname = ("    %s (%s)"):format(t.name, typename)
						nl(("%-37s %d/%d"):format(skillname, self.actor:getTalentLevelRaw(t.id), t.points))						
					end
				end
			end
		end
	end

    -- Current Effects
    
    nl()
    nl("  [Current Effects]")
    nl()
    
	for tid, act in pairs(game.player.sustain_talents) do	   
		if act then nl("- "..game.player:getTalentFromId(tid).name)	end
	end
	for eff_id, p in pairs(game.player.tmp) do
		local e = game.player.tempeffect_def[eff_id]
		if e.status == "detrimental" then
		    nl("+ "..e.desc)
		else
		    nl("- "..e.desc)
		end
	end
		
	-- Quests, Active and Completed
	
	local first = true
	for id, q in pairs(self.actor.quests or {}) do	       
		if q:isEnded() then
		 	if first then
	       		nl()
	       		nl("  [Completed Quests]")
	       		nl()
	       		first=false
	    	end	
		     nl(" -- ".. q.name)
		     nl(q:desc(self.actor):gsub("#.-#", "   "))
		end
	end
		
    first=true
	for id, q in pairs(self.actor.quests or {}) do	    
		if not q:isEnded() then
			if first then
	   	    	first=false
	    	   	nl()
			   	nl("  [Active Quests]")
	   		 	nl()
	  		 end 
		     nl(" -- ".. q.name)
		     nl(q:desc(self.actor):gsub("#.-#", "   "))		     
		end
	end
	
	
	--All Equipment
	nl()
	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 item, o in ipairs(self.actor.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}))					
					nl(("   %s"):format(o:getTextualDesc()))
					index = index + 1
				end
			end
		end
	end
	
	nl()
	nl("  [Character Inventory]")
	nl()
	for item, o in ipairs(self.actor: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}))			
			nl(("   %s"):format(o:getTextualDesc()))
		end
	end

	fff:close()

	Dialog:simplePopup("Character dump complete", "File: "..fs.getRealPath(file))
end

Re: Character dump code

Posted: Fri Jul 02, 2010 1:47 pm
by darkgod
Nice!
Just a comment, why have a near duplicate of Object:getDesc ?
I dont like duplicate code much :)

Re: Character dump code

Posted: Fri Jul 02, 2010 1:50 pm
by shani
We Could unite most of the the duplicate code (I don't like duplicate code also)
But I don't want the beginning of the getDesc function - so maybe we can converge them into two
short functions and one shared.
Hmmm... I'll work on that. If you want me.

Re: Character dump code

Posted: Fri Jul 02, 2010 1:51 pm
by darkgod
yeah please :)

Re: Character dump code

Posted: Thu Sep 23, 2010 6:10 pm
by Final Master
So.... are the character dumps finished or are they still being worked on?

Re: Character dump code

Posted: Thu Sep 23, 2010 9:48 pm
by Shoob
they won't technically be done until tome is complete because of the new stuff :P

Re: Character dump code

Posted: Tue Oct 12, 2010 5:16 am
by Final Master
Any chance to have the basic character sheet put up when loading your character?