Module:Infobox/Mechanic

--Get Required Modules local loadLib = require('Module:LoadLib')

loadLib(_G, {	infobox = 'Infobox',	templates = 'String/Templates',	{'Minimap', values = {		'getMinimapForInfobox',	}},	animate = 'Animate',	infoboxdata = 'Infobox/Data',	sprite = 'Sprite',	mayor = 'Mayor', })

mw.html.create = require('Module:Html').create local curTitle = mw.title.getCurrentTitle local allstats, MAX_INDEX, MAX_TAB = infoboxdata.allstats --D1+, infoboxdata.MAX_INDEX, infoboxdata.MAX_TAB

--Begin Exports local p = {} local yesIcon, noIcon, unknownIcon = templates.yes(1), templates.no(1), templates.unknown(1)

local function yesnodefault(val, yes, no, def) if tostring(val):sub(1, 1):lower == 'u' then return unknownIcon end local bool = yesno(val); if bool == nil then return def or val elseif bool then return yes else return no	end end

local function yesnoIcon(val, def) return yesnodefault(val, yesIcon, noIcon, def) end

local function additergroup(pref, sdata, parent) for count = 1,MAX_INDEX,1 do		local desc, name = (pref..'%d_desc'):format(count), (pref..'%d_name'):format(count) parent:addData{ sdata[desc], label = sdata[name] } end end

local function argNormalize(tb) -- Simple replacement functions for the whole table local ret = {} for oldkey, v in pairs(tb) do		local key = oldkey:gsub('[{}]', '') ret[key] = v	end return ret end

function p.infoboxCreate(frame) local args = getArgs(frame) return (frame.getParent and frame:getParent or mw.getCurrentFrame):preprocess(p._infoboxCreate(args)) end

