Module:Infobox/Item

-- Get Required Modules local loader = require('Module:Loader')

local string, table, yesno, arguments, statname, Infobox, mRarity, mLink, mOdds, bazaar, templates, list, ability, currency, animate, mItem, pet, inventorySlot = loader.lazy.require('String', 'Table', 'Yesno', 'Arguments', 'Statname', 'Infobox', 'RarityTier', 'Link', 'Odds', 'Bazaar', 'String/Templates', 'List', 'Ability', 'Currency', 'Animate',' Item', 'Pet', 'Inventory slot')

local iData = loader.lazy.loadData('Infobox/Data') local getArgs = arguments.getArgs

local curTitle = mw.title.getCurrentTitle

-- Function to iterate through armor pieces *in correct order* local function armorPiecesIterable return table.sortedPairsByValue(iData.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({ bazaar.lastUpdatedIcon, }, 'sup') }, layout = 'horizontal', ['row-items'] = 2 } :addData{ label = 'Buy', table.concat{ (''):format(1, id, 'buy', 'true'), string.wrapTag(bazaar._getPriceChange(id, 'buy', 'icononly'), 'sup')} } :addData{ label = 'Sell', table.concat{ (''):format(1, id, 'sell', 'true'), string.wrapTag(bazaar._getPriceChange(id, 'sell', 'icononly'), 'sup')} } :addGroup{ ['row-items'] = 1 } :addData{ string.wrapTag("Price Spread: "..bazaar._getPriceSpread(id, nil, true), 'center') } :done :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, isPowerStone, isArmorSet, isArmorPiece, isWeapon, isSack, isPet do local function check(v) return (deftype or ''):lower:match(v) and true or false end isEnchantment = check('enchantment') isReforgeStone = check('reforge stone') isPowerStone = check('power 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.baseText 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(iData.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 iData.sacksSuffix[3][3] or cap) end end for j = 1, iData.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 = iData.sacksSuffix[j][1] or ( j == 1 and '' or j ) _i = iData.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(iData.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 iData.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' --0.5			s.tab_title = argJ('tab_title') local tabPage = argJ('tab_page') or pagename -- page to get images/slots from --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 if isPet --and not argI('image') then s.image = '*[Image]' .. tabPage end s.image = not s.image_gallery and string.wrapTag(animate.animate({ s.image or argI('image') or tabPage, class = 'pi-image-thumbnail', caption = s.caption }), 'center') or nil if s.image_gallery and s.caption then s.caption = string.wrapHtml(s.caption, 'div', { class = 'pi-item-spacing pi-caption' }) end --[3]]			local slotdone = false if isArmorSet then -- LEGACY SUPPORT: MAY BE REMOVED AT ANY TIME for _, v in ipairs(armorPieces) do					s['slot_'..v] = armorArgI('slot_$1', v)				end local ret = {} for _, v in ipairs(armorPieces) do					table.push(ret, s['slot_'..v] and inventorySlot.slot{						s['slot_'..v]					}) end if #ret > 0 then s.slot_item = string.wrapHtml(table.concat(ret), 'center') .. ''					slotdone = true end end if not slotdone then -- Current implementation: s.slot_item = argI('slot_item') or argI('slot') if isPet or isArmorSet then s.slot_item = s.slot_item or ('*' .. tabPage) end s.slot_item = yesno(s.slot_item, true) and (s.slot_item or tabPage) or s.slot_item s.slot_item = s.slot_item and string.wrapHtml(not s.slot_item:match('(.-)') and 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),					display = 'inline-grid'				} or s.slot_item, 'center') 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') and mLink.collectionLink{ argI('hotm_requirement'), showIcon = true } --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') --23			s.essence = argI('essence') and mItem._itemDisplay(argI('essence'):gsub('%s+[Ee]ssence$', '') .. ' Essence') -- 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') -- Garden group s.organic_matter = argI('organicmatter') -- Stats group if isArmorSet then --D0 s.stats = argI('stats') --D1+ for _, v in pairs(iData.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(iData.allstats), function (v) local ln, sh = v[1], v[2] --D1+(-H/-C/-L/-B) s[('%s_%s'):format(a, sh)] = armorArgI('$1_' .. sh, a) or armorArgI('$1_' .. ln, a)					end)				end) else --D0 s.stats = argI('stats') --D1+ table.each(table.values(iData.allstats), function(v)					local ln = v[1]					s[ln] = argI(ln)				end) end --D24 s.swing_range = argI('swing_range') --D25 s.shot_cooldown = argI('shot_cooldown') -- 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.tiered_armor_bonus = argI('tiered_armor_bonus') --E5 s.piece_bonus = argI('piece_bonus') --E6 s.full_set_bonus2 = argI('full_set_bonus2') --E7 s.tiered_armor_bonus_2 = argI('tiered_armor_bonus_2') --E8 s.piece_bonus2 = argI('piece_bonus2') -- Abilities for k = 1, table.length(iData.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] = '' end if s['ability_activation'..counter] then abnmdc[#abnmdc+1] = '  ' 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['coin_cost'..counter] = arg('coin_cost') or arg('coin.cost') or arg('coincost') or arg('ia_coin_cost') --F5 s['cooldown'..counter] = arg('cooldown') or arg('ia_cooldown') --F6 s['int_scaling'..counter] = arg('int_scaling') --F7 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 mItem._itemDisplay(argI('upgrades_from')) or (argI('upgrades_to') and 'None (lowest tier item)') --H1 s.upgrades_to = argI('upgrades_to') and mItem._itemDisplay(argI('upgrades_to')) or (argI('upgrades_from') and 'None (top tier item)') -- Tiers group --I0 s.lower_tier = argI('lower_tier') and mItem._itemDisplay(argI('lower_tier')) or (argI('higher_tier') and 'None (lowest tier item)') --I1 s.higher_tier = argI('higher_tier') and mItem._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') } -- Enchantment Requirements s.min_level = argI("min_level") --T1 s.max_level = argI("max_level") --T2 s.applied_to = argI("applied_to") and list.plainlist{argI("applied_to")} --T3 s.experience_cost = argI('experience_cost') and (""):format(argI('experience_cost')) --T4 s.req_enchanting_level = argI('req_enchanting_level') -- 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.attributes = yesnoIcon(argI('attributes')) --K4 s.salable = yesnoIcon(argI('salable') or argI('sellable')) --K5 s.tradeable = yesnoIcon(argI('tradeable') or argI('trade')) --K6 s.auctionable = yesnoIcon(argI('auctionable')) --K7 s.rideable = yesnoIcon(argI('rideable')) --K8 s.donatable = yesnoIcon(argI('donatable') or argI('museum')) --K9 s.soulbound = argI('soulbound') and yesnoIcon(not not argI('soulbound')) .. ' (' .. argI('soulbound') .. ')' -- 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 or isReforgeStone or isPowerStone)) 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 not argI('color'):find(',') 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 (argI('buy'):match('.-') and argI('buy') or currency.currency{ argI('buy') }) or nil --M3 if argI('sell') then if argI('sell'):find('^[%s%d%.,%-Kk]+$') or (argI('sell'):find('%s+%w+$') and argI('sell'):find('^[%s%d%.,]+')) then s.sell = currency.currency{ argI('sell') } else local price = mItem._sellPrice(argI('sell')) s.sell = price and currency.currency{ price } end end --M4-21 if isPet then for _, v in ipairs(iData.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 currency.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 currency.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 = mLink._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 local doTitle = yesno(args['title'], true) if doTitle then ibox:addTitle{ args['title'] or curTitle.text } end local panel = ibox:addPanel for i, sectionData in ipairs(sections) do		local sdata = argNormalize(sectionData) local section = --0 panel:addSection{ label = sdata.tab } if sdata.tab_title then section:addTitle{ sdata.tab_title } end --1|2		if sdata.image_gallery then -- seems like galleries does not accept caption section:addImage{ sdata.image_gallery, --caption = { sdata.caption }, source = 'image'..(i == 1 and '' or i) } section:addData{ sdata.caption } 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 = 'Tooltip Text' } --21 :addData{ sdata.mob, label = 'Mob' } --22 :addData{ sdata.rarities, label = 'Rarities' } --23 :addData{ sdata.essence, label = string.makeLink('Essence') } :addGroup{ header = 'Sack Stats' } --A0 :addData{ sdata.sack_capacity, label = 'Max Capacity' } --A1 :addData{ sdata.sack_items, label = 'Items' } :done :addGroup{ header = 'Garden' } --C0 :addData{ sdata.organic_matter, label = 'Organic Matter' } :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(iData.allstats) do				local ln = v[1] --D1+group_:addData{ sdata[ln], label = statname._getStatName(ln, nil, true) } end --D24 group_:addData{ sdata.swing_range, label = 'Swing Range'} --D25 group_:addData{ sdata.shot_cooldown, label = 'Shot Cooldown' } -- 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(iData.allstats) do						local ln, sh = val[1], val[2] --D1+(-H/-C/-L/-B)group_:addData{ sdata[('%s_%s'):format(piece, sh)], label = statname._getStatName(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.tiered_armor_bonus, label = ability.tieredArmorBonus } --E5 :addData{ sdata.piece_bonus, label = ability.pieceBonus } --E6 :addData{ sdata.full_set_bonus2, label = ability.fullSetBonus } --E7 :addData{ sdata.tiered_armor_bonus_2, label = ability.tieredArmorBonus } --E8 :addData{ sdata.piece_bonus2, label = ability.pieceBonus } :done for k = 1, table.length(iData.abilityPlaces), 1 do			local counter = k > 1 and k or '' section:addGroup{ header = iData.abilityPlaces[k]..' Ability', name = 'infobox-stats-list' } --F0 :addData{ sdata['ability_name_desc'..counter] } --F1 :addData{ sdata['soulflow_cost'..counter], label = statname._getStatName('Soulflow Cost') } --F2 :addData{ sdata['mana_cost'..counter], label = statname._getStatName('Manacost') } --F3 :addData{ sdata['health_cost'..counter], label = statname._getStatName('Health Cost') } --F4 :addData{ sdata['coin_cost'..counter], label = 'Coin Cost'} --F5 :addData{ sdata['cooldown'..counter], label = 'Cooldown' } --F6 :addData{ sdata['int_scaling'..counter], label = { '%s Scaling', statname._getStatName('int', nil, true) } } --F7 :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 :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 = 'Enchantment Requirements', collapse = 'open'} --T0 :addData{ sdata.min_level, label = 'Minimum Level' } --T1 :addData{ sdata.max_level, label = 'Maximum Level' } --T2 :addData{ sdata.applied_to, label = 'Applied To' } --T3 :addData{ sdata.experience_cost, label = 'Experience Cost' } --T4 :addData{ sdata.req_enchanting_level, label = 'Req. Enchanting Level' } :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.attributes, label = string.makeTitle('Attributes', 'Whether or not the item(s) come with 2 Attributes applied when obtained, and can have Attribute Shards applied to them') } --K4 :addData{ sdata.salable, label = string.makeTitle('Salable', 'Whether or not the item(s) can be sold to an NPC.\nIf an item is not salable but has enchantments on it, it becomes salable.') } --K5 :addData{ sdata.tradeable, label = 'Tradeable' } --K6 :addData{ sdata.auctionable, label = 'Auctionable' } --K7 :addData{ sdata.rideable, label = 'Rideable' } --K8 :addData{ sdata.donatable, label = string.makeTitle('Museum', 'Whether or not the item(s) can be donated to the Museum') } --K9 :addData{ sdata.soulbound, label = 'Soulbound' } :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(iData.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