Module:BTD6 hero xp: Difference between revisions

From Blooncyclopedia, the independent Bloons knowledge base
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
-- This code is copyrighted and available under the Creative Commons Attribution-NonCommercial-ShareAlike International license, version 4.0. You may use and adapt this code if:
-- * You give appropriate credit
-- * You are not using this material for commercial purposes
-- * You are releasing it under the same license
-- Further information: https://www.bloonswiki.com/Blooncyclopedia:Copyrights
-- By editing this code, you agree to release your changes under the same terms.
local p = {}
local p = {}
local lang = mw.language.new("en")
local mFloor = math.floor
local mFloor = math.floor


Line 13: Line 5:
local floored = mFloor(num)
local floored = mFloor(num)
return floored + ((num - floored == 0.5) and 1 or 0)
return floored + ((num - floored >= 0.5) and 1 or 0)
end
end


function _main(curve)
function Main(curve)
local level_reqs = { 180, 460, 1000, 1860, 3280, 5180, 8320, 9380, 13620, 16380, 14400, 16650, 14940, 16380, 17820, 19260, 20700, 16470, 17280 }
local levelReqs = { 180, 460, 1000, 1860, 3280, 5180, 8320, 9380, 13620, 16380, 14400, 16650, 14940, 16380, 17820, 19260, 20700, 16470, 17280 }
local xp_modifiers = { 1, 1.1, 1.2, 1.3, 1 * 1.1 * 1.05 * 1.08, 1.1 * 1.1 * 1.05 * 1.08, 1.2 * 1.1 * 1.05 * 1.08, 1.3 * 1.1 * 1.05 * 1.08 }
local xpModifiers = { 1, 1.1, 1.2, 1.3, 1 * 1.1 * 1.05 * 1.08, 1.1 * 1.1 * 1.05 * 1.08, 1.2 * 1.1 * 1.05 * 1.08, 1.3 * 1.1 * 1.05 * 1.08 }
local wikitable = {
local wikitable = {
'<div class="hatnote">Note: the number of rounds to level up assumes the Hero is placed on round 1 and no other Heroes are placed.</div>\n{|class="wikitable" style="text-align:center"\n!rowspan="2"|Level!!rowspan="2"|XP required!!colspan="4"|Rounds to level up!!colspan="4"|Rounds to level up w/ [[File:BTD6_mk_MonkeyEducationIcon.png|x20px|link=Monkey Education]][[File:BTD6_mk_SelfTaughtHeroesIcon.png|x20px|link=Self Taught Heroes]][[File:BTD6_mk_MonkeysStrongerTogetherIcon.png|x20px|link=Monkeys Together Strong]][[File:BTD6_mk_EmpoweredHeroesIcon.png|x20px|link=Empowered Heroes]]\n|-\n![[Beginner]]!![[Intermediate]]!![[Advanced]]!![[Expert]]!![[Beginner]]!![[Intermediate]]!![[Advanced]]!![[Expert]]'
'<div class="hatnote">Note: the number of rounds to level up assumes the Hero was placed on round 1 and there are no other Heroes on the map.</div>\n{|class="wikitable" style="text-align:center"\n!rowspan="2"|Level!!rowspan="2"|XP required!!colspan="4"|Rounds to level up!!colspan="4"|Rounds to level up w/ [[File:BTD6_mk_MonkeyEducationIcon.png|x20px|link=Monkey Education]][[File:BTD6_mk_SelfTaughtHeroesIcon.png|x20px|link=Self Taught Heroes]][[File:BTD6_mk_MonkeysStrongerTogetherIcon.png|x20px|link=Monkeys Together Strong]][[File:BTD6_mk_EmpoweredHeroesIcon.png|x20px|link=Empowered Heroes]]\n|-\n![[Beginner]]!![[Intermediate]]!![[Advanced]]!![[Expert]]!![[Beginner]]!![[Intermediate]]!![[Advanced]]!![[Expert]]'
}
}
-- local functions to improve performance
-- local functions to improve performance
local tinsert = table.insert
local lang = mw.language.new("en")
local sformat = string.format
local tInsert = table.insert
local sFormat = string.format
local xp_lv3 = RoundHalfUp(640 * curve)
local xpLv3 = RoundHalfUp(640 * curve)
local total_required = 0
local totalRequired = 0
local total_xp_diff = {0, 0, 0, 0, xp_lv3, xp_lv3, xp_lv3, xp_lv3}
local totalXpDifference = {0, 0, 0, 0, xpLv3, xpLv3, xpLv3, xpLv3}
local total_rounds_diff = {0, 0, 0, 0, 0, 0, 0, 0}
local totalRoundsDifference = {0, 0, 0, 0, 0, 0, 0, 0}
local function insert_rounds(index, req)
local function InsertRounds(index, req)
local xp = 0
local xp = 0
local mult = xp_modifiers[index]
local mult = xpModifiers[index]
local total_xp = total_xp_diff[index]
local totalXp = totalXpDifference[index]
local total_rounds = total_rounds_diff[index]
local totalRounds = totalRoundsDifference[index]
while total_xp < req do
while totalXp < req do
total_rounds = total_rounds + 1
totalRounds = totalRounds + 1
if total_rounds <= 20 then xp = (total_rounds * 20 + 20)
if totalRounds <= 20 then xp = (totalRounds * 20 + 20)
elseif total_rounds > 20 and total_rounds <= 50 then xp = (total_rounds * 40 - 380)
elseif totalRounds > 20 and totalRounds <= 50 then xp = (totalRounds * 40 - 380)
else xp = (total_rounds * 90 - 2880) end
else xp = (totalRounds * 90 - 2880) end
    -- Check if it is a perfect half tie-breaker
    totalXp = totalXp + RoundHalfUp(xp * mult)
    total_xp = total_xp + RoundHalfUp(xp * mult)
