Module:Spawn table

From Alex's Caves Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Spawn table/doc

local p = {}

local i18n = {
	processArgsModule = 'Module:ProcessArgs',
	entityLinkTemplate = 'EntityLink',
	mobColumn = 'Mob',
	chanceColumn = mw.getCurrentFrame():expandTemplate{title='Tooltip', args={'Spawn weight', 'Weight relative to other spawn entries in the category'}},
	groupSizeColumn = mw.getCurrentFrame():expandTemplate{title='Tooltip', args={'Group size', 'Number of mobs the game tries to spawn per attempt'}},
	chargeColumn = mw.getCurrentFrame():expandTemplate{title='Tooltip', args={'Charge', 'Charge generated by the mob' }},
	budgetColumn = mw.getCurrentFrame():expandTemplate{title='Tooltip', args={'Budget', 'Maximum charge potential allowing spawning'}},
	spawnCostNote = 'When spawning a mob with a budget, take the sum of the charge of each existing mob divided by the distance to that mob. If the total times the new mob\'s charge is greater than the new mob\'s budget, the spawn fails. See [[Spawn#Spawn costs]] for details.'
}

local spawnData = {}  -- contains mob spawn info

local groupArgs = {
	['creature'] = 'Creature category',
	['passive'] = 'Creature category', --Deprecated
	['monster'] = 'Monster category',
	['hostile'] = 'Monster category', --Deprecated
	['ambient'] = 'Ambient category',
	['axolotl'] = 'Axolotl category',
	['watercreature'] = 'Water creature category',
	['cavecreature'] = 'Cave creature category',
	['underground'] = 'Underground water creature category',
	['waterambient'] = 'Water ambient category',
	['misc'] = 'Misc category'
}

local hasNotes = false
local hasSpawnCost = false

-- parses input arguments into spawnData table
local function parseInput(args)
	for argName in pairs(groupArgs) do
		local groupArg = args[argName]
		
		if groupArg then
			local currentGroup = {}
			local totalWeight = 0
			currentGroup.mobs = {}
			
			groupArg = groupArg .. '\n'  -- allow last line to be matched like the rest
			
			-- parse input of group parameter
			for line in mw.ustring.gmatch(groupArg, '[^\r\n]+[\r\n]') do  -- split on newline
				local parsedLine = {}
				for key, value in mw.ustring.gmatch(line, '([%a]+)%s*=%s*(.-)%s*[,\r\n]') do
					if value ~= '' then
						parsedLine[key:lower()] = value
					end
				end
				
				parsedLine.note = mw.ustring.match(line, 'note=%s*(.-)%s*[\r\n]')
				
				local currentMob = {}
				
				-- convert weight to number; becomes nil if conversion fails
				if parsedLine.weight then
					weightNum = tonumber(parsedLine.weight)
					-- if converted to number successfully
					if weightNum then
						currentMob.weight = weightNum
						totalWeight = totalWeight + weightNum
					end
				end
				
				if parsedLine.size then
					currentMob.size = parsedLine.size
				end

				if parsedLine.charge then
					hasSpawnCost = true
					currentMob.charge = parsedLine.charge
				end

				if parsedLine.budget then
					hasSpawnCost = true
					currentMob.budget = parsedLine.budget
				end
				
				if parsedLine.note then
					hasNotes = true
					currentMob.note = parsedLine.note
				end
				
				if parsedLine.notename then
					currentMob.notename = parsedLine.notename
				end
				
				if parsedLine.mob then
					currentMob.mob = parsedLine.mob
					table.insert(currentGroup.mobs, currentMob)
				end
			end
			currentGroup.totalWeight = totalWeight
			spawnData[argName] = currentGroup
		end
	end
end


-- takes root <table> html object and adds table body using info in spawnData 
local function addTableBody(tableRoot, numberOfColumns)
	local frame = mw.getCurrentFrame()
	local groupNumber = 1
	
	for groupArg, groupTable in pairs(spawnData) do
		local groupHeader = mw.html.create('tr')
		groupHeader:tag('th')
			:attr('colspan', numberOfColumns)
			:wikitext(groupArgs[groupArg])
			
		tableRoot:node(groupHeader)
		
		for _, mobData in ipairs(groupTable.mobs) do
			local tableRow = mw.html.create('tr')
			
			local mobCellText = frame:expandTemplate{title=i18n.entityLinkTemplate, args={mobData.mob}}
			
			if mobData.note then 
				mobCellText = mobCellText .. frame:extensionTag{name='ref', content=mobData.note, args={name=mobData.mob:lower(), group='note'}}
			elseif mobData.notename then
				mobCellText = mobCellText .. frame:extensionTag{name='ref', args={name=mobData.notename:lower(), group='note'}}
			end
			
			tableRow:tag('th')
				:css('text-align', 'left')
				:css('font-weight', 'normal')
				:wikitext(mobCellText)
			
			-- Simplify weights for pools with single entries to avoid confusion from e.g. 10/10 and 25/25
			local weightText = '1'
			if mobData.weight ~= groupTable.totalWeight then
				weightText = '<sup>' .. mobData.weight .. '</sup>&frasl;<sub>' .. groupTable.totalWeight .. '</sub>'
		    end
			
			tableRow:tag('td')
				:css('text-align', 'center')
				:wikitext(weightText)
			
			tableRow:tag('td')
				:css('text-align', 'center')
				:wikitext(mobData.size)

			if hasSpawnCost then
				tableRow:tag('td')
					:css('text-align', 'center')
					:wikitext(mobData.charge)
				tableRow:tag('td')
					:css('text-align', 'center')
					:wikitext(mobData.budget)
			end

			tableRoot:node(tableRow)
		end
	end
end


-- function called from template
function p.mobSpawnTable(frame)
	local args = frame
	if frame == mw.getCurrentFrame() then
		args = require(i18n.processArgsModule).merge( true )
	else
		frame = mw.getCurrentFrame()
	end
	
	parseInput(args)

	local columns = {i18n.mobColumn, i18n.chanceColumn, i18n.groupSizeColumn}
	
	local tableRoot = mw.html.create('table'):attr('class', 'wikitable')
	
	local titleStr = args.title

	if hasSpawnCost then
		hasNotes = true
		table.insert( columns, i18n.chargeColumn .. frame:extensionTag{name='ref', content=i18n.spawnCostNote, args={name='spawn-cost', group='note'}} )
		table.insert( columns, i18n.budgetColumn .. frame:extensionTag{name='ref', args={name='spawn-cost', group='note'}} )
	end
	
	
	if titleStr then
		tableRoot
			:tag('caption')
				:wikitext(titleStr)
	end
	
	local colHeaders = mw.html.create('tr')
	
	for _, value in pairs(columns) do
		colHeaders:tag('th'):wikitext(value)
	end
	
	tableRoot:node(colHeaders)
	
	addTableBody(tableRoot, #columns)
	
	local outputWikitext = tostring(tableRoot)

	if hasNotes then
		outputWikitext = outputWikitext .. '\n\n' .. frame:extensionTag{name='references', args={group='note'}}
	end
	
	return outputWikitext
end

return p