Module:BTD6 stats: Difference between revisions

mNo edit summary
Pymonkibot (talk | contribs)
m Text replacement - "[[Bloons TD 6 v" to "[[Update history:Bloons TD 6/Version "
 
(52 intermediate revisions by 2 users not shown)
Line 11: Line 11:


local template_names = {
local template_names = {
attacks = "BTD6 attack",
attacks ="BTD6 attack",
projectiles = "BTD6 projectile",
projectiles ="BTD6 projectile",
abilities = "BTD6 ability",
collectables="BTD6 collectable",
effects = "BTD6 effect",
abilities ="BTD6 ability",
zones = "BTD6 zone",
effects ="BTD6 effect",
subtowers = "BTD6 tower",
buffs ="BTD6 buff",
buffs = "BTD6 buff"
zones ="BTD6 zone",
subtowers ="BTD6 tower"
}
}
local function parse_beast_table(data, tiers)
local ret = {"\n{|class='wikitable mw-collapsible mw-collapsed'\n|+style='white-space:nowrap'|Beast Power-dependent stats"}
-- local functions to improve performance
local tconcat = table.concat
local sformat = string.format
local msqrt = math.sqrt
local mfloor = math.floor
-- -- -- -- -- --
-- CREATE HEADING
-- -- -- -- -- --
local headingUpper = {}
local upperColspans = {}
local headingLower = {}
local headingEffects = function(effects)
for i, v in ipairs(effects["_order"]) do
local effect = effects[v]
local amount = 0
if v == "Knockback" and effect.lifespan then headingLower[#headingLower+1] = "Lifespan" amount = amount + 1 end
if amount > 0 then
headingUpper[#headingUpper+1] = v
upperColspans[#upperColspans+1] = amount
end
end
end
local headingProjectiles = function(projectiles)
for i, v in ipairs(projectiles["_order"]) do
local projectile = projectiles[v]
local amount = 0
if projectile["maxPierce"]<1 and projectile["pierce"]<99999 then headingLower[#headingLower+1] = "Pierce" amount = amount + 1 end
if projectile["damage"]~=nil and projectile["damage"]>0 then headingLower[#headingLower+1] = "Damage" amount = amount + 1 end
if projectile["damageModifierForStunned"]~=nil then headingLower[#headingLower+1] = "Damage to stunned" amount = amount + 1 end
if amount > 0 then
headingUpper[#headingUpper+1] = v
upperColspans[#upperColspans+1] = amount
end
end
end
local headingAttacks = function(attacks)
for i, v in ipairs(attacks["_order"]) do
local attack = attacks[v]
local amount = 0
if attack.rate and attack.rate < 9999 and not attack.rateMin then headingLower[#headingLower+1] = "Cooldown" amount = amount + 1 end
if attack.initialDamage and attack.initialDamage > 0 then headingLower[#headingLower+1] = "Scratch damage" amount = amount + 1 end
if attack.grapplingDamage and attack.grapplingDamage > 0 then headingLower[#headingLower+1] = "Grappling damage" amount = amount + 1 end
if attack.thrashingProjectileRate then headingLower[#headingLower+1] = "Thrash cooldown" amount = amount + 1 end
if amount > 0 then
headingUpper[#headingUpper+1] = v
upperColspans[#upperColspans+1] = amount
end
-- projectiles
if attack.projectiles then headingProjectiles(attack.projectiles) end
end
end
local headingAbilities = function(abils)
for i, v in ipairs(abils["_order"]) do
local abil = abils[v]
local amount = 0
if abil.cooldown then headingLower[#headingLower+1] = "Cooldown" amount = amount + 1 end
if amount > 0 then
headingUpper[#headingUpper+1] = v
upperColspans[#upperColspans+1] = amount
end
-- projectiles
if abil.projectiles then headingProjectiles(abil.projectiles) end
end
end
local minPower = {
["_002"] = 3,
["_003"] = 8,
["_004"] = 16,
["_005"] = 36,
["_020"] = 3,
["_030"] = 8,
["_040"] = 16,
["_050"] = 36,
["_200"] = 3,
["_300"] = 8,
["_400"] = 16,
["_500"] = 36
}
local maxPower = {
["_200"] = 6,
["_300"] = 24,
["_400"] = 64,
["_500"] = 132,
["_020"] = 6,
["_030"] = 24,
["_040"] = 64,
["_050"] = 132,
["_002"] = 6,
["_003"] = 24,
["_004"] = 64,
["_005"] = 132
}
-- insert headings
if data.speedRangeGyrfalcon > 0 then
headingLower[#headingLower+1] = "Flight speed"
headingUpper[#headingUpper+1]= "Beast"
upperColspans[#upperColspans+1] = 1
end
if data.attacks then headingAttacks(data.attacks) end
if data.abilities then headingAbilities(data.abilities) end
ret[#ret+1] = "!rowspan=2|Power!!rowspan=2|Scale"
for i, v in ipairs(headingUpper) do
ret[#ret+1] = sformat("!colspan=%i|%s", upperColspans[i], v)
end
ret[#ret+1] = "|-\n!" .. table.concat(headingLower, "!!")
-- -- -- -- -- -- --
-- CALCULATE STATS
-- -- -- -- -- -- --
-- current scale
local scale
-- attack cooldown
local insertRate = function(amt)
ret[#ret+1] = sformat("| %.4gs", amt - (data.cooldownScaleRange*scale))
end
-- thrash cooldown
local insertThrashRate = function(amt, thrashRate)
ret[#ret+1] = sformat("| %.4gs", (1 - data.cooldownScaleRange*scale/amt) * thrashRate)
end
-- ability cooldown
local insertAbilityCooldown = function(amt, mainAttackRate)
ret[#ret+1] = sformat("|%.4gs", amt * (1 - (data.cooldownScaleRange*scale/(mainAttackRate - (data.cooldownScaleRange*scale)))))
end
-- damage
local insertDamage = function(amt)
ret[#ret+1] = sformat("|%i", amt + mfloor(data.damageRange*scale))
end
-- dino stun damage
local insertStunDamage = function(amt)
ret[#ret+1] = sformat("|%i", amt + mfloor(data.damageRange*scale/data.stunBonusDivideMicroraptor))
end
-- pierce
local insertPierce = function(amt)
ret[#ret+1] = sformat("|%i", amt + mfloor(data.pierceRange*scale))
end
-- thrash knockback duration
local insertKnockback = function(amt)
ret[#ret+1] = sformat("|%.4gs", amt + (data.thrashKnockbackLifetimeRange*scale))
end
-- bird flight speed
local insertGyrfalconSpeed = function()
ret[#ret+1] = sformat("|%.4g units/s", data.speed + (data.speedRangeGyrfalcon*scale))
end
local parseEffects = function(effects)
for i, v in ipairs(effects["_order"]) do
local effect = effects[v]
if v == "Knockback" and effect.duration then insertKnockback(effect.lifespan) end
end
end
local parseProjectiles = function(projectiles)
for i, v in ipairs(projectiles["_order"]) do
local projectile = projectiles[v]
if projectile.maxPierce < 1 and projectile.pierce < 99999 then insertPierce(projectile.pierce) end
if projectile.damage and projectile.damage > 0 then insertDamage(projectile.damage) end
if projectile.damageModifierForStunned then insertStunDamage(projectile.damageModifierForStunned) end
if projectile.effects then parseEffects(projectile.effects) end
end
end
local parseAttacks = function(attacks)
for i, v in ipairs(attacks["_order"]) do
local attack = attacks[v]
if attack.rate and attack.rate < 9999 and not attack.rateMin then insertRate(attack.rate) end
if attack.initialDamage and attack.initialDamage > 0 then insertDamage(attack.initialDamage) end
if attack.grapplingDamage and attack.grapplingDamage > 0 then insertDamage(attack.initialDamage) end
if attack.thrashingProjectileRate then insertThrashRate(attack.rate, attack.thrashingProjectileRate) end
-- projectiles
if attack.projectiles then parseProjectiles(attack.projectiles) end
end
end
local parseAbilities = function(abils)
for i, v in ipairs(abils["_order"]) do
local abil = abils[v]
local attackRate = data.attacks["Attack"].rate
-- rate
insertAbilityCooldown(abil.cooldown, attackRate)
if abil.projectiles ~= nil then parseProjectiles(abil.projectiles) end
end
end
for i = minPower[tiers], maxPower[tiers] do
scale = ((i - minPower[tiers]) / (maxPower[tiers] - minPower[tiers]))
ret[#ret+1] = sformat("|-\n!%i\n|%.4g%%", i, scale*100)
-- calculations
if data.speedRangeGyrfalcon > 0 then insertGyrfalconSpeed() end
if data.attacks then parseAttacks(data.attacks) end
if data.abilities then parseAbilities(data.abilities) end
end
ret[#ret+1] = "|}"
return table.concat(ret, "\n")
end
function parse_paragon_table(data)
local ret = {"\n{|class='wikitable mw-collapsible mw-collapsed'\n|+style='white-space:nowrap'|Degree-dependent stats"}
-- local functions to improve performance
local tinsert = table.insert
local tconcat = table.concat
local sformat = string.format
local msqrt = math.sqrt
local mfloor = math.floor
local degree_requirements = {
0,      2000,  2324,  2666,  3027,  3408,  3808,  4228,  4669,  5131,
5615,  6121,  6650,  7203,  7779,  8379,  9004,  9654,  10330,  11032,
11761,  12518,  13302,  14114,  14955,  15825,  16725,  17655,  18616,  19609,
20633,  21689,  22778,  23900,  25056,  26246,  27471,  28732,  30028,  31360,
32729,  34135,  35579,  37061,  38582,  40143,  41743,  43383,  45064,  46786,
48550,  50356,  52205,  54098,  56034,  58014,  60039,  62109,  64225,  66387,
68596,  70853,  73157,  75509,  77910,  80360,  82860,  85410,  88011,  90664,
93368,  96124,  98933,  101795, 104711, 107681, 110706, 113787, 116923, 120115,
123364, 126670, 130034, 133456, 136937, 140478, 144078, 147738, 151459, 155241,
159085, 162991, 166960, 170993, 175089, 179249, 183474, 187764, 192120, 200000
}
-- -- -- -- -- --
-- CREATE HEADING
-- -- -- -- -- --
local heading_upper = {}
local upper_colspans = {}
local heading_lower = {}
local heading_effects = function(effects)
for i, v in ipairs(effects["_order"]) do
local effect = effects[v]
local amount = 0
if effect["damage"]~=nil then tinsert(heading_lower, "Damage") amount = amount + 1 end
if effect["damageModifierForBoss"]~=nil then tinsert(heading_lower, "Damage to bosses") amount = amount + 1 end
if effect["damageModifierForMoabs"]~=nil then tinsert(heading_lower, "Damage to MOAB-Class") amount = amount + 1 end
if effect["damageModifierForCeramic"]~=nil then tinsert(heading_lower, "Damage to Ceramic") amount = amount + 1 end
if effect["damageModifierForCamo"]~=nil then tinsert(heading_lower, "Damage to Camo") amount = amount + 1 end
if effect["damageModifierForStunned"]~=nil then tinsert(heading_lower, "Damage to stunned") amount = amount + 1 end
if effect["damageModifierForStickied"]~=nil then tinsert(heading_lower, "Damage to stickied") amount = amount + 1 end
if amount > 0 then
tinsert(heading_upper, v)
tinsert(upper_colspans, amount)
end
end
end
local heading_projectiles = function(projectiles)
for i, v in ipairs(projectiles["_order"]) do
local projectile = projectiles[v]
local amount = 0
if projectile["maxPierce"]<1 and projectile["pierce"]<99999 then tinsert(heading_lower, "Pierce") amount = amount + 1 end
if projectile["damage"]~=nil and projectile["damage"]>0 then tinsert(heading_lower, "Damage") amount = amount + 1 end
if projectile["damageModifierForBoss"]~=nil then tinsert(heading_lower, "Damage to bosses") amount = amount + 1 end
if projectile["damageModifierForMoabs"]~=nil then tinsert(heading_lower, "Damage to MOAB-Class") amount = amount + 1 end
if projectile["damageModifierForCeramic"]~=nil then tinsert(heading_lower, "Damage to Ceramic") amount = amount + 1 end
if projectile["damageModifierForCamo"]~=nil then tinsert(heading_lower, "Damage to Camo") amount = amount + 1 end
if projectile["damageModifierForStunned"]~=nil then tinsert(heading_lower, "Damage to stunned") amount = amount + 1 end
if projectile["damageModifierForStickied"]~=nil then tinsert(heading_lower, "Damage to stickied") amount = amount + 1 end
if amount > 0 then
tinsert(heading_upper, v)
tinsert(upper_colspans, amount)
end
if projectile["effects"] ~= nil then heading_effects(projectile["effects"]) end
end
end
local heading_attacks = function(attacks)
for i, v in ipairs(attacks["_order"]) do
local attack = attacks[v]
-- rate
if attack["rate"] ~= nil and attack["rate"] < 9999 and attack["rateMin"] == nil then
tinsert(heading_lower, "Cooldown")
tinsert(heading_upper, v)
tinsert(upper_colspans, 1)
end
-- projectiles
if attack["projectiles"] ~= nil then heading_projectiles(attack["projectiles"]) end
end
end
local heading_abilities = function(abils)
for i, v in ipairs(abils["_order"]) do
local abil = abils[v]
-- rate
tinsert(heading_lower, "Cooldown")
tinsert(heading_upper, v)
tinsert(upper_colspans, 1)
if abil["projectiles"] ~= nil then heading_projectiles(abil["projectiles"]) end
if abil["attacks"] ~= nil then heading_attacks(abil["attacks"]) end
end
end
-- insert headings
if data["projectiles"] ~= nil then heading_attacks(data["projectiles"]) end
if data["attacks"] ~= nil then heading_attacks(data["attacks"]) end
if data["abilities"] ~= nil then heading_abilities(data["abilities"]) end
if data["zones"] ~= nil then heading_effects(data["zones"]) end
tinsert(ret, "!rowspan=2|Degree\n!rowspan=2|Power\n!rowspan=2|Boss multiplier")
for i, v in ipairs(heading_upper) do
tinsert(ret, sformat("!colspan=%i|%s", upper_colspans[i], v))
end
tinsert(ret, "|-\n!" .. table.concat(heading_lower, "!!"))
-- -- -- -- -- -- --
-- CALCULATE STATS
-- -- -- -- -- -- --
-- current degree
local d = 1
-- attack cooldowns and ability cooldowns
local insert_rate = function(amt)
tinsert(ret, sformat("|%.4gs", amt / (1 + (0.01 * msqrt((d-1)*50)))))
end
-- damage
local insert_damage = function(amt)
if d == 100 then tinsert(ret, sformat("|%.4g", amt * 2 + 10))
else tinsert(ret, sformat("|%.4g", amt * (1 + (d-1) * 0.01) + mfloor((d-1)/10))) end
end
-- pierce
local insert_pierce = function(amt)
if d == 100 then tinsert(ret, sformat("|%.4g", amt * 2 + 10))
else tinsert(ret, sformat("|%.4g", mfloor(amt * (1 + (d-1) * 0.01)) + (d-1)/10)) end
end
-- damage modifiers
local insert_damage_mod = function(amt)
if d == 100 then tinsert(ret, sformat("| +%.4g", amt * 2 + 10))
else tinsert(ret, sformat("| +%.4g", amt * (1 + (d-1) * 0.01))) end
end
local parse_effects = function(effects)
for i, v in ipairs(effects["_order"]) do
local effect = effects[v]
if effect["damage"]~=nil then insert_damage(effect["damage"]) end
if effect["damageModifierForBoss"]~=nil then insert_damage_mod(effect["damageModifierForBoss"]) end
if effect["damageModifierForMoabs"]~=nil then insert_damage_mod(effect["damageModifierForMoabs"]) end
if effect["damageModifierForCeramic"]~=nil then insert_damage_mod(effect["damageModifierForCeramic"]) end
if effect["damageModifierForCamo"]~=nil then insert_damage_mod(effect["damageModifierForCamo"]) end
if effect["damageModifierForStunned"]~=nil then insert_damage_mod(effect["damageModifierForStunned"]) end
if effect["damageModifierForStickied"]~=nil then insert_damage_mod(effect["damageModifierForStickied"]) end
end
end
local parse_projectiles = function(projectiles)
for i, v in ipairs(projectiles["_order"]) do
local projectile = projectiles[v]
if projectile["maxPierce"]<1 and projectile["pierce"]<99999 then insert_pierce(projectile["pierce"]) end
if projectile["damage"]~=nil and projectile["damage"]>0 then insert_damage(projectile["damage"]) end
if projectile["damageModifierForBoss"]~=nil then insert_damage_mod(projectile["damageModifierForBoss"]) end
if projectile["damageModifierForMoabs"]~=nil then insert_damage_mod(projectile["damageModifierForMoabs"]) end
if projectile["damageModifierForCeramic"]~=nil then insert_damage_mod(projectile["damageModifierForCeramic"]) end
if projectile["damageModifierForCamo"]~=nil then insert_damage_mod(projectile["damageModifierForCamo"]) end
if projectile["damageModifierForStunned"]~=nil then insert_damage_mod(projectile["damageModifierForStunned"]) end
if projectile["damageModifierForStickied"]~=nil then insert_damage_mod(projectile["damageModifierForStickied"]) end
if projectile["effects"] ~= nil then parse_effects(projectile["effects"]) end
end
end
local parse_attacks = function(attacks)
for i, v in ipairs(attacks["_order"]) do
local attack = attacks[v]
-- rate
if attack["rate"] ~= nil and attack["rate"] < 9999 and attack["rateMin"] == nil then
insert_rate(attack["rate"])
end
-- projectiles
if attack["projectiles"] ~= nil then parse_projectiles(attack["projectiles"]) end
end
end
local parse_abilities = function(abils)
for i, v in ipairs(abils["_order"]) do
local abil = abils[v]
-- rate
insert_rate(abil["cooldown"])
if abil["projectiles"] ~= nil then parse_projectiles(abil["projectiles"]) end
if abil["attacks"] ~= nil then parse_attacks(abil["attacks"]) end
end
end
-- degree loop
while d <= 100 do
-- new row
tinsert(ret, sformat("|-\n!%i\n|%i", d, degree_requirements[d]))
-- boss damage mult
if d < 20 then tinsert(ret, "|×1.0")
elseif d < 40 then tinsert(ret, "|×1.25")
elseif d < 60 then tinsert(ret, "|×1.5")
elseif d < 80 then tinsert(ret, "|×1.75")
elseif d ~= 100 then tinsert(ret, "|×2.0")
else tinsert(ret, "|×2.25") end
-- calculations
if data["projectiles"] ~= nil then parse_attacks(data["projectiles"]) end
if data["attacks"] ~= nil then parse_attacks(data["attacks"]) end
if data["abilities"] ~= nil then parse_abilities(data["abilities"]) end
if data["zones"] ~= nil then parse_effects(data["zones"]) end
d = d + 1
end
tinsert(ret, "|}")
return table.concat(ret, "\n")
end
function parse_tower_base(frame, data, header, paragon)
local template = {}
-- local functions to improve performance
local tinsert = table.insert
local tconcat = table.concat
local sformat = string.format
local ssub = string.sub
-- search through tables
for k, v in pairs(data) do
if type(v) == "table" and ssub(k, 1, 1) ~= "_" then
template[k] = {}
-- iterate through attacks/abilities/subtowers
for _, i in ipairs(v["_order"]) do
if k == "subtowers" then tinsert(template[k], sformat(header, i)) end
-- parse sub-table of table
local stats = parse_stats_base(frame, i, v[i], template_names[k])
if k == "subtowers" and paragon then stats = stats .. parse_paragon_table(v[i]) end
tinsert(template[k], stats)
end
template[k] = tconcat(template[k])
elseif type(v) ~= "table" then
template[k] = data[k]
end
end
if paragon then template["paragon stats"] = parse_paragon_table(data) end
return frame:expandTemplate{title = "BTD6 tower", args = template}
end
function parse_stats_base(frame, name, data, template_name)
local template = {name = name}
-- local functions to improve performance
local tinsert = table.insert
local tconcat = table.concat
-- search through tables
for k, v in pairs(data) do
if type(v) == "table" then
template[k] = {}
-- iterate through attacks/abilities/subtowers
for _, i in ipairs(v["_order"]) do
-- parse sub-table of table
tinsert(template[k], parse_stats_base(frame, i, v[i], template_names[k]))
end
template[k] = tconcat(template[k])
else
template[k] = v
end
end
return frame:expandTemplate{title = template_name, args = template}
end


function parse_tower(frame, new_data, prev_data, header)
function parse_tower(frame, new_data, prev_data, header)
Line 33: Line 564:
if type(v) == "table" and ssub(k, 1, 1) ~= "_" then
if type(v) == "table" and ssub(k, 1, 1) ~= "_" then
template[k] = {}
template[k] = {}
if prev_data[k] == nil then prev_data[k] = {} end
if prev_data[k] == nil then prev_data[k] = {} end
-- iterate through attacks/abilities/subtowers
-- iterate through attacks/abilities/subtowers
for kk, vv in pairs(v) do
for _, i in ipairs(v["_order"]) do
if k == "subtowers" then tinsert(template[k], sformat(header, kk)) end
if k == "subtowers" then tinsert(template[k], sformat(header, i)) end
if prev_data[k][kk] == nil then prev_data[k][kk] = {} end
if prev_data[k][i] == nil then prev_data[k][i] = {} end
-- parse sub-table of table
-- parse sub-table of table
tinsert(template[k], parse_stats(frame, kk, vv, prev_data[k][kk], template_names[k]))
local stats = parse_stats(frame, i, v[i], prev_data[k][i], template_names[k])
tinsert(template[k], stats)
end
end
Line 78: Line 610:
-- iterate through attacks/abilities/subtowers
-- iterate through attacks/abilities/subtowers
for kk, vv in pairs(v) do
for _, i in ipairs(v["_order"]) do
if prev_data[k][kk] == nil then prev_data[k][kk] = {} end
if prev_data[k][i] == nil then prev_data[k][i] = {} end
-- parse sub-table of table
-- parse sub-table of table
tinsert(template[k], parse_stats(frame, kk, vv, prev_data[k][kk], template_names[k]))
tinsert(template[k], parse_stats(frame, i, v[i], prev_data[k][i], template_names[k]))
end
end
Line 116: Line 648:
if type(v) == "table" and ssub(k, 1, 1) ~= "_" then
if type(v) == "table" and ssub(k, 1, 1) ~= "_" then
if template[k] == nil then template[k] = {} end
if template[k] == nil then template[k] = {} end
if prev_data[k] == nil then prev_data[k] = {} end
if prev_data[k] == nil then prev_data[k] = {} end
if prev_data[k]["_order"] == nil then
prev_data[k]["_order"] = {}
prev_data[k]["_keys"] = {}
end
-- iterate through attacks/abilities/subtowers
-- iterate through attacks/abilities/subtowers
for kk, vv in pairs(v) do
for _, i in ipairs(v["_order"]) do
if prev_data[k][kk] == nil then prev_data[k][kk] = {} end
if prev_data[k][i] == nil then prev_data[k][i] = {} end
if prev_data[k]["_keys"][i] == nil then
tinsert(prev_data[k]["_order"], i)
prev_data[k]["_keys"][i] = true
end
-- parse sub-table of table
-- parse sub-table of table
parse_stats_full(frame, kk, vv, prev_data[k][kk], template_names[k])
parse_stats_full(frame, i, v[i], prev_data[k][i], template_names[k])
end
end
Line 138: Line 677:
-- iterate through attacks/abilities/subtowers
-- iterate through attacks/abilities/subtowers
for kk, vv in pairs(v) do
for _, i in ipairs(v["_order"]) do
if k == "subtowers" then tinsert(template[k], sformat(header, kk)) end
if k == "subtowers" then tinsert(template[k], sformat(header, i)) end
tinsert(template[k], parse_stats_full(frame, kk, nil, vv, template_names[k]))
tinsert(template[k], parse_stats_full(frame, i, nil, v[i], template_names[k]))
end
end
Line 165: Line 704:
for k, v in pairs(new_data) do
for k, v in pairs(new_data) do
if type(v) == "table" then
if type(v) == "table" then
mw.logObject(k)
if prev_data[k] == nil then prev_data[k] = {} end
if prev_data[k] == nil then prev_data[k] = {} end
if prev_data[k]["_order"] == nil then
prev_data[k]["_order"] = {}
prev_data[k]["_keys"] = {}
end
-- iterate through attacks/abilities/subtowers
-- iterate through attacks/abilities/subtowers
for kk, vv in pairs(v) do
for _, i in ipairs(v["_order"]) do
if prev_data[k][kk] == nil then prev_data[k][kk] = {} end
if prev_data[k][i] == nil then prev_data[k][i] = {} end
if prev_data[k]["_keys"][i] == nil then
tinsert(prev_data[k]["_order"], i)
prev_data[k]["_keys"][i] = true
end
-- parse sub-table of table
-- parse sub-table of table
parse_stats_full(frame, kk, vv, prev_data[k][kk], template_names[k])
parse_stats_full(frame, i, v[i], prev_data[k][i], template_names[k])
end
end
Line 186: Line 732:
-- iterate through attacks/abilities/subtowers
-- iterate through attacks/abilities/subtowers
for kk, vv in pairs(v) do
for _, i in ipairs(v["_order"]) do
if prev_data[k][kk] == nil then prev_data[k][kk] = {} end
if prev_data[k][i] == nil then prev_data[k][i] = {} end
-- parse sub-table of table
-- parse sub-table of table
tinsert(template[k], parse_stats_full(frame, kk, nil, vv, template_names[k]))
tinsert(template[k], parse_stats_full(frame, i, nil, v[i], template_names[k]))
end
end
Line 204: Line 750:
-- stats of a single tower
-- stats of a single tower
function p.base_stats(frame)
function p.base_stats(frame)
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s", frame.args[1]))
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s/new", frame.args[1]))
local header_level = frame.args["header level"] ~= nil and frame.args["header level"] or "3"
local header_level = frame.args["header level"] ~= nil and frame.args["header level"] or "3"
local header = "<h" .. header_level .. ">%s</h" .. header_level .. ">"
local header = "<h" .. header_level .. ">%s</h" .. header_level .. ">"
Line 210: Line 756:
if frame.args[2] == nil then
if frame.args[2] == nil then
if data["_000"] ~= nil then
if data["_000"] ~= nil then
return parse_tower(frame, data["_000"], my_data, header)
return parse_tower_base(frame, data["_000"], header, false)
else
else
return parse_tower(frame, data, my_data, header)
return parse_tower_base(frame, data, header, false)
end
end
else
else
return parse_tower(frame, data["_" .. frame.args[2]], my_data, header)
return parse_tower_base(frame, data["_" .. frame.args[2]], header, false)
end
end
end
end
Line 221: Line 767:
-- stats of a paragon
-- stats of a paragon
function p.paragon(frame)
function p.paragon(frame)
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s", frame.args[1]))
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s/new", frame.args[1]))
local out = parse_tower(frame, data, my_data, "<h3>%s</h3>")
local out = parse_tower_base(frame, data, "<h3>%s</h3>", true)
return string.format("<div class='hatnote'>This data was last updated for: [[Bloons TD 6 v%s|version %s]]</div>", data["_last_updated"], data["_last_updated"]) .. out
return string.format("<div class='hatnote'>This data was last updated for: [[Update history:Bloons TD 6/Version %s|version %s]]</div>", data["_last_updated"], data["_last_updated"]) .. out
end
end


-- stat changes of a tower
-- stat changes of a tower
function p.tower_upgrade_stats(frame)
function p.tower_upgrade_stats(frame)
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s", frame.args[1]))
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s/new", frame.args[1]))
local ret = {}
local ret = {}
Line 241: Line 788:
local upgrade_crosspaths = {
local upgrade_crosspaths = {
--["100"] = {{"_110", "_120", "_130", "_140", "_150"}, {"_101", "_102", "_103", "_104", "_105"}},
["_000"] = {{}},
--["200"] = {{"_210", "_220", "_230", "_240", "_250"}, {"_201", "_202", "_203", "_204", "_205"}},
["_100"] = {{"_110"}, {"_101"}},
--["010"] = {{"_110", "_210", "_310", "_410", "_510"}, {"_011", "_012", "_013", "_014", "_015"}},
["_200"] = {{"_210", "_220"}, {"_201", "_202"}},
--["020"] = {{"_120", "_220", "_320", "_420", "_520"}, {"_021", "_022", "_023", "_024", "_025"}},
["_010"] = {{"_110"}, {"_011"}},
--["001"] = {{"_101", "_201", "_301", "_401", "_501"}, {"_011", "_021", "_031", "_041", "_051"}},
["_020"] = {{"_120", "_220"}, {"_021", "_022"}},
--["002"] = {{"_102", "_202", "_302", "_402", "_502"}, {"_012", "_022", "_032", "_042", "_052"}},
["_001"] = {{"_101"}, {"_011"}},
["_100"] = {{}},
["_002"] = {{"_102", "_202"}, {"_012", "_022"}},
["_200"] = {{}},
["_010"] = {{}},
["_020"] = {{}},
["_001"] = {{}},
["_002"] = {{}},
["_300"] = {{"_310", "_320"}, {"_301", "_302"}},
["_300"] = {{"_310", "_320"}, {"_301", "_302"}},
["_400"] = {{"_410", "_420"}, {"_401", "_402"}},
["_400"] = {{"_410", "_420"}, {"_401", "_402"}},
Line 264: Line 806:
}
}
tinsert(ret, sformat("<div class='hatnote'>This data was last updated for: [[Bloons TD 6 v%s|version %s]]</div>", data["_last_updated"], data["_last_updated"]))
tinsert(ret, sformat("<div class='hatnote'>This data was last updated for: [[Update history:Bloons TD 6/Version %s|version %s]]</div>", data["_last_updated"], data["_last_updated"]))
for i, v in ipairs(upgrade_crosspaths[frame.args[2]]) do
for i, v in ipairs(upgrade_crosspaths[frame.args[2]]) do
local result = parse_tower(frame, base_data, my_data, "<h3>%s</h3>")
my_data = {}
local result = parse_tower(frame, base_data, my_data, "<h3>%s</h3>", false)
-- inject beast handler stats table
if frame.args[1] == "Beast Handler" and not (frame.args[2] == "_000" or frame.args[2] == "_100" or frame.args[2] == "_010" or frame.args[2] == "_001") then
result = result .. parse_beast_table(base_data.subtowers.Beast, frame.args[2])
end
if i == 1 then tinsert(ret, result) end
if i == 1 then tinsert(ret, result) end
for ii, vv in ipairs(v) do
for ii, vv in ipairs(v) do
if base_data[vv] ~= nil then
if base_data[vv] ~= nil then
tinsert(ret, sformat("<h3>%s-%s-%s</h3>", ssub(vv, 2, 2), ssub(vv, 3, 3), ssub(vv, 4, 4)))
local crosspath = parse_tower(frame, base_data[vv], my_data, "<h4>%s</h4>", false)
tinsert(ret, parse_tower(frame, base_data[vv], my_data, "<h4>%s</h4>"))
if mw.text.trim(crosspath) ~= [[
]] then
tinsert(ret, sformat("<h3>%s-%s-%s</h3>", ssub(vv, 2, 2), ssub(vv, 3, 3), ssub(vv, 4, 4)))
tinsert(ret, crosspath)
end
end
end
end
end
Line 282: Line 835:
-- stat changes of a hero
-- stat changes of a hero
function p.hero_level_changes(frame)
function p.hero_level_changes(frame)
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s", frame.args[1]))
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s/new", frame.args[1]))
local ret = {}
local ret = {}
Line 291: Line 844:
-- calculate base tower stats for later comparison
-- calculate base tower stats for later comparison
parse_tower(frame, data, my_data, "<h3>%s</h3>")
parse_tower(frame, data, my_data, "<h3>%s</h3>", false)
for i = 2, 20 do
for i = 2, 20 do
tinsert(ret, sformat("===Level %i===", i))
tinsert(ret, sformat("===Level %i===", i))
tinsert(ret, parse_tower(frame, data["_" .. i], my_data, "<h4>%s</h4>"))
tinsert(ret, parse_tower(frame, data["_" .. i], my_data, "<h4>%s</h4>", false))
end
end
Line 303: Line 856:
-- stat changes of a hero
-- stat changes of a hero
function p.hero_level_stats(frame)
function p.hero_level_stats(frame)
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s", frame.args[1]))
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s/new", frame.args[1]))
local ret = {}
local ret = {}
Line 312: Line 865:
-- calculate base tower stats for later comparison
-- calculate base tower stats for later comparison
parse_tower(frame, data, my_data, "<h3>%s</h3>")
parse_tower(frame, data, my_data, "<h3>%s</h3>", false)
for i = 2, 20 do
for i = 2, 20 do
tinsert(ret, sformat("===Level %i===", i))
tinsert(ret, sformat("===Level %i===", i))
tinsert(ret, parse_tower_full(frame, data["_" .. i], my_data, "<h4>%s</h4>"))
tinsert(ret, parse_tower_full(frame, data["_" .. i], my_data, "<h4>%s</h4>", false))
end
end
Line 323: Line 876:


function p.last_updated(frame)
function p.last_updated(frame)
return string.format("<div class='hatnote'>This data was last updated for: [[Bloons TD 6 v%s|version %s]]</div>", data["_last_updated"], data["_last_updated"])
local data = mw.loadJsonData(string.format("Module:BTD6 stats/%s/new", frame.args[1]))
return string.format("<div class='hatnote'>This data was last updated for: [[Update history:Bloons TD 6/Version %s|version %s]]</div>", data["_last_updated"], data["_last_updated"])
end
end


return p
return p