end
end
if total_rounds == 0 then tinsert(wikitable, '|—')
if totalRounds == 0 then tInsert(wikitable, '|—')
else tinsert(wikitable, sformat('|%i (%i)', total_rounds - total_rounds_diff[index], total_rounds))
else tInsert(wikitable, sFormat('|%i (%i)', totalRounds - totalRoundsDifference[index], totalRounds))
end
end
total_xp_diff[index] = total_xp
totalXpDifference[index] = totalXp
total_rounds_diff[index] = total_rounds
totalRoundsDifference[index] = totalRounds
end
end
for i, v in ipairs(level_reqs) do
for i, v in ipairs(levelReqs) do
local req = RoundHalfUp(v * curve)
local req = RoundHalfUp(v * curve)
total_required = total_required + req
totalRequired = totalRequired + req
tinsert(wikitable, sformat('|-\n!%i\n|%s (%s)', i + 1, lang:formatNum(req), lang:formatNum(total_required)))
tInsert(wikitable, sFormat('|-\n!%i\n|%s (%s)', i + 1, lang:formatNum(req), lang:formatNum(totalRequired)))
insert_rounds(1, total_required)
InsertRounds(1, totalRequired)
insert_rounds(2, total_required)
InsertRounds(2, totalRequired)
insert_rounds(3, total_required)
InsertRounds(3, totalRequired)
insert_rounds(4, total_required)
InsertRounds(4, totalRequired)
insert_rounds(5, total_required)
InsertRounds(5, totalRequired)
insert_rounds(6, total_required)
InsertRounds(6, totalRequired)
insert_rounds(7, total_required)
InsertRounds(7, totalRequired)
insert_rounds(8, total_required)
InsertRounds(8, totalRequired)
end
end
tinsert(wikitable, '|}')
tInsert(wikitable, '|}')
return table.concat(wikitable, '\n')
return table.concat(wikitable, '\n')
Line 81: Line 73:


function p.main(frame)
function p.main(frame)
return _main(tonumber(frame.args[1]))
return Main(tonumber(frame.args[1]))
end
end


return p
return p

Latest revision as of 03:57, 13 August 2026

