From Dark and Darker Wiki
(Temporarily removed animation times table cell. Moved impact resistance to Impact Zones cell, for a more natural fit.) |
(Moved some logic out from row(). Added Throwables to ranged type.) |
||
| Line 350: | Line 350: | ||
end | end | ||
return "<td>"..wt.."</td>" | return "<td>"..wt.."</td>" | ||
end | |||
---@param weapon table | |||
---@return string | |||
local function determine_table_type(weapon) | |||
if weapon.args then | |||
if weapon.args[1] == "Shield" then return "Shield" | |||
elseif (weapon.args[1]):lower():match("bow") or weapon.args[1] == "Firearm" or weapon.args[1] == "Throwable" then return "Ranged" end | |||
elseif weapon.types then | |||
if weapon.types.Shield then return "Shield" | |||
elseif weapon.types.Bow or weapon.types.Crossbow or weapon.types.Firearm or weapon.types.Throwable then return "Ranged" end | |||
end | |||
return "Default" | |||
end | end | ||
| Line 366: | Line 381: | ||
local function row(weapon, is_header) | local function row(weapon, is_header) | ||
is_header = is_header or false | is_header = is_header or false | ||
local wt = {} | local wt = {} | ||
wt[#wt+1] = "<tr>" | wt[#wt+1] = "<tr>" | ||
for _,content in ipairs(row_type[ | for _,content in ipairs(row_type[determine_table_type(weapon)]) do | ||
wt[#wt+1] = content(weapon,is_header) | wt[#wt+1] = content(weapon,is_header) | ||
end | end | ||
Revision as of 08:05, 15 March 2026
Overview
Functions for making Weapon table. Data comes from Data:Weapon.json.
Functions
draw_table
Creates a table of weapons
Parameters
- 1 - <Type>
- 2 - Craftable or Uncraftable or Artifact
draw_table examples
Sword, Craftable
{{#invoke:Weapon|draw_table|Sword|Craftable}}
| Name | Class | Slot | Movement Speed | Damage on Hit | Stats | Hitbox + Impact Resist | Impact Zones + Impact Power | Combo | Action Movement Penalty | Slowdown On Hit |
|---|---|---|---|---|---|---|---|---|---|---|
| Fighter Warlock Sorcerer | Main-Hand Two Handed | -30 | Physical Base Weapon Damage 38 | Undead Race Damage Bonus 15% | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Special Riposte Attack 2 100%/90% + 4 Impact Resist 3 | Primary Attacks Pierce/Slash/Slash 100%/105%/110% Special Attacks Slash/Slash 150%/150% | Other Actions Always: x/85% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -30/-30/-30 for 0.35/0.35/0.35s | ||
| Ranger Rogue Bard | Main-Hand One Handed | -15 | Physical Base Weapon Damage 26 Magical Base Weapon Damage 1 | Primary Attack 1 100%/90% + 2 Primary Attack 2 100%/90% + 2 Primary Attack 3 100%/90% + 2 Primary Attack 4 100%/90% + 2 Special Riposte Attack 1 100%/90% + 2 Special Riposte Attack 2 100%/90% + 2 Impact Resist 3 | Primary Attacks Pierce/Pierce/Pierce/Pierce 100%/105%/110%/115% Special Attacks Slash/Pierce 150%/150% | Other Actions Always: x/85% Primary Attacks Mid Attack: x60%/60%/60%/60% Otherwise: x92.5%/92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -15/-15/-15/-15 for 0.2/0.2/0.2/0.2s | |||
| Fighter Warlock Sorcerer | Main-Hand Two Handed | -30 | Physical Base Weapon Damage 39 | Undead Race Damage Bonus 15% | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Special Riposte Attack 2 100%/90% + 4 Impact Resist 3 | Primary Attacks Pierce/Slash/Slash 100%/105%/110% Special Attacks Slash/Slash 150%/150% | Other Actions Always: x/85% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -30/-30/-30 for 0.35/0.35/0.35s | ||
| Fighter Rogue Ranger Bard | Off-Hand One Handed | -15 | Physical Base Weapon Damage 26 | Undead Race Damage Bonus 15% | Secondary Attack 1 100%/90% + 2 Secondary Attack 2 100%/90% + 2 Secondary Attack 3 100%/90% + 2 Special Riposte Attack 1 100%/90% + 2 Special Riposte Attack 2 100%/90% + 2 Impact Resist 3 | Secondary Attacks Slash/Slash/Pierce 100%/105%/110% Special Attacks Slash/Pierce 150%/150% | Other Actions Always: x/75% Secondary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -15/-15/-30 for 0.2/0.2/0.2s | ||
| Fighter Bard Warlock Sorcerer | Main-Hand One Handed | -25 | Physical Base Weapon Damage 37 | Armor Penetration 2~3% | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Impact Resist 3 | Primary Attacks Slash/Slash/Slash 100%/105%/110% Special Attacks Slash 150% | Other Actions Always: x/75% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85% | Hitslow -25/-25/-25 for 0.35/0.35/0.35s | ||
| Wizard Warlock Sorcerer | Main-Hand Two Handed | -25 | Physical Base Weapon Damage 13 Magical Base Weapon Damage 18 | Action Speed 2% | Primary Attack 1 100%/90% + 3 Primary Attack 2 100%/90% + 3 Primary Attack 3 100%/90% + 3 Special Riposte Attack 1 100%/90% + 3 Impact Resist 3 | Primary Attacks Slash/Slash/Slash 100%/105%/110% Special Attacks Slash 150% | Other Actions Always: x/70%/75% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x85% Special Attacks Always: x85% | Hitslow -25/-25/-25 for 0.35/0.35/0.35s | ||
| Fighter Barbarian | Main-Hand One Handed | -20 | Physical Base Weapon Damage 33 | Luck 10 Magical Damage Reduction 2% | Primary Attack 1 100%/90% + 3 Primary Attack 2 100%/90% + 3 Primary Attack 3 100%/90% + 3 Special Riposte Attack 1 100%/90% + 3 Impact Resist 3 | Primary Attacks Slash/Slash/Pierce 100%/105%/110% Special Attacks Slash 150% | Other Actions Always: x/75% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85% | Hitslow -20/-20/-20 for 0.35/0.35/0.35s | ||
| Fighter Barbarian Warlock | Main-Hand Two Handed | -40 | Physical Base Weapon Damage 45~46 | Physical Power 5 Undead Race Damage Bonus 30% | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Impact Resist 3 | Primary Attacks Slash/Slash/Slash 100%/105%/110% Special Attacks Slash 125% | Other Actions Mid Attack: x/70%/85% Otherwise: x//92.5% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x85% Special Attacks Always: x85% | Hitslow -40/-40/-40 for 0.35/0.35/0.35s | ||
| Fighter Rogue Ranger Bard | Off-Hand One Handed | -15 | Physical Base Weapon Damage 25 | Undead Race Damage Bonus 15% | Secondary Attack 1 100%/90% + 2 Secondary Attack 2 100%/90% + 2 Secondary Attack 3 100%/90% + 2 Special Riposte Attack 1 100%/90% + 2 Special Riposte Attack 2 100%/90% + 2 Impact Resist 3 | Secondary Attacks Slash/Slash/Pierce 100%/105%/110% Special Attacks Slash/Pierce 150%/150% | Other Actions Always: x/75% Secondary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -15/-15/-30 for 0.2/0.2/0.2s | ||
| Wizard Warlock Sorcerer | Main-Hand Two Handed | -25 | Physical Base Weapon Damage 13 Magical Base Weapon Damage 18 | Outgoing Magical Healing Add 2 Move Speed Bonus 2% | Primary Attack 1 100%/90% + 3 Primary Attack 2 100%/90% + 3 Primary Attack 3 100%/90% + 3 Special Riposte Attack 1 100%/90% + 3 Impact Resist 3 | Primary Attacks Slash/Slash/Slash 100%/105%/110% Special Attacks Slash 150% | Other Actions Always: x/70%/75% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x85% Special Attacks Always: x85% | Hitslow -25/-25/-25 for 0.35/0.35/0.35s | ||
| Fighter Warlock Sorcerer | Main-Hand Two Handed | -30 | Physical Base Weapon Damage 40 | Action Speed 5% Headshot Damage Modifier 5% | File:Spectral Blade Hitbox.png | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Special Riposte Attack 2 100%/90% + 4 Impact Resist 3 | Primary Attacks Pierce/Slash/Slash 100%/105%/110% Special Attacks Slash/Slash 150%/150% | Other Actions Always: x/85% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -30/-30/-30 for 0.35/0.35/0.35s | |
| Fighter Warlock Sorcerer | Main-Hand Two Handed | -30 | Physical Base Weapon Damage 37 | Undead Race Damage Bonus 15% | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Special Riposte Attack 2 100%/90% + 4 Impact Resist 3 | Primary Attacks Pierce/Slash/Slash 100%/105%/110% Special Attacks Slash/Slash 150%/150% | Other Actions Always: x/85% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -30/-30/-30 for 0.35/0.35/0.35s | ||
| Fighter Rogue Ranger Bard | Off-Hand One Handed | -15 | Physical Base Weapon Damage 24 | Undead Race Damage Bonus 15% | Secondary Attack 1 100%/90% + 2 Secondary Attack 2 100%/90% + 2 Secondary Attack 3 100%/90% + 2 Special Riposte Attack 1 100%/90% + 2 Special Riposte Attack 2 100%/90% + 2 Impact Resist 3 | Secondary Attacks Slash/Slash/Pierce 100%/105%/110% Special Attacks Slash/Pierce 150%/150% | Other Actions Always: x/75% Secondary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -15/-15/-30 for 0.2/0.2/0.2s | ||
| Fighter Bard Warlock Sorcerer | Main-Hand One Handed | -25 | Physical Base Weapon Damage 37 | Debuff Duration Bonus 1.5% | File:Tidal Falchion Hitbox.png | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Impact Resist 3 | Primary Attacks Slash/Slash/Slash 100%/105%/110% Special Attacks Slash 150% | Other Actions Always: x/75% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85% | Hitslow -25/-25/-25 for 0.35/0.35/0.35s | |
| Fighter Warlock Sorcerer | Main-Hand Two Handed | -30 | Physical Base Weapon Damage 41 Magical Base Weapon Damage 2 | True Magical Damage 2 | Primary Attack 1 100%/90% + 4 Primary Attack 2 100%/90% + 4 Primary Attack 3 100%/90% + 4 Special Riposte Attack 1 100%/90% + 4 Special Riposte Attack 2 100%/90% + 4 Impact Resist 3 | Primary Attacks Pierce/Slash/Slash 100%/105%/110% Special Attacks Slash/Slash 150%/150% | Other Actions Always: x/85% Primary Attacks Mid Attack: x60%/60%/60% Otherwise: x92.5%/92.5%/92.5% Block Actions Always: x97% Special Attacks Always: x85%/85% | Hitslow -30/-30/-30 for 0.35/0.35/0.35s |
Firearm, Uncraftable
{{#invoke:Weapon|draw_table|Firearm|Uncraftable}}
Code
| Name | Class | Slot | Movement Speed | Damage on Hit | Stats | Impact Zones + Impact Power | Action Movement Penalty | Slowdown On Hit | Initial Projectile Speed (m/s) |
|---|---|---|---|---|---|---|---|---|---|
| Fighter Ranger | Main-Hand Two Handed | -30 | Physical Base Weapon Damage 45~46 47~48 49~50 51~52 53~54 55~56 57~58 | True Physical Damage 10 | Primary Attack 1 100% + 6 Impact Resist 3 | Other Actions Always: x/50%/70% Primary Attacks Always: x50% Block Actions Always: x85% | Hitslow -135 for 1.5s | 38 |
local p = {}
local WD = mw.loadJsonData("Data:Weapon.json") --Global var holding tables from Data:Weapon.json
local concat = table.concat
---Get the item's size in pixels
--- @param item table
--- @return string
local function size(item)
return tostring(item.invwidth*45).."x"..tostring(item.invheight*45).."px"
end
---Counts number of keys. Tables from Weapon.json don't work with next() or the # operator
--- @param t table
--- @return number
local function count(t)
local c = 0
for _ in pairs(t) do c = c + 1 end
return c
end
---Marks up a list of values with color based on rarity
--- @param values string|table
--- @param weapon table
--- @return string
local function color_values(weapon, values)
if values == nil then return "" end
if type(values)=="string" or type(values)=="number" then
if count(weapon.rarities) == 1 then return "<span class='cr"..weapon.rarities[1].."'>"..values.."</span>" end
return tostring(values)
end
local wt = ""
local newline = ""
for i, key in ipairs(weapon.rarities) do
wt = wt..newline.."<span class='cr"..key.."'>"..tostring(values[tonumber(key)] or "").."</span>"
if i == 1 then newline = "<br>" end
end
return wt
end
---Marks up a stat block with the stat name and colored values and appropriate margins and alignment
--- @param weapon table
--- @param stat string
--- @return string
local function inline_block(weapon,stat)
if weapon.stats[(stat):lower()] == nil then return "" end
return "<div style='display:inline-block;vertical-align:top;margin:0 15px 0 15px'><b style='color:#eee8'>"..stat.."</b><br>"..color_values(weapon,weapon.stats[(stat):lower()]).."</div>"
end
---Formats a table cell for the iconbox
---@param item table
---@return string
local function name(item, is_header)
if is_header then return [[<th style="width:5%">Name</th>]] end
local color = "2"
local bold_link = "|<b>"..item.name
if count(item.rarities) == 1 then
color = item.rarities[1]
bold_link = "|<b class=cr"..color..">"..item.name
end
local icon_amount = ""
if item.maxammocount > 0 then
icon_amount = "<span class='iconamount' style='pointer-events:none;color:#EEEA;font-size:16px'>"..item.maxammocount.."</span>"
end
return "<td><div class='iconbox'><div class='rarity"..color.." rounded relative'>[[File:"..item.name..".png|"..size(item).."|link="..item.name.."]]"
..icon_amount
.."</div><br>[["..item.name..bold_link.."</b>]]</div></td>"
end
---Formats the weapon's list of classes into a table cell of classes separated by linebreaks
--- @param weapon table
--- @param is_header boolean
--- @return string
local function classes(weapon,is_header)
if is_header then return [[<th style="width:5%">Class</th>]] end
local wt = ""
local newline = ""
for i, class in ipairs(weapon.classes) do
wt = wt..newline..class
if i == 1 then newline = "<br>" end -- Subsequent loops will prefix a linebreak
end
return "<td>"..wt.."</td>"
end
---Formats a table cell of slottype and handtype
--- @param weapon table
--- @param is_header boolean
--- @return string
local function slot_type(weapon,is_header)
if is_header then return [[<th style="width:5%">Slot</th>]] end
return "<td>"..weapon.slottype.."<br>"..weapon.handtype.."</td>"
end
---Formats a table cell of move speeds
--- @param weapon table
--- @param is_header boolean
--- @return string
local function move_speed(weapon,is_header)
if is_header then return [[<th style="width:5%">Movement Speed</th>]] end
return "<td>"..color_values(weapon,weapon.stats["move speed"]).."</td>"
end
---Formats a table cell of Armor rating and Magical Resistance
--- @param weapon table
--- @param is_header boolean
--- @return string
local function armor_rating(weapon,is_header)
if is_header then return [[<th style="width:15%">Armor Rating</th>]] end
return "<td>"..inline_block(weapon,"Armor Rating")..inline_block(weapon,"Magical Resistance").."</td>"
end
local function impact_zones(weapon,is_header)
if is_header then return [[<th style="width:10%">Impact Zones + Impact Power</th>]] end
local wt= ""
for i,ability in ipairs(weapon.abilities.order) do
if ability ~= "Other" then
for j,attack in ipairs(weapon.abilities[ability].order) do
if weapon.abilities[ability][attack].impactpower and weapon.abilities[ability][attack].impactzones then
wt = wt.."<br><span style='color:#eee8'>"..ability.." "..attack.."</span><br>"
for k,impact_zone in ipairs(weapon.abilities[ability][attack].impactzones) do
if k~=1 then wt = wt.."/" end
wt = wt..impact_zone
end
wt = wt.." + "..weapon.abilities[ability][attack].impactpower.."<br>"
end
end
end
end
if weapon.impactresistance~="" then
wt = wt.."<br><span style='color:#eee8'>Impact Resist</span><br>"..weapon.impactresistance
end
return "<td>"..wt.."</td>"
end
---Helper function: Collects move mult and prepare move mult for display
---@param ability table
---@return string
---@return string
local function collect_multipliers(ability)
local move, prep_move = "",""
for i,attack_name in ipairs(ability.order) do
if ability[attack_name].movementmultiplier then
if i ~= 1 then
move = move.."/"
prep_move = prep_move.."/"
end
move = move..(ability[attack_name].movementmultiplier or "")
prep_move = prep_move..(ability[attack_name].preparemovementmultiplier or "")
i = i + 1
end
end
return move,prep_move
end
---Formats a table cell containing speed penalties for each action
---@param weapon table
---@param is_header boolean
---@return string
local function action_move_speed_penalty(weapon,is_header)
if is_header then return [=[<th style="width:10%">[[Weapons#Movement_Multiplier_Explanation|Action Movement Penalty]]</th>]=] end
local wt = ""
for i,ability_name in ipairs(weapon.abilities.order) do
if i~=1 then wt = wt.."<br><br>" end
wt = wt.."<span style='color:#eee8; font-size:110%; font-weight:bold'>"
if ability_name=="Other" or ability_name=="Block" then wt = wt..ability_name.." Actions" else wt = wt..ability_name.." Attacks" end
wt = wt.."</span><br>"
local movement_multiplier,prepare_movement_multiplier = collect_multipliers(weapon.abilities[ability_name])
if #prepare_movement_multiplier > 3 then
wt = wt.."<span style='color:#eee8'>Mid Attack: </span>x"..movement_multiplier
.."<br><span style='color:#eee8'>Otherwise: </span>x"..prepare_movement_multiplier
else
wt = wt.."<span style='color:#eee8'>Always: </span>x"..movement_multiplier
end
end
return "<td>"..wt.."</td>"
end
---Formats a table cell containing base Physical and Magical damage, if present.
---@param weapon any
---@param is_header any
---@return string
local function damage_on_hit(weapon,is_header)
if is_header then return [[<th style="width:25%">Damage on Hit</th>]] end
local wt = ""
wt = wt..inline_block(weapon,"Physical Base Weapon Damage")
..inline_block(weapon,"Magical Base Weapon Damage")
return "<td>"..wt.."</td>"
end
---These stats get their own table cells, as such they are excluded from the stats cell to avoid needless redundancy
local exclude_stat = {["Physical Base Weapon Damage"]=true,["Magical Base Weapon Damage"]=true,["Armor Rating"]=true,["Magical Resistance"]=true,["Move Speed"]=true}
---Formats a table cell containing any stats not covered by the rest of the row
---@param weapon table
---@param is_header boolean
---@return string
local function stats(weapon,is_header)
if is_header then return [[<th style="width:12%">Stats</th>]] end
local wt = ""
for i,stat in ipairs(weapon.stats.order) do
if not exclude_stat[stat] then
wt = wt..inline_block(weapon,stat)
end
end
return "<td>"..wt.."</td>"
end
---Formats a table cell containing animation times for ranges weapons
---@param weapon table
---@param is_header boolean
---@return string
local function animation_time(weapon,is_header)
if is_header then return [[<th style="width:10%">Animation Times</th>]] end
local windup = "<br>Windup:"
local finish = "<br>Finish:"
local reload = "<br><br><span style='color:#eee8'>Reload</span><br>"
if weapon.animationtimes["Attack 1"] then
-- windup = windup..weapon.animationtimes["Attack 1"].Windup
-- finish = finish..weapon.animationtimes["Attack 1"].Finish
else
windup = ""
finish = ""
end
if weapon.animationtimes["Other"] then
-- reload = reload..weapon.animationtimes["Other"].Reload
else
reload = ""
end
if #windup == 0 and #finish == 0 and #reload == 0 then
return ""
else
return "<td><span style='color:#eee8'>Primary Attack</span>"..windup..finish..reload.."</td>"
end
end
---Formats a table cell containing hitslow for each attack
---@param weapon table
---@param is_header boolean
---@return string
local function slowdown_on_hit(weapon,is_header)
if is_header then return [[<th style="width:8%">Slowdown On Hit</th>]] end
if not (weapon.abilities.Primary or weapon.abilities.Secondary or weapon.abilities.Special) then return "<td></td>" end
local ability_type = "Primary"
if weapon.slottype == "Off-Hand" then ability_type = "Secondary" end
local wt = "<span style='color:#eee8'>Hitslow</span><br>"
local duration = " for "
for i,attack in ipairs(weapon.abilities[ability_type].order) do
if i~=1 then wt = wt.."/" end
wt = wt..(weapon.abilities[ability_type][attack].effects.HitSlow.rarity.Global["Move Speed Add"]
or weapon.abilities[ability_type][attack].effects.HitSlow.rarity.Global["Move Speed Bonus"] or "")
end
for i,attack in ipairs(weapon.abilities[ability_type].order) do
if i~=1 then duration = duration.."/" end
duration = duration..(weapon.abilities[ability_type][attack].effects.HitSlow.rarity.Global["Duration"] or "")
end
return "<td>"..wt..duration.."s</td>"
end
---Formats a table cell containing the projectile's initial speed
---@param weapon table
---@param is_header boolean
---@return string
local function initial_speed(weapon,is_header)
if is_header then return [[<th style="width:5%">Initial Projectile Speed (m/s)</th>]] end
return "<td>"..weapon.initialspeed.."</td>"
end
---Formats a table cell containing the hitbox image resized by inventory size
---@param weapon table
---@param is_header boolean
---@return string
local function hitbox(weapon,is_header)
if is_header then return [[<th style="width:10%">Hitbox + Impact Resist</th>]] end
return "<td>[[File:"..weapon.name.." Hitbox.png|link=|"..size(weapon).."]]</td>"
end
---Helps format a string containing either Combo Damage or damagetype values
---@param weapon table
---@param ability string
---@param value string
---@return string
local function format_combo(weapon,ability,value)
local wt = ""
for i,attack in ipairs(weapon.abilities[ability].order) do
if i~=1 then wt = wt.."/" end
wt = wt..(weapon.abilities[ability][attack][value] or "")
end
return wt
end
---Formats a table cell containing ability combo values per attack
---@param weapon table
---@param is_header boolean
---@return string
local function combo(weapon,is_header)
if is_header then return [[<th style="width:8%">Combo</th>]] end
local wt = ""
if weapon.abilities["Primary"] then
wt = wt.."<span style='color:#eee8'>Primary Attacks</span><br>"..format_combo(weapon,"Primary","damagetype").."<br>"..format_combo(weapon,"Primary","combodamage")
end
if weapon.abilities["Secondary"] then
if #wt ~= 0 then wt = wt.."<br><br>" end
wt = wt.."<span style='color:#eee8'>Secondary Attacks</span><br>"..format_combo(weapon,"Secondary","damagetype").."<br>"..format_combo(weapon,"Secondary","combodamage")
end
if weapon.abilities["Special"] then
if wt:match("Primary") or wt:match("Secondary") then wt = wt.."<br><br>" end
wt = wt.."<span style='color:#eee8'>Special Attacks</span><br>"..format_combo(weapon,"Special","damagetype").."<br>"..format_combo(weapon,"Special","combodamage")
end
return "<td>"..wt.."</td>"
end
---@param weapon table
---@return string
local function determine_table_type(weapon)
if weapon.args then
if weapon.args[1] == "Shield" then return "Shield"
elseif (weapon.args[1]):lower():match("bow") or weapon.args[1] == "Firearm" or weapon.args[1] == "Throwable" then return "Ranged" end
elseif weapon.types then
if weapon.types.Shield then return "Shield"
elseif weapon.types.Bow or weapon.types.Crossbow or weapon.types.Firearm or weapon.types.Throwable then return "Ranged" end
end
return "Default"
end
---Determines which table data goes into the table row
local row_type = {
["Shield"] = {name,classes,slot_type,move_speed,armor_rating,impact_zones,action_move_speed_penalty},
["Ranged"] = {name,classes,slot_type,move_speed,damage_on_hit,stats,impact_zones,action_move_speed_penalty,slowdown_on_hit,initial_speed},
["Default"] = {name,classes,slot_type,move_speed,damage_on_hit,stats,hitbox,impact_zones,combo,action_move_speed_penalty,slowdown_on_hit}
}
---Return a table row of data cells containing weapon information,
--- @param weapon table
--- @return string
local function row(weapon, is_header)
is_header = is_header or false
local wt = {}
wt[#wt+1] = "<tr>"
for _,content in ipairs(row_type[determine_table_type(weapon)]) do
wt[#wt+1] = content(weapon,is_header)
end
wt[#wt+1] = "</tr>"
return concat(wt)
end
---Returns a predetermined weapon list
---@param frame table contains args, first key is determined by types, second key must be {Uncraftable, Craftable, Artifact}
---@return table
local function get_list(frame)
if not (frame.args and frame.args[1] and frame.args[2]) then return {} end
if not (WD[frame.args[1]] and WD[frame.args[1]][frame.args[2]]) then return {} end
return WD[frame.args[1]][frame.args[2]]
end
--- @param frame any
--- @return string
function p.draw_table(frame)
local wt = {}
wt[#wt+1] = [[<table cellspacing="0" class="wikitable sortable jquery-tablesorter" style="text-align:center; vertical-align:middle;">]]
wt[#wt+1] = row(frame, true)
for _,item_name in ipairs(get_list(frame)) do
wt[#wt+1] = row(WD.Weapon[item_name])
end
wt[#wt+1] = "</table>"
return concat(wt)
end
return p
---- Test on wiki with: mw.log(p.draw_table({args={"Crossbow","Uncraftable"}}))
---- Test on wiki with: mw.log(p.draw_table({args={"Shield","Craftable"}}))
---- Test on wiki with: mw.log(p.draw_table({args={"Polearm","Artifact"}}))