Module:VehicleHardpoint

local VehicleHardPoint = {}

local metatable = {} local methodtable = {}

local common = require( 'Module:Common' ) local data = mw.loadData( 'Module:VehicleHardpoint/Data' )

metatable.__index = methodtable

-- Local functions

--- Checks if an entry contains a 'child' key with further entries --- --- @return boolean local function hasChildren( row ) return row.children ~= nil and type( row.children ) == 'table' and #row.children > 0 end

--- Creates a key to be used in 'setHardPointObjects' --- This allows to sum the total count of each similar object --- --- @param row table - API Data --- @param hardpointData table - Data from getHardpointData --- @param parent table|nil - Parent hardpoint --- @param root string|nil - Root hardpoint --- @return string Key local function makeKey( row, hardpointData, parent, root ) local key

if type( row.item ) == 'table' then if row.type == 'ManneuverThruster' or          row.type == 'MainThruster' or           row.type == 'WeaponDefensive' or           row.type == 'WeaponLocker' or           row.type == 'ArmorLocker' or           row.type == 'Bed' or           row.type == 'CargoGrid' then key = row.type .. row.sub_type else key = row.type .. row.sub_type .. row.item.uuid end else key = hardpointData.class .. hardpointData.type end

if row.type ~= 'WeaponDefensive' then if parent ~= nil then key = key .. parent[ 'Hardpoint name' ] end

if root ~= nil and not string.match( key, root ) and ( hardpointData.class == 'Weapons' ) then key = key .. root end end

if hardpointData.class == 'Weapons' and row.name ~= nil and row.type == 'MissileLauncher' then key = key .. row.name end

--mw.log(string.format('Key: %s', key)) return key end

--- Tries to fix hardpoints that have no item, but everything set on the 'child' key --- --- @param row table - API Data --- @return table - Fixed entry local function fixChild( row ) if row.item == nil and hasChildren( row ) and #row.children == 1 then local item = row.children[ 1 ]

local children = {}

if hasChildren( item ) then children = item.children if item.item ~= nil and item.item.children ~= nil then item.item.children = {} end end

row.name = item.name row.type = item.type row.sub_type = item.sub_type row.item = item.item if #children > 1 then row.children = children else row.children = { data = {} } end end

return row end

--- Get pre-defined hardpoint data for a given hardpoint type or name --- --- @param hardpointType string --- @return table|nil function methodtable.getHardpointData( self, hardpointType ) if type( data.hardPointMappings[ hardpointType ] ) == 'table' then return data.hardPointMappings[ hardpointType ] end

for hType, mappingData in pairs( data.hardPointMappings ) do       if hardpointType == hType then return mappingData elseif type( mappingData.matches ) == 'table' then for _, matcher in pairs( mappingData.matches ) do               if string.match( hardpointType, matcher ) ~= nil then return mappingData end end end end

return nil end

--- Creates a settable SMW Subobject --- --- @param row table - API Data --- @param hardpointData table - Data from getHardpointData --- @param parent table|nil - Parent hardpoint --- @param root string|nil - Root hardpoint --- @return table function methodtable.makeObject( self, row, hardpointData, parent, root ) local object = {}

if hardpointData == nil then hardpointData = self:getHardpointData( row.type or row.name ) end

if hardpointData == nil then return nil end

object[ 'Hardpoint name' ] = row.name --object[ 'From game data' ] = true object[ 'Hardpoint minimum size' ] = row.min_size object[ 'Hardpoint maximum size' ] = row.max_size object[ 'Class' ] = hardpointData.class

if data.hardPointNames[ row.type ] ~= nil then object[ 'Hardpoint type' ] = data.hardPointNames[ row.type ] else object[ 'Hardpoint type' ] = hardpointData.type end

if data.hardPointNames[ row.sub_type ] ~= nil then object[ 'Hardpoint subtype' ] = data.hardPointNames[ row.sub_type ] else object[ 'Hardpoint subtype' ] = hardpointData.type end