Documentation for this module may be created at Module:BTD6 hero xp/doc

local p = {}
local mFloor = math.floor

local function RoundHalfUp(num)
	local floored = mFloor(num)
	
	return floored + ((num - floored >= 0.5) and 1 or 0)
end

function Main(curve)
	local levelReqs = { 180, 460, 1000, 1860, 3280, 5180, 8320, 9380, 13620, 16380, 14400, 16650, 14940, 16380, 17820, 19260, 20700, 16470, 17280 }
	local xpModifiers = { 1, 1.1, 1.2, 1.3, 1 * 1.1 * 1.05 * 1.08, 1.1 * 1.1 * 1.05 * 1.08, 1.2 * 1.1 * 1.05 * 1.08, 1.3 * 1.1 * 1.05 * 1.08 }
	
	local wikitable = {
		'<div class="hatnote">Note: the number of rounds to level up assumes the Hero was placed on round 1 and there are no other Heroes on the map.</div>\n{|class="wikitable" style="text-align:center"\n!rowspan="2"|Level!!rowspan="2"|XP required!!colspan="4"|Rounds to level up!!colspan="4"|Rounds to level up w/ [[File:BTD6_mk_MonkeyEducationIcon.png|x20px|link=Monkey Education]][[File:BTD6_mk_SelfTaughtHeroesIcon.png|x20px|link=Self Taught Heroes]][[File:BTD6_mk_MonkeysStrongerTogetherIcon.png|x20px|link=Monkeys Together Strong]][[File:BTD6_mk_EmpoweredHeroesIcon.png|x20px|link=Empowered Heroes]]\n|-\n![[Beginner]]!![[Intermediate]]!![[Advanced]]!![[Expert]]!![[Beginner]]!![[Intermediate]]!![[Advanced]]!![[Expert]]'
	}
	
	-- local functions to improve performance
	local lang = mw.language.new("en")
	local tInsert = table.insert
	local sFormat = string.format
	
	local xpLv3 = RoundHalfUp(640 * curve)
	
	local totalRequired = 0
	
	local totalXpDifference = {0, 0, 0, 0, xpLv3, xpLv3, xpLv3, xpLv3}
	local totalRoundsDifference = {0, 0, 0, 0, 0, 0, 0, 0}
	
	local function InsertRounds(index, req)
		local xp = 0
		local mult = xpModifiers[index]
		local totalXp = totalXpDifference[index]
		local totalRounds = totalRoundsDifference[index]
		
		while totalXp < req do
			totalRounds = totalRounds + 1
			
			if		totalRounds <= 20						then xp = (totalRounds * 20 + 20)
			elseif	totalRounds > 20 and totalRounds <= 50	then xp = (totalRounds * 40 - 380)
			else												 xp = (totalRounds * 90 - 2880) end
		
		    totalXp = totalXp + RoundHalfUp(xp * mult)
		end
		
		if totalRounds == 0 then tInsert(wikitable, '|—')
		else tInsert(wikitable, sFormat('|%i (%i)', totalRounds - totalRoundsDifference[index], totalRounds))
		end
		
		totalXpDifference[index] = totalXp
		totalRoundsDifference[index] = totalRounds
	end	
	
	for i, v in ipairs(levelReqs) do
		local req = RoundHalfUp(v * curve)
		totalRequired = totalRequired + req
		tInsert(wikitable, sFormat('|-\n!%i\n|%s (%s)', i + 1, lang:formatNum(req), lang:formatNum(totalRequired)))
		
		InsertRounds(1, totalRequired)
		InsertRounds(2, totalRequired)
		InsertRounds(3, totalRequired)
		InsertRounds(4, totalRequired)
		InsertRounds(5, totalRequired)
		InsertRounds(6, totalRequired)
		InsertRounds(7, totalRequired)
		InsertRounds(8, totalRequired)
	end
	
	tInsert(wikitable, '|}')
	
	return table.concat(wikitable, '\n')
end

function p.main(frame)
	return Main(tonumber(frame.args[1]))
end

return p