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", | ||
effects ="BTD6 effect", | |||
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 | for _, i in ipairs(v["_order"]) do | ||
if k == "subtowers" then tinsert(template[k], sformat(header, | if k == "subtowers" then tinsert(template[k], sformat(header, i)) end | ||
if prev_data[k][ | if prev_data[k][i] == nil then prev_data[k][i] = {} end | ||
-- parse sub-table of table | -- parse sub-table of table | ||
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 | for _, i in ipairs(v["_order"]) do | ||
if prev_data[k][ | 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, | 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 | for _, i in ipairs(v["_order"]) do | ||
if prev_data[k][ | 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, 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 | for _, i in ipairs(v["_order"]) do | ||
if k == "subtowers" then tinsert(template[k], sformat(header, | if k == "subtowers" then tinsert(template[k], sformat(header, i)) end | ||
tinsert(template[k], parse_stats_full(frame, | 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 | ||
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 | for _, i in ipairs(v["_order"]) do | ||
if prev_data[k][ | 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, | 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 | for _, i in ipairs(v["_order"]) do | ||
if prev_data[k][ | 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, | 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 | return parse_tower_base(frame, data["_000"], header, false) | ||
else | else | ||
return | return parse_tower_base(frame, data, header, false) | ||
end | end | ||
else | else | ||
return | 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 = | 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 | |||
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 = { | ||
["_000"] = {{}}, | |||
["_100"] = {{"_110"}, {"_101"}}, | |||
["_200"] = {{"_210", "_220"}, {"_201", "_202"}}, | |||
["_010"] = {{"_110"}, {"_011"}}, | |||
["_020"] = {{"_120", "_220"}, {"_021", "_022"}}, | |||
["_001"] = {{"_101"}, {"_011"}}, | |||
["_002"] = {{"_102", "_202"}, {"_012", "_022"}}, | |||
["_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 | 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) | ||
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 | 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 | ||