Module:WeaponData

-- local p = {}

local factions = {"TR", "NC", "VS", "NSO", "NS"}

local weaponList = { ["Assault Rifle"] = { ["VS"] = { "Pulsar VS1", "Pulsar Burst", "Equinox VE2", "H-V45", "CME", "Terminus VX-9", "Corvus VA55", "VE-A Lacerta", "Darkstar", },		["NC"] = { "NC1 Gauss Rifle", "Gauss Rifle Burst", "Gauss Rifle S", "GR-22", "Reaper DMR", "Carnage AR", "NC-9 A-Tross", "MGR-A1 Vanquisher", "Gauss Prime", },		["TR"] = { "T1 Cycler", "T1B Cycler", "T1S Cycler", "TAR", "SABR-13", "Cycler TRV", "TORQ-9", "MG-A1 Arbalest", "T1A Unity", },		["NSO"] = { "AR-100", "AR-101", "AR-N203", },		["NS"] = { "NS-11A", "NSX Yumi", "NSX Kuwa", },	},	["Carbine"] = { ["VS"] = { "Solstice VE3", "Solstice Burst", "Prominence VE4", "Serpent VE92", "VX6-7", "Zenith VX-5", "Pulsar C", "VE-C Horizon", "Eclipse VE3A", },		["NC"] = { "AF-19 Mercenary", "AF-20 Rogue", "NC2 Gauss Compact", "GD-7F", "AC-X11", "AF-4A Bandit", "Razor GD-23", "MGR-C1 Charger", "19A Fortuna", },		["TR"] = { "TRAC-5", "TRAC-5 Burst", "TRAC-5 S", "LC2 Lynx", "T5 AMC", "LC3 Jaguar", "HC1 Cougar", "MG-C1 Kindred", "TRAC-Shot", },		["NSO"] = { "CB-100", "CB-200", "CB-X75", "CB-ARX Newton", },		["NS"] = { "NS-11C", "NSX Tanto", },	},	["LMG"] = { ["TR"] = { "T9 CARV", "T9 CARV-S", "MSW-R", "T16 Rhino", "TMG-50", "T32 Bull", "MG-H1 Watchman", 'T9A "Butcher"', },		["NC"] = { "GD-22S", "NC6S Gauss SAW S", "NC6 Gauss SAW", "LA1 Anchor", "EM1", "EM6", "MGR-L1 Promise", "NC6A GODSAW", },		["VS"] = { "Orion VS54", "Flare VE6", "SVA-88", "VX29 Polaris", "Ursa", "Pulsar LSW", "VE-H Maw", "Betelgeuse 54-A", },		["NSO"] = { "XMG-100", "XMG-155", "XMG-200", "XMG-ARX Galilei", },		["NS"] = { "NS-15M2", "NSX Naginata", },	},	["Scout Rifle"] = { ["TR"] = { "AMR-66", "MG-HBR1 Dragoon", "HSR-1", "SOAS-20", "DMR-99", },		["NC"] = { "Warden", "MGR-M1 Bishop", "AF-6 Shadow", "AF-18 Stalker", "GD Guardian", },		["VS"] = { "Eidolon VE33", "VE-LR Obelisk", "Nyx VX31", "Artemis VX26", "Revenant", },		["NSO"] = { "BAR-100", "BAR-200", "BAR-A50", "BAR-ARX Feynman", },		["NS"] = { "NS-30 Vandal", "NSX Tomoe", "NS-30 Tranquility", "NSX Sesshin", },	},	["SMG"] = { ["TR"] = { "SMG-46 Armistice", "PDW-16 Hailstorm", "MG-S1 Jackal", "Shuriken", },		["NC"] = { "AF-4 Cyclone", "Blitz GD-10", "MGR-S1 Gladius", "Tempest", },		["VS"] = { "Eridani SX5", "Sirius SX12", "VE-S Canis", "Skorpios", },		["NSO"] = { "PMG-100", "PMG-200", "PMG-3XB", "PMG-ARX Schrodinger", },		["NS"] = { "NS-7 PDW", "MKV Suppressed", "NSX Tengu", "NS-66 Punisher", "NSX Kappa", },	},	["Sidearm"] = { ["TR"] = { "TX1 Repeater", "TX2 Emperor", "TS2 Inquisitor", "T4 AMP", "The President", },		["NC"] = { "NC4 Mag-Shot", "LA8 Rebel", "LA3 Desperado", "NC08 Mag-Scatter", "The Executive", },		["VS"] = { "Beamer VS3", "Manticore SX40", "Cerberus", "Spiker", "The Immortal", },		["NSO"] = { "U-100 Lastly", "U-150 Recall", "U-200 Harbinger", "U-ARX Dirac", },		["NS"] = { "NS-357 Underboss", "NS-44 Commissioner", "NS44L Blackhand", "NS-45 Pilot", "NS-61 Emissary", "Hunter QCX",

"NS-357IA", "NS-44L Showdown", "NSX Yawara",

"NS Deep Freeze", "NS CandyCannon 3000", "NS-1999 Party Pistol", "Patriot Flare Gun", -- NS/TR/NC/VS variants "Triumph Flare Gun", -- TR/NC/VS variants "Ectobblaster", "Soldier Soaker", },	} }

