Module:Weapon
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Weapon/doc
-- Module for handling information related to weapons -- p for "package". This is the interface returned by the module. it starts as -- a blank table, to which we add all of the modules functions. the module ends -- with "return p" local p = {} -- -- imports -- local cargo = mw.ext.cargo local getArgs = require('Module:Arguments').getArgs -- -- cargo -- -- this is the code for managing connecting the weapons definitions to the -- cargo database. p.cargo = {} -- p.cargo.weapons defines the schema of the Weapons table -- TODO(rust dev): currently missing a few complex fields: -- * The whole "Custom" map -- * BonusValueA and BonusValueB -- * statusEffects -- * ComponentTags -- TODO(rust dev): we can probably define a generic schema for all items and -- reuse it for defining both weapons and equipment. p.cargo.weapons = { -- table defines the name of the cargo table table = 'Weapons', -- fields contains the schema of all of the fields of a weapon; that is, all -- of the columns of the database table. the 'Field' element is the name of -- the cargo field, and is the same as the key in the json object. fields = { category = { -- TODO(rust dev): category is probably an enum, and we can do some -- special handling for it. field = 'Category', type = 'String', }, type = { field = 'Type', type = 'String', }, weaponSubType = { field = 'WeaponSubType', type = 'String', }, minRange = { field = 'MinRange', type = 'Integer', }, maxRange = { field = 'MaxRange', type = 'Integer', }, rangeSplit = { field = 'RangeSplit', -- rangeSplit is special. it stores a list of integers which represent -- the ranges. in this case, it's comma separated. type = 'List (,) of Integer', -- TODO(rust dev): add code to parse RangeSplit into a native lua -- array. }, ammoCategory = { field = 'AmmoCategory', type = 'String', }, startingAmmoCapacity = { field = 'StartingAmmoCapacity', type = 'Integer', }, heatGenerated = { field = 'HeatGenerated', type = 'Integer', }, damage = { field = 'Damage', type = 'Integer', }, overheatedDamageMultiplier = { field = 'OverheatedDamageMultiplier', type = 'Integer', }, evasiveDamageMultiplier = { field = 'EvasiveDamageMultiplier', type = 'Integer', }, evasionPipsIgnored = { field = 'EvasionPipsIgnored', type = 'Integer', }, damageVariance = { field = 'DamageVariance', type = 'Integer', }, heatDamage = { field = 'HeatDamage', type = 'Integer', }, accuracyModifier = { field = 'AccuracyModifier', type = 'Integer', }, criticalChanceMultiplier = { field = 'CriticalChanceMultiplier', type = 'Integer', }, aoeCapable = { field = 'AOECapable', type = 'Boolean', }, indirectFireCapable = { field = 'IndirectFireCapable', type = 'Boolean', }, refireModifier = { field = 'RefireModifier', type = 'Integer', }, shotsWhenFire = { field = 'ShotsWhenFired', type = 'Integer', }, projectilesPerShot = { field = 'ProjectilesPerShot', type = 'Integer', }, attackRecoil = { field = 'AttackRecoil', type = 'Integer', }, instability = { field = 'Instability', type = 'Integer', }, weaponEffectID = { field = 'WeaponEffectId', type = 'String', }, cost = { field = 'Cost', type = 'Integer', }, rarity = { field = 'Rarity', type = 'Integer', }, purchasable = { field = 'Purchasable', type = 'Boolean', }, manufacturer = { field = 'Manufacturer', type = 'String', }, model = { field = 'Model', type = 'String', }, uiName = { field = 'UIName', type = 'String', }, id = { field = 'Id', type = 'String', }, name = { field = 'Name', type = 'String', }, details = { field = 'Details', -- details is a text type. this is different from a String type because -- a Text type is un-indexed, and meant for longer-form text. -- TODO(rust dev): maybe this should be Wikitext? Details can have some -- markup in them. type = 'Text', }, icon = { field = 'Icon', type = 'String', }, componentType = { field = 'ComponentType', type = 'String', }, componentSubType = { field = 'ComponentSubType', type = 'String', }, prefabIdentifier = { field = 'PrefabIdentifier', type = 'String', }, battleValue = { field = 'BattleValue', type = 'Integer', }, inventorySize = { field = 'InventorySize', type = 'Integer', }, tonnage = { field = 'Tonnage', -- tonnage can be in half-ton increments, so use a float type = 'Float', }, allowedLocations = { field = 'AllowedLocations', -- AllowedLocations is a comma separated list in the json, not an -- actual array of strings. nevertheless, it will be more convenient -- for us to treat it as a list. -- TODO(rust dev): write code to unpack this to a native lua list. type = 'List (,) of String', }, disallowedLocations = { field = 'DisallowedLocations', type = 'List (,) of String', }, criticalComponent = { field = 'CriticalComponent', type = 'Boolean', } } } -- cargo_store stores items into cargo. -- taken from the Path of Exile wiki's Module:Cargo function cargo_store(frame, values) for kv, v in pairs(values) do if type(v) == 'table' then if #v == 0 then values[k] = nil else values[k] = table.concat(v, ',') end elseif type(v) == 'boolean' then if v == true then v = '1' else v = '0' end values[k] = v end end return frame:callParserFunction('#cargo_store:', values) end -- cargo_declare is a function which returns another function. The return value -- is evaluated to declare the cargo table. -- -- this is taken in large part from the Path of Exile wiki's Item2 module. -- -- TODO(rust dev): define this in a separate module for reuse function cargo_declare (data) return function (frame) if frame == nil then frame = mw.getCurrentFrame() end -- dcl_args are the arguments we will be passing to #cargo_declare local dcl_args = {} -- set the table name dcl_args._table = data.table -- for every field, we create an argument mapping the field name to its -- type. for k, field_data in pairs(data.fields) do if field_data then dcl_args[field_data.field] = field_data.type end end -- call #cargo_declare to declare the table before ending the function. frame:callParserFunction('#cargo_declare:', dcl_args) end end -- to declare the weapons table, call table_weapons from a template. p.table_weapons = cargo_declare(p.cargo.weapons) -- -- Template:Weapon -- -- -- weapon_full_name returns the full name of a given weapon function weapon_full_name(tpl_args) return string.format( '%s %s %s', tpl_args[p.cargo.weapons.fields.manufacturer.field], tpl_args[p.cargo.weapons.fields.model.field], tpl_args[p.cargo.weapons.fields.name.field] ) end function p.infobox (frame) tpl_args = getArgs(frame, { -- parentFirst tells us to prefer args from the parent page (the template -- that calls #invoke parentFirst = true }) -- build the infobox -- TODO(rust dev): this is just a test infobox, so it's not the final thing. -- don't use tables local weaponTable = mw.html.create('table') weaponTable:addClass('wikitable') weaponTable:tag('tr') :tag('th') :wikitext('Manufacturer') :done() :tag('td') :wikitext(tpl_args[p.cargo.weapons.fields.manufacturer.field]) weaponTable:tag('tr') :tag('th') :wikitext('Model') :done() :tag('td') :wikitext(tpl_args[p.cargo.weapons.fields.model.field]) weaponTable:tag('tr') :tag('th') :wikitext('Name') :done() :tag('td') :wikitext(tpl_args[p.cargo.weapons.fields.name.field]) weaponTable:tag('tr') :tag('th') :wikitext('Category') :done() :tag('td') :wikitext(tpl_args[p.cargo.weapons.fields.category.field]) weaponTable:tag('tr') :tag('th') :wikitext('Type') :done() :tag('td') :wikitext(tpl_args[p.cargo.weapons.fields.type.field]) -- attach the weapons table. we declare the weapons table in a separate -- template, and to use it, we need to attach it here. -- frame:callParserFunction('#cargo_attach:', {_table = p.cargo.weapons.table}) -- store the data in cargo -- we don't simply send in the argument verbatim. there may be options to the -- template that we don't want to pass into the cargo_store. instead, we -- iterate through the fields in p.cargo.weapons and look for field names local cargo_data = {} for _, field in pairs(p.cargo.weapons.fields) do local arg = tpl_args[field.field] if arg ~= nil then cargo_data[field.field] = arg end end cargo_store(frame, cargo_data) return tostring(weaponTable) end -- return the module as we have constructed it. return p