Module:Spawn table

From WoopMC

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

local p = {}

local i18n = {
	processArgsModule = 'Module:ProcessArgs',
	editionsTemplate = 'Template:Editions',
	mobColumn = 'Mob',
	chanceColumn = 'Spawn chance ' ..mw.getCurrentFrame():expandTemplate{title='Tip', args={Info='Chance to spawn relative to other mobs in the category.'}},
	groupSizeColumn = 'Group size ' ..mw.getCurrentFrame():expandTemplate{title='Tip', args={Info='Number of mobs the game tries to spawn per attempt.'}}
}

local spawnData = {}  -- contains mob spawn info

local groupArgs = {
	['passive'] = 'Passive category',
	['hostile'] = 'Hostile category ' ..mw.getCurrentFrame():expandTemplate{title='Tip', args={Info='Slimes spawn rates only applies inside slime chunks, below layer 40. They can also spawn in swamp biomes between layers 50 and 70 in light levels of 7 or less, with these layers tending to be near the surface.'}},
	['water'] = 'Water category',
	['watercreature'] = 'Water creature category',
	['ambient'] = 'Ambient category',
	['waterambient'] = 'Water ambient category',
	['underground'] = 'Underground water creature category',
	['axolotl'] = 'Axolotl category'
}

local hasNotes = 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.mob = mw.ustring.match(line, '^%s*(.-)%s*,')
				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.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 = mobData.mob
			
			tableRow:tag('td')
				:css('text-align', 'left')
				:css('font-weight', 'normal')
				:wikitext(mobCellText)
			
			tableRow:tag('td')
				:css('text-align', 'center')
				:wikitext('<sup>' .. mobData.weight .. '</sup>&frasl;<sub>' .. groupTable.totalWeight .. '</sub>')
			
			tableRow:tag('td')
				:css('text-align', 'center')
				:wikitext(mobData.size)
			
			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 biome = string.lower(args.biome or mw.title.getCurrentTitle().text)  -- may be useful if Cargo functionality is added
	
	local tableRoot = mw.html.create('table'):attr('class', 'wikitable')
	
	local titleStr = args.title
	
	if args.edition then
		local editionStr = frame:expandTemplate{title=i18n.editionsTemplate, args={args.edition}}
		if titleStr then
			titleStr = titleStr .. ' in ' .. editionStr
		else
			titleStr = 'In ' .. editionStr
		end
	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