Module:Sandbox/DutyS12345/WeaponData/weapon

-- archived version that handles variants as normal weapons using a mapping -- -- temp weapon type to classes mapping local weaponClasses = { ["Assault Rifle"] = {"Combat Medic"}, ["Carbine"] = {"Light Assault", "Engineer"}, ["Heavy Gun"] = {"Heavy Assault"}, ["LMG"] = {"Heavy Assault"}, ["Rocket Launcher"] = {"Heavy Assault"}, ["Shotgun"] = {"Light Assault", "Combat Medic", "Engineer", "Heavy Assault"}, ["Sniper Rifle"] = {"Infiltrator"}, ["SMG"] = {"Infiltrator", "Light Assault", "Combat Medic", "Engineer", "Heavy Assault"}, ["Scout Rifle"] = {"Infiltrator", "Combat Medic", "Engineer", "Heavy Assault"}, -- Sidearms ["Pistol"] = {"Infiltrator", "Light Assault", "Combat Medic", "Engineer", "Heavy Assault"}, ["Sidearm"] = {"Infiltrator", "Light Assault", "Combat Medic", "Engineer", "Heavy Assault"}, }

-- table of variants so all data doesnt need to be loaded for one gun local variants = { ["TAR-AE"] = "TAR", ["GR-22AE"] = "GR-22", ["H-V45 AE"] = "H-V45", ["NS-11AB"] = "NS-11A", ["NS-11AG"] = "NS-11A", ["NS-11P"] = "NS-11A", ['NS-11A "Heatwave"'] = "NS-11A", ["PSA-02 Diamondback"] = "NS-11A", ['NS-11 "Endeavor" Assault Rifle'] = "NS-11A", ['NSX "Networked" Yumi'] = "NSX Yumi", ["LC2 Lynx AE"] = "LC2 Lynx", ["AF-4A Bandit AE"] = "AF-4A Bandit", ["Zenith VX-5AE"] = "Zenith VX-5", ["NS-11CB"] = "NS-11C", ["NS-11CG"] = "NS-11C", ["NS-11CP"] = "NS-11C", ['NS-11 "Endeavor" Carbine'] = "NS-11C", ["NSX-P Tanto"] = "NSX Tanto", ['"Treasured" MSW-R'] = "MSW-R", ["MG-H1 Watchman AE"] = "MG-H1 Watchman", ["LA1 Service Anchor"] = "LA1 Anchor", ['"Treasured" LA1 Anchor'] = "LA1 Anchor", ["MGR-L1 Promise AE"] = "MGR-L1 Promise", ['"Treasured" Orion VS54'] = "Orion VS54", ["SVA-GG"] = "SVA-88", ["VE-H Maw AE"] = "VE-H Maw", ["NS-15MB"] = "NS-15M2", ["NS-15MG"] = "NS-15M2", ["NS-15MP"] = "NS-15M2", ["NS-15M1"] = "NS-15M2", ["NS-15M AE"] = "NS-15M2", ['NS-15 "Endeavor" Machinegun'] = "NS-15M2", ["NS-15 Gallows"] = "NS-15M2", ["NSX-P Naginata"] = "NSX Naginata", ['NSX "Networked" Naginata'] = "NSX Naginata", ["SMG-46G Armistice"] = "SMG-46 Armistice", ["SMG-46AE Armistice"] = "SMG-46 Armistice", ["AF-4G Cyclone"] = "AF-4 Cyclone", ["AF-4AE Cyclone"] = "AF-4 Cyclone", ["Eridani SX5G"] = "Eridani SX5", ["Eridani SX5-AE"] = "Eridani SX5", ["SOAS-20 AE"] = "SOAS-20", ["AF-18 Stalker AE"] = "AF-18 Stalker", ["Artemis VX26 AE"] = "Artemis VX26", ["TX1-FB Repeater"] = "TX1 Repeater", ['TX2 "Jackpot" Emperor'] = "TX2 Emperor", ["NC4-FB Mag-Shot"] = "NC4 Mag-Shot", ['LA3 "Jackpot" Desperado'] = "LA3 Desperado", ["Beamer VS3-FB"] = "Beamer VS3", ['"Jackpot" Cerberus'] = "Cerberus", }

-- special access functions for data, allowing for default values, calculated values, special fields that aren't in the data, etc. local get = {}

function get:id return self.id end

function get:name return self.name end

function get:description return self.description end

function get:cert_cost return self.cert_cost end

function get:dc_cost return self.dc_cost end

function get:weapon_type return self.weapon_type end

function get:classes return self.classes or weaponClasses[self.weapon_type] end

function get:faction return self.faction end

function get:fire_modes return self.fire_modes end

function get:range return self.range end

function get:aim_move_speed_multiplier return self.stats and self.stats.move_modifier end

function get:equip_time return self.stats and self.stats.equip_ms end

function get:headshot_multiplier return self.stats and self.stats.damage_head_multiplier end

function get:fire_rate return self.stats and (self.stats.fire_rate		or math.floor((60000 / self.stats.fire_refire_ms) + 0.5)) end

function get:max_damage return self.stats and self.stats.max_damage end

function get:max_damage_range return self.stats and self.stats.max_damage_range end

function get:min_damage return self.stats and self.stats.min_damage end

