Module:Infobox/Item

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

loadLib(_G, {	infobox = 'Infobox',	mRarity = 'RarityTier',	mLink = 'Link',	mOdds = 'Odds',	{'Bazaar', values = {		bazaarLastUpdatedIcon = 'lastUpdatedIcon',		getBazaarPriceChange = '_getPriceChange',		getBazaarPriceSpred = '_getPriceSpread',	}},	templates = 'String/Templates',	list = 'List',	ability = 'Ability',	{'Currency', values = {		'currency',	}},	animate = 'Animate',	iData = 'Infobox/Data',	mItem = 'Item',	pet = 'Pet',	inventorySlot = 'Inventory slot', })

mw.html.create = require('Module:Html').create local curTitle = mw.title.getCurrentTitle local armorInfo, allstats, rarityList, MAX_INDEX, MAX_TAB, sacksSuffix, abilityPlaces = iData.armorInfo, iData.allstats --D1+, iData.rarityList --M4-21, iData.MAX_INDEX, iData.MAX_TAB, iData.sacksSuffix, iData.abilityPlaces

-- Function to iterate through armor pieces *in correct order* local function armorPiecesIterable return table.sortedPairsByValue(armorInfo, function(a, b)		return a.order < b.order	end) end -- Armor Pieces in order local armorPieces = table.toCustomArrayNamed(armorPiecesIterable)