if hardpointData.item ~= nil then if type( hardpointData.item.name ) == 'string' then object[ 'Component name' ] = hardpointData.item.name end if type( hardpointData.item.size ) == 'string' then object[ 'Component size' ] = hardpointData.item.size end if type( hardpointData.item.type ) == 'string' then object[ 'Component type' ] = hardpointData.item.type end if type( hardpointData.item.sub_type ) == 'string' then object[ 'Component subtype' ] = hardpointData.item.sub_type end end

if type( row.item ) == 'table' then local itemObj = row.item if itemObj.name ~= '<= PLACEHOLDER =>' then local match = string.match( row.class_name or '', 'Destruct_(%d+s)') if row.type == 'SelfDestruct' and match ~= nil then object[ 'Component name' ] = 'Self destruct (' .. match .. ')' else object[ 'Component name' ] = row.item.name end end

if itemObj.type == 'WeaponDefensive' and type( itemObj.counter_measure ) == 'table' then object[ 'Magazine capacity' ] = itemObj.counter_measure.capacity end

if ( itemObj.type == 'Cargo' or itemObj.type == 'SeatAccess' or itemObj.type == 'CargoGrid' or itemObj.type == 'Container' ) and type( itemObj.inventory ) == 'table' then object[ 'SCU' ] = common.formatNum( (itemObj.inventory.scu or nil), nil ) end

if object[ 'Hardpoint minimum size' ] == nil then object[ 'Hardpoint minimum size' ] = itemObj.size object[ 'Hardpoint maximum size' ] = itemObj.size end

object[ 'UUID' ] = row.item.uuid end

if parent ~= nil then object[ 'Parent hardpoint UUID' ] = parent[ 'UUID' ] object[ 'Parent hardpoint name' ] = parent[ 'Hardpoint name' ] end

if root ~= nil and root ~= row.name then object[ 'Root hardpoint name' ] = root end

-- Remove SeatAccess Hardpoints without storage if row.item ~= nil and row.item.type == 'SeatAccess' and object[ 'SCU' ] == nil then object = nil end

return object; end

--- Sets all available hardpoints as sub-objects --- This is the main method called by others --- --- @param hardpoints table API Hardpoint data function methodtable.setHardPointObjects( self, hardpoints ) if type( hardpoints ) ~= 'table' or #hardpoints == 0 then error( 'Hardpoints need to be a table' ) end

local out = {}

local function addToOut( object, key ) if object == nil then return end

if type( out[ key ] ) ~= 'table' then if object ~= nil then out[ key ] = object out[ key ][ 'Quantity' ] = 1 end else out[ key ][ 'Quantity' ] = out[ key ][ 'Quantity' ] + 1

if type( out[ key ][ 'Magazine capacity' ] ) == 'number' then out[ key ][ 'Magazine capacity' ] = out[ key ][ 'Magazine capacity' ] + object[ 'Magazine capacity' ] end

if object[ 'Hardpoint type' ] == 'Cargo grid' then out[ key ][ 'Quantity' ] = 1 if out[ key ][ 'SCU' ] ~= nil and object[ 'SCU' ] ~= nil then out[ key ][ 'SCU' ] = tonumber(out[ key ][ 'SCU' ]) + tonumber(object[ 'SCU' ]) end end end end

local depth = 1

local function addHardpoints( hardpoints, parent, root ) for _, hardpoint in pairs( hardpoints ) do           hardpoint.name = string.lower( hardpoint.name ) hardpoint = fixChild( hardpoint )

if depth == 1 then root = hardpoint.name --mw.log(string.format('Root: %s', root)) end

hardpoint = VehicleHardPoint.fixTypes( hardpoint )

local hardpointData = self:getHardpointData( hardpoint.type or hardpoint.name )

if hardpointData ~= nil then local key = makeKey( hardpoint, hardpointData, parent, root )

local obj = self:makeObject( hardpoint, hardpointData, parent, root )

addToOut( obj, key )

if hasChildren( hardpoint ) then depth = depth + 1 addHardpoints( hardpoint.children, obj, root ) end end end

depth = depth - 1

if depth < 1 then depth = 1 root = nil end end

addHardpoints( hardpoints )

--mw.logObject(out)

for _, subobject in pairs( out ) do       mw.smw.subobject( subobject ) end end