function get:min_damage_range return self.stats and self.stats.min_damage_range end

function get:muzzle_velocity return self.stats and self.stats.muzzle_velocity end

function get:short_reload return self.stats and self.stats.short_reload end

function get:long_reload return self.stats and self.stats.long_reload end

function get:magazine_size return self.stats and (self.stats.magazine_size		or self.stats.clip_size) end

function get:ammunition return self.stats and (self.stats.ammunition		or self.stats.capacity) end

function get:hip_accuracy(stance) if stance then return self.stats and self.stats.hip_accuracy[stance] else return self.stats and self.stats.hip_accuracy end end

function get:aim_accuracy(stance) if stance then return self.stats and self.stats.aim_accuracy[stance] else return self.stats and self.stats.aim_accuracy end end

function get:min_vertical_recoil return self.stats and self.stats.recoil_magnitude_min end

function get:max_vertical_recoil return self.stats and self.stats.recoil_magnitude_max end

function get:min_horizontal_recoil return self.stats and self.stats.recoil_horizontal_min end

function get:max_horizontal_recoil return self.stats and self.stats.recoil_horizontal_max end

function get:horizontal_recoil_tolerance return self.stats and self.stats.recoil_horizontal_tolerance end

function get:min_recoil_angle return self.stats and self.stats.recoil_angle_min end

function get:max_recoil_angle return self.stats and self.stats.recoil_angle_max end

function get:recoil_bias if self.stats and self.stats.recoil_angle_min and self.stats.recoil_angle_max then local cmp = self.stats.recoil_angle_min + self.stats.recoil_angle_max if cmp == 0 then return "← = →" elseif cmp > 0 then return "→" elseif cmp < 0 then return "←" end else return nil end end

function get:recoil_decrease return self.stats and self.stats.recoil_recovery_rate end

function get:first_shot_recoil_multiplier return self.stats and self.stats.recoil_first_shot_modifier end

-- heat function get:isHeatWeapon return self.stats and self.stats.heat_threshold ~= nil end

function get:heat_recovery return self.stats and self.stats.heat_bleed_off_rate end function get:heat_recovery_delay return self.stats and self.stats.heat_recovery_delay_ms end function get:overheat_penalty return self.stats and self.stats.heat_overheat_penalty_ms end

function get:heat_per_shot return self.stats and self.stats.heat_per_shot end

function get:heat_capacity return self.stats and (self.stats.heat_threshold		or self.stats.heat_capacity) end

function get:heat_short_reload if self.stats and self.stats.heat_per_shot and self.stats.heat_bleed_off_rate and self.stats.heat_recovery_delay_ms then return string.format("", math.floor((1000 * self.stats.heat_per_shot / self.stats.heat_bleed_off_rate) + 0.5) / 1000, self.stats.heat_recovery_delay_ms / 1000) else return nil end end

function get:heat_long_reload return self.stats and string.format("%.3f", self.stats.heat_overheat_penalty_ms / 1000) -- if self.stats.heat_recovery_delay_ms and self.stats.heat_threshold and self.stats.heat_bleed_off_rate then -- 	return string.format("%.3f", (self.stats.heat_recovery_delay_ms + math.floor((1000 * self.stats.heat_threshold / self.stats.heat_bleed_off_rate) + 0.5)) / 1000) -- else -- 	return nil -- end end

function get:heat_magazine_size if self.stats and self.stats.heat_per_shot and self.stats.heat_threshold then return string.format("", self.stats.heat_per_shot, math.ceil(self.stats.heat_threshold / self.stats.heat_per_shot)) else return nil end end

local Weapon = {}

-- checks Weapon object weaponName against data name to check if variant function Weapon:get(field, ...) if self[1] ~= get["name"](self) then return self:getVariant(self[1], field, unpack(arg)) end return self:getBase(field, unpack(arg)) end

-- any values inside variant should override the main values function Weapon:getVariant(variant, ...) return variant and self["variants"] and self["variants"][variant] and self["variants"][variant] and Weapon.getBase(self["variants"][variant], unpack(arg))	-- looks in variants for variant overrides or self:getBase(unpack(arg))				-- falls back to base values end

function Weapon:getBase(field, ...) return get[field] and get[field](self, unpack(arg)) 	-- looks in get for a special access function or self[field]											-- falls back to value stored in data or (self["stats"] and self["stats"][field])				-- checks stats table as well end

function Weapon:isHeatWeapon return get.isHeatWeapon(self) end

-- Weapon object constructor -- @param weapon		weapon name (can be variant name) -- @param dataModule	data module page title or data table object for override; optional - defaults to weapon's data module function Weapon:new(weapon, dataModule) local o = {} -- local weaponData = mw.loadData("Module:WeaponData/data/ ")\ local weaponData local weaponName = weapon if type(dataModule) == "table" then weaponData = dataModule else if variants[weapon] then weaponData = mw.loadData("Module:WeaponData/data/" .. variants[weapon])[variants[weapon]] else weaponData = mw.loadData(dataModule or ("Module:WeaponData/data/" .. weapon))[weapon] end end setmetatable(o, {		__index = function (t, k) return k==1 and weaponName or self[k] or weaponData[k] end,		__newindex = weaponData,	}) return o end

return Weapon --