--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 addBazaarGroup(id, parent) if id then parent :addGroup{ header = { 'Bazaar', string.wrapTag({ bazaarLastUpdatedIcon, '', }, 'sup') }, layout = 'horizontal', ['row-items'] = 2 } :addData{ label = 'Buy', (''):format(1, id, 'buy', 'true') } :addData{ label = 'Sell', (''):format(1, id, 'sell', 'true') } :addData{ label = 'Buy (stack)', (''):format(64, id, 'buy', 'true') } :addData{ label = 'Sell (stack)', (''):format(64, id, 'sell', 'true') } :addGroup{ ['row-items'] = 1 } :addData{ label = string.wrapTag('Price Spread', 'center'), string.wrapTag(getBazaarPriceSpred(id, nil, true), 'center') } :done :addData{ getBazaarPriceChange(id, 'buy', true), label = { 'Buy Price Change', string.wrapTag(bazaarLastUpdatedIcon, 'sup') } } :addData{ getBazaarPriceChange(id, 'sell', true), label = { 'Sell Price Change', string.wrapTag(bazaarLastUpdatedIcon, 'sup') } } :done 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; Need to check if reforge stone due to naming conflict with 'reforge' and a 'reforgeable' alt name local isReforgeStone, isArmorSet, isArmorPiece, isWeapon, isSack, isPet do local function check(v) return (deftype or ''):lower:match(v) and true or false end isReforgeStone = check('reforge stone') isArmorSet = check('armor') and check('set') isArmorPiece = check('armor') and not check('set') isWeapon = check('weapon') isSack = check('sack') isPet = check('pet') end local pagename = curTitle.text or 'Diamond' local title = args.title or pagename local category_to_add = args.category_to_add or '' local onmain = curTitle.namespace == 0 local sections = {} local idsExistForAllTabs = true local propertiesExistForAllTabs = true local idRequirementDisabled = isPet or false -- Sack Handler if isSack then local onetier = yesno(args.only_one_tier or args.is_ench_sack, false) for i, v in ipairs(sacksSuffix) do			local sf, fl, cap = v[1], v[2], v[3] local function argS(name) return args[name..i] or args[name..sf] end args['tab'..i] = argS('tab') or not onetier and fl or nil args['tab'..sf] = args['tab'..i]			args['image'..sf] = argS('image') or onetier and ('%s.png'):format(pagename) or ('%s %s.png'):format(fl, pagename) args['slot'..sf] = argS('slot') or onetier and pagename or ('%s %s'):format(fl, pagename) args['sack_capacity'..sf] = argS('sack_capacity') or ('%s for each item'):format(onetier and sacksSuffix[3][3] or cap) end end 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 local i, _i if isSack then -- Support custom syntax i = sacksSuffix[j][1] or ( j == 1 and '' or j ) _i = sacksSuffix[j][1] or ( j == 1 and '' or '_'..j ) else -- section one does have numbers after params; on 2+ do that i = j == 1 and  or j				_i = j == 1 and  or '_'..j -- needed for when a param ends in a number naturally end local function armorArgI(name, piece, default) -- accepts '$1' inside the name representing the armor piece local ret for _, v in ipairs(armorInfo[piece].aliases) do					local arg = name:gsub(('%$1'), v)					ret = ret or args[arg..(arg:match('%d$') and _i or i)] end return ret or default end local function argI(name, default) -- Special handler for armor pieces alternative syntax: { } local piece = name:match('{(%w+)}') if piece and armorInfo[piece] then name = name:gsub('{%w+}', '$1') return armorArgI(name, piece, default) end -- Normal flow return args[name..(name:match('%d$') and _i or i)] or default end local function sumStat(attr) local ret = 0 for _, piece in ipairs(armorPieces) do ret = ret + (tonumber(armorArgI('$1_' .. attr, piece)) or 0) end return ret > 0 and ret or nil end local function processStat(long, short) return argI(long) or argI(short) or sumStat(short) end if isArmorSet then if not (argI('{chest}_id') and argI('{legs}_id') and argI('{boots}_id')) then idsExistForAllTabs = false end else if not argI('id') then idsExistForAllTabs = false end end -- table of all params for this section local s = {} -- whether default properties is turned off local noProperties = yesno(argI('noProperties') or argI('noproperties') or argI('noprop'), false) -- 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 string.wrapTag(animate.animate({ argI('image') or pagename..'.png', class = 'pi-image-thumbnail', caption = s.caption }), 'center') or nil --[3]]			if isArmorSet then for _, v in ipairs(armorPieces) do					s['slot_'..v] = armorArgI('slot_$1', v)					s['slot_'..v] = yesno(s['slot_'..v], true) and (s['slot_'..v] or pagename:gsub('%s*Armor$',' '..armorInfo[v].name)) or nil end local ret = {} for _, v in ipairs(armorPieces) do					table.push(ret, s['slot_'..v] and inventorySlot.slot{						s['slot_'..v],						link = not onmain and 'none' or nil					}) end s.slot_item = string.wrapHtml(table.concat(ret), 'center') else s.slot_item = argI('slot_item') or argI('slot') if isPet then local _slot = pet.inquireslots(s.slot_item or pagename) s.slot_item = table.concat{ string.wrapHtml((_slot == '') and s.slot_item or _slot, 'center'), string.wrapHtml('Above displays all rarities of this pet.', 'div', { class = 'pi-item-spacing pi-caption' }), }				else s.slot_item = yesno(s.slot_item, true) and (s.slot_item or pagename) or nil s.slot_item = s.slot_item and string.wrapHtml(inventorySlot.slot{						s.slot_item,						text = argI('slot_text') or nil,						title = argI('slot_title') or nil,						link = argI('slot_link') or (not onmain and 'none' or nil),					}, 'center') end end --4			s.aka = argI('aka') --5			s.type = argI('type') or deftype or 'Item' --6			s.rarity = argI('rarity') and mRarity.link{ argI('rarity'), addcategory = true } --7			s.collection = argI('collection') and mLink.collectionLink{ argI('collection'), showIcon = true } --8			s.combat_level_requirement = argI('combat_level_requirement') --9			s.slayer_level_requirement = argI('slayer_level_requirement') and mLink.collectionLink{ argI('slayer_level_requirement'), showIcon = true } --10			s.dungeon_level_requirement = argI('dungeon_level_requirement') --11			s.dungeon_floor_clearing_requirement = argI('dungeon_floor_clearing_requirement') --12			s.hotm_requirement = argI('hotm_requirement') --13			s.other_level_requirement = argI('other_level_requirement') --14			s.reforge_name = (isReforgeStone and argI('reforge')) or argI('reforge_name') --15			s.source = argI('source') --16			s.obtained = argI('obtained') or argI('obtain') or argI('obtaining') --17			s.drop_chance = argI('drop_chance') or argI('odds') if s.drop_chance then if s.drop_chance:sub(1,1):lower == 'u' then s.drop_chance = templates.unknown(1) else s.drop_chance = mOdds.odds{ s.drop_chance, big = true } end end --18			s.uses = argI('uses') or argI('usage') --19			s.minion_xp = argI('minion_xp') and (''):format(argI('minion_xp')) --20			s.lore = argI('lore') --21			s.mob = argI('mob') --22			s.rarities = argI('rarities') -- Sack Stats group -- since all sacks share same items, no reason to pass it in multiple times --A0 s.sack_capacity = argI('sack_capacity') --A1 s.sack_items = argI('sack_items') or args['sack_items'] if s.sack_items then -- If the list of items is to large to easily fit, collapse it				local _, count = string.gsub(s.sack_items, '%*', '') s.sack_items = (''):format(s.sack_items) if count > 4 then s.sack_items = string.wrapHtml(s.sack_items,'div',{						class = 'mw-collapsible mw-collapsed'					}) end end -- Block Details group --B0 s.location = argI('location') and (''):format(argI('location')) --B1 s.tool = argI('tool') and (''):format(argI('tool')) --B2 s.breaking_power_required = argI('breaking_power_required') --B3 s.skill_xp_given = argI('skill_xp_given') and (''):format(argI('skill_xp_given')) --B4 -- Block Drops s.experience_given = argI('experience_given') --B5 s.normal_drop = argI('normal_drop') --B6 s.silk_touch_drop = argI('silk_touch_drop') --B7 s.smelting_touch_drop = argI('smelting_touch_drop') -- Function group --C0 s['function']= argI('function') -- Stats group if isArmorSet then --D0 s.stats = argI('stats') --D1+ for _, v in pairs(allstats) do					local ln, sh = v[1], v[2] s[ln] = processStat(ln,sh) end table.each( armorPieces, function(a)					--D0(-H/-C/-L/-B) s[a .. '_stats'] = armorArgI('$1_stats', a)					table.each( table.values(allstats), function (v) local b = v[2] -- stat short name --D1+(-H/-C/-L/-B) s[('%s_%s'):format(a, b)] = armorArgI('$1_' .. b, a)					end)				end) else --D0 s.stats = argI('stats') --D1+ table.each(table.values(allstats), function(v)					local ln = v[1]					s[ln] = argI(ln)				end) end -- Special Effects --E0 s.effects = argI('effects') or argI('effect') or argI('special_effect') or argI('additional_effects') --E1 s.duration = argI('duration') --E2 s.speed_boost = argI('speed_boost') -- used by minion fuel --E3 s.full_set_bonus = argI('full_set_bonus') --E4 s.piece_bonus = argI('piece_bonus') --E5 s.full_set_bonus2 = argI('full_set_bonus2') --E6 s.piece_bonus2 = argI('piece_bonus2') -- Abilities for k = 1, #abilityPlaces, 1 do				local counter = k > 1 and k or '' local function arg(name) return args[name..counter.._i] end --F0 s['ability_name'..counter] = arg('ability_name') or arg('ability') or arg('ia_name') or arg('abilityname') s['ability_desc'..counter] = arg('ability_desc') or arg('item_ability') or arg('ia_desc') or arg('abilitydesc') s['ability_activation'..counter] = arg('ability_activation') or arg('ia_activation') if s['ability_name'..counter] or s['ability_desc'..counter] then local abnmdc = {} -- ability_name_desc abnmdc[#abnmdc+1] = '\'\'\'' if s['ability_name'..counter] then abnmdc[#abnmdc+1] = ability.ability{ s['ability_name'..counter] } else abnmdc[#abnmdc+1] = colorText('Gray', '\'\'\'\'') end if s['ability_activation'..counter] then abnmdc[#abnmdc+1] = '  '..colorText('Yellow', s['ability_activation'..counter]:upper) end abnmdc[#abnmdc+1] = '\'\'\'' abnmdc[#abnmdc+1] = ' '					abnmdc[#abnmdc+1] = s['ability_desc'..counter] or '\'\'description missing\'\'' -- Combine final product s['ability_name_desc'..counter] = table.concat(abnmdc) end --F1 s['soulflow_cost'..counter] = arg('soulflow_cost') or arg('soulflow.cost') or arg('soulflow') or arg('sfcost') or arg('ia_soulflow') --F2 s['mana_cost'..counter] = arg('mana_cost') or arg('mana.cost') or arg('mana') or arg('manacost') or arg('ia_mana_cost') --F3 s['health_cost'..counter] = arg('health_cost') or arg('health.cost') or arg('hpcost') or arg('ia_health_cost') --F4 s['cooldown'..counter] = arg('cooldown') or arg('ia_cooldown') --F5 s['int_scaling'..counter] = arg('int_scaling') --F6 s['max_souls'..counter] = arg('max_souls') end -- Material Tiers group --G0 s.prev_material = argI('prev_material') and list.imageList{ argI('prev_material') } or (argI('next_material') and 'None (lowest tier material)') --G1 s.next_material = argI('next_material') and list.imageList{ argI('next_material') } or (argI('prev_material') and 'None (top tier material)') -- Upgrades group --H0 s.upgrades_from = argI('upgrades_from') and itemDisplay(argI('upgrades_from')) or (argI('upgrades_to') and 'None (lowest tier item)') --H1 s.upgrades_to = argI('upgrades_to') and itemDisplay(argI('upgrades_to')) or (argI('upgrades_from') and 'None (top tier item)') -- Tiers group --I0 s.lower_tier = argI('lower_tier') and itemDisplay(argI('lower_tier')) or (argI('higher_tier') and 'None (lowest tier item)') --I1 s.higher_tier = argI('higher_tier') and itemDisplay(argI('higher_tier')) or (argI('lower_tier') and 'None (top tier item)') -- Gemstone Upgrades --R0 s.gemstone_slots = argI('gemstone_upgrades') or argI('gemstone_slots') if s.gemstone_slots then s.gemstone_slots = list.gemstoneSlots{ s.gemstone_slots }..(onmain and  or ) end --R1 s.gemstone_slots_fragged = argI('gemstone_slots_fragged') and list.gemstoneSlots{ argI('gemstone_slots_fragged') } -- Reforge Requirements --J0 s.req_item_rarity = argI('req_item_rarity') --J1 s.apply_cost = argI('apply_cost') --J2 s.req_skill_level = argI('req_skill_level') and '' -- Properties group --K0 s.upgradeable = yesnoIcon(argI('upgradeable')) --K1 s.enchantable = yesnoIcon(argI('enchant') or argI('enchantable')) --K2 s.reforgeable = yesnoIcon((not isReforgeStone and argI('reforge')) or argI('reforgeable')) --K3 s.salable = yesnoIcon(argI('salable') or argI('sellable')) --K4 s.tradeable = yesnoIcon(argI('tradeable') or argI('trade')) --K5 s.auctionable = yesnoIcon(argI('auctionable')) --K6 s.rideable = yesnoIcon(argI('rideable')) --K7 s.donatable = yesnoIcon(argI('donatable') or argI('museum')) -- Set default values for Property value (Group K), if applicable -- Since they are yes/no icons, no need to check 'if nil'. if not noProperties then s.salable = s.salable or yesnoIcon(not (isPet or isSack)) s.tradeable = s.tradeable or yesnoIcon(not isSack and true or false) s.auctionable = s.auctionable or yesnoIcon(not isSack and true or false) s.donatable = s.donatable or yesnoIcon(isArmorSet or isArmorPiece or isWeapon) if isPet then s.rideable = s.rideable or yesnoIcon(false) end end -- Property value (Group K) checks if isPet then if (argI('rideable') or ''):sub(1,1):lower == 'u' then propertiesExistForAllTabs = false end end for _, v in ipairs{'upgradeable', {'enchant', 'enchantable'}, {'reforge', 'reforgeable'}, {'salable', 'sellable'}, {'tradeable', 'trade'}, 'auctionable'} do				local okay = true for _,a in ipairs(type(v) == 'table' and v or {v}) do if (argI(a) or ''):sub(1,1):lower == 'u' then okay = false end end if not okay then propertiesExistForAllTabs = false end end -- Color Group --L0 s.color = argI('color') and ():format(				argI('color'),				( not isArmorSet or yesno(argI('all_colors_the_same')) )					and '|all = true' or 			) -- Shop --M0 s.merchant = argI('merchant') and list.npcList{ argI('merchant'), noerr = true, liststyle = 'text-align:center;' } --M1 s.daily_limit = argI('daily_limit') --M2 s.buy = argI('buy') and currency{ argI('buy') } --M3 if argI('sell') then if argI('sell'):find('^[%s%d%.,]+$') or (argI('sell'):find('%s+%w+$') and argI('sell'):find('^[%s%d%.,]+')) then s.sell = currency{ argI('sell') } else local price = mItem._sellPrice(argI('sell')) s.sell = price and currency{ price } end end --M4-21 if isPet then for _, v in ipairs(rarityList) do					s['buy'..v[1]] = argI('buy'..v[1]) s['sell'..v[1]] = argI('sell'..v[1]) and ('US$%s'):format(argI('sell'..v[1])) end end -- Bazaar --N0 s.bazaar = argI('bazaar') -- Materials --O0 s.raw_materials = argI('raw_materials') and list.resourceList{ image = 1, argI('raw_materials') } --O1 s.material_cost = argI('material_cost') and coins{ argI('material_cost') } --O2 s.mat_cost_bazaar = argI('mat_cost_bazaar') and ():format(				argI('mat_cost_bazaar') or argI('raw_materials'),				argI('bazaar_not_including') and '|not_including='..argI('bazaar_not_including') or 				):gsub('\n', '') --O3 s.raw_materials_upgr = argI('raw_materials_upgr') and list.resourceList{ image = 1, argI('raw_materials_upgr') } --O4 s.material_cost_upgr = argI('material_cost_upgr') and coins{ argI('material_cost_upgr') } --O5 s.mat_cost_bazaar_upgr = argI('mat_cost_bazaar_upgr') and ():format(				argI('mat_cost_bazaar_upgr') or argI('raw_materials_upgr'),				argI('bazaar_not_including_upgr') and '|not_including='..argI('bazaar_not_including_upgr') or 				):gsub('\n', '') -- Trade --P0 s.trade_requirement = argI('trade_requirement') or argI('trade.requirement') if s.trade_requirement then s.trade_requirement = link._collectionLink(s.trade_requirement, nil, true) end --P1 s.trade_from = argI('trade_from') or argI('trade.from') --P2 s.trade_to = argI('trade_to') or argI('trade.to') -- 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 -- Item Metadata s.id = argI('item_id') or (isPet and pet.inquirerarities(argI('tab') or title) or nil) for _, v in ipairs(table.merge( --Q0 { 'id' }, --Q1-4 table.map(armorPieces, function(a) return ('{%s}_id'):format(a) end) )) do				s[v] = s[v] or argI(v) if s[v] then -- Always show ID in all caps s[v] = string.wrapTag(s[v]:upper, 'code') -- If array syntax, make a list s[v] = s[v]:gsub(' ', '') -- lazy trim for array; ids never naturally have spaces s[v] = table.concat(mw.text.split(s[v], ','), ' ') end end --Q5 s.head_texture = argI('head_texture') or argI('head_tex') s.head_texture = s.head_texture and string.wrapTag(s.head_texture, 'code') for _, v in ipairs(table.merge( --Q6 { 'nbt' }, --Q7-10 table.map(armorPieces, function(a) return ('{%s}_nbt'):format(a) end) )) do				s[v] = argI(v) and argI(v):gsub('(   +)', ' %1') -- Since newlines are being deleted, can't be used; and since escape br tags, need to make own fake pre tag s[v] = s[v] and string.wrapHtml(s[v], 'div', {					style = {						['background-color'] = 'rgba(0,0,0,0.35)',						border = '1px solid #9b8d8e',						overflow = 'auto',						['word-wrap'] = 'normal',						['white-space'] = 'pre',					}				}):gsub('} ', ' } ') 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 = --0 panel: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.rarity, label = 'Rarity' } --7 :addData{ sdata.collection, label = string.makeLink('Collections', 'Collection') } --8 :addData{ sdata.combat_level_requirement, label = 'Combat Level Requirement' } --9 :addData{ sdata.slayer_level_requirement, label = 'Slayer Level Requirement' } --10 :addData{ sdata.dungeon_level_requirement, label = 'Dungeon Level Requirement' } --11 :addData{ sdata.dungeon_floor_clearing_requirement, label = 'Requires Dungeon Floor Cleared' } --12 :addData{ sdata.hotm_requirement, label = 'Heart of the Mountain Level Requirement' } --13 :addData{ sdata.other_level_requirement, label = 'Skill Level Requirement' } --14 :addData{ sdata.reforge_name, label = 'Reforge' } --15 :addData{ sdata.source, label = 'Source' } --16 :addData{ sdata.obtained, label = 'Obtained via' } --17 :addData{ sdata.drop_chance, label = 'Drop Chance' } --18 :addData{ sdata.uses, label = 'Uses' } --19 :addData{ sdata.minion_xp, label = string.makeTitle('Minion XP', 'The amount of xp a player receives when taking this material from a minion inventory.') } --20 :addData{ sdata.lore, label = 'Lore' } --21 :addData{ sdata.mob, label = 'Mob' } --22 :addData{ sdata.rarities, label = 'Rarities' } :addGroup{ header = 'Sack Stats' } --A0 :addData{ sdata.sack_capacity, label = 'Max Capacity' } --A1 :addData{ sdata.sack_items, label = 'Items' } :done :addGroup{ header = 'Block Details' } --B0 :addData{ sdata.location, label = 'Location' } --B1 :addData{ sdata.tool, label = string.makeLink('Tool') } --B2 :addData{ sdata.breaking_power_required, label = ' Required' } --B3 :addData{ sdata.skill_xp_given, label = 'Skill XP Given' } --B4 :addData{ sdata.experience_given, label = 'Experience Given' } :addGroup{ header = 'Block Drops', layout = 'horizontal', ['row-items'] = 3 } --B5 :addData{ sdata.normal_drop, label = 'Normal drop' } --B6 :addData{ sdata.silk_touch_drop, label = 'Silk Touch drop' } --B7 :addData{ sdata.smelting_touch_drop, label = 'Smelting Touch Drop' } :done :done :addGroup{ header = 'Function' } --C0 :addData{ sdata['function'] } :done do -- define first group local panel_, group_ if isArmorSet then panel_ = section:addPanel{ header = 'Stats', collapse = 'open' } group_ = panel_:addSection{ label = 'Total' }:addGroup{ name = 'infobox-stats-list' } else group_ = section:addGroup{ header = 'Stats', name = 'infobox-stats-list' } end -- process first group --D0 group_:addData{ sdata.stats } for _, v in pairs(allstats) do				local ln = v[1] --D1+group_:addData{ sdata[ln], label = makeStat(ln, nil, true) } end -- process all armor groups if isArmorSet then for piece, data in armorPiecesIterable do					local lbl = data.shortname group_ = panel_:addSection{ label = lbl }:addGroup{ name = 'infobox-stats-list' } --D0 (-H/-C/-L/-B)group_:addData{ sdata[('%s_stats'):format(piece)] } for _, val in pairs(allstats) do						local ln, sh = val[1], val[2] --D1+(-H/-C/-L/-B)group_:addData{ sdata[('%s_%s'):format(piece, sh)], label = makeStat(ln, nil, true) } end end end end section:addGroup{ header = 'Special Effects' } --E0 :addData{ sdata.effects } --E1 :addData{ sdata.duration, label = 'Duration' } --E2 :addData{ sdata.speed_boost, label = 'Speed Boost' } --E3 :addData{ sdata.full_set_bonus, label = ability.fullSetBonus } --E4 :addData{ sdata.piece_bonus, label = ability.pieceBonus } --E5 :addData{ sdata.full_set_bonus2, label = ability.fullSetBonus } --E6 :addData{ sdata.piece_bonus2, label = ability.pieceBonus } :done for k = 1, #abilityPlaces, 1 do			local counter = k > 1 and k or '' section:addGroup{ header = abilityPlaces[k]..' Ability', name = 'infobox-stats-list' } --F0 :addData{ sdata['ability_name_desc'..counter] } --F1 :addData{ sdata['soulflow_cost'..counter], label = makeStat('Soulflow Cost') } --F2 :addData{ sdata['mana_cost'..counter], label = makeStat('Manacost') } --F3 :addData{ sdata['health_cost'..counter], label = makeStat('Health Cost') } --F4 :addData{ sdata['cooldown'..counter], label = 'Cooldown' } --F5 :addData{ sdata['int_scaling'..counter], label = { '%s Scaling', makeStat('int', nil, true) } } --F6 :addData{ sdata['max_souls'..counter], label = 'Max Souls' } :done end section:addGroup{ header = 'Material Tiers', layout = 'horizontal' } --G0 :addData{ sdata.prev_material, label = '← Previous' } --G1 :addData{ sdata.next_material, label = 'Next →' } :done :addGroup{ header = 'Upgrades', layout = 'horizontal' } --H0 :addData{ sdata.upgrades_from, label = '← Previous' } --H1 :addData{ sdata.upgrades_to, label = 'Next →' } :done :addGroup{ header = 'Tiers', layout = 'horizontal' } --I0 :addData{ sdata.lower_tier, label = '← Previous' } --I1 :addData{ sdata.higher_tier, label = 'Next →' } :done section:addGroup{ header = isArmorSet and string.makeTitle('Gemstone Slots', 'These are the gemtone slots available to each armor piece.') or 'Gemstone Slots' } --R0 :addData{ sdata.gemstone_slots } --R1 :addData{ sdata.gemstone_slots_fragged, label = 'Fragged Slots' } :done :addGroup{ header = 'Reforge Requirements', collapse = 'open' } --J0 :addData{ sdata.req_item_rarity, label = 'Req. Item Rarity' } --J1 :addData{ sdata.apply_cost, label = 'Apply Cost' } --J2 :addData{ sdata.req_skill_level, label = 'Req. Skill Level' } :done :addGroup{ header = 'Properties', layout = 'horizontal', ['row-items'] = 2 } --K0 :addData{ sdata.upgradeable, label = 'Upgradeable' } --K1 :addData{ sdata.enchantable, label = 'Enchantable' } --K2 :addData{ sdata.reforgeable, label = 'Reforgeable' } --K3 :addData{ sdata.salable, label = 'Salable' } --K4 :addData{ sdata.tradeable, label = 'Tradeable' } --K5 :addData{ sdata.auctionable, label = 'Auctionable' } --K6 :addData{ sdata.rideable, label = 'Rideable' } --K7 :addData{ sdata.donatable, label = string.makeTitle('Museum', 'Whether or not the item(s) can be donated to the Museum') } :done :addGroup --L0 :addData{ sdata.color, label = 'Color' } :done local shop_group = section :addGroup{ header = 'Shop', layout = 'horizontal', ['row-items'] = 2 } if isPet then local merchant_panel = shop_group --M0 :addData{ sdata.merchant, label = 'Merchant'..(sdata.merchant and sdata.merchant:find('%s*%*%s*') and 's' or '') } :addPanel{ ['row-items'] = 1 } for _, v in ipairs(rarityList) do				merchant_panel:addSection{ label = v[2] } --M4-21 :addData{ sdata['buy'..v[1]], label = 'Buy' } :addData{ sdata['sell'..v[1]], label = 'Sell' } end else shop_group:addGroup{ ['row-items'] = 1 } --M0 :addData{ sdata.merchant, label = 'Merchant'..(sdata.merchant and sdata.merchant:find('%s*%*%s*') and 's' or '') } :done --M1 :addData{ sdata.daily_limit, label = string.makeTitle('Daily Limit', 'A limit on how much items of this type a player can buy in one day.') } --M2 :addData{ sdata.buy, label = 'Buy' } --M3 :addData{ sdata.sell, label = 'Sell' } end addBazaarGroup(--N0 sdata.bazaar, section) section:addGroup{ header = 'Materials' } --O0 :addData{ sdata.raw_materials, label = string.makeTitle('Raw Materials', 'All materials in their most basic form needed to obtain the item.') } --O1 :addData{ sdata.material_cost, label = string.makeTitle('Material cost', 'Cost to buy all necessary materials from merchants.') } --O2 :addData{ sdata.mat_cost_bazaar, label = string.makeTitle('Bazaar Material cost', 'Cost to buy all necessary materials from the Bazaar.') } --O3 :addData{ sdata.raw_materials_upgr, label = string.makeTitle('Raw Materials to upgrade', 'All materials in their most basic form needed to obtain the item.') } --O4 :addData{ sdata.material_cost_upgr, label = string.makeTitle('Material cost to upgrade', 'Cost to buy all necessary materials from merchants.') } --O5 :addData{ sdata.mat_cost_bazaar_upgr, label = string.makeTitle('Bazaar Material cost to upgrade', 'Cost to buy all necessary materials from the Bazaar.') } :done :addGroup{ header = 'Trade', layout = 'horizontal' } --P0 :addData{ sdata.trade_requirement, label = 'Requires' } --P1 :addData{ sdata.trade_from, label = 'From' } --P2 :addData{ sdata.trade_to, label = 'To' } :done :addGroup{ header = 'Next Event', collapse = 'open' } --S0 :addData{ sdata.datetime, label = 'Date & Time' } --S1 :addData{ sdata.countdown, label = 'Happening In' } :done :addGroup{ header = 'Item Metadata', ['row-items'] = 1, collapse = 'closed' } --Q0 :addData{ sdata.id, label = 'Item ID' } --Q1 :addData{ sdata.helmet_id, label = 'Helmet Item ID' } --Q2 :addData{ sdata.chest_id, label = 'Chestplate Item ID' } --Q3 :addData{ sdata.legs_id, label = 'Leggings Item ID' } --Q4 :addData{ sdata.boots_id, label = 'Boots Item ID' } --Q5 :addData{ sdata.head_texture, label = 'Head Texture' } --Q6 :addData{ sdata.nbt, label = 'NBT Data' } --Q7 :addData{ sdata.helmet_nbt, label = 'Helmet NBT Data' } --Q8 :addData{ sdata.chest_nbt, label = 'Chestplate NBT Data' } --Q9 :addData{ sdata.legs_nbt, label = 'Leggings NBT Data' } --Q10 :addData{ sdata.boots_nbt, label = 'Boots NBT Data' } :done end return table.concat{ ibox:tostring, curTitle.namespace == 0 and category_to_add or '', curTitle.namespace == 0 and not idsExistForAllTabs and not idRequirementDisabled and  or , curTitle.namespace == 0 and not propertiesExistForAllTabs and  or , } end

function p.test return p._infoboxCreate{ health = '+450', helmet_hp = '+90', chest_hp = '+150', legs_hp = '+130', boots_hp = '+80', defense = '+600', helmet_def = '+130', chest_def = '+190', legs_def = '+170', boots_def = '+110', speed = '+12', helmet_spd = '+3', chest_spd = '+3', legs_spd = '+3', boots_spd = '+3', intelligence = '+100', helmet_int = '+25', chest_int = '+25', legs_int = '+25', boots_int = '+25', default_type = 'Armor Set', id = 'GOBLIN_ARMOR', head_id = 'GOBLIN_HELMET', chest_id = 'GOBLIN_CHESTPLATE', legs_id = 'GOBLIN_LEGGINGS', boots_id = 'GOBLIN_BOOTS', } end

--Finish Module/Exports return p