--- Manually fix some (sub_)types by checking the hardpoint name --- --- @param hardpoint table Entry from the api --- @return table The fixed entry function VehicleHardPoint.fixTypes( hardpoint ) if hardpoint.type == 'ManneuverThruster' or hardpoint.type == 'MainThruster' then if ( hardpoint.sub_type == 'FixedThruster' or hardpoint.sub_type == 'UNDEFINED' ) and string.match( string.lower( hardpoint.name ), 'vtol' ) ~= nil then hardpoint.sub_type = 'VtolThruster' end

if ( hardpoint.sub_type == 'FixedThruster' or hardpoint.sub_type == 'UNDEFINED' ) and string.match( string.lower( hardpoint.name ), 'retro' ) ~= nil then hardpoint.sub_type = 'RetroThruster' end

if ( hardpoint.sub_type == 'FixedThruster' or hardpoint.sub_type == 'UNDEFINED' ) and string.match( string.lower( hardpoint.name ), 'retro' ) ~= nil then hardpoint.sub_type = 'RetroThruster' end

if hardpoint.type == 'MainThruster' then hardpoint.sub_type = 'Main' .. hardpoint.sub_type end end

if hardpoint.type == 'WeaponDefensive' then if ( hardpoint.sub_type == 'CountermeasureLauncher' or hardpoint.sub_type == 'UNDEFINED' ) and ( string.match( string.lower( hardpoint.class_name ), 'decoy' ) ~= nil or                 string.match( string.lower( hardpoint.class_name ), 'flare' ) ~= nil) then hardpoint.sub_type = 'DecoyLauncher' end

if ( hardpoint.sub_type == 'CountermeasureLauncher' or hardpoint.sub_type == 'UNDEFINED' ) and ( string.match( string.lower( hardpoint.class_name ), 'chaff' ) ~= nil or              string.match( string.lower( hardpoint.class_name ), 'noise' ) ~= nil) then hardpoint.sub_type = 'NoiseLauncher' end

if type( hardpoint.item ) == 'table' and hardpoint.item ~= nil then hardpoint.item.name = '<= PLACEHOLDER =>' end end

if hardpoint.type == 'FuelTank' or hardpoint.type == 'QuantumFuelTank' then local prefix = '' if hardpoint.type == 'QuantumFuelTank' then prefix = 'Quantum' end

if string.match( string.lower( hardpoint.class_name ), 'small' ) ~= nil then hardpoint.sub_type = prefix .. 'FuelTankSmall' end

if string.match( string.lower( hardpoint.class_name ), 'large' ) ~= nil then hardpoint.sub_type = prefix .. 'FuelTankLarge' end end

if hardpoint.type == 'Turret' then if ( hardpoint.sub_type == 'GunTurret' or hardpoint.sub_type == 'UNDEFINED' ) and string.match( string.lower( hardpoint.class_name ), 'mining' ) ~= nil then hardpoint.sub_type = 'MiningTurret' end end

if type( hardpoint.item ) == 'table' and hardpoint.item ~= nil then if hardpoint.item.manufacturer.code ~= nil then --- Use Module:Manufacturer for data instead local manufacturer = require( 'Module:Manufacturer' )._manufacturer( { hardpoint.item.manufacturer.code } ) if manufacturer ~= nil then hardpoint.item.manufacturer.name = manufacturer.name end end

if string.match( hardpoint.item.manufacturer.name, '%[PH%]' ) ~= nil then hardpoint.item.manufacturer.name = 'Unknown Manufacturer' end

for _, mapping in pairs( { 'PersonalInventory', 'ArmorLocker', 'WeaponLocker', 'Bed', 'Container' } ) do	   	for _, matcher in pairs( data.hardPointMappings[mapping]['matches'] ) do	    		if string.match( hardpoint.name, matcher ) ~= nil then hardpoint.type = mapping return hardpoint end end end end

return hardpoint end

--- New Instance --- --- @return table VehicleHardPoint function VehicleHardPoint.new( self, page ) local instance = { page = page or nil, spairs = require( 'Module:Common' ).spairs }

setmetatable( instance, metatable )

return instance end

return VehicleHardPoint