Modulabhängigkeiten
Modulinfo
Dieses Modul ist ein Metamodul zur Speicherung und Abfrage von Fahrzeug Hardpoints.
Es gibt Komponenten in tabellarischer Form aus.
Diese Vorlage dient der Erstellung einer Übersicht von Fahrzeugkomponenten.
Die verfügbaren Komponenten eines Fahrzeugs werden automatisch in tabellarischer Form dargestellt.
Wird kein Paramter angegeben, so wird der aktuelel Seitenname als Name des Fahrzeugs verwendet.
Kopiervorlage
{{FahrzeugKomponenten}}
Beispiele
{{FahrzeugKomponenten|300i}}
Radar | |
Scanner | |
Kraftwerksanlage | |
Kühlaggregat | |
Schildgenerator | |
Selbstzerstörung | |
Einträge stammen aus der Ship-Matrix
Quantentreibstofftank | 1x1 | QuantentreibstofftankUnbekannter Hersteller |
|
Sprungmodul | |
Treibstoffeinlass | 2x1 | TreibstoffeinlassUnbekannter Hersteller | 1x1 | |
|
Treibstofftank | 2x1 | TreibstofftankUnbekannter Hersteller |
|
Manövriertriebwerk | 12x1 | | 2x1 | RetroschubdüseUnbekannter Hersteller |
|
Primärtriebwerk | |
Einträge stammen aus der Ship-Matrix
Hilfsmittel | |
Raketenwerfer | |
Waffen | |
Einträge stammen aus der Ship-Matrix
Erzeugt eine tabellarische Übersicht der Komponenten eines Fahrzeugs
Template parameters
This template prefers inline formatting of parameters.
Parameter | Description | Type | Status |
---|
Fahrzeugname | 1 | no description
| Page | suggested |
---|
local VehicleHardPoint = {}
local metatable = {}
local methodtable = {}
metatable.__index = methodtable
local TNT = require( 'Module:TNT' )
local common = require( 'Module:Common' )
local data = mw.loadData( 'Module:VehicleHardpoint/Data' )
--- Calls TNT with the given key
local function translate( key )
local success, translation = pcall( TNT.format, 'I18n/Module:VehicleHardpoint.tab', key or '' )
if not success or translation == nil then
return key
end
return translation
end
-- 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.data > 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' then
key = row.type .. row.sub_type
else
key = row.type .. row.sub_type .. row.item.data.uuid
end
else
key = hardpointData.class.de_DE .. hardpointData.type.de_DE
end
if row.type ~= 'WeaponDefensive' then
if parent ~= nil then
key = key .. parent[ 'Hardpoint' ]
end
if root ~= nil and hardpointData.class.de_DE == 'Bewaffnung' and not string.match( key, root ) then
key = key .. root
end
end
if hardpointData.class.de_DE == 'Bewaffnung' 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.data == 1 then
local item = row.children.data[ 1 ]
local children = { data = {} }
if hasChildren( item ) then
children = item.children
if item.item.children ~= nil then
item.item.children.data = {}
end
end
row.name = item.name
row.type = item.type
row.sub_type = item.sub_type
row.item = item.item
if #children.data > 1 then
row.children = children
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( matcher, hardpointType ) ~= 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' ] = row.name
object[ 'Aus Spieldaten' ] = true
object[ 'Minimalgröße' ] = row.min_size
object[ 'Maximalgröße' ] = row.max_size
object[ 'Komponentenklasse' ] = common.mapTranslation( hardpointData.class )
if data.hardPointNames[ row.type ] ~= nil then
object[ 'Typ' ] = common.mapTranslation( data.hardPointNames[ row.type ] )
else
object[ 'Typ' ] = common.mapTranslation( hardpointData.type )
end
if data.hardPointNames[ row.sub_type ] ~= nil then
object[ 'Subtyp' ] = common.mapTranslation( data.hardPointNames[ row.sub_type ] )
else
object[ 'Subtyp' ] = common.mapTranslation( hardpointData.type )
end
if hardpointData.item ~= nil and type( hardpointData.item.name ) == 'string' then
object[ 'Name' ] = hardpointData.item.name
end
if type( row.item ) == 'table' then
local itemObj = row.item.data
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[ 'Name' ] = 'Selbstzerstörung ' .. match
else
object[ 'Name' ] = row.item.data.name
end
end
-- TODO: Use query chain when all items have accompanying pages instead of setting it on the subobject
if itemObj.manufacturer ~= 'Unknown Manufacturer' then
object[ 'Hersteller' ] = itemObj.manufacturer
end
if itemObj.type == 'Weapon Defensive' and type( itemObj.counterMeasure ) == 'table' then
object[ 'Magazingröße' ] = itemObj.counterMeasure.data.max_ammo_count
end
if object[ 'Minimalgröße' ] == nil then
object[ 'Minimalgröße' ] = itemObj.size
object[ 'Maximalgröße' ] = itemObj.size
end
object[ 'UUID' ] = row.item.data.uuid
end
if parent ~= nil then
object[ 'Parent UUID' ] = parent[ 'UUID' ]
object[ 'Parent Hardpoint' ] = parent[ 'Hardpoint' ]
end
if root ~= nil and root ~= row.name then
object[ 'Root Hardpoint' ] = root
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 ][ 'Anzahl' ] = 1
end
else
out[ key ][ 'Anzahl' ] = out[ key ][ 'Anzahl' ] + 1
if type( out[ key ][ 'Magazingröße' ] ) == 'number' then
out[ key ][ 'Magazingröße' ] = out[ key ][ 'Magazingröße' ] + object[ 'Magazingröße' ]
end
end
end
local depth = 0
local function addHardpoints( hardpoints, parent, root )
for _, hardpoint in pairs( hardpoints ) do
hardpoint.name = string.lower( hardpoint.name )
hardpoint = fixChild( hardpoint )
if depth == 0 then
root = hardpoint.name
mw.log(string.format('Root: %s', root))
end
local hardpointData = self:getHardpointData( hardpoint.type or hardpoint.name )
if hardpointData ~= nil then
hardpoint = VehicleHardPoint.fixTypes( hardpoint )
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.data, obj, root )
end
end
end
depth = depth - 1
if depth < 0 then
depth = 0
root = nil
end
end
addHardpoints( hardpoints )
--mw.logObject(out)
for _, subobject in pairs( out ) do
mw.smw.subobject( subobject )
end
end
--- Queries the SMW store for all available hardpoint subobjects for a given page
---
--- @param page string - The page to query
--- @return table hardpoints
function methodtable.querySmwStore( self, page )
-- Cache multiple calls
if self.smwData ~= nil then
return self.smwData
end
local smwData = mw.smw.ask( {
'[[-Has subobject::' .. page .. ']][[Typ::+]]',
'?Aus Spieldaten#-=from_gamedata',
'?Anzahl#-=count',
'?Minimalgröße#-=min_size',
'?Maximalgröße#-=max_size',
'?Komponentenklasse=class', '+lang=' .. common.getLocaleForPage(),
'?Komponentenklasse=class_de',
'+lang=de',
'?Typ=type', '+lang=' .. common.getLocaleForPage(),
'?Typ=type_de', '+lang=de',
'?Subtyp=sub_type', '+lang=' .. common.getLocaleForPage(),
'?Subtyp=sub_type_de', '+lang=de',
'?Name#-=name',
'?UUID#-=uuid',
'?Hardpoint#-=hardpoint',
'?Magazingröße#-=magazine_size',
'?Hersteller#-=manufacturer',
'?Parent Hardpoint#-=parent_hardpoint',
'?Root Hardpoint#-=root_hardpoint',
'?Parent UUID#-=parent_uuid',
'?Name.Grad#-=item_grade',
'?Name.Klasse#-=item_class',
'?Name.Größe#-=item_size',
'sort=Komponentenklasse,Typ,Maximalgröße,Anzahl',
'order=asc,asc,asc,asc',
} )
if smwData == nil or smwData[ 1 ] == nil then
return nil
end
--mw.logObject( data )
self.smwData = smwData
return self.smwData
end
--- Group Hardpoints by Class and type
---
--- @param smwData table SMW data - Requires a 'class' key on each row
--- @return table
function methodtable.group( self, smwData )
local grouped = {}
if type( smwData ) ~= 'table' then
return {}
end
for _, row in self.spairs( smwData ) do
if not row.isChild and row.class ~= nil and row.type ~= nil then
if type( grouped[ row.class ] ) ~= 'table' then
grouped[ row.class ] = {}
end
if type( grouped[ row.class ][ row.type ] ) ~= 'table' then
grouped[ row.class ][ row.type ] = {}
end
table.insert( grouped[ row.class ][ row.type ], row )
end
end
--mw.logObject( grouped )
return grouped
end
--- Adds children to the according parents
---
--- @param smwData table All available Hardpoint objects for this page
--- @return table The stratified table
function methodtable.createDataStructure( self, smwData )
-- Maps object id to key in array
local idMapping = {}
for key, object in pairs( smwData ) do
if object.hardpoint ~= nil then
local keyMap = ( object.root_hardpoint or object.hardpoint ) .. object.hardpoint
idMapping[ keyMap ] = key
end
end
local function stratify( toStratify )
for _, object in pairs( toStratify ) do
if object.parent_hardpoint ~= nil then
local parentEl = toStratify[ idMapping[ (object.root_hardpoint or '') .. object.parent_hardpoint ] ]
if parentEl ~= nil then
if parentEl.children == nil then
parentEl.children = {}
end
object.isChild = true
table.insert( parentEl.children, object )
end
end
end
end
stratify( smwData )
return smwData
end
--- Generate the output
---
--- @param groupedData table Grouped SMW data
--- @return table
function methodtable.makeOutput( self, groupedData )
local classOutput = {}
local function makeEntry( item, depth )
if classOutput.info == nil then
local text
if item.from_gamedata == true then
text = translate( 'msg_from_gamedata' )
else
text = translate( 'msg_from_shipmatrix' )
end
classOutput.info = string.format( '<p class="hatnote">%s</p>', text )
end
depth = depth or 0
local row = mw.html.create( 'tr' )
:addClass( 'hardpoint--entry' )
:addClass( string.format( 'depth-%d', depth) )
if item.magazine_size ~= nil then
item.count = item.magazine_size
end
local size = '-'
local prefix = ''
if item.from_gamedata == true or item.class_de == 'Bewaffnung' then
prefix = 'S'
end
if item.item_size ~= nil then
size = string.format( '%s%s', prefix, item.item_size )
else
size = string.format( '%s%s', prefix, item.max_size )
--[[ if item.max_size ~= item.min_size then
size = string.format( '<span class="hardpoint--entry__size-min">S%s</span>-<span class="hardpoint--entry__size-max">S%s</span>', item.min_size, item.max_size )
end]]
end
local nodeSizeCount = mw.html.create( 'div' )
:tag( 'span' )
:addClass( 'hardpoint--entry__count' )
:wikitext( string.format( '%dx', item.count ) )
:done()
:tag( 'span' )
:addClass( 'hardpoint--entry__size' )
:wikitext( size )
:done()
:allDone()
local name = item.sub_type or item.type
if item.name ~= nil then
if data.nameFixes[ item.name ] ~= nil then
name = string.format( '[[%s|%s]]', data.nameFixes[ item.name ], item.name )
else
name = string.format( '[[%s]]', item.name )
end
end
local manufacturer = item.manufacturer or 'Unbekannter Hersteller'
if item.manufacturer ~= nil then
manufacturer = string.format( '[[%s]]', item.manufacturer )
end
local nodeItemManufacturer = mw.html.create( 'div' )
:tag( 'span' )
:addClass( 'hardpoint--entry__item' )
:wikitext( name )
:done()
:tag( 'span' )
:addClass( 'hardpoint--entry__manufacturer' )
:wikitext( manufacturer )
:done()
:allDone()
row:tag('td')
:addClass( 'hardpoint--size-count')
:node( nodeSizeCount )
:done()
:tag('td')
:addClass( 'hardpoint--item-manufacturer')
:node( nodeItemManufacturer )
:done()
:done()
row = tostring(row)
if type( item.children ) == 'table' then
depth = depth + 1
for _, child in self.spairs( item.children ) do
row = row .. makeEntry( child, depth )
end
end
return row
end
local function makeClassTable( types )
local out = ''
for classType, items in self.spairs( types ) do
local icon = classType
if icon == 'Raketenwerfer' then
icon = 'Flugkörper'
end
local success
success, icon = pcall( TNT.formatInLanguage, 'de', 'I18n/Module:VehicleHardpoint.tab', icon )
if success then
icon = string.format( '[[Datei:Hardpoints Icon %s.svg|20px|link=|class=hardpoint--class-icon__desaturated]]', icon )
if classType == 'Selbstzerstörung' or classType == 'Scanner' then
icon = ''
end
else
icon = ''
end
local row = mw.html.create( 'tr' )
:addClass( 'hardpoint--type')
:tag( 'td' )
:addClass( 'hardpoint--class-icon' )
:wikitext( string.format(
'%s %s',
icon,
translate( classType )
) )
:done()
local inner = mw.html.create('table')
:addClass( 'hardpoint--entries')
local str = ''
for _, item in self.spairs( items ) do
if not item.isChild then
str = str .. tostring( makeEntry( item ) )
end
end
row:tag( 'td' )
:node(inner:node(str):allDone())
:done()
:allDone()
out = out .. tostring(row)
end
return out
end
for class, types in self.spairs( groupedData ) do
local tbl = mw.html.create( 'table' ):addClass( 'hardpoint--class' )
tbl:tag( 'tr' )
:addClass( 'hardpoint--class__header' )
:tag( 'th' )
:attr( 'colspan', 2 )
:wikitext( translate( class ) )
:done()
:done()
tbl:node( makeClassTable( types ) )
classOutput[ class ] = tbl:allDone()
end
mw.logObject(classOutput)
return classOutput
end
function methodtable.test(self)
local json = mw.text.jsonDecode( mw.ext.Apiunto.get_raw( 'ships/' .. self.page , {
locale = 'de_DE',
include = { 'hardpoints', 'shops.items' },
} ) )
json = json.data.hardpoints.data
self:setHardPointObjects(json)
end
--- Generates tabber output
function methodtable.out( self )
local smwData = self:querySmwStore( self.page )
if smwData == nil then
return '<p class="hatnote">' .. translate( 'msg_no_data' ) .. '</p>'
end
smwData = self:createDataStructure( smwData )
smwData = self:group( smwData )
local output = self:makeOutput( smwData )
local avSys = ( tostring( output[ translate ('Avionik' ) ] or '' ) ) .. ( tostring( output[ translate( 'Systeme' ) ] or '' ) )
local anTri = ( tostring( output[ translate ('Antrieb' ) ] or '' ) ) .. ( tostring( output[ translate( 'Triebwerk' ) ] or '' ) )
local bewaf = ( tostring( output[ translate ('Bewaffnung' ) ] or '' ) )
if #avSys > 0 then
avSys = avSys .. ( output.info or '' )
else
avSys = translate( 'msg_no_systems' )
end
if #anTri > 0 then
anTri = anTri .. ( output.info or '' )
else
anTri = translate( 'msg_no_thruster' )
end
if #bewaf > 0 then
bewaf = bewaf .. ( output.info or '' )
else
bewaf = translate( 'msg_no_weapons' )
end
local format = string.format([[
%s=%s
|-|
%s=%s
|-|
%s=%s
]],
translate( 'tab_avionics_systems' ),
avSys,
translate( 'tab_engine_propulsion' ),
anTri,
translate( 'tab_weapons' ),
bewaf
)
return mw.getCurrentFrame():extensionTag{
name = 'tabber',
content = format,
}
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.data ~= nil then
hardpoint.item.data.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.data ~= nil then
if hardpoint.item.data.manufacturer == 'Talon' then
hardpoint.item.data.manufacturer = 'Talon Weapon Systems'
end
if string.match( hardpoint.item.data.manufacturer, '%[PH%]' ) ~= nil then
hardpoint.item.data.manufacturer = 'Unknown Manufacturer'
end
end
return hardpoint
end
--- New Instance
---
--- @return table VehicleHardPoint
function VehicleHardPoint.new( self, page )
local instance = {
page = page or nil,
spairs = require( 'Modul:Common' ).spairs
}
setmetatable( instance, metatable )
return instance
end
--- Parser call for setting hardpoints
function VehicleHardPoint.fromArgs( frame )
local page = frame.args[ 1 ] or frame:getParent().args[ 1 ]
local instance = VehicleHardPoint:new( page )
instance:test()
end
--- Parser call for generating the table
function VehicleHardPoint.outputTable( frame )
local page = frame.args[ 1 ] or frame:getParent().args[ 1 ] or mw.title.getCurrentTitle().rootText
local instance = VehicleHardPoint:new( page )
return instance:out()
end
return VehicleHardPoint