Forked from
tome / Tales of MajEyal
12017 commits behind the upstream repository.
-
dg authored
git-svn-id: http://svn.net-core.org/repos/t-engine4@3087 51575b47-30f0-44d4-a5cc-537603b46e54
dg authoredgit-svn-id: http://svn.net-core.org/repos/t-engine4@3087 51575b47-30f0-44d4-a5cc-537603b46e54
PlayerDumpJSON.lua 15.44 KiB
-- ToME - Tales of Maj'Eyal
-- 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.interface.PlayerDumpJSON"
local DamageType = require "engine.DamageType"
module(..., package.seeall, class.inherit(class.make{}, base))
function _M:dumpToJSON(js)
if not base.dumpToJSON(self, js) then return end
local nb_inscriptions = 0
for i = 1, self.max_inscriptions do if self.inscriptions[i] then nb_inscriptions = nb_inscriptions + 1 end end
local cur_exp, max_exp = self.exp, self:getExpChart(self.level+1)
local title = ("%s the level %d %s %s"):format(self.name, self.level, self.descriptor.subrace, self.descriptor.subclass)
-------------------------------------------------------------------
-- Character
-------------------------------------------------------------------
local deaths = "no deaths recorded"
if #self.died_times > 0 then
deaths = "<ul>"
for i, reason in ipairs(self.died_times) do
deaths = deaths..string.format("<li>Killed by %s at level %d on the %s</li>", reason.name or "unknown", reason.level, game.calendar:getTimeDate(reason.turn, "%s %s %s year of Ascendancy at %02d:%02d"))
end
deaths = deaths.."</ul>"
end
js:newSection("character", "char", "pairs", "add", {
{ game = string.format("%s (version %d.%d.%d)", game.__mod_info.long_name, game.__mod_info.version[1], game.__mod_info.version[2], game.__mod_info.version[3]) },
{ name = self.name },
{ sex = self.descriptor.sex },
{ type = self.descriptor.subrace .. " " .. self.descriptor.subclass },
{ campaign = self.descriptor.world },
{ difficulty = self.descriptor.difficulty },
{ level = self.level },
{ exp = string.format("%d%%", 100 * cur_exp / max_exp) },
{ gold = string.format("%d", self.money) },
{ died = { val=string.format("%d times (now %s)", #self.died_times or 0, self.dead and "dead" or "alive"), tooltip=deaths } },
})
-------------------------------------------------------------------
-- Stats
-------------------------------------------------------------------
js:newSection("primary stats", "stats", "pairs", "break", {
{ strength = self:getStr() },
{ dexterity = self:getDex() },
{ magic = self:getMag() },
{ willpower = self:getWil() },
{ cunning = self:getCun() },
{ constitution = self:getCon() },
})
-------------------------------------------------------------------
-- Resources
-------------------------------------------------------------------
local r = js:newSection("resources", "resources", "pairs", "add")
r[#r+1] = {life=string.format("%d/%d", self.life, self.max_life)}
if self:knowTalent(self.T_STAMINA_POOL) then r[#r+1] = {stamina=string.format("%d/%d", self.stamina, self.max_stamina)} end
if self:knowTalent(self.T_MANA_POOL) then r[#r+1] = {mana=string.format("%d/%d", self.mana, self.max_mana)} end
if self:knowTalent(self.T_POSITIVE_POOL) then r[#r+1] = {positive=string.format("%d/%d", self.positive, self.max_positive)} end
if self:knowTalent(self.T_NEGATIVE_POOL) then r[#r+1] = {negative=string.format("%d/%d", self.negative, self.max_negative)} end
if self:knowTalent(self.T_VIM_POOL) then r[#r+1] = {vim=string.format("%d/%d", self.vim, self.max_vim)} end
if self:knowTalent(self.T_EQUILIBRIUM_POOL) then r[#r+1] = {equilibrium=string.format("%d", self.equilibrium)} end
if self:knowTalent(self.T_HATE_POOL) then r[#r+1] = {hate=string.format("%0.2f/%0.2f", self.hate, self.max_hate)} end
-------------------------------------------------------------------
-- Inscriptions
-------------------------------------------------------------------
local ins = js:newSection(("inscriptions (%d/%d)"):format(nb_inscriptions, self.max_inscriptions), "inscriptions", "pairs", "break")
for i = 1, self.max_inscriptions do if self.inscriptions[i] then
local t = self:getTalentFromId("T_"..self.inscriptions[i])
local desc = tostring(self:getTalentFullDescription(t))
local p = t.name:split(": ")
ins[#ins+1] = {[p[1]] = {val=p[2], tooltip=desc}}
end end
-------------------------------------------------------------------
-- Winner
-------------------------------------------------------------------
if self.winner then
local win = js:newSection("winner", "win", "text", nil)
for i, line in ipairs(self.winner_text) do
win[#win+1] = { val=line:removeColorCodes(), bg="000000"}
end
end
-------------------------------------------------------------------
-- Offense
-------------------------------------------------------------------
local c = js:newSection("offense", "offense", "pairs", "add")
if self:getInven(self.INVEN_MAINHAND) then
for i, o in ipairs(self:getInven(self.INVEN_MAINHAND)) do
local mean, dam = o.combat, o.combat
if o.archery and mean then
dam = (self:getInven("QUIVER")[1] and self:getInven("QUIVER")[1].combat) or o.basic_ammo
end
if mean and dam then
c[#c+1] = { ["accuracy (main hand)"] = string.format("%d", self:combatAttack(mean)) }
c[#c+1] = { ["damage (main hand)"] = string.format("%d", self:combatDamage(dam)) }
c[#c+1] = { ["APR (main hand)"] = string.format("%d", self:combatAPR(dam)) }
c[#c+1] = { ["crit (main hand)"] = string.format("%d%%", self:combatCrit(dam)) }
c[#c+1] = { ["speed (main hand)"] = string.format("%0.2f", self:combatSpeed(mean)) }
end
if mean and mean.range then c[#c+1] = { ["range (main hand)"] = mean.range } end
end
end
if self:getInven(self.INVEN_OFFHAND) then
local offmult = self:getOffHandMult()
for i, o in ipairs(self:getInven(self.INVEN_OFFHAND)) do
local mean, dam = o.combat, o.combat
if o.archery and mean then
dam = (self:getInven("QUIVER")[1] and self:getInven("QUIVER")[1].combat) or o.basic_ammo
end
if mean and dam then
c[#c+1] = { ["accuracy (off hand)"] = string.format("%d", self:combatAttack(mean)) }
c[#c+1] = { ["damage (off hand)"] = string.format("%d", self:combatDamage(dam) * offmult) }
c[#c+1] = { ["APR (off hand)"] = string.format("%d", self:combatAPR(dam)) }
c[#c+1] = { ["crit(off hand)"] = string.format("%d%%", self:combatCrit(dam)) }
c[#c+1] = { ["speed(off hand)"] = string.format("%0.2f", self:combatSpeed(mean)) }
end
if mean and mean.range then c[#c+1] = { ["range (main hand)"] = mean.range } end
end
end
c[#c+1] = { spellpower = self:combatSpellpower() }
c[#c+1] = { ["spell crit"] = self:combatSpellCrit() }
c[#c+1] = { ["spell speed"] = self:combatSpellSpeed() }
if self.inc_damage.all then c[#c+1] = { ["all damage"] = string.format("%d%%", self.inc_damage.all) } end
for i, t in ipairs(DamageType.dam_def) do
if self.inc_damage[DamageType[t.type]] and self.inc_damage[DamageType[t.type]] ~= 0 then
c[#c+1] = { [t.name.." damage"] = string.format("%d%%", self.inc_damage[DamageType[t.type]] + (self.inc_damage.all or 0)) }
end
end
-------------------------------------------------------------------
-- Defense
-------------------------------------------------------------------
local d = js:newSection("defense", "defense", "pairs", "break")
d[#d+1] = { ["fatigue"] = self:combatFatigue() }
d[#d+1] = { ["armour"] = self:combatArmor() }
d[#d+1] = { ["defense"] = self:combatDefense() }
d[#d+1] = { ["ranged defense"] = self:combatDefenseRanged() }
d[#d+1] = { ["physical save"] = self:combatPhysicalResist() }
d[#d+1] = { ["spell save"] = self:combatSpellResist() }
d[#d+1] = { ["mental save"] = self:combatMentalResist() }
if self.resists.all then d[#d+1] = { ["all resists(cap)"] = string.format("%3d%%(%3d%%)", self.resists.all, self.resists_cap.all or 0) } end
for i, t in ipairs(DamageType.dam_def) do
if self.resists[DamageType[t.type]] and self.resists[DamageType[t.type]] ~= 0 then
d[#d+1] = { [t.name.." resist(cap)"] = string.format("%3d%%(%3d%%)", self.resists[DamageType[t.type]] + (self.resists.all or 0), (self.resists_cap[DamageType[t.type]] or 0) + (self.resists_cap.all or 0)) }
end
end
immune_type = "poison_immune" immune_name = "Poison Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "cut_immune" immune_name = "Bleed Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "confusion_immune" immune_name = "Confusion Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "blind_immune" immune_name = "Blind Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "silence_immune" immune_name = "Silence Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "disarm_immune" immune_name = "Disarm Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "pin_immune" immune_name = "Pinning Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "stun_immune" immune_name = "Stun Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "fear_immune" immune_name = "Fear Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "knockback_immune" immune_name = "Knockback Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "stone_immune" immune_name = "Stoning Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
immune_type = "teleport_immune" immune_name = "Teleport Resistance" if self:attr(immune_type) then d[#d+1] = { [immune_name] = string.format("%d%%", util.bound(self:attr(immune_type) * 100, 0, 100)) } end
-------------------------------------------------------------------
-- Effects
-------------------------------------------------------------------
local tdef = js:newSection("talents", "talents", "pairs", "add")
for i, tt in ipairs(self.talents_types_def) do
local ttknown = self:knowTalentType(tt.type)
if not (self.talents_types[tt.type] == nil) and ttknown then
local cat = tt.type:gsub("/.*", "")
local catname = ("%s / %s"):format(cat:capitalize(), tt.name:capitalize())
tdef[#tdef+1] = { [catname] = ("(mastery %.02f)"):format(self: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 = "class"
if t.generic then typename = "generic" end
local skillname = ("<ul><li>%s (%s)</li></ul>"):format(t.name, typename)
tdef[#tdef+1] = { [skillname] = ("%d/%d"):format(self:getTalentLevelRaw(t.id), t.points) }
end
end
end
end
end
-------------------------------------------------------------------
-- Effects
-------------------------------------------------------------------
local e = js:newSection("current effects", "effects", "pairs", "add")
for tid, act in pairs(self.sustain_talents) do
if act then
local t = self:getTalentFromId(tid)
e[#e+1] = { Talent = t.name }
end
end
for eff_id, p in pairs(self.tmp) do
local e = self.tempeffect_def[eff_id]
local desc = e.long_desc(self, p)
if e.status == "detrimental" then
e[#e+1] = { ["detrimental effect"] = e.desc }
else
e[#e+1] = { ["beneficial effect"] = e.desc }
end
end
-------------------------------------------------------------------
-- Quests
-------------------------------------------------------------------
local quests = js:newSection("quests", "quests", "pairs", "add")
for id, q in pairs(game.party.quests or {}) do
quests[#quests+1] = { [q.status_text[q.status]] = {val=q.name, tooltip=q:desc(self)} }
end
table.sort(quests, function(a, b) local _, aname = next(a) local _, bname = next(b) return aname.val < bname.val end)
-------------------------------------------------------------------
-- Achievements
-------------------------------------------------------------------
local achs = js:newSection("achievements", "achievements", "pairs", "break")
for id, data in pairs(self.achievements or {}) do
local a = world:getAchievementFromId(id)
achs[#achs+1] = { [a.name] = {val=game.calendar:getTimeDate(data.turn, "%s %s %s year of Ascendancy at %02d:%02d"), tooltip=a.desc} }
end
table.sort(achs, function(a, b) local aname = next(a) local bname = next(b) return aname < bname end)
-------------------------------------------------------------------
-- Equip
-------------------------------------------------------------------
local equip = js:newSection("equipment", "equip", "pairs", "add")
for inven_id = 1, #self.inven_def do
if self.inven[inven_id] and self.inven_def[inven_id].is_worn then
for item, o in ipairs(self.inven[inven_id]) do
local desc = tostring(o:getDesc())
equip[#equip+1] = { [self.inven_def[inven_id].name] = { val=o:getName{do_color=true, no_image=true}, tooltip=desc, bg="000000" } }
end
end
end
-------------------------------------------------------------------
-- Inventory
-------------------------------------------------------------------
local inven = js:newSection("inventory", "inven", "list", "break")
for item, o in ipairs(self.inven[self.INVEN_INVEN]) do
local desc = tostring(o:getDesc())
inven[#inven+1] = { val=o:getName{do_color=true, no_image=true}, tooltip=desc, bg="000000" }
end
-------------------------------------------------------------------
-- Log
-------------------------------------------------------------------
local log = js:newSection("last messages", "log", "text", nil)
log[#log+1] = { val=table.concat(game.logdisplay:getLines(30), "#LAST#\n"), bg="000000" }
-- Cleanup numbers
for _, sec in ipairs(js.sections) do
if sec.type == "pairs" then
for __, line in ipairs(js[sec.table]) do
local k, e = next(line)
if type(e) == "number" then line[k] = math.floor(e) end
end
end
end
local tags = {
game = game.__mod_info.version_name,
level = self.level,
name = self.name,
difficulty = self.descriptor.difficulty,
campaign = self.descriptor.world,
race = self.descriptor.subrace,
class = self.descriptor.subclass,
dead = self.dead and "dead" or nil,
winner = self.winner and "winner" or nil,
}
return title, tags
end