function p._infoboxCreate(args) local deftype = args.default_type -- All checkings local isNPC, isMayor, isQuest, isPuzzle, isStat, isMinion, isLocation do local function checkval(v) return (deftype or ''):lower:match(v) and true or false end isNPC = checkval('npc') or checkval('character') or checkval('mayor') isMayor = checkval('mayor') isQuest = checkval('quest') isPuzzle = checkval('puzzle') isStat = checkval('stat') isMinion = checkval('minion') isLocation = checkval('location') end local minimalist = (isQuest or isPuzzle) and true local pagename = curTitle.text or 'Diamond' local title = args.title or ((not minimalist) and pagename or nil) if isLocation then local status, spriteAndTitle = pcall(function return sprite._locationSprite(title) end) if status and spriteAndTitle then title = spriteAndTitle end elseif isMayor then title = mayor.getMayorLink(title) elseif isNPC then local status, spriteAndTitle = pcall(function return sprite._npcSprite(title) end) if status and spriteAndTitle then title = spriteAndTitle end end local category_to_add = args.category_to_add local sections = {} for j = 1,MAX_TAB,1 do		local function argJ(name, default) return args[name..j] or default end local sectionExists = j == 1 or argJ('tab') if sectionExists then -- section one does have numbers after params; on 2+ do that local i = j == 1 and  or j			local _i = j == 1 and  or '_'..j -- needed for when a param ends in a number naturally local function argI(name, default) return args[name..((type(name) == 'string' and name:match('%d$')) and _i or i)] or default end -- table of all params for this section local s = {} local function additerdata(pref) for count = 1,MAX_INDEX,1 do					local desc, name = (pref..'%d_desc'):format(count), (pref..'%d_name'):format(count) s[desc] = argI(desc) s[name] = argI(name) or ('%s %d'):format(string.ucfirst(pref), count) end end -- Top level infobox values --0			s.tab = argJ('tab') or argI('tab') -- purposefully use 'j' here since default section does actually use 'tab1' --1|2			s.caption = argI('caption') or argI('imagecaption') s.image_gallery = (argI('image') and argI('image'):match('UNIQ%-%-gallery')) and argI('image') or nil s.image = not s.image_gallery and (argI('image') or not (minimalist or isStat or isMinion)) and string.wrapTag(animate.animate({ argI('image') or pagename..'.png', class = 'pi-image-thumbnail' }), 'center') or nil if not s.image_gallery and not s.image and isMinion then s.image_gallery = string.dedent:format(pagename, pagename) end --3			s.slot_item = argI('slot_item') or argI('slot') if not s.slot_item and isMayor then s.slot_item = string.wrapHtml((''):format( args.title or pagename, args.title or pagename ), 'center') else s.slot_item = yesno(s.slot_item, (isMinion and true or false)) and (s.slot_item or pagename) or nil s.slot_item = s.slot_item and string.wrapHtml((''):format( s.slot_item, argI('slot_text') and '|text='..argI('slot_text') or '', argI('slot_title') and '|title='..argI('slot_title') or '', argI('slot_link') and '|link='..argI('slot_link') or '' ), 'center') end --4			s.aka = argI('aka') --5			s.type = argI('type') or ((not minimalist) and deftype or nil) --6			s.color = argI('color') --7			s.appearance = argI('appearance') --8			s.collection = argI('collection') and (''):format(argI('collection')) --9			s.usage = argI('usage') --10			s.uses = argI('uses') --11			s.ways_to_increase = argI('ways_to_increase') --12			s.category = argI('category') --13			s.collects = argI('collects') and (''):format(argI('collects')) --14			s.upgrade_with = argI('upgrade_with') and (''):format(argI('upgrade_with')) --15			s.travel_scroll = argI('travel_scroll') --16			s.level = argI('level') --17			s.sublocations = argI('sublocations') and (''):format(argI('sublocations')) --18			s.fairy_souls = argI('fairy_souls') --19			s.election_wins = argI('election_wins') or isMayor and mayor.getWins{ args.title or pagename } .. ' [Based on existing data]' or nil -- Dungeon Information group --A0 do local d = argI('dungeon') if d then d = d:lower:gsub('_', ' ') end s.dungeon = d and (					(d == 'c' or d == 'cat' or d == 'catacombs' or d == 'the catacombs')					and 'The Catacombs'					or ' Invalid dungeon name '				) end --A1 s.floor = argI('floor') --A2 s.boss = argI('boss') --A3 s.status = argI('status') --A4 s.dungeon_size = argI('dungeon_size') --A5 s.party_size = argI('party_size') --A6 s.required_combat_level = argI('required_combat_level') --A7 s.required_catacombs_level = argI('required_catacombs_level') --A8 s.reqs = argI('reqs') --A9 s.base_xp = argI('base_xp') --A10 s.failable = yesnoIcon(argI('failable')) -- Mob Information group --B0 s.mob_level = argI('mob_level') --B1 s.damage_deals = argI('damage_deals') --B2 s.damage_resistance = argI('damage_resistance') --B3 s.spawn_location = argI('spawn_location') and (''):format(argI('spawn_location')) --B4 s.spawn_condition = argI('spawn_condition') --B5 s.special = argI('special') --B6 s.special_behavior = argI('special_behavior') --B7 local ee = argI('effective_enchant') s.effective_enchant = ee and (				(ee == 'none' or ee == 'no' or ee == 'n') and 'None'				or (''):format(ee)			) -- Quest group --C0 s.requirements = argI('requirements') or argI('requirement') --C1 s.rewards = argI('rewards') or argI('reward') -- Stats group --D0 s.stats = argI('stats') --D1+ table.each(table.values(allstats), function(v)				local ln = v[1]				s[ln] = argI(ln)			end) -- Perks group --E0+ additerdata('perk') if isMayor then for i, v in ipairs(mayor._mayorPerksTable(args.title or pagename)) do					local desc, name = ('perk%d_desc'):format(i), ('perk%d_name'):format(i) if v[2] and not s[desc] then s[desc] = v[2] s[name] = v[1] and string.gsub(v[1], '^%[%[(.*)%]%]*%]$', '\'\'\'%1\'\'\'') or s[name] end end end -- Capacity group --F0 s.default_desc = argI('default_desc') s.default_name = argI('default_name') or 'Default' --F1+ additerdata('upgrade') -- Location group --G0 s.xyz = argI('x') and (' %s  %s  %s  '):format(argI('x'), argI('y') or , argI('z') or ) s.xyz = s.xyz and string.wrapHtml(s.xyz, 'table', { style = 'width:100%; table-layout:fixed; text-align:center;' }) --G1 s.coordinates = argI('coordinates') --G2 s.location = argI('location') and (''):format(argI('location')) --G3 s.start_location = argI('start_location') and (''):format(argI('start_location')) --G4 s.start_npc = argI('start_npc') and (''):format(argI('start_npc')) --G5 s.prev_location = argI('prev_location') or (argI('next_location') and 'None (lowest tier location)') --G6 s.next_location = argI('next_location') or (argI('prev_location') and 'None (top tier location)') -- Inhabitants group --H0 s.npcs = argI('npcs') and (''):format(argI('npcs')) --H1 s.mobs = argI('mobs') and (''):format(argI('mobs')) -- Resources group --I0 s.drops = argI('drops') and string.wrapHtml(				(''):format(argI('drops')),				'div', { style = 'text-align:left;' }			) --I1 s.resources = argI('resources') and string.wrapHtml(				(''):format(argI('resources')),				'div', { style = 'text-align:left;' }			) -- Drops group --R0 s.mob_drops = argI('mob_drops') and (''):format(argI('mob_drops')) --R1 s.xp = argI('xp') and (''):format(argI('xp')) --R2 s.coins = argI('coins') and (''):format(argI('coins')) --R3 s.essence = argI('essence') and (''):format(argI('essence')) -- Values group --J0 s.base_value = argI('base_value') --J1 s.max_value = argI('max_value') -- Properties group --K0 s.unlock_requirement = argI('unlock_requirement') --K1 s.max_level = argI('max_level') -- Special Effects group --L0 s.skill_special_effect = argI('skill_special_effect') -- Upgrades group --M0 s.super_compactor = isMinion and yesnoIcon(argI('super_compactor') or true) or nil --M1 s.compactor = isMinion and yesnoIcon(argI('compactor')) or nil --M2 s.auto_smelter = isMinion and yesnoIcon(argI('auto_smelter')) or nil -- Player Interactions group --N0 s.quests = argI('quests') --N1 s.shop = yesnoIcon(argI('shop') or isMayor and 'n' or nil) -- Next Event local skydate_start, skydate_end = argI('skydate_start') or argI('skydate_begin'), argI('skydate_end') if skydate_start then --S0 s.datetime = string.wrapHtml('', 'span', {					class = 'skydate-timestamp',					['data-skydate'] = skydate_start,				}) --S1 skydate_end = skydate_end or skydate_start skydate_end = skydate_end .. (skydate_end:match(',') and '' or ', 23:59') s.countdown = string.wrapHtml('', 'span', {					class = 'skydate-countdown',					['data-skydate-start'] = skydate_start,					['data-skydate-end'] = skydate_end,				}) end -- Minimap (at Coordinates) if not argI('location') and isMayor then s.minimap = getMinimapForInfobox{ 'Community Center', x = 7, z = -110 } elseif isNPC then --O0 s.minimap = getMinimapForInfobox{ argI('location'), x = argI('x'), z = argI('z') } end -- Ideal Layout --P0 s.ideal_layout = argI('ideal_layout') and string.wrapHtml(argI('ideal_layout'), 'center', {style = 'margin:0 auto; width:272px;'}) -- Item Metadata -- Q0 s.id = argI('item_id') or argI('id') if s.id then -- Always show ID in all caps s.id = string.wrapTag(s.id:upper, 'code') -- If array syntax, make a list s.id = s.id:gsub(' ', '') -- lazy trim for array; ids never naturally have spaces s.id = table.concat(mw.text.split(s.id, ','), ' ') end -- Push section data into array sections[#sections+1] = s		end end -- Make infobox local ibox = infobox.create ibox:addTitle{ title } local panel = ibox:addPanel for i, sectionData in ipairs(sections) do		local sdata = argNormalize(sectionData) local section = --0panel:addSection{ label = sdata.tab } --1|2		if sdata.image_gallery then section:addImage{ sdata.image_gallery, caption = { sdata.caption }, source = 'image'..(i == 1 and '' or i) } else section:addData{ sdata.image } end section --3 :addData{ sdata.slot_item } --4 :addData{ sdata.aka, label = 'Also known as' } --5 :addData{ sdata.type, label = 'Type' } --6 :addData{ sdata.color, label = 'Color' } --7 :addData{ sdata.appearance, label = 'Appearance' } --8 :addData{ sdata.collection, label = 'Collection' } --9 :addData{ sdata.usage, label = 'Usage' } --10 :addData{ sdata.uses, label = 'Uses' } --11 :addData{ sdata.ways_to_increase, label = 'Ways to Increase' } --12 :addData{ sdata.category, label = 'Category' } --13 :addData{ sdata.collects, label = string.makeTitle('Collects', 'Average items collected per action') } --14 :addData{ sdata.upgrade_with, label = 'Upgrade with' } --15 :addData{ sdata.travel_scroll, label = '\'\'\'Travel Scroll\'\'\'' } --16 :addData{ sdata.level, label = 'Level' } --17 :addData{ sdata.sublocations, label = 'Sub-locations' } --18 :addData{ sdata.fairy_souls, label = (' \'\'\'Fairy Souls\'\'\''):format(pagename) } --19 :addData{ sdata.election_wins, label = '\'\'\'Election Wins\'\'\'' } :addGroup --A0 :addData{ sdata.dungeon, label = 'Dungeon' } --A1 :addData{ sdata.floor, label = 'Dungeon Floor' } --A2 :addData{ sdata.boss, label = 'Boss' } --A3 :addData{ sdata.status, label = 'Status' } --A4 :addData{ sdata.dungeon_size, label = 'Dungeon Size' } --A5 :addData{ sdata.party_size, label = 'Party Size' } --A6 :addData{ sdata.required_combat_level, label = 'Required Level' } --A7 :addData{ sdata.required_catacombs_level, label = 'Required Level' } --A8 :addData{ sdata.reqs, label = 'Requirements to enter' } --A9 :addData{ sdata.base_xp, label = 'Base XP' } --A10:addData{ sdata.failable, label = 'Failable' } :done :addGroup --B0 :addData{ sdata.mob_level, label = 'Mob Level' } --B1 :addData{ sdata.damage_deals, label = 'Damage Deals' } --B2 :addData{ sdata.damage_resistance, label = 'Damage Resistance' } --B3 :addData{ sdata.spawn_location, label = 'Spawn Location' } --B4 :addData{ sdata.spawn_condition, label = 'Spawn Condition' } --B5 :addData{ sdata.special, label = 'Special' } --B6 :addData{ sdata.special_behavior, label = 'Special Behavior' } --B7 :addData{ sdata.effective_enchant, label = string.makeTitle('Effective Enchant', 'The weapon enchant that is most effective for killing this mob') } :done :addGroup --C0 :addData{ sdata.requirements, label = 'Start Req.' } --C1 :addData{ sdata.rewards, label = 'Reward' } :done do local group_ group_ = section:addGroup{ header = 'Stats', name = 'infobox-stats-list' } --D0 group_:addData{ sdata.stats } table.each(table.values(allstats), function(v)				local ln = v[1]				--D1+group_:addData{ sdata[ln], label = makeStat(ln, nil, true) }			end) end do local group = section:addGroup{ header = 'Perks' } --E0+ additergroup('perk', sdata, group) end do local group = section:addGroup{ header = 'Perks' } --F0 if sdata.default_desc then group:addData{ sdata.default_desc, label = sdata.default_name } end --F1+ additergroup('upgrade', sdata, group) end section:addGroup{ header = (not minimalist) and 'Location' or '' } --G0 :addData{ sdata.xyz, label = string.wrapHtml(' Coordinates', 'span', { style = 'white-space:nowrap; vertical-align: middle;' })} --G1 :addData{ sdata.coordinates, label = ' Coordinates' } --G2 :addData{ sdata.location, label = 'Location' } --G3 :addData{ sdata.start_location, label = 'Start Location' } --G4 :addData{ sdata.start_npc, label = 'Start NPC' } :addGroup{ layout = 'horizontal' } --G5 :addData{ sdata.prev_location, label = '← Previous Location' } --G6 :addData{ sdata.next_location, label = 'Next Location →' } :done :done :addGroup{ header = 'Inhabitants' } --H0 :addData{ sdata.npcs, label = 'NPCs' } --H1 :addData{ sdata.mobs, label = 'Mobs' } :done :addGroup{ header = 'Resources' } :addGroup{ layout = 'horizontal', ['row-items'] = 2 } --I0 :addData{ sdata.drops, label = 'Mob Drops' } --I1 :addData{ sdata.resources, label = 'Resources' } :done :done section:addGroup{ header = 'Drops' } --R0 :addData{ sdata.mob_drops, label = 'Drops' } --R1 :addData{ sdata.xp, label = 'XP' } --R2 :addData{ sdata.coins, label = '' } --R3 :addData{ sdata.essence, label = 'Essence' } :done :addGroup{ header = 'Values' } --J0 :addData{ sdata.base_value, label = 'Base value' } --J1 :addData{ sdata.max_value, label = 'Max value' } :done :addGroup{ header = 'Properties' } --K0 :addData{ sdata.unlock_requirement, label = 'Unlock Requirements' } --K1 :addData{ sdata.max_level, label = 'Skill Max Level' } :done :addGroup{ header = 'Special Effects' } --L0 :addData{ sdata.skill_special_effect, label = 'Special Effect' } :done :addGroup{ header = 'Upgrades', layout = 'horizontal', ['row-items'] = 1 } --M0 :addData{ sdata.super_compactor, label = 'Super Compactor 3000' } :addGroup{ layout = 'horizontal', ['row-items'] = 2 } --M1 :addData{ sdata.compactor, label = 'Compactor' } --M2 :addData{ sdata.auto_smelter, label = 'Auto Smelter' } :done :done :addGroup{ header = 'Player interactions' } --N0 :addData { sdata.quests, label = 'Quests' } --N1 :addData { sdata.shop, label = 'Shop' } :done :addGroup{ header = 'Next Event', collapse = 'open' } --S0 :addData{ sdata.datetime, label = 'Date & Time' } --S1 :addData{ sdata.countdown, label = 'Happening In' } :done :addGroup{ header = 'Minimap (at Coordinates)', collapse = 'open' } --O0 :addData { sdata.minimap } :done :addGroup{ header = 'Ideal Layout', collapse = 'closed' } --P0 :addData{ sdata.ideal_layout } :done :addGroup{ header = 'Metadata', ['row-items'] = 1, collapse = 'closed' } --Q0 :addData{ sdata.id, label = 'ID' } :done end return table.concat{ ibox:tostring, curTitle.namespace == 0 and category_to_add or '', } end

function p.test return p._infoboxCreate{ } end

--Finish Module/Exports return p