From Dark and Darker Wiki

(Fleshed out the item category row functions.)
(only show passive for artifact or mini artifact)
 
(10 intermediate revisions by one other user not shown)
Line 43: Line 43:
local function header(args)
local function header(args)
local header_content = ""
local header_content = ""
if args.link == "nolink" then
if args.link then
header_content = string.format("<span class='bold cr%s'>%s</span>", args.rarity, args.name)
elseif args.link then
header_content = string.format("[[%s|<span class='cr%s'>%s</span>]]", args.link, args.rarity, args.name)
header_content = string.format("[[%s|<span class='cr%s'>%s</span>]]", args.link, args.rarity, args.name)
else
else
header_content = string.format("[[%s|<span class='cr%s'>%s</span>]]", args.name, args.rarity, args.name)
header_content = string.format("<span class='bold cr%s'>%s</span>", args.rarity, args.name)
end
end


Line 62: Line 60:
end
end


local function stat_index(item,rarity)
return 1 + tonumber(rarity) - item.rarities[1]
end


local function stat_block(wt, args, weapon)
local function stat_block(wt, args, item)
if count(weapon.stats.order) == 0 or weapon.numenchants[args.rarity] == 0 then return end
if not item.stats or count(item.stats.order) == 0 or item.numenchants[tonumber(args.rarity)] == 0 then return end


wt[#wt+1] = "<div style='text-align:center'>"
wt[#wt+1] = "<div style='text-align:center'>"
for i,stat_name in ipairs(weapon.stats.order) do
for i,stat_name in ipairs(item.stats.order) do
if i==1 then wt[#wt+1] = "<div style='margin-top:10px;display:flex;width:100%;flex-direction:row;justify-content:space-between'>"
wt[#wt+1] = "<div style='margin-top:10px;display:flex;width:100%;flex-direction:row;justify-content:space-between'>"
else        wt[#wt+1] = "<div style='display:flex;width:100%;flex-direction:row;justify-content:space-between'>" end
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
wt[#wt+1] = string.format("<div>%s %s</div>",stat_name,weapon.stats[(stat_name):lower()][tonumber(args.rarity)] or weapon.stats[(stat_name):lower()])
wt[#wt+1] = string.format("<div>%s %s</div>",stat_name,item.stats[(stat_name):lower()][stat_index(item,args.rarity)] or item.stats[(stat_name):lower()])
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
end
end


if weapon.numenchants[tonumber(args.rarity)] then
if item.numenchants[tonumber(args.rarity)] then
wt[#wt+1] = "<div class='cr4' style='margin-top:10px;display:flex; width:100%;flex-direction:row; justify-content:space-between'>"
wt[#wt+1] = "<div class='cr4' style='margin-top:10px;display:flex; width:100%;flex-direction:row; justify-content:space-between'>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
wt[#wt+1] = string.format("<div>Up to %i extra enchantments</div>",weapon.numenchants[tonumber(args.rarity)])
wt[#wt+1] = string.format("<div>Up to %i extra enchantments</div>",item.numenchants[tonumber(args.rarity)])
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
end
end


if weapon.haspassive then
if item.haspassive and item.isminiartifact or item.isartifact then
wt[#wt+1] = "<div style='margin-top:10px;display:flex;width:100%;flex-direction:row;justify-content:space-between;color:rgb(211,178,125)'>"
wt[#wt+1] = "<div style='margin-top:10px;display:flex;width:100%;flex-direction:row;justify-content:space-between;color:rgb(211,178,125)'>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
wt[#wt+1] = string.format("<div>%s</div>",weapon.artifactpower)
wt[#wt+1] = string.format("<div>%s</div>",item.artifactpower)
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
end
end
Line 94: Line 94:
local ret = ""
local ret = ""
for i,v in ipairs(list) do
for i,v in ipairs(list) do
if i~=1 then ret = ret.."," end
if i ~= 1 then ret = ret..", " end
ret = ret..v
ret = ret..v
end
end
return ret
end
end


local function type_list(t,type)
local function type_list(t,type)
local ret = ""
local ret = ""
local i = 1
for k,v in pairs(t) do
for k,v in pairs(t) do
if v==type then ret=ret..k end
if i ~= 1 then ret = ret..", " end
if v == type then
ret = ret..k
end
i = i + 1
end
end
return ret
return ret
Line 108: Line 114:


local function weapon_rows(rows, args, weapon)
local function weapon_rows(rows, args, weapon)
local index = tonumber(args.rarity)
rows[#rows+1] = hline()
rows[#rows+1] = hline()
stat_block(rows,args,weapon)
stat_block(rows,args,weapon)
Line 120: Line 128:
rows[#rows+1] = row_h("Quiver Size",weapon.maxammocount)
rows[#rows+1] = row_h("Quiver Size",weapon.maxammocount)


rows[#rows+1] = hline()
if count(weapon.hitbox) ~= 0 then
rows[#rows+1] = row_h("Hitbox",string.format("%sx%sx%s",weapon.hitbox.height,weapon.hitbox.width,weapon.hitbox.depth))
rows[#rows+1] = hline()
rows[#rows+1] = row_h("Hitbox",string.format("%sx%sx%s",weapon.hitbox.height,weapon.hitbox.width,weapon.hitbox.depth))
end


rows[#rows+1] = hline()
if weapon.invwidth ~= "" then
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",weapon.invwidth,weapon.invheight))
rows[#rows+1] = hline()
rows[#rows+1] = row_h("Gear Score",weapon.gearscore[args.rarity])
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",weapon.invwidth,weapon.invheight))
rows[#rows+1] = row_h("Sell Price",weapon.sellprices[args.rarity])
if weapon.maxcount ~= 1 then
rows[#rows+1] = row_h("Stack Size",weapon.maxcount)
rows[#rows+1] = row_h("Stack Size",weapon.maxcount)
end
rows[#rows+1] = row_h("Gear Score",weapon.gearscore[index])
rows[#rows+1] = row_h("Item Achieve",weapon.ap[index])
rows[#rows+1] = row_h("Sell Price",weapon.sellprices[index])
end


rows[#rows+1] = hline()
if weapon.flavortext ~= "" then
rows[#rows+1] = row_v3(weapon.flavortext)
rows[#rows+1] = hline()
rows[#rows+1] = row_v3(weapon.flavortext)
end
end
end


local function armor_rows(rows, args, armor)
local function armor_rows(rows, args, armor)
local index = tonumber(args.rarity)
rows[#rows+1] = hline()
rows[#rows+1] = hline()
stat_block(rows,args,armor)
stat_block(rows,args,armor)
Line 139: Line 158:
rows[#rows+1] = hline()
rows[#rows+1] = hline()
rows[#rows+1] = row_v("Required Class",class_list(armor.classes))
rows[#rows+1] = row_v("Required Class",class_list(armor.classes))
rows[#rows+1] = row_h("Armor Type",type_list(armor.types,"Armor"))
rows[#rows+1] = row_h("Slot Type",armor.slottype)
rows[#rows+1] = row_h("Slot Type",armor.slottype)


rows[#rows+1] = hline()
rows[#rows+1] = hline()
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",armor.invwidth,armor.invheight))
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",armor.invwidth,armor.invheight))
rows[#rows+1] = row_h("Gear Score",armor.gearscore[args.rarity])
rows[#rows+1] = row_h("Gear Score",armor.gearscore[index])
rows[#rows+1] = row_h("Sell Price",armor.sellprices[args.rarity])
rows[#rows+1] = row_h("Item Achieve",armor.ap[index])
rows[#rows+1] = row_h("Sell Price",armor.sellprices[index])


rows[#rows+1] = hline()
rows[#rows+1] = hline()
Line 151: Line 172:


local function accessory_rows(rows, args, accessory)
local function accessory_rows(rows, args, accessory)
local index = tonumber(args.rarity)
rows[#rows+1] = hline()
rows[#rows+1] = hline()
stat_block(rows,args,armor)
stat_block(rows,args,accessory)


rows[#rows+1] = hline()
rows[#rows+1] = hline()
Line 159: Line 182:
rows[#rows+1] = hline()
rows[#rows+1] = hline()
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",accessory.invwidth,accessory.invheight))
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",accessory.invwidth,accessory.invheight))
rows[#rows+1] = row_h("Gear Score",accessory.gearscore[args.rarity])
rows[#rows+1] = row_h("Gear Score",accessory.gearscore[index])
rows[#rows+1] = row_h("Sell Price",accessory.sellprices[args.rarity])
rows[#rows+1] = row_h("Item Achieve",accessory.ap[index])
rows[#rows+1] = row_h("Sell Price",accessory.sellprices[index])


rows[#rows+1] = hline()
rows[#rows+1] = hline()
Line 168: Line 192:


local function utility_rows(rows, args, utility)
local function utility_rows(rows, args, utility)
rows[#rows+1] = hline()
error("monster_rows() needs to be implemented")
stat_block(rows,args,utility)
 
rows[#rows+1] = hline()
rows[#rows+1] = row_v("Required Class",class_list(armor.classes))
rows[#rows+1] = row_h("Slot Type",utility.slottype)
 
rows[#rows+1] = hline()
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",accessory.invwidth,accessory.invheight))
rows[#rows+1] = row_h("Gear Score",utility.gearscore[args.rarity])
rows[#rows+1] = row_h("Sell Price",utility.sellprices[args.rarity])
 
rows[#rows+1] = hline()
rows[#rows+1] = row_v3(utility.flavortext)
end
end


local function misc_rows(rows, args, misc)
local function misc_rows(rows, args, misc)
rows[#rows+1] = hline()
local index = tonumber(args.rarity)
stat_block(rows,args,misc)


rows[#rows+1] = hline()
rows[#rows+1] = hline()
Line 194: Line 204:
rows[#rows+1] = hline()
rows[#rows+1] = hline()
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",misc.invwidth,misc.invheight))
rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",misc.invwidth,misc.invheight))
rows[#rows+1] = row_h("Gear Score",misc.gearscore[args.rarity])
if misc.maxcount ~= 1 then
rows[#rows+1] = row_h("Sell Price",misc.sellprices[args.rarity])
rows[#rows+1] = row_h("Stack Size",misc.maxcount)
rows[#rows+1] = row_h("Item Achieve",misc.ap[args.rarity])
end
rows[#rows+1] = row_h("Max Contents",misc.maxcontentscount)
rows[#rows+1] = row_h("Item Achieve",misc.ap[index])
rows[#rows+1] = row_h("Sell Price",misc.sellprices[index])


rows[#rows+1] = hline()
rows[#rows+1] = hline()
Line 249: Line 262:
local function panel(rarity, args, data)
local function panel(rarity, args, data)
if not search(data.rarities,rarity) then return "" end
if not search(data.rarities,rarity) then return "" end
args.rarity = rarity


local hidden_panel = "cardtabs__panel--js-hidden"
local hidden_panel = "cardtabs__panel--js-hidden"
if args.is_active==rarity then hidden_panel = "" end
if args.is_active == rarity then hidden_panel = "" end


args.rarity = rarity
return string.format("<div data-cardtabs-panel='%s' style='overflow:auto' class='cardtabs__panel %s'>%s</div>", rarity, hidden_panel, infobox(args, data))
return string.format("<div data-cardtabs-panel='%s' style='overflow:auto' class='cardtabs__panel %s'>%s</div>", rarity, hidden_panel, infobox(args, data))
end
end
Line 298: Line 310:
local data = mw.loadJsonData(CATEGORY[frame.args.category].Data)
local data = mw.loadJsonData(CATEGORY[frame.args.category].Data)
data = data[frame.args.category][frame.args.name] -- load data of a specific object
data = data[frame.args.category][frame.args.name] -- load data of a specific object
if not frame.args.is_active then frame.args.is_active = data.rarities[1] end -- If missing argument, make the first make the first rarity infobox active


local wt = {}
local wt = {}
Line 311: Line 325:


--[=[
--[=[
mw.log(p.draw({args={name="Halberd",link="nolink",category="Weapon"}}))
mw.log(p.draw({args={name="Halberd",is_active="2",category="Weapon"}}))
mw.log(p.draw({args={name="Halberd",is_active="2",category="Weapon"}}))
mw.log(p.draw({args={name="Cinder",is_active="8",category="Weapon"}}))
mw.log(p.draw({args={name="Bloodthirst",category="Weapon"}}))
 
mw.log(p.draw({args={name="Golden Scarf",category="Armor"}}))
mw.log(p.draw({args={name="Plate Pants",category="Armor"}}))
 
mw.log(p.draw({args={name="Grimsmile Ring",category="Accessory"}}))
 
mw.log(p.draw({args={name="Diamond",category="Misc"}}))
mw.log(p.draw({args={name="Gold Coin Chest",category="Misc"}}))
mw.log(p.draw({args={name="Quiver",category="Misc"}}))
]=]
]=]

Latest revision as of 06:56, 3 July 2026

Overview

Function for making Iconbox tabs. Data comes from various data jsons: Data:Weapon.json, Data:Armor.json, Data:Accessory.json, Data:Misc.json, Data:Monster.json.

Functions

draw

Creates an iconbox that floats to the right.

Parameters

  • name - <Name>
  • is_active - {1,2,3,4,5,6,7,8,Common,Elite,Nightmare}
  • category - {Weapon,Armor,Accessory,Utility,Misc,Monster,Prop}


draw examples

Halberd,7,Weapon


{{#invoke:Infobox|draw|name=Halberd|category=Weapon}}
 I 
 II 
 III 
 IV 
 V 
 VI 
 VII 
Halberd
Halberd.png
-
Physical Base Weapon Damage 45
-
-
Move Speed -50
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.
Halberd
Halberd.png
-
Physical Base Weapon Damage 47
-
-
Move Speed -50
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
Gear Score:
1
Sell Price:
20
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.
Halberd
Halberd.png
-
Physical Base Weapon Damage 49
-
-
Move Speed -50
-
-
Up to 1 extra enchantments
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
Gear Score:
5
Item Achieve:
10
Sell Price:
30
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.
Halberd
Halberd.png
-
Physical Base Weapon Damage 51
-
-
Move Speed -50
-
-
Up to 2 extra enchantments
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
Gear Score:
30
Item Achieve:
20
Sell Price:
60
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.
Halberd
Halberd.png
-
Physical Base Weapon Damage 53
-
-
Move Speed -50
-
-
Up to 3 extra enchantments
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
Gear Score:
40
Item Achieve:
30
Sell Price:
100
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.
Halberd
Halberd.png
-
Physical Base Weapon Damage 55
-
-
Move Speed -50
-
-
Up to 4 extra enchantments
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
Gear Score:
50
Item Achieve:
50
Sell Price:
200
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.
Halberd
Halberd.png
-
Physical Base Weapon Damage 57
-
-
Move Speed -50
-
-
Up to 1 extra enchantments
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.68x15.84x2.25
2x5InvSlot.jpg
Gear Score:
60
Item Achieve:
100
Sell Price:
300
A two handed pole-arm with a long reach, devised with an axe blade containing a sharp spike firmly fasted to the end.


Cinder,8,Weapon


{{#invoke:Infobox|draw|name=Cinder|is_active=8|category=Weapon}}
 VIII 
Cinder
Cinder.png
-
Physical Base Weapon Damage 60
-
-
Move Speed -50
-
-
Up to 5 extra enchantments
-
-
Successful weapon attacks sears the target for 10 Fire Fire Magical Base Damage (100% Scaling) and burns them for 27 Fire Fire Magical Base Damage (50% Scaling) over 9 seconds.
-
Required Class:
Weapon Type:
Polearm
Slot Type:
Main-Hand
Hand Type:
Two Handed
Hitbox:
119.7x15.84x2.14
2x5InvSlot.jpg
Item Achieve:
100
Sell Price:
1000
It will be difficult to keep track of your kill count for they have all been reduced to a pile of ash.


Ranger Hood,5,Armor


{{#invoke:Infobox|draw|name=Ranger Hood|is_active=5|category=Armor}}
 I 
 II 
 III 
 IV 
 V 
 VI 
 VII 
Ranger Hood
Ranger Hood.png
-
Armor Rating 25
-
-
Headshot Damage Reduction 10%
-
-
Agility 1
-
-
Move Speed -2
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Lightweight and breathable, cut to hug the head and protect from the elements.
Ranger Hood
Ranger Hood.png
-
Armor Rating 26
-
-
Headshot Damage Reduction 10%
-
-
Agility 2
-
-
Move Speed -2
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Gear Score:
1
Sell Price:
8
Lightweight and breathable, cut to hug the head and protect from the elements.
Ranger Hood
Ranger Hood.png
-
Armor Rating 27
-
-
Headshot Damage Reduction 10%
-
-
Agility 2
-
-
Move Speed -2
-
-
Up to 1 extra enchantments
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Gear Score:
1
Item Achieve:
4
Sell Price:
12
Lightweight and breathable, cut to hug the head and protect from the elements.
Ranger Hood
Ranger Hood.png
-
Armor Rating 28~29
-
-
Headshot Damage Reduction 10%
-
-
Agility 3
-
-
Move Speed -2
-
-
Up to 2 extra enchantments
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Gear Score:
15
Item Achieve:
8
Sell Price:
24
Lightweight and breathable, cut to hug the head and protect from the elements.
Ranger Hood
Ranger Hood.png
-
Armor Rating 30~31
-
-
Headshot Damage Reduction 10%
-
-
Agility 4
-
-
Move Speed -2
-
-
Up to 3 extra enchantments
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Gear Score:
20
Item Achieve:
12
Sell Price:
40
Lightweight and breathable, cut to hug the head and protect from the elements.
Ranger Hood
Ranger Hood.png
-
Armor Rating 32
-
-
Headshot Damage Reduction 10%
-
-
Agility 5
-
-
Move Speed -2
-
-
Up to 4 extra enchantments
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Gear Score:
30
Item Achieve:
20
Sell Price:
80
Lightweight and breathable, cut to hug the head and protect from the elements.
Ranger Hood
Ranger Hood.png
-
Armor Rating 33
-
-
Headshot Damage Reduction 10%
-
-
Agility 5
-
-
Move Speed -2
-
-
Up to 1 extra enchantments
-
Required Class:
Armor Type:
Cloth
Slot Type:
Head
2x2InvSlot.jpg
Gear Score:
40
Item Achieve:
40
Sell Price:
120
Lightweight and breathable, cut to hug the head and protect from the elements.


Code


local p = {}
local concat = table.concat

local function count(t)
	local c = 0
	for _,_ in pairs(t) do c = c + 1 end
	return c
end

local function search(t,v)
	for ind,val in ipairs(t) do
		if v == val then return true end
	end
	return false
end

local function hline()
	return "<div class='line' style='background-image:linear-gradient(to right,rgb(10,10,10),rgb(100,100,100),rgb(10,10,10))'></div>"
end

local function row_h(title, content)
	if not content or content == "" or content == 0 then return "" end
	return string.format("<div style='display:flex;flex-direction:row;justify-content:center;white-space:pre-wrap;color:rgb(160,160,140)'><div style='text-align:right; color:rgb(70,70,70)'>%s: </div><div>%s</div></div>", title, content)
end

local function row_v(title, content)
	if not content or content == "" or content == 0 then return "" end
	return string.format("<div style='display:flex;flex-direction:column;align-items:center;color:rgb(160,160,140);margin-bottom:5px'><div style='color:rgb(70,70,70)'>%s: </div><div>%s</div></div>", title, content)
end


local function row_v2(content)
	if not content or content == "" or content == 0 then return "" end
	return string.format("<div style='display:flex;margin-top:10px;flex-direction:column;align-items:center;text-align:center;margin-bottom:15px'>%s</div>",content)
end


local function row_v3(content)
	if not content or content == "" or content == 0 then return "" end
	return string.format("<div style='display:flex;flex-direction:column;align-items:center;text-align:center;color:rgb(115,83,67)'>%s</div>",content)
end

local function header(args)
	local header_content = ""
	if args.link then
		header_content = string.format("[[%s|<span class='cr%s'>%s</span>]]", args.link, args.rarity, args.name)
	else
		header_content = string.format("<span class='bold cr%s'>%s</span>", args.rarity, args.name)
	end

	return string.format(
		"<div class='itemboxheader' style='width:280px;padding:20px;box-shadow:inset 0px 0px 20px 5px rgb(0 0 0 / 0.5);display:flex;flex-direction:column;align-items:center;background-color:rgb(var(--rarity-%s),0.1);border:2px solid rgb(var(--rarity-%s),0.5)'><div class='bold' style='margin-top:0px!important;font-size:22px'>%s</div></div>",
		args.rarity, args.rarity, header_content
	)
end

local function image(args)
	if not args.name then return end
	return "<div style='display:flex;flex-direction:column;align-items:center'><div class='iconbox' style='width:max-content;align-items:center'><div class='rarity-1 rounded relative'>[[File:"..args.name..".png|90px|link=]]</div></div></div>"
end

local function stat_index(item,rarity)
	return 1 + tonumber(rarity) - item.rarities[1]
end

local function stat_block(wt, args, item)
	if not item.stats or count(item.stats.order) == 0 or item.numenchants[tonumber(args.rarity)] == 0 then return end

	wt[#wt+1] = "<div style='text-align:center'>"
	for i,stat_name in ipairs(item.stats.order) do
		wt[#wt+1] = "<div style='margin-top:10px;display:flex;width:100%;flex-direction:row;justify-content:space-between'>"
		wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
		wt[#wt+1] = string.format("<div>%s %s</div>",stat_name,item.stats[(stat_name):lower()][stat_index(item,args.rarity)] or item.stats[(stat_name):lower()])
		wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
	end

	if item.numenchants[tonumber(args.rarity)] then
		wt[#wt+1] = "<div class='cr4' style='margin-top:10px;display:flex; width:100%;flex-direction:row; justify-content:space-between'>"
		wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
		wt[#wt+1] = string.format("<div>Up to %i extra enchantments</div>",item.numenchants[tonumber(args.rarity)])
		wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
	end

	if item.haspassive and item.isminiartifact or item.isartifact then
		wt[#wt+1] = "<div style='margin-top:10px;display:flex;width:100%;flex-direction:row;justify-content:space-between;color:rgb(211,178,125)'>"
		wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div>"
		wt[#wt+1] = string.format("<div>%s</div>",item.artifactpower)
		wt[#wt+1] = "<div style='padding:0px 5px' class='bold'>-</div></div>"
	end
	wt[#wt+1] = "</div>"
end

local function class_list(list)
	local ret = ""
	for i,v in ipairs(list) do
		if i ~= 1 then ret = ret..", " end
		ret = ret..v
	end
	return ret
end

local function type_list(t,type)
	local ret = ""
	local i = 1
	for k,v in pairs(t) do
		if i ~= 1 then ret = ret..", " end
		if v == type then
			ret = ret..k
		end
		i = i + 1
	end
	return ret
end

local function weapon_rows(rows, args, weapon)
	local index = tonumber(args.rarity)

	rows[#rows+1] = hline()
	stat_block(rows,args,weapon)

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v("Required Class",class_list(weapon.classes))
	rows[#rows+1] = row_h("Weapon Type",type_list(weapon.types,"Weapon"))
	rows[#rows+1] = row_h("Utility Type",type_list(weapon.types,"Utility"))
	rows[#rows+1] = row_h("Slot Type",weapon.slottype)
	rows[#rows+1] = row_h("Hand Type",weapon.handtype)
	rows[#rows+1] = row_h("Reload Speed",weapon.reloadtime)
	rows[#rows+1] = row_h("Quiver Size",weapon.maxammocount)

	if count(weapon.hitbox) ~= 0 then
		rows[#rows+1] = hline()
		rows[#rows+1] = row_h("Hitbox",string.format("%sx%sx%s",weapon.hitbox.height,weapon.hitbox.width,weapon.hitbox.depth))
	end

	if weapon.invwidth ~= "" then
		rows[#rows+1] = hline()
		rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",weapon.invwidth,weapon.invheight))
		if weapon.maxcount ~= 1 then
			rows[#rows+1] = row_h("Stack Size",weapon.maxcount)
		end
		rows[#rows+1] = row_h("Gear Score",weapon.gearscore[index])
		rows[#rows+1] = row_h("Item Achieve",weapon.ap[index])
		rows[#rows+1] = row_h("Sell Price",weapon.sellprices[index])
	end

	if weapon.flavortext ~= "" then
		rows[#rows+1] = hline()
		rows[#rows+1] = row_v3(weapon.flavortext)
	end
end

local function armor_rows(rows, args, armor)
	local index = tonumber(args.rarity)

	rows[#rows+1] = hline()
	stat_block(rows,args,armor)

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v("Required Class",class_list(armor.classes))
	rows[#rows+1] = row_h("Armor Type",type_list(armor.types,"Armor"))
	rows[#rows+1] = row_h("Slot Type",armor.slottype)

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",armor.invwidth,armor.invheight))
	rows[#rows+1] = row_h("Gear Score",armor.gearscore[index])
	rows[#rows+1] = row_h("Item Achieve",armor.ap[index])
	rows[#rows+1] = row_h("Sell Price",armor.sellprices[index])

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v3(armor.flavortext)
end

local function accessory_rows(rows, args, accessory)
	local index = tonumber(args.rarity)

	rows[#rows+1] = hline()
	stat_block(rows,args,accessory)

	rows[#rows+1] = hline()
	rows[#rows+1] = row_h("Slot Type",accessory.slottype)

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",accessory.invwidth,accessory.invheight))
	rows[#rows+1] = row_h("Gear Score",accessory.gearscore[index])
	rows[#rows+1] = row_h("Item Achieve",accessory.ap[index])
	rows[#rows+1] = row_h("Sell Price",accessory.sellprices[index])

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v3(accessory.flavortext)

end

local function utility_rows(rows, args, utility)
	error("monster_rows() needs to be implemented")
end

local function misc_rows(rows, args, misc)
	local index = tonumber(args.rarity)

	rows[#rows+1] = hline()
	rows[#rows+1] = row_h("Type",type_list(misc.types,"Misc"))


	rows[#rows+1] = hline()
	rows[#rows+1] = row_v2(string.format("[[File:%sx%sInvSlot.jpg]]",misc.invwidth,misc.invheight))
	if misc.maxcount ~= 1 then
		rows[#rows+1] = row_h("Stack Size",misc.maxcount)
	end
	rows[#rows+1] = row_h("Max Contents",misc.maxcontentscount)
	rows[#rows+1] = row_h("Item Achieve",misc.ap[index])
	rows[#rows+1] = row_h("Sell Price",misc.sellprices[index])

	rows[#rows+1] = hline()
	rows[#rows+1] = row_v3(misc.flavortext)
end

local function monster_rows(rows, args, monster)
	error("monster_rows() needs to be implemented")
end

local function prop_rows(rows, args, prop)
	error("prop_rows() needs to be implemented")
end

local CATEGORY = {	["Weapon"]    = {["Data"]="Data:Weapon.json"   , ["Function"]=weapon_rows},
					["Armor"]     = {["Data"]="Data:Armor.json"    , ["Function"]=armor_rows},
					["Accessory"] = {["Data"]="Data:Accessory.json", ["Function"]=accessory_rows},
					["Utility"]   = {["Data"]="Data:Utility.json"  , ["Function"]=utility_rows},
					["Misc"]      = {["Data"]="Data:Misc.json"     , ["Function"]=misc_rows},
					["Monster"]   = {["Data"]="Data:Monster.json"  , ["Function"]=monster_rows},
					["Prop"]      = {["Data"]="Data:Prop.json"     , ["Function"]=prop_rows}}


local function get_rows(args, data)
	local rows = {}

	if CATEGORY[args.category] then CATEGORY[args.category].Function(rows,args,data)
	else error("Module:Infobox received an invalid category.  Ensure it is capitalized and singular.") end

	return rows
end

local function infobox(args, data)
	local wt = {}

	wt[#wt+1] = "<div style='background-color:rgb(var(--background-color),0.3);max-width:470px;float:right'>" --Infobox container
	wt[#wt+1] = header(args)
	wt[#wt+1] = "<div style='width:280px;border:2px solid rgb(70,70,70,0.5);padding:20px'>" -- Content container
	wt[#wt+1] = image(args)

	-- Category-specific rows
	local rows = get_rows(args, data)
	for _, row in ipairs(rows) do
		wt[#wt+1] = row
	end

	wt[#wt+1] = "</div></div>"

	return concat(wt)
end

local function panel(rarity, args, data)
	if not search(data.rarities,rarity) then return "" end

	local hidden_panel = "cardtabs__panel--js-hidden"
	if args.is_active == rarity then hidden_panel = "" end

	args.rarity = rarity
	return string.format("<div data-cardtabs-panel='%s' style='overflow:auto' class='cardtabs__panel %s'>%s</div>", rarity, hidden_panel, infobox(args, data))
end

local function tab_panels(args, wt, data)
	wt[#wt+1] = "<div class='mytabs__panels' data-cardtabs-panels>"
	wt[#wt+1] = panel("1", args, data)
	wt[#wt+1] = panel("2", args, data)
	wt[#wt+1] = panel("3", args, data)
	wt[#wt+1] = panel("4", args, data)
	wt[#wt+1] = panel("5", args, data)
	wt[#wt+1] = panel("6", args, data)
	wt[#wt+1] = panel("7", args, data)
	wt[#wt+1] = panel("8", args, data)
	wt[#wt+1] = "</div>"
end

local ROMAN_NUMERAL = {"I","II","III","IV","V","VI","VII","VIII"}

local function button(rarity, args, data)
	if not search(data.rarities,rarity) then return "" end

	local is_active_button = ""
	if args.is_active==rarity then is_active_button = " cardtabs__button--active" end

	return string.format("<div data-cardtabs-btn='%s' class='cardtabs__button rarity%s%s'>&nbsp;%s&nbsp;</div>", rarity, rarity, is_active_button, ROMAN_NUMERAL[tonumber(rarity)])
end

local function tab_buttons(args, wt, data)
	wt[#wt+1] = "<div class='cardtabs__buttons' data-cardtabs-btns>"
	wt[#wt+1] = button("1", args, data)
	wt[#wt+1] = button("2", args, data)
	wt[#wt+1] = button("3", args, data)
	wt[#wt+1] = button("4", args, data)
	wt[#wt+1] = button("5", args, data)
	wt[#wt+1] = button("6", args, data)
	wt[#wt+1] = button("7", args, data)
	wt[#wt+1] = button("8", args, data)
	wt[#wt+1] = "</div>"
end

function p.draw(frame)
	local data = mw.loadJsonData(CATEGORY[frame.args.category].Data)
	data = data[frame.args.category][frame.args.name] -- load data of a specific object

	if not frame.args.is_active then frame.args.is_active = data.rarities[1] end -- If missing argument, make the first make the first rarity infobox active

	local wt = {}
	wt[#wt+1] = "<div class='cardtabs' data-cardtabs>"
	tab_buttons(frame.args, wt, data)
	tab_panels(frame.args, wt, data)
	wt[#wt+1] = "</div>"

	return concat(wt)
end

return p

--[=[
mw.log(p.draw({args={name="Halberd",is_active="2",category="Weapon"}}))
mw.log(p.draw({args={name="Bloodthirst",category="Weapon"}}))

mw.log(p.draw({args={name="Golden Scarf",category="Armor"}}))
mw.log(p.draw({args={name="Plate Pants",category="Armor"}}))

mw.log(p.draw({args={name="Grimsmile Ring",category="Accessory"}}))

mw.log(p.draw({args={name="Diamond",category="Misc"}}))
mw.log(p.draw({args={name="Gold Coin Chest",category="Misc"}}))
mw.log(p.draw({args={name="Quiver",category="Misc"}}))
]=]