sc>FoXFTW KKeine Bearbeitungszusammenfassung |
K (1 Version importiert) |
(kein Unterschied)
| |
Aktuelle Version vom 3. September 2023, 08:02 Uhr
Die Dokumentation für dieses Modul kann unter Modul:CharArmor/Doku erstellt werden
local CharArmor = {}
local metatable = {}
local methodtable = {}
metatable.__index = methodtable
local objectData = mw.loadData( 'Module:CharArmor/Data' )
-- Extensions
local common = require( 'Module:Common' )
local api = require( 'Module:Common/Api' )
local localized = require( 'Module:Localized' )
local TNT = require( 'Module:Translate' ):new()
local log = require( 'Module:Log' )
local item = require( 'Module:Item' )
local commodity = require( 'Module:Commodity' )
--- Sorts all attachments into pre-defined groups
--- Outputs a table containing the min and max size for the attachment port
--- As well as the overall count of attachments for a group
--- @param attachments table
--- @return table
local function makeArmorAttachmentTable( attachments )
local out = {}
local sortedOut = {}
for _, attachment in pairs( attachments ) do
local attachmentName = CharArmor.translateArmorAttachment( attachment[ 'Halterungsname' ] )
local minNum = tonumber( attachment[ 'Minimalgröße' ] )
if minNum == nil then
minNum = 0
end
local maxNum = tonumber( attachment[ 'Maximalgröße' ] )
if maxNum == nil then
maxNum = 0
end
if attachmentName ~= nil then
if out[ attachmentName ] == nil then
out[ attachmentName ] = {
name = attachmentName,
min = minNum,
max = maxNum,
count = 1
}
else
out[ attachmentName ].count = out[ attachmentName ].count + 1
if minNum < out[ attachmentName ].min then
out[ attachmentName ].min = minNum
end
if maxNum > out[ attachmentName ].max then
out[ attachmentName ].max = maxNum
end
end
end
end
for _, class in ipairs( objectData.attachmentOrder ) do
if out[ class ] ~= nil then
table.insert(sortedOut, out[ class ])
end
end
--[[ TODO remove comment to show all attachments
for name, attachment in pairs( out ) do
if order[ name ] == nil then
table.insert( sortedOut, attachment )
end
end
]]--
return sortedOut
end
--- Add manual smw data
function methodtable.addManual( self )
if self.frameArgs == nil then
return
end
local setObj = {
[ 'Name' ] = self.frameArgs.Name or nil,
[ 'Beschreibung' ] = self.frameArgs.Beschreibung or nil,
[ 'Größe' ] = self.frameArgs[ 'Größe' ] or nil,
[ 'Hersteller' ] = self.frameArgs[ 'Hersteller' ] or nil,
[ 'Rüstungstyp' ] = self.frameArgs[ 'Rüstungstyp' ] or nil,
[ 'Rüstungsklasse' ] = self.frameArgs[ 'Rüstungsklasse' ] or nil,
[ 'Ist Basisversion' ] = self.frameArgs[ 'Ist Basisversion' ] or nil,
[ 'Basisversion UUID' ] = self.frameArgs[ 'Basisversion UUID' ] or nil,
[ 'SP' ] = self.frameArgs[ 'SP' ] or nil,
[ 'Temperaturresistenz Minmal' ] = self.frameArgs[ 'Temperaturresistenz Minmal' ] or nil,
[ 'Temperaturresistenz Maximal' ] = self.frameArgs[ 'Temperaturresistenz Maximal' ] or nil,
[ 'Resistenzmultiplikator Physisch' ] = self.frameArgs[ 'Resistenzmultiplikator Physisch' ] or nil,
[ 'Resistenzmultiplikator Energie' ] = self.frameArgs[ 'Resistenzmultiplikator Energie' ] or nil,
[ 'Resistenzmultiplikator Distortion' ] = self.frameArgs[ 'Resistenzmultiplikator Distortion' ] or nil,
[ 'Resistenzmultiplikator Thermisch' ] = self.frameArgs[ 'Resistenzmultiplikator Thermisch' ] or nil,
[ 'Resistenzmultiplikator Biochemisch' ] = self.frameArgs[ 'Resistenzmultiplikator Biochemisch' ] or nil,
[ 'Resistenzmultiplikator Betäubung' ] = self.frameArgs[ 'Resistenzmultiplikator Betäubung' ] or nil,
[ 'Spielversion' ] = self.frameArgs[ 'Spielversion' ] or nil,
}
mw.smw.set( setObj )
end
--- Request Api Data
--- Using current subpage name
--- @return table
function methodtable.getApiDataForCurrentPage( self )
local name = self.frameArgs[ 'uuid' ] or self.frameArgs[ 'name' ] or mw.title.getCurrentTitle().text
local json = mw.text.jsonDecode( mw.ext.Apiunto.get_raw( 'v2/armor/' .. name, {
include = {
'shops.items'
},
} ) )
api.checkResponseStructure( json, true, false )
self.apiData = json[ 'data' ]
return self.apiData
end
--- Request armor attachments from SMW
--- @param name string
--- @return table
function methodtable.getArmorAttachments( self, name )
local query = {
'[[-Has subobject::' .. name .. ']][[Typ::Halterung]]',
'?Halterungsname#-',
'?Minimalgröße#-',
'?Maximalgröße#-',
'mainlabel=-'
}
return mw.smw.ask( query )
end
--- Queries the SMW Store
--- @return table
function methodtable.getSmwData( self )
-- Cache multiple calls
if self.smwData ~= nil then
return self.smwData
end
-- name from args or current page
local queryName = self.frameArgs[ 'name' ] or localized.getMainTitle()
local data = mw.smw.ask( {
'[[' .. queryName .. ']][[Hersteller::+]]',
'?#-=page',
'?Name#-',
'?Größe#-',
'?Hersteller#-',
'?Beschreibung', '+lang=' .. common.getLocaleForPage(),
'?Schadensreduktion#-',
'?SP',
'?Rüstungstyp=type', '+lang=' .. common.getLocaleForPage(),
'?Rüstungstyp=type_de', '+lang=de',
'?Rüstungsklasse=class', '+lang=' .. common.getLocaleForPage(),
'?Rüstungsklasse=class_de', '+lang=de',
'?Temperaturresistenz#-n',
'?Resistenzmultiplikator Physisch#-n',
'?Resistenzmultiplikator Energie#-n',
'?Resistenzmultiplikator Distortion#-n',
'?Resistenzmultiplikator Thermisch#-n',
'?Resistenzmultiplikator Biochemisch#-n',
'?Resistenzmultiplikator Betäubung#-n',
'?Länge',
'?Breite',
'?Höhe',
'?Volumen',
'?Spielversion#-=version',
'mainlabel=-'
} )
if data == nil or data[ 1 ] == nil then
return TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'msg_smw_loading' )
end
self.smwData = data[ 1 ]
self.smwData.attachments = self:getArmorAttachments( queryName )
self.smwData.price = commodity.getPrice( queryName )
if self.smwData.price ~= nil then
self.smwData.price = self.smwData.price[ 1 ].price
end
return self.smwData
end
--- Base Properties that are shared across all Vehicles
--- @return table SMW Result
function methodtable.setSemanticProperties( self )
-- Api Error, don't set anything
if self.apiData == nil then
return
end
local item = item:new( '', self.apiData )
local setObj = item:makeSmwObject()
setObj[ 'Set' ] = CharArmor.getArmorSet( self.apiData.name )
setObj[ 'Schadensreduktion' ] = self.apiData.clothing.damage_reduction or nil
setObj[ 'Rüstungstyp' ] = api.mapTranslation( CharArmor.translateArmorType( self.apiData.clothing.armor_type or nil ) )
setObj[ 'Rüstungsklasse' ] = api.mapTranslation( CharArmor.translateClass( self.apiData.type or nil ) )
setObj[ 'Temperaturresistenz' ] = {
CharArmor.formatTemperature( self.apiData.clothing.temp_resistance_min ),
CharArmor.formatTemperature( self.apiData.clothing.temp_resistance_max ),
}
if type( self.apiData.clothing.resistances ) == 'table' then
for _, resistance in pairs( self.apiData.clothing.resistances ) do
if resistance.type == 'physical' then
setObj['Resistenzmultiplikator Physisch'] = common.formatNum( resistance.multiplier )
end
if resistance.type == 'energy' then
setObj['Resistenzmultiplikator Energie'] = common.formatNum( resistance.multiplier )
end
if resistance.type == 'distortion' then
setObj['Resistenzmultiplikator Distortion'] = common.formatNum( resistance.multiplier )
end
if resistance.type == 'thermal' then
setObj['Resistenzmultiplikator Thermisch'] = common.formatNum( resistance.multiplier )
end
if resistance.type == 'biochemical' then
setObj['Resistenzmultiplikator Biochemisch'] = common.formatNum( resistance.multiplier )
end
if resistance.type == 'stun' then
setObj['Resistenzmultiplikator Betäubung'] = common.formatNum( resistance.multiplier )
end
end
end
local result = mw.smw.set( setObj )
if self.apiData.ports ~= nil and type( self.apiData.ports ) == 'table' then
for _, attachment in pairs( self.apiData.ports ) do
if attachment.name ~= nil then
mw.smw.subobject( {
[ 'Typ' ] = {
'Halterung@de',
'Attachment@en',
},
[ 'Halterungsname' ] = attachment.name,
[ 'Minimalgröße' ] = attachment.min_size or 0,
[ 'Maximalgröße' ] = attachment.max_size or 0,
} )
end
end
end
commodity:new():addShopData( self.apiData )
return result
end
--- Sets the main categories for this object
function methodtable.setCategories( self, smwData )
if smwData.Hersteller == nil then
table.insert( self.categories, '[[Category:Seiten mit Skriptfehlern]]' )
return
end
if self.lang == 'de' then
table.insert( self.categories, '[[Category:' .. smwData.Hersteller .. '|' .. smwData.Name .. ' ]]' )
if smwData.class ~= nil then
table.insert( self.categories, string.format('[[Kategorie:%s|%s]]', smwData.class_de, smwData.Name ) )
end
if smwData.type ~= nil and smwData.type ~= 'Unbekannter Typ' then
table.insert( self.categories, string.format('[[Kategorie:%s|%s]]', smwData.type_de, smwData.Name ) )
end
else
table.insert( self.categories, '[[Category:' .. smwData.Name ..'|' .. smwData.Name .. ' ]]' )
end
end
--- Entrypoint for {{#seo:}}
function methodtable.setSeoData( self )
local data = self:getSmwData()
if nil == data.Hersteller then
-- Faulty SMW data, don't call #seo
return
end
require( 'Module:SEO' ).set(
TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'seo_section' ),
data.page,
table.concat({
data.Name,
data.Hersteller,
self.currentFrame:preprocess( '{{SITENAME}}' )
}, ' - '),
'replace',
{
data.Name,
data.type or '',
data.class or '',
data.Hersteller,
require( 'Module:Hersteller' ).getCodeFromName( data.Hersteller ),
TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'seo_section' ),
},
nil,
self.frameArgs[ 'image' ],
data.page
)
end
--- Creates the infobox
function methodtable.getInfoBox( self )
local data = self:getSmwData()
if type( data ) == 'string' then
return log.info( data )
end
if nil == data.Hersteller then
data.Hersteller = 'Unbekannter Hersteller'
end
-- Set Title
common.setDisplayTitle( self.currentFrame, data.Name )
local box = require( 'Module:InfoboxNeue' ):new( {
removeEmpty = true,
emptyString = '-',
placeholderImage = 'Platzhalter Rüstung.webp',
} )
local nameNormalized, _ = mw.ustring.gsub( data.Name, "[^%w-]", ' ' )
nameNormalized, _ = mw.ustring.gsub( nameNormalized, "%s+", ' ' )
local nameCleaned, _ = mw.ustring.gsub( nameNormalized, "%(", '' )
nameCleaned, _ = mw.ustring.gsub( nameCleaned, "%)", '' )
box:renderImage( common.getImage( {
self.frameArgs[ 'image' ],
mw.text.trim( nameNormalized ) .. '.jpg',
mw.text.trim( nameCleaned ) .. '.jpg',
} ) )
box:renderHeader( {
title = data.Name,
subtitle = '[[' .. data.Hersteller .. ']]' .. api.getVersionInfoRef( data.version, self.lang ),
} )
local tempMinRes, tempMaxRes = CharArmor.temperatureResistanceToText( data[ 'Temperaturresistenz' ] )
local armorClass = data.class
if armorClass ~= nil then
armorClass = string.format('[[:Kategorie:%s|%s]]', data.class_de, armorClass)
end
local armorType = data.type
if armorType ~= nil then
armorType = string.format('[[:Kategorie:%s|%s]]', data.type_de, armorType)
end
local set = CharArmor.getArmorSet( data.Name )
if set ~= nil then
table.insert( self.categories, string.format('[[Kategorie:%s|%s]]', set, data.Name ) )
set = mw.ustring.format( '[[:Kategorie:%s|%s]]', set, set )
end
local damageReduction = data[ 'Schadensreduktion' ]
if damageReduction ~= nil then
damageReduction = (100 * damageReduction) .. '%'
else
damageReduction = '-'
end
box:renderSection( {
col = 2,
content = {
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_type' ), armorType or '-' ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_price' ), data.price or TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'txt_cant_buy' ) ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_carrying_capacity' ), data[ 'SP' ] or '-' ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_weight' ), data[ 'Volumen' ] or '-' ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_damage_reduction' ), damageReduction ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_class' ), armorClass or '-' ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_set' ), set or '-' ),
}
} )
box:renderSection( {
title = TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_temperature_resistance' ),
col = 2,
content = {
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_temperature_resistance_min' ), tempMinRes or '-' ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_temperature_resistance_max' ), tempMaxRes or '-' ),
}
} )
box:renderSection( {
title = TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_resistances' ),
col = 3,
content = {
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_physical' ), CharArmor.resistanceToString( data[ 'Resistenzmultiplikator Physisch' ] ) ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_energy' ), CharArmor.resistanceToString( data[ 'Resistenzmultiplikator Physisch' ] ) ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_distortion' ), CharArmor.resistanceToString( data[ 'Resistenzmultiplikator Distortion' ] ) ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_thermal' ), CharArmor.resistanceToString( data[ 'Resistenzmultiplikator Thermisch' ] ) ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_biochemical' ), CharArmor.resistanceToString( data[ 'Resistenzmultiplikator Biochemisch' ] ) ),
box:renderItem( TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_stun' ), CharArmor.resistanceToString( data[ 'Resistenzmultiplikator Betäubung' ] ) ),
}
} )
if data.attachments ~= nil and type( data.attachments ) == 'table' and #data.attachments > 0 then
local attachTable = makeArmorAttachmentTable( data.attachments )
if #attachTable > 0 then
local attachs = {}
for _, attachment in ipairs( attachTable ) do
local size = ''
if attachment.min ~= 0 and attachment.max ~= 0 then
if attachment.min ~= attachment.max then
size = string.format( '(S%s - S%s)', attachment.min, attachment.max )
end
elseif attachment.min ~= nil and attachment.min ~= 1 then
size = string.format( '(S%s)', attachment.min )
end
if attachment.name == 'Abwerfbar' then
attachment.name = 'Abwerfbar ' .. mw.smw.info( 'Granaten, Knicklichter, etc.' )
end
table.insert( attachs, box:renderItem( attachment.name, string.format( '%dx %s', attachment.count, size ) ) )
end
box:renderSection( {
col = 3,
title = TNT.formatInLanguage( self.lang, 'Module:CharArmor/i18n.json', 'lbl_attachments' ),
content = attachs
} )
end
end
return tostring( box )
end
--- Set the frame and load args
--- @param frame table
function methodtable.setFrame( self, frame )
self.currentFrame = frame
self.frameArgs = require( 'Module:Arguments' ).getArgs( frame )
if type( self.frameArgs[ 'Bild' ] ) == 'string' then
self.frameArgs[ 'image' ] = self.frameArgs[ 'Bild' ]
end
end
--- Get categories
function methodtable.getCategories( self )
return tostring( table.concat( self.categories ) )
end
--- Save Api Data to SMW store
function methodtable.saveApiData( self )
if self.currentFrame == nil then
error( 'No frame set. Call "setFrame" first.', 0 )
end
local data = self:getApiDataForCurrentPage()
self:setSemanticProperties()
return data
end
--[[
Char Armor Methods
]]--
--- @param name string
--- @return string
function CharArmor.getArmorSet( name )
for _, setName in ipairs( objectData.armorSets ) do
if mw.ustring.find( name, setName, 1, true ) then
return setName
end
end
return nil
end
--- @param class string
--- @return table
function CharArmor.translateClass( class )
if objectData.itemClassTranslations[ class ] == nil then
return {
de_DE = class,
en_EN = class
}
end
return objectData.itemClassTranslations[ class ]
end
--- @param type string
--- @return table
function CharArmor.translateArmorType( type )
return {
de_DE = objectData.armorTypeTranslations[ type ] or type,
en_EN = type
}
end
--- Calculates the resistance
--- @return number
function CharArmor.calculateResistance( resistance )
if resistance == nil then
return nil
end
return 100 * ( 1 - resistance )
end
--- Resistance to string
--- @return string
function CharArmor.resistanceToString( resistance )
local res = CharArmor.calculateResistance( resistance )
local span = mw.html.create( 'span' )
if res == nil then
return '-'
end
if res > 100 then
-- Armor has negative resistance
span:addClass( 'resistance-negative' )
else
span:addClass( 'resistance-positive' )
end
span:wikitext( res .. '%' )
return tostring( span:allDone() )
end
--- Returns temperature resistances as strings containing °C
--- @param resTable table containing an arbitrary amount of temperatures
--- @return string, string
function CharArmor.temperatureResistanceToText( resTable )
local tempMinRes = math.huge
local tempMaxRes = -math.huge
if resTable ~= nil and type( resTable ) == 'table' then
for _, res in pairs( resTable ) do
res = common.toNumber( res, 0 )
if res < tempMinRes then
tempMinRes = res
end
if res > tempMaxRes then
tempMaxRes = res
end
end
end
if tempMinRes == math.huge then
tempMinRes = '-'
else
tempMinRes = tempMinRes .. '°C'
end
if tempMaxRes == -math.huge then
tempMaxRes = '-'
else
tempMaxRes = tempMaxRes .. '°C'
end
return tempMinRes, tempMaxRes
end
--- Translates an internal attachment name to text
--- @param name string The internal name
--- @return string
function CharArmor.translateArmorAttachment( name )
if name == nil then
return name
end
local matchAttachName = mw.ustring.match(name, "(%w+)_attach_%d")
local matchStockedName = mw.ustring.match(name, "(%w+)_stocked_%d")
if matchAttachName ~= nil then
name = matchAttachName
elseif matchStockedName ~= nil then
name = matchStockedName
end
if objectData.armorAttachmentTranslations[ name ] ~= nil then
if common.getLocaleForPage() == 'de' then
return objectData.armorAttachmentTranslations[ name ].de_DE
end
return objectData.armorAttachmentTranslations[ name ].en_EN
end
return name
end
--- Format the carrying capacity
--- @param capacity string|number|nil
--- @return string
function CharArmor.formatCarryingCapacity( capacity )
if capacity == nil then
return nil
end
if type( capacity ) == 'string' then
capacity = mw.ustring.gsub( capacity, 'K SP', '' )
capacity = mw.ustring.gsub( capacity, 'K µSCU', '' )
capacity = common.toNumber( capacity )
if capacity ~= nil then
capacity = capacity * 1000
end
end
capacity = common.toNumber( capacity )
if capacity == nil then
return nil
end
return common.formatNum( capacity ) .. ' µSCU'
end
--- Format the emperature resistance
--- @param temperature string|number|nil
--- @return string
function CharArmor.formatTemperature( temperature )
if temperature == nil then
return nil
end
temperature = common.toNumber(temperature, false )
if temperature == nil then
return nil
end
return common.formatNum( temperature ) .. ' °C'
end
--- Template entry
function CharArmor.main( frame )
local instance = CharArmor:new()
instance:setFrame( frame )
if not localized.isLanguagePage() then
if instance.frameArgs[ 'Manuell' ] ~= nil then
instance:addManual()
else
instance:saveApiData()
end
end
instance:setCategories( instance:getSmwData() )
instance:setSeoData()
return tostring( instance:getInfoBox() ) .. instance:getCategories()
end
--- New Instance
function CharArmor.new( self, name )
local instance = {
categories = {},
frameArgs = {
[ 'name' ] = name
},
lang = require( 'Module:Template translation' )._getLanguageSubpage( mw.title.getCurrentTitle() )
}
setmetatable( instance, metatable )
return instance
end
return CharArmor