Module:BATTD costs: Difference between revisions

From Blooncyclopedia, the independent Bloons knowledge base
Jump to navigation Jump to search
No edit summary
mNo edit summary
 
(One intermediate revision by the same user not shown)
Line 25: Line 25:
local upgrades, upgradePrereqs, upgradeLocks =
local upgrades, upgradePrereqs, upgradeLocks =
query("battd_upgrades", "_pageName, id, name, tower, cost", {
query("battd_upgrades", "_pageName, id, name, tower, cost", {
where=sFormat("tower='%s'", towerName)
where=sFormat("tower='%s'", towerName),
orderBy="cost"
}),
}),
query("battd_upgrades=main, battd_upgrades__previous=prev", "main.id=thisId, prev._value=prevId", {
query("battd_upgrades=main, battd_upgrades__previous=prev", "main.id=thisId, prev._value=prevId", {
Line 137: Line 138:
-- lock this combination so it isn't repeated on the graph again
-- lock this combination so it isn't repeated on the graph again
--if not upgradeLocksById[thisUpgradeId] then upgradeLocksById[thisUpgradeId] = {} end
if not upgradeLocksById[thisUpgradeId] then upgradeLocksById[thisUpgradeId] = {} end
--upgradeLocksById[thisUpgradeId][nextUpgradeId] = true
upgradeLocksById[thisUpgradeId][nextUpgradeId] = true
--if not upgradeLocksById[nextUpgradeId] then upgradeLocksById[nextUpgradeId] = {} end
if not upgradeLocksById[nextUpgradeId] then upgradeLocksById[nextUpgradeId] = {} end
--upgradeLocksById[nextUpgradeId][thisUpgradeId] = true
upgradeLocksById[nextUpgradeId][thisUpgradeId] = true
end
end
end
end
Line 163: Line 164:


function p.upgrade(frame)
function p.upgrade(frame)
--return upgrade(frame.args[1], frame.args[2], frame:expandTemplate{title = "Y", args = {}}, frame:expandTemplate{title = "N", args = {}})
return upgrade(frame.args[1], frame.args[2], frame:expandTemplate{title = "Y", args = {}}, frame:expandTemplate{title = "N", args = {}})
return upgrade(frame.args[1], frame.args[2], "Y", "N")
--return upgrade(frame.args[1], frame.args[2], "Y", "N")
end
end


return p
return p

Latest revision as of 05:13, 13 January 2026

Documentation for this module may be created at Module:BATTD costs/doc

local p = {}

-- LOCAL FUNCTIONS

local function upgrade(towerName, upgradeName, Y, N)
	local sFormat = string.format
	local tConcat = table.concat
	local query = mw.ext.cargo.query
	local lang = mw.language.new("en")
	
	local outputTable = {}
	local upgradeId = ""
	
	local upgradesById = {}				-- key:value table  - upgrade:upgrade data
	local upgradeLocksById = {}			-- key:values table - upgrades:upgrades that this upgrade locks
	local upgradePrereqsById = {}		-- key:values table - upgrade:prerequisites to purchase this upgrade
	local upgradePrereqsOfById = {		-- key:values table - upgrades:upgrades this is a prerequisite of
		root = {}
	}
	local alreadyPurchasedUpgrades = {	-- this upgrade and all upgrades the player has to have already purchased to get it
		root = true
	}
	
	-- cargo queries for data
	local upgrades, upgradePrereqs, upgradeLocks =
	query("battd_upgrades", "_pageName, id, name, tower, cost", {
		where=sFormat("tower='%s'", towerName),
		orderBy="cost"
	}),
	query("battd_upgrades=main, battd_upgrades__previous=prev", "main.id=thisId, prev._value=prevId", {
		where=sFormat("main.tower='%s'", towerName),
		join="main._ID=prev._RowID"
	}),
	query("battd_upgrades=main, battd_upgrades__locked_by_upgrades=lock", "main.id=thisId, lock._value=lockId", {
		where=sFormat("main.tower='%s'", towerName),
		join="main._ID=lock._RowID"
	})

	-- build upgradesById
	for i, upgrade in ipairs(upgrades) do
		upgradesById[upgrade.id] = upgrade
		if upgrade.name == upgradeName then upgradeId = upgrade.id end
	end

	-- build upgradePrereqsById, upgradePrereqsOfById
	for i, upgrade in ipairs(upgradePrereqs) do
		-- upgrade:next table
		if upgrade.prevId then
			if upgradePrereqsOfById[upgrade.prevId] then
				upgradePrereqsOfById[upgrade.prevId][#upgradePrereqsOfById[upgrade.prevId]+1] = upgrade.thisId
			else
				upgradePrereqsOfById[upgrade.prevId] = {upgrade.thisId}
			end
		else
			-- if this upgrade is a root upgrade and is not already purchased
			upgradePrereqsOfById["root"][#upgradePrereqsOfById["root"]+1] = upgrade.thisId
		end
		
		-- upgrade:prev table
		if upgradePrereqsById[upgrade.thisId] then
			upgradePrereqsById[upgrade.thisId][#upgradePrereqsById[upgrade.thisId]+1] = upgrade.prevId
		else
			upgradePrereqsById[upgrade.thisId] = {upgrade.prevId}
		end
	end
	
	-- build alreadyPurchasedUpgrades
	local function getAlreadyPurchasedUpgrades(myUpgradeId)
		local cost = upgradesById[myUpgradeId].cost
		alreadyPurchasedUpgrades[myUpgradeId] = true
		
		for i, id in ipairs(upgradePrereqsById[myUpgradeId]) do
			cost = cost + getAlreadyPurchasedUpgrades(id)
		end
		return cost
	end
	
	-- tower cost + total cost of this upgrade and all its prereqs
	local baseCost = getAlreadyPurchasedUpgrades(upgradeId) + query("battd_characters", "cost", {
		where=sFormat("name='%s'", towerName)
	})[1].cost

	-- build upgradeLocksById
	for i, upgrade in ipairs(upgradeLocks) do
		if upgrade.lockId then
			if upgradeLocksById[upgrade.thisId] then
				upgradeLocksById[upgrade.thisId][upgrade.lockId] = true
			else
				upgradeLocksById[upgrade.thisId] = {[upgrade.lockId] = true}
			end
		end
	end
	
	-- generate table header
	local row = {"{|class=\"wikitable sortable\" style=\"text-align:center\"\n!Total cost!!Sell value"}
	
	for i, upgrade in ipairs(upgrades) do
		if not alreadyPurchasedUpgrades[upgrade.id] then row[#row+1] = sFormat("!![[%s|%s]]", upgrade._pageName, upgrade.name) end
	end
	
	--mw.logObject(upgradeLocksById)
	
	outputTable[1] = tConcat(row)
	
	local function recursiveGetTotalCosts(currentCost, purchasedUpgrades)
		-- add row to outputTable
		row = {sFormat("\n|-\n|$%s||$%s", lang:formatNum(currentCost), lang:formatNum(currentCost*0.7))}
		
		for i, upgrade in ipairs(upgrades) do
			if not alreadyPurchasedUpgrades[upgrade.id] then
				row[#row+1] = sFormat("||%s", purchasedUpgrades[upgrade.id] and Y or N)
			end
		end
		
		outputTable[#outputTable+1] = tConcat(row, "\n")
		
		for thisUpgradeId, _ in pairs(purchasedUpgrades) do
			-- skip if this upgrade is a leaf
			if upgradePrereqsOfById[thisUpgradeId] then
				for _, nextUpgradeId in pairs(upgradePrereqsOfById[thisUpgradeId]) do
					if not purchasedUpgrades[nextUpgradeId] then
						-- shallow copy purchasedUpgrades and check if nextUpgradeId is locked by another upgrade
						local purchasedUpgradesNext = {}
						local doNext = true
						
						for purchasedUpgrade, _ in pairs(purchasedUpgrades) do
							-- if nextUpgradeId is locked by a purchasedUpgrade then don't proceed
							if upgradeLocksById[purchasedUpgrade] and upgradeLocksById[purchasedUpgrade][nextUpgradeId] then
								doNext = false
								break
							end
							purchasedUpgradesNext[purchasedUpgrade] = true
						end
						
						if doNext then
							purchasedUpgradesNext[nextUpgradeId] = true
							recursiveGetTotalCosts(currentCost + upgradesById[nextUpgradeId].cost, purchasedUpgradesNext)
							
							-- lock this combination so it isn't repeated on the graph again
							if not upgradeLocksById[thisUpgradeId] then upgradeLocksById[thisUpgradeId] = {} end
							upgradeLocksById[thisUpgradeId][nextUpgradeId] = true
							if not upgradeLocksById[nextUpgradeId] then upgradeLocksById[nextUpgradeId] = {} end
							upgradeLocksById[nextUpgradeId][thisUpgradeId] = true
						end
					end
				end
			end
		end
	end
	
	recursiveGetTotalCosts(baseCost, alreadyPurchasedUpgrades)
	
	--mw.logObject(upgradeLocksById)
	
	outputTable[#outputTable+1] = "\n|}"
	return tConcat(outputTable)
end

-- GLOBAL FUNCTIONS

function p.tower(frame)
	return ""
end

function p.upgrade(frame)
	return upgrade(frame.args[1], frame.args[2], frame:expandTemplate{title = "Y", args = {}}, frame:expandTemplate{title = "N", args = {}})
	--return upgrade(frame.args[1], frame.args[2], "Y", "N")
end

return p