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
 
(2 intermediate revisions by the same user not shown)
Line 10: Line 10:
local mFloor = math.floor
local mFloor = math.floor


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


Line 28: Line 28:
local sformat = string.format
local sformat = string.format
local xp_lv3 = mfloor(640 * curve)
local xp_lv3 = RoundHalfUp(640 * curve)
local total_required = 0
local total_required = 0
Line 47: Line 47:
elseif total_rounds > 20 and total_rounds <= 50 then xp = (total_rounds * 40 - 380)
elseif total_rounds > 20 and total_rounds <= 50 then xp = (total_rounds * 40 - 380)
else xp = (total_rounds * 90 - 2880) end
else xp = (total_rounds * 90 - 2880) end
local floor = mfloor(xp * mult)
    -- Check if it is a perfect half tie-breaker
    -- Check if it is a perfect half tie-breaker
    total_xp = total_xp + roundHalfToEven(xp * mult)
    total_xp = total_xp + RoundHalfUp(xp * mult)
end
end
Line 63: Line 61:
for i, v in ipairs(level_reqs) do
for i, v in ipairs(level_reqs) do
local req = roundHalfToEven(v * curve)
local req = RoundHalfUp(v * curve)
total_required = total_required + req
total_required = total_required + 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(total_required)))

Latest revision as of 23:33, 3 June 2026

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

-- 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 lang = mw.language.new("en")
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 level_reqs = { 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 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]]'
	}
	
	-- local functions to improve performance
	local tinsert = table.insert
	local sformat = string.format
	
	local xp_lv3 = RoundHalfUp(640 * curve)
	
	local total_required = 0
	
	local total_xp_diff = {0, 0, 0, 0, xp_lv3, xp_lv3, xp_lv3, xp_lv3}
	local total_rounds_diff = {0, 0, 0, 0, 0, 0, 0, 0}
	
	local function insert_rounds(index, req)
		local xp = 0
		local mult = xp_modifiers[index]
		local total_xp = total_xp_diff[index]
		local total_rounds = total_rounds_diff[index]
		
		while total_xp < req do
			total_rounds = total_rounds + 1
			
			if		total_rounds <= 20							then xp = (total_rounds * 20 + 20)
			elseif	total_rounds > 20 and total_rounds <= 50	then xp = (total_rounds * 40 - 380)
			else													 xp = (total_rounds * 90 - 2880) end
		
		    -- Check if it is a perfect half tie-breaker
		    total_xp = total_xp + RoundHalfUp(xp * mult)
		end
		
		if total_rounds == 0 then tinsert(wikitable, '|—')
		else tinsert(wikitable, sformat('|%i (%i)', total_rounds - total_rounds_diff[index], total_rounds))
		end
		
		total_xp_diff[index] = total_xp
		total_rounds_diff[index] = total_rounds
	end	
	
	for i, v in ipairs(level_reqs) do
		local req = RoundHalfUp(v * curve)
		total_required = total_required + req
		tinsert(wikitable, sformat('|-\n!%i\n|%s (%s)', i + 1, lang:formatNum(req), lang:formatNum(total_required)))
		
		insert_rounds(1, total_required)
		insert_rounds(2, total_required)
		insert_rounds(3, total_required)
		insert_rounds(4, total_required)
		insert_rounds(5, total_required)
		insert_rounds(6, total_required)
		insert_rounds(7, total_required)
		insert_rounds(8, total_required)
	end
	
	tinsert(wikitable, '|}')
	
	return table.concat(wikitable, '\n')
end

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

return p