Module:CalculatedStats
Documentation
Basic use
To use this module, do as follows:
{{#invoke:CalculatedStats|<function>}}
This module should not be invoked directly in the mainspace and should be part of a template; the values get filled in by template parameters.
Valid values for function (case sensitive):
smt1for Shin Megami Tenseismt2for Shin Megami Tensei IIsmtiffor Shin Megami Tensei if... (alias forsmt2)smtnfor Shin Megami Tensei: Ninedesumfor Shin Megami Tensei: Devil Summonersh1for Devil Summoner: Soul Hackersp2isfor Persona 2: Innocent Sin
Platform
Shin Megami Tensei: Devil Summoner by default shows the normal, Super CD-ROM², and Mega-CD values for all calculated stats. Set the named parameter platform to CD2 or MCD (case insensitive) to display only the Super CD-ROM² or Mega-CD stats, or set it to anything else to only display the usual calculations.
Shin Megami Tensei: Devil Summoner by default shows both the Sega Saturn and PlayStation Portable values for Magic Defense. Set the named parameter platform to either SAT or PSP (case insensitive) to display only one of them.
For Persona 2: Innocent Sin, set the named parameter platform to PS or PSP to show only one platform's set of stats. PSP stats only apply to demons; Personas always use the PS calculations even on PSP.
Boss
Shin Megami Tensei (Mega-CD) uses different stat calculations for bosses than it does for regular demons. Set the named parameter boss to something (recommended: y) to use the boss calculations.
Manual stat inputting
Devil Summoner: Soul Hackers and Shin Megami Tensei: Nine support manual input of stats through named arguments (see the code to know what to use). This is because some of the calculations for Devil Summoner: Soul Hackers and Shin Megami Tensei: Nine are not yet perfect.
Sources
All sources were verified and, if they were wrong, corrected formulas are used in this module.
- Shin Megami Tensei
- Shin Megami Tensei (Mega-CD)
- Shin Megami Tensei II and if...
- Shin Megami Tensei: Devil Summoner
- Devil Summoner: Soul Hackers
--For calculated stats in SMT1, SMT2, SMTif, SMT Devil Summoner, Soul Hackers, Persona 2 IS, Persona 2 EP, SMT Nine, Hazama-hen/20XX
--To do:
--Fix Shin Megami Tensei: Nine accuracy
--Fix Soul Hackers p. hit and m. atk
--Add Persona 2: Eternal Punishment (formulas unknown)
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function round(number)
return math.floor(number + 0.5)
end
local function outputCells(array)
local output = ""
for i, stat in ipairs(array) do
output = output .. "| " .. stat .. "\n"
end
return output:sub(1,-2)
end
function p.smt1(frame)
local args = getArgs(frame)
local platform = nil
if args["platform"] then
platform = string.lower(args["platform"])
end
local level = args["level"] --Level
local strength = args["st"] --Strength
local intelligence = args["in"] --Intelligence
local magic = args["ma"] --Magic
local vitality = args["vi"] --Vitality
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local isBoss = false
if args["boss"] then
isBoss = true
end
local levelMinus19 = math.max(level - 19,0)
local levelMinus20 = math.max(level - 20,0)
local statTable = {
atk = levelMinus19 + (strength * 3) + round(vitality / 4),
acc = round(strength / 4) + agility,
def = round(levelMinus19 / 2) + round(strength / 4) + (vitality * 2),
eva = round(intelligence / 8) + agility,
matk = round(intelligence / 8) + magic,
mefc = intelligence + round(magic / 8),
atkCD2 = levelMinus19 + (strength * 3) + round(vitality / 4),
accCD2 = math.floor(strength / 4) + agility,
defCD2 = round(levelMinus19 / 2) + math.floor(strength / 4) + (vitality * 2),
evaCD2 = round(intelligence / 8) + agility,
matkCD2 = math.floor(intelligence / 8) + magic,
mefcCD2 = intelligence + math.floor(magic / 8),
atkMCD = levelMinus20 + (strength * 3) + math.floor(vitality / 4),
accMCD = math.floor(vitality / 4) + agility,
defMCD = math.floor(levelMinus20 / 2) + math.floor(strength / 4) + (vitality * 3),
evaMCD = round(intelligence / 8) + agility,
matkMCD = round(intelligence / 8) + magic,
mefcMCD = intelligence + round(magic / 8)
}
if isBoss then
statTable["atkMCD"] = levelMinus20 + 1 + (strength * 3) + round(vitality / 4)
statTable["accMCD"] = round(strength / 4) + agility
statTable["defMCD"] = math.floor((levelMinus20 + 1) / 2) + math.floor(strength / 4) + (vitality * 2)
statTable["evaMCD"] = math.floor(intelligence / 8) + agility
statTable["matkMCD"] = math.floor(intelligence / 8) + magic
statTable["mefcMCD"] = intelligence + math.floor(magic / 8)
end
local stats = { "atk", "acc", "def", "eva", "matk", "mefc" }
local function bothPlatsValue(stat)
if platform == "mcd" then
return statTable[stat.."MCD"]
elseif platform == "cd2" then
return statTable[stat.."CD2"]
elseif platform == "sfc" then
return statTable[stat]
elseif statTable[stat] == statTable[stat.."MCD"] and statTable[stat] ~= statTable[stat.."CD2"] then
return frame:expandTemplate{ title = "tt", args = { statTable[stat], "Most versions" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."CD2"], "Super CD-ROM²" } }
elseif statTable[stat] ~= statTable[stat.."MCD"] and statTable[stat] == statTable[stat.."CD2"] then
return frame:expandTemplate{ title = "tt", args = { statTable[stat], "Most versions" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."MCD"], "Mega-CD" } }
elseif statTable[stat] ~= statTable[stat.."MCD"] and statTable[stat] ~= statTable[stat.."CD2"] and statTable[stat.."MCD"] == statTable[stat.."CD2"] then
return frame:expandTemplate{ title = "tt", args = { statTable[stat], "Most versions" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."MCD"], "Super CD-ROM² and Mega-CD" } }
elseif platform ~= nil or (statTable[stat] == statTable[stat.."MCD"] and statTable[stat] == statTable[stat.."CD2"]) then
return statTable[stat]
else
return frame:expandTemplate{ title = "tt", args = { statTable[stat], "Most versions" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."CD2"], "Super CD-ROM²" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."MCD"], "Mega-CD" } }
end
end
local outputStats = {}
for i, stat in ipairs(stats) do --Manual override
table.insert(outputStats,i,bothPlatsValue(stat))
end
return outputCells(outputStats)
end
function p.smt2(frame)
local args = getArgs(frame)
local level = args["level"] --Level
local strength = args["st"] --Strength
local intelligence = args["in"] --Intelligence
local magic = args["ma"] --Magic
local vitality = args["vi"] --Vitality
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local statTable = {
atk = (level + strength) * 2,
acc = math.floor(level * 1.5) + agility + math.floor((strength + luck) / 4),
def = (level + vitality) * 2,
eva = math.floor(level * 1.5) + agility + math.floor((intelligence + luck) / 4),
matk = math.floor(intelligence / 4) + magic,
mefc = intelligence + math.floor(magic / 4)
}
local stats = { "atk", "acc", "def", "eva", "matk", "mefc" }
local outputStats = {}
for i, stat in ipairs(stats) do --Add category
table.insert(outputStats,i,statTable[stat])
end
return outputCells(outputStats)
end
p.smtif = p.smt2
function p.desum(frame)
local args = getArgs(frame)
local level = args["level"] --Level
local strength = args["st"] --Strength
local intelligence = args["in"] --Intelligence
local magic = args["ma"] --Magic
local endurance = args["en"] --Endurance
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local platform = ""
if args["platform"] then
platform = string.lower(args["platform"]) --game platform
end
local isHuman = false
if args["human"] then
isHuman = true
end
local statTable = {
atk = (level + strength) * 2,
acc = math.floor(level * 1.5) + agility + math.floor((strength + luck) / 4),
def = (level + endurance) * 2,
eva = math.floor(level * 1.5) + agility + math.floor((intelligence + luck) / 4),
matk = math.floor(intelligence / 2) + (magic * 2),
mdef = intelligence + math.floor(level / 2) + math.floor(magic / 4) + math.floor(endurance / 2),
mdefPSP = math.floor(intelligence + (level / 2) + (magic / 4) + (endurance / 2))
}
local statTableHuman = { --Not right, but very low priority due to how few people it affects; won't be implemented into template for now.
--swdatk = math.floor(level / 4) + strength,
--swdacc = level + agility + math.floor(luck / 2),
--gunatk = math.floor(level / 4),
--gunacc = level + agility + math.floor(luck / 2),
def = endurance + agility,
eva = level + agility + math.floor((intelligence + luck) / 4),
matk = math.floor(intelligence / 2) + (magic * 2),
mdef = math.floor(intelligence + magic / 4 + agility / 4),
mdefPSP = intelligence + math.floor(magic / 4) + math.floor(agility / 4)
}
local stats = { "atk", "acc", "def", "eva", "matk", "mdef" }
local statsHuman = { "def", "eva", "matk", "mdef" }
if isHuman then
statTable = statTableHuman
stats = statsHuman
end
local function bothPlatsValue(stat)
if args[stat] then --Manual override
return args[stat]
elseif platform == "psp" and statTable[stat.."PSP"] then
return statTable[stat.."PSP"]
elseif platform == "sat" or statTable[stat] == statTable[stat.."PSP"] or not statTable[stat.."PSP"] then
return statTable[stat]
else
return frame:expandTemplate{ title = "tt", args = { statTable[stat], "Sega Saturn" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."PSP"], "PlayStation Portable" } }
end
end
local outputStats = {}
local additionalOutput = ""
for i, stat in ipairs(stats) do
if args[stat] then --Manual override
additionalOutput = "[[Category:Pages with manually input calculated stats]]"
end
table.insert(outputStats,i,bothPlatsValue(stat))
end
return outputCells(outputStats) .. additionalOutput
end
function p.sh1(frame)
local args = getArgs(frame)
local level = args["level"] --Level
local strength = args["st"] --Strength
local intelligence = args["in"] --Intelligence
local magic = args["ma"] --Magic
local endurance = args["en"] --Endurance
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local statTable = {
patk = (level + strength) * 2,
phit = math.floor(level * 1.5) + math.floor((agility * 2 + luck) * 0.6), --Needs work
matk = math.floor(intelligence / 2) * 4 + math.floor(magic * 7.5), --Needs work
mhit = (intelligence + math.floor(magic / 2)) * 2,
def = (level + endurance) * 2 + 16,
eva = math.floor(level * 1.5) + agility + math.floor(luck / 2)
}
local stats = { "patk", "phit", "matk", "mhit", "def", "eva" }
local outputStats = {}
local additionalOutput = ""
for i, stat in ipairs(stats) do
if args[stat] then --Manual override
statTable[stat] = args[stat]
additionalOutput = "[[Category:Pages with manually input calculated stats]]"
end
table.insert(outputStats,i,statTable[stat])
end
return outputCells(outputStats) .. additionalOutput
end
function p.p2is(frame)
local args = getArgs(frame)
local level = args["level"] --Level
local strength = args["st"] --Strength
local vitality = args["vi"] --Vitality
local dexterity = args["dx"] --Dexterity
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local platform = ""
if args["platform"] then
platform = string.lower(args["platform"]) --game platform
end
local statTable = {
atk = (level + strength) * 2,
def = (level + vitality) * 2,
matk = dexterity * 2 + math.floor(level * 0.8),
mdef = math.floor(dexterity * 2.5) + math.floor(vitality / 2),
atkPSP = math.floor(0.7 * ((level + strength) * 2)),
defPSP = math.floor(0.8 * ((level + vitality) * 2)),
matkPSP = math.floor(0.7 * (dexterity * 2 + math.floor(level * 0.8))),
mdefPSP = math.floor(0.8 * (math.floor(dexterity * 2.5) + math.floor(vitality / 2)))
}
local function bothPlatsValue(stat)
if platform == "psp" then
return statTable[stat.."PSP"]
elseif platform == "ps" then
return statTable[stat]
else
return frame:expandTemplate{ title = "tt", args = { statTable[stat], "PlayStation" } } .. "/" .. frame:expandTemplate{ title = "tt", args = { statTable[stat.."PSP"], "PlayStation Portable" } }
end
end
local stats = { "atk", "def", "matk", "mdef" }
local outputStats = {}
for i, stat in ipairs(stats) do
table.insert(outputStats,i,bothPlatsValue(stat))
end
return outputCells(outputStats)
end
function p.smtn(frame)
local args = getArgs(frame)
local level = args["level"] --Level
local strength = args["st"] --Strength
local intelligence = args["in"] --Intelligence
local magic = args["ma"] --Magic
local vitality = args["vi"] --Vitality
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local statTable = {
atk = (level + strength) * 2,
acc = math.floor(level * 1.5) + math.floor(agility * 1.25) + math.floor(luck * 5/8), --Needs work
hit = 1,
pdef = (level + vitality) * 2 + 16,
peva = math.floor(level * 1.5) + agility + math.floor(luck / 2),
matk = level + math.floor(intelligence / 4) + math.floor(intelligence / 8) + magic * 3,
msuc = intelligence + math.floor(magic / 2),
mdef = level + vitality + intelligence * 2 + math.floor(magic/4)
}
local stats = { "atk", "acc", "hit", "pdef", "peva", "matk", "msuc", "mdef" }
local additionalOutput = ""
local outputStats = {}
for i, stat in ipairs(stats) do
if args[stat] then --Manual override
statTable[stat] = args[stat]
if stat ~= "hit" then
additionalOutput = "[[Category:Pages with manually input calculated stats]]"
end
end
table.insert(outputStats,i,statTable[stat])
end
return outputCells(outputStats) .. additionalOutput
end
function p.smt20xx(frame)
local args = getArgs(frame)
local level = args["level"] --Level
local strength = args["st"] --Strength
local intelligence = args["in"] --Intelligence
local magic = args["ma"] --Magic
local vitality = args["vi"] --Vitality
local agility = args["ag"] --Agility
local luck = args["lu"] --Luck
local statTable = {
atk = (level + strength) * 2,
acc = round(level * 1.5 + agility + (strength + luck) / 4),
def = (level + vitality) * 2,
eva = round(level * 1.5 + agility + (intelligence + luck) / 4),
matk = round(intelligence / 4 + magic),
mefc = round(intelligence + magic / 4)
}
local stats = { "atk", "acc", "def", "eva", "matk", "mefc" }
local outputStats = {}
for i, stat in ipairs(stats) do --Add category
table.insert(outputStats,i,statTable[stat])
end
return outputCells(outputStats)
end
p.smtifh = p.smt20xx
return p