Module:Spawn table

local p = {}

local i18n = { processArgsModule = 'Module:ProcessArgs', entityLinkTemplate = 'EntityLink', editionsTemplate = 'Template:Editions', 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 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', ['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 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 = '' .. mobData.weight .. '&frasl;' .. groupTable.totalWeight .. ''		   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 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