local normalize = { ["assault rifle"] = "Assault Rifle", ["assault rifles"] = "Assault Rifle", ["ar"] = "Assault Rifle", ["ars"] = "Assault Rifle", ["carbine"] = "Carbine", ["carbines"] = "Carbine", ["light machine gun"] = "LMG", ["light machine guns"] = "LMG", ["lmg"] = "LMG", ["lmgs"] = "LMG", ["heavy gun"] = "Heavy Gun", ["heavy guns"] = "Heavy Gun", ["heavy"] = "Heavy Gun", ["sniper rifle"] = "Sniper Rifle", ["sniper rifles"] = "Sniper Rifle", ["sniper"] = "Sniper Rifle", ["snipers"] = "Sniper Rifle", ["scout rifle"] = "Scout Rifle", ["scout rifles"] = "Scout Rifle", ["scout"] = "Scout Rifle", ["scouts"] = "Scout Rifle", ["battle rifle"] = "Battle Rifle", ["battle rifles"] = "Battle Rifle", ["submachine gun"] = "SMG", ["submachine guns"] = "SMG", ["smg"] = "SMG", ["smgs"] = "SMG", ["rocket launcher"] = "Rocket Launcher", ["rocket launchers"] = "Rocket Launcher", ["rocket"] = "Rocket Launcher", ["launcher"] = "Rocket Launcher", ["launchers"] = "Rocket Launcher", ["shotgun"] = "Shotgun", ["shotguns"] = "Shotgun", ["sidearm"] = "Sidearm", ["sidearms"] = "Sidearm", ["pistol"] = "Sidearm", ["pistols"] = "Sidearm", }

function p.getWeaponList(frame) return weaponList end

function p.normalizeName(nickname) local key = string.lower(nickname) if normalize[key] then return normalize[key] else return nickname end end

-- basic args function function arguments(origArgs) local args = {}

for k, v in pairs(origArgs) do       if v ~= '' then args[k] = v       end end

return args end -- basic parent args function function mergeFrames(frame, parent) local args = {}

if frame then for k,v in pairs(frame.args) do           args[k] = v        end end

if parent then for k,v in pairs(parent.args) do           args[k] = v        end end

return args end -- table concat from League of Legends Wiki function tbl_concat(frame) local args = (frame.args and arguments(frame.args)) or arguments(frame) args["pre"] = args["pre"] or args["prepend"]  or "" args["app"] = args["app"] or args["append"]   or "" args["sep"] = args["sep"] or args["separator"] or "," args["tbl"] = args["tbl"] or args[1] if args["sep"] == "false" then args["sep"] = "" end if args["index"] ~= nil then return args["pre"] .. args["tbl"][tonumber(args["index"])] .. args["app"] end

local s = {} local s_len = 0 local indexed_args = {} for i,v in ipairs(args["tbl"]) do       s_len = s_len + 1 s[s_len] = args["pre"] .. v .. args["app"] indexed_args[i] = true end

local keys = {} local keys_len = 0 for k in pairs(args["tbl"]) do   	if indexed_args[k] == nil then keys_len = keys_len + 1 keys[keys_len] = k	   end end

if keys_len ~= 0 then table.sort(keys)

for k = 1, keys_len do       	s_len = s_len + 1 s[s_len] = args["pre"] .. args["tbl"][keys[k]] .. args["app"] end end

return table.concat(s,args["sep"]) end

-- temp stat to units mapping local statUnits = { ["aim_move_speed_multiplier"] = "x", ["equip_time"] = " ms", ["headshot_multiplier"] = "x", ["fire_rate"] = " RPM", ["max_damage_range"] = "m", ["min_damage_range"] = "m", ["max_indirect_damage_range"] = "m", ["min_indirect_damage_range"] = "m", ["muzzle_velocity"] = " m/s", ["short_reload"] = "s", ["long_reload"] = "s", ["max_recoil_angle"] = "°", ["min_recoil_angle"] = "°", ["first_shot_recoil_multiplier"] = "x", }

function p.weaponComparisonTable(frame) -- args -- local args; if frame.args == nil then args = arguments(frame) else args = arguments(frame.args) end local args; if frame.args == nil then args = arguments(frame) else if frame:getParent.args ~= nil then args = arguments(mergeFrames(frame, frame:getParent)) else args = arguments(frame.args) end end frame = mw.getCurrentFrame local Weapon = require("Module:WeaponData/weapon") local excludeRows = {} if args["exclude"] ~= nil then for exclude in mw.text.gsplit(args["exclude"], "[, ]+") do			excludeRows[mw.text.trim(exclude)] = true end end local totalCols = 2 local weapons = {} for i, weapon in ipairs(args) do		weapons[i] = Weapon:new(mw.text.trim(weapon)) totalCols = totalCols + 2 end local statList = { "name", "image", -- "description", "faction", "cert_cost", "dc_cost", "weapon_type", "classes", "fire_modes", "range", "aim_move_speed_multiplier", "equip_time", "headshot_multiplier", "fire_rate", "max_damage", "max_damage_range", "min_damage", "min_damage_range", "muzzle_velocity", "short_reload", "long_reload", "magazine_size", "ammunition", "accuracy", -- "hip_accuracy", -- 	"crouch_still", -- 	"crouch_move", -- 	"stand_still", -- 	"stand_move", -- 	"bloom_per_shot", -- "aim_accuracy", -- 	"crouch_still", -- 	"crouch_move", -- 	"stand_still", -- 	"stand_move", -- 	"bloom_per_shot", "min_vertical_recoil", "max_vertical_recoil", "min_horizontal_recoil", "max_horizontal_recoil", "horizontal_recoil_tolerance", "min_recoil_angle", "max_recoil_angle", "recoil_bias", "recoil_decrease", "first_shot_recoil_multiplier", }	local statName = { ["name"] = "Weapon", ["faction"] = "Faction", ["cert_cost"] = "Cert Cost", ["dc_cost"] = "Daybreak Cash Cost", ["weapon_type"] = "Weapon Type", ["classes"] = "Classes", ["fire_modes"] = "Fire Modes", ["range"] = "Range", ["aim_move_speed_multiplier"] = "Aim Move Speed Multiplier", ["equip_time"] = "Equip Time", ["headshot_multiplier"] = "Headshot Multiplier", ["fire_rate"] = "Fire Rate", ["max_damage"] = "Maximum Damage", ["max_damage_range"] = "Maximum Damage Range", ["min_damage"] = "Minimum Damage", ["min_damage_range"] = "Minimum Damage Range", ["muzzle_velocity"] = "Muzzle Velocity", ["short_reload"] = "Short Reload", ["long_reload"] = "Long Reload", ["magazine_size"] = "Magazine Size", ["ammunition"] = "Ammunition",

["hip"] = "Hip", ["aim"] = "Aim", ["crouch"] = "Crouch", ["stand"] = "Stand", ["still"] = "Still", ["move"] = "Move", ["bloom_per_shot"] = "Bloom per Shot",

["min_vertical_recoil"] = "Minimum Vertical Recoil", ["max_vertical_recoil"] = "Maximum Vertical Recoil", ["min_horizontal_recoil"] = "Minimum Horizontal Recoil", ["max_horizontal_recoil"] = "Maximum Horizontal Recoil", ["horizontal_recoil_tolerance"] = "Horizontal Recoil Tolerance", ["min_recoil_angle"] = "Minimum Recoil Angle", ["max_recoil_angle"] = "Maximum Recoil Angle", ["recoil_bias"] = "Recoil Bias", ["recoil_decrease"] = "Recoil Decrease", ["first_shot_recoil_multiplier"] = "First Shot Recoil Multiplier", }	local weaponStatTable = mw.html.create("table") :addClass("weapon-comparison-table") for _, stat in ipairs(statList) do		if excludeRows[stat] then -- pass elseif stat == "accuracy" then local accuracyRow = mw.html.create(nil) local tableRows = {} tableRows["headers"] = accuracyRow :tag("tr") :tag("th") :attr("colspan", 2) :done tableRows["crouch_still"] = accuracyRow :tag("tr") :tag("th") :attr("rowspan", 2) :css("vertical-align", "middle") :wikitext(statName["crouch"]) :done :tag("th") :wikitext(statName["still"]) :done tableRows["crouch_move"] = accuracyRow :tag("tr") :tag("th") :wikitext(statName["move"]) :done tableRows["stand_still"] = accuracyRow :tag("tr") :tag("th") :attr("rowspan", 2) :css("vertical-align", "middle") :wikitext(statName["stand"]) :done :tag("th") :wikitext(statName["still"]) :done tableRows["stand_move"] = accuracyRow :tag("tr") :tag("th") :wikitext(statName["move"]) :done tableRows["bloom_per_shot"] = accuracyRow :tag("tr") :tag("th") :attr("colspan", 2) :wikitext(statName["bloom_per_shot"]) :done

for _, weapon in ipairs(weapons) do				for stance, row in pairs(tableRows) do					if stance == "headers" then row :tag("th") :css("text-align", "center") :wikitext(statName["hip"]) :done :tag("th") :css("text-align", "center") :wikitext(statName["aim"]) :done else row :tag("td") :wikitext(weapon:get("hip_accuracy", stance)) :done :tag("td") :wikitext(weapon:get("aim_accuracy", stance)) :done end end end weaponStatTable:node(accuracyRow) else local tableRow = mw.html.create("tr") :tag("th") :attr("colspan", "2") :wikitext(statName[stat] or "") :done for _, weapon in ipairs(weapons) do				local tableCell = tableRow :tag("td") :attr("colspan", 2) if stat == "name" then local weaponName = weapon:get("name") tableCell:wikitext("" .. weaponName .. "") elseif stat == "image" then local weaponName = weapon:get("name") tableCell:wikitext("") elseif stat == "faction" then local factions = weapon:get("faction") local factionsList = "" local i = 0 for _, faction in ipairs(factions) do factionsList = factionsList .. frame:expandTemplate{ title = "Icon", args = { faction }} end tableCell:wikitext(factionsList) elseif stat == "cert_cost" then local cost = weapon:get("cert_cost") if type(cost) == "number" then tableCell:wikitext(frame:expandTemplate{ title = "Resources", args = { cost, "cert", "small" }}) else tableCell:wikitext(cost) end elseif stat == "dc_cost" then local cost = weapon:get("dc_cost") if type(cost) == "number" then tableCell:wikitext(frame:expandTemplate{ title = "Resources", args = { cost, "dc", "small" }}) else tableCell:wikitext(cost) end elseif stat == "classes" then for _, class in pairs(weapon:get("classes")) do						tableCell:wikitext(frame:expandTemplate{ title = "Icon", args = { class }}) end elseif stat == "fire_modes" then local fireModesList = "" for i, mode in ipairs(weapon:get("fire_modes")) do if i > 1 then fireModesList = fireModesList .. ", " end fireModesList = fireModesList .. mode end tableCell:wikitext(fireModesList) elseif stat == "short_reload" and weapon:isHeatWeapon then tableCell:wikitext(frame:preprocess(weapon:get("heat_short_reload")) .. (statUnits[stat] or "")) elseif stat == "long_reload" and weapon:isHeatWeapon then tableCell:wikitext(weapon:get("heat_long_reload") .. (statUnits[stat] or "")) elseif stat == "magazine_size" and weapon:isHeatWeapon then tableCell:wikitext(frame:preprocess(weapon:get("heat_magazine_size"))) elseif stat == "ammunition" and weapon:isHeatWeapon then tableCell:wikitext(weapon:get("heat_capacity") .. " heat") else -- if weapon:get(stat) == nil then -- 	mw.log(stat) -- 	mw.log(weapon:get(stat)) -- end local statValue = weapon:get(stat) if statValue then if type(statValue) == "table" then local statFireModesList = "" for i, mode in ipairs(weapon:get("fire_modes")) do if i > 1 then statFireModesList = statFireModesList .. "/" end statFireModesList = statFireModesList .. statValue[mode] .. (statUnits[stat] or "") end tableCell:wikitext(statFireModesList) else if string.find(statValue, "{{") then tableCell:wikitext(frame:preprocess(statValue) .. (statUnits[stat] or "")) else tableCell:wikitext(statValue .. (statUnits[stat] or "")) end end else -- no stat end end end weaponStatTable:node(tableRow) end end return tostring(weaponStatTable) end

function p.weaponGroupComparisonTable(frame) -- args -- local args; if frame.args == nil then args = arguments(frame) else args = arguments(frame.args) end local args; if frame.args == nil then args = arguments(frame) else if frame:getParent.args ~= nil then args = arguments(mergeFrames(frame, frame:getParent)) else args = arguments(frame.args) end end local weaponGroup = args[1] or nil local faction = args[2] or nil weaponGroup = p.normalizeName(weaponGroup) if weaponGroup and faction and weaponList[weaponGroup] and weaponList[weaponGroup][faction] then return p.weaponComparisonTable( weaponList[weaponGroup][faction]) end return end

function p.weaponComparisonMenu(frame) local args; if frame.args == nil then args = arguments(frame) else if frame:getParent.args ~= nil then args = arguments(mergeFrames(frame, frame:getParent)) else args = arguments(frame.args) end end local menu = mw.html.create('table') local weaponGroups if args[1] then weaponGroups = {p.normalizeName(args[1])} else weaponGroups = {} for weaponGroup, _ in pairs(weaponList) do   		table.insert(weaponGroups, weaponGroup) end table.sort(weaponGroups) end for _, weaponGroup in ipairs(weaponGroups) do		local factionRow = mw.html.create('tr') local weaponsRow = mw.html.create('tr') local factionCount = 0 for _, faction in ipairs(factions) do			if weaponList[weaponGroup] and weaponList[weaponGroup][faction] then factionCount = factionCount + 1 factionRow :tag('td') :css('text-align', 'center') :wikitext(faction) local weaponCell = weaponsRow :tag('td') :css('vertical-align', 'top') :newline for _, weapon in ipairs(weaponList[weaponGroup][faction]) do					weaponCell :wikitext('* ' .. weapon .. ' \n') end end end menu :tag('tr') :tag('td') :css('text-align', 'center') :attr('colspan', factionCount) :wikitext(weaponGroup .. "s") :done :done :node(factionRow) :node(weaponsRow) end return tostring(menu:allDone) end

function p.weaponModuleList(frame) local args; if frame.args == nil then args = arguments(frame) else if frame:getParent.args ~= nil then args = arguments(mergeFrames(frame, frame:getParent)) else args = arguments(frame.args) end end local menu = mw.html.create('table') local weaponGroups if args[1] then weaponGroups = {p.normalizeName(args[1])} else weaponGroups = {} for weaponGroup, _ in pairs(weaponList) do   		table.insert(weaponGroups, weaponGroup) end table.sort(weaponGroups) end for _, weaponGroup in ipairs(weaponGroups) do		local factionRow = mw.html.create('tr') local weaponsRow = mw.html.create('tr') local factionCount = 0 for _, faction in ipairs(factions) do			if weaponList[weaponGroup] and weaponList[weaponGroup][faction] then factionCount = factionCount + 1 factionRow :tag('td') :css('text-align', 'center') :wikitext(faction) local weaponCell = weaponsRow :tag('td') :css('vertical-align', 'top') :newline for _, weapon in ipairs(weaponList[weaponGroup][faction]) do					weaponCell :wikitext('* ' .. weapon .. '\n') end end end menu :tag('tr') :tag('td') :css('text-align', 'center') :attr('colspan', factionCount) :wikitext(weaponGroup .. "s") :done :done :node(factionRow) :node(weaponsRow) end return tostring(menu:allDone) end

function p.get(frame) local args; if frame.args == nil then args = arguments(frame) else if frame:getParent.args ~= nil then args = arguments(mergeFrames(frame, frame:getParent)) else args = arguments(frame.args) end end local weaponName = mw.text.trim(args["weapon"] or args[1]) local stat			= string.gsub(args["stat"] or args[2], " ", "_") if not weaponName or not stat then return end local outputformat	= args["output"] or args[3] local units 		= args["units"] or statUnits[stat] or "" local variant		= args["variant"] or nil local append		= units .. (args["append"] or "") local prepend		= args["prepend"] or "" local separator		= args["separator"] or ", " local index			= args["index"] or nil if index then index = string.gsub(index, " ", "_") end local Weapon = require("Module:WeaponData/weapon") local weapon = Weapon:new(weaponName) local statValue if variant then statValue = weapon:getVariant(variant, stat) else statValue = weapon:get(stat) end if type(statValue) == "table" then if args['output'] == "csv" then return tbl_concat{statValue} elseif args['output'] == "template" then return frame:preprocess(tbl_concat{statValue, prepend = "{{" .. args['t_name'] .. "|", append = "}}", separator = args['separator']}) -- elseif args['output'] == "category" then --    return frame:preprocess(tbl_concat{statValue, prepend = "", separator = args['separator'] or " "}) else if index then return prepend .. statValue[tonumber(index) or index] .. append end return frame:preprocess(tbl_concat{statValue, prepend = prepend, append = append, separator = separator}) end elseif statValue == nil then return "" else return frame:preprocess(prepend .. statValue .. append) end end

return p --