Module:SpaceBodyLister/Bombard/Single
From Terra Invicta Official Wiki
Documentation for this module may be created at Module:SpaceBodyLister/Bombard/Single/doc
---
---Reads the SpaceBody data files and uses them to compute bombard damage for different weapons.
---
---@module SpaceBodyLister
local SpaceBodyLister = {}
--region Dependencies
local IconModule = require('Module:Icon')
local MagneticGunData = mw.loadData('Module:CSVReader/MagneticGun')
local MagneticGunNames = mw.loadData('Module:ENReader/MagneticGun')
local SpaceBodyData = mw.loadData('Module:CSVReader/SpaceBody')
local SpaceBodyBombardData = mw.loadData('Module:SpaceBodyLister/Bombard')
local SpaceBodyNames = mw.loadData('Module:ENReader/SpaceBody')
--endregion
--region Private constants
local floor = math.floor
local round = function(num, decimals)
local mult = 10^(decimals or 0)
return floor(num * mult + 0.5) / mult
end
--endregion
--region Private member variables
--none
--endregion
--region Private methods
-- Safe value access with fallback
local function getValue(row, key, default)
local value = row[key]
if value == nil or value == '' then
return default or 0
end
return value
end
local function calculatePerAmmoResourceCost( amass, resourceWeight)
return tonumber(amass) * (tonumber(resourceWeight) or 0) / 10000
end
--endregion
--region Public methods
---@return wiki table of Space Body Bombard Values
function SpaceBodyLister.ListBombardValues(frame)
if not frame.args[1] or frame.args[1] == '' then
return "Error: Space Body not specified."
elseif not SpaceBodyData[frame.args[1]] then
return "Error: Space Body " .. frame.args[1] .. " not found."
end
local spaceBodyName = (SpaceBodyNames['TISpaceBodyTemplate.displayName.' .. frame.args[1]] or frame.args[1])
local spaceBodyMass = SpaceBodyData[frame.args[1]]['mass_kg']
local computedMeanRadius = SpaceBodyBombardData[frame.args[1]]['computedMeanRadius']
local SOIradius = SpaceBodyBombardData[frame.args[1]]['SOIradius']
local surfaceGravity = SpaceBodyBombardData[frame.args[1]]['surfaceGravity']
local atmosphere = SpaceBodyData[frame.args[1]]['atmosphere']
local atmosphereScaleHeight_km = SpaceBodyData[frame.args[1]]['atmosphereScaleHeight_km']
local atmosphereSurfaceDensity_kgpm3 = SpaceBodyData[frame.args[1]]['atmosphereSurfaceDensity_kgpm3']
local distanceToSpaceBodyCoreM = {}
distanceToSpaceBodyCoreM[1] = computedMeanRadius * 1000 + 200000
distanceToSpaceBodyCoreM[2] = computedMeanRadius * 1000 + 400000
distanceToSpaceBodyCoreM[3] = computedMeanRadius * 1000 + 600000
local meanOrbitalSpeedMS = {}
meanOrbitalSpeedMS[1] = (6.67384E-11 * spaceBodyMass / distanceToSpaceBodyCoreM[1]) ^ 0.5
meanOrbitalSpeedMS[2] = (6.67384E-11 * spaceBodyMass / distanceToSpaceBodyCoreM[2]) ^ 0.5
meanOrbitalSpeedMS[3] = (6.67384E-11 * spaceBodyMass / distanceToSpaceBodyCoreM[3]) ^ 0.5
local initialGravitationalAccelerationMS2 = {}
local averageGravitationalAccelerationMS2 = {}
for i = 1, 3 do
if distanceToSpaceBodyCoreM[i] > SOIradius * 1000 then
initialGravitationalAccelerationMS2[i] = 0
else
initialGravitationalAccelerationMS2[i] = 6.67384E-11 * spaceBodyMass / (distanceToSpaceBodyCoreM[i] ^ 2)
end
averageGravitationalAccelerationMS2[i] = (surfaceGravity + initialGravitationalAccelerationMS2[i]) / 2
end
local returnString = '{| class="wikitable sortable mw-collapsible" style="text-align: center;"'
returnString = returnString .. '\n|+ Bombardment Values for ' .. spaceBodyName
returnString = returnString .. '\n|-'
returnString = returnString .. '\n! rowspan=2 | Weapon'
returnString = returnString .. "\n! colspan=3 | Damage at Altitude"
returnString = returnString .. "\n! colspan=3 | Anti-PD Value at Altitude"
returnString = returnString .. "\n! colspan=3 | Cost per Ammo"
returnString = returnString .. '\n|-'
returnString = returnString .. '\n! 200km'
returnString = returnString .. '\n! 400km'
returnString = returnString .. '\n! 600km'
returnString = returnString .. '\n! 200km'
returnString = returnString .. '\n! 400km'
returnString = returnString .. '\n! 600km'
returnString = returnString .. '\n!' .. IconModule.Icon({args={'volatiles'}})
returnString = returnString .. '\n!' .. IconModule.Icon({args={'metals'}})
returnString = returnString .. '\n!' .. IconModule.Icon({args={'nobles'}})
returnString = returnString .. '\n|-'
for rowID, row in pairs(MagneticGunData) do
returnString = returnString .. '\n| ' .. (MagneticGunNames['TIMagneticGunTemplate.displayName.' .. rowID] or rowID)
local initialProjectileVelocityMS = {}
local initialProjectileKineticEnergyJ = {}
local initialProjectileGravitationalPotentialEnergyJ = {}
local totalInitialProjectileEnergyJ = {}
local baseSurfaceImpactVelocityMS = {}
for i = 1, 3 do
initialProjectileVelocityMS[i] = ((row['muzzleVelocity_kps'] * 1000) ^ 2 + meanOrbitalSpeedMS[i] ^ 2) ^ 0.5
initialProjectileKineticEnergyJ[i] = 0.5 * row['warheadMass_kg'] * initialProjectileVelocityMS[i] ^ 2
initialProjectileGravitationalPotentialEnergyJ[i] = row['warheadMass_kg'] * 200000 * i * averageGravitationalAccelerationMS2[i]
totalInitialProjectileEnergyJ[i] = initialProjectileKineticEnergyJ[i] + initialProjectileGravitationalPotentialEnergyJ[i]
baseSurfaceImpactVelocityMS[i] = (2 * totalInitialProjectileEnergyJ[i] / row['warheadMass_kg']) ^ 0.5
end
local actualSurfaceImpactVelocityMS = {}
if atmosphere == 'Trace' or atmosphere == 'None' then
actualSurfaceImpactVelocityMS = baseSurfaceImpactVelocityMS
else
local lengthOfProjectilePathThroughAtmosphereM = {}
local energyLostToAtmosphericDragJ = {}
local remainingEnergyJ = {}
local modifiedSurfaceImpactVelocityMS = {}
local terminalVelocityMS = (2 * row['warheadMass_kg'] * surfaceGravity / 4.0000003E-5 / atmosphereSurfaceDensity_kgpm3) ^ 0.5
for i = 1,3 do
lengthOfProjectilePathThroughAtmosphereM[i] = atmosphereScaleHeight_km * initialProjectileVelocityMS[i] / row['muzzleVelocity_kps']
energyLostToAtmosphericDragJ[i] = atmosphereSurfaceDensity_kgpm3 * lengthOfProjectilePathThroughAtmosphereM[i] * 0.001 * initialProjectileVelocityMS[i] ^ 2
remainingEnergyJ[i] = totalInitialProjectileEnergyJ[i] - energyLostToAtmosphericDragJ[i]
if remainingEnergyJ[i] < 0 then
remainingEnergyJ[i] = 0
end
modifiedSurfaceImpactVelocityMS[i] = (2 * remainingEnergyJ[i] / row['warheadMass_kg']) ^ 0.5
if baseSurfaceImpactVelocityMS[i] > terminalVelocityMS then
if terminalVelocityMS > modifiedSurfaceImpactVelocityMS[i] then
actualSurfaceImpactVelocityMS[i] = terminalVelocityMS
else
actualSurfaceImpactVelocityMS[i] = modifiedSurfaceImpactVelocityMS[i]
end
else
if terminalVelocityMS < modifiedSurfaceImpactVelocityMS[i] then
actualSurfaceImpactVelocityMS[i] = terminalVelocityMS
else
actualSurfaceImpactVelocityMS[i] = modifiedSurfaceImpactVelocityMS[i]
end
end
end
end
local impactEnergyJ = {}
local projectileDamage = {}
local antiPDValue = {}
local averageCooldown = tonumber(row['cooldown_s'])
if row['salvo_shots'] and row['salvo_shots'] ~= '' and tonumber(row['salvo_shots']) then
averageCooldown = (averageCooldown + (tonumber(row['salvo_shots']) - 1) * tonumber(row['intraSalvoCooldown_s'])) / tonumber(row['salvo_shots'])
end
for i = 1,3 do
impactEnergyJ[i] = 0.5 * row['warheadMass_kg'] * actualSurfaceImpactVelocityMS[i] ^ 2
projectileDamage[i] = impactEnergyJ[i] / 20000000
antiPDValue[i] = impactEnergyJ[i] / 1000000 / averageCooldown
end
local directDamageFraction = 1 - tonumber(row['flatChipping'])
local directDamage = {}
for i = 1,3 do
directDamage[i] = directDamageFraction * projectileDamage[i]
if directDamage[i] < projectileDamage[i] / 2 and frame.args[1] == 'Earth' then
directDamage[i] = projectileDamage[i] / 2
end
end
returnString = returnString .. '\n| ' .. round(directDamage[1],3)
returnString = returnString .. '\n| ' .. round(directDamage[2],3)
returnString = returnString .. '\n| ' .. round(directDamage[3],3)
returnString = returnString .. '\n| ' .. round(antiPDValue[1],3)
returnString = returnString .. '\n| ' .. round(antiPDValue[2],3)
returnString = returnString .. '\n| ' .. round(antiPDValue[3],3)
-- Ammo resources
local ammoVolatiles = calculatePerAmmoResourceCost(getValue(row, 'ammoMass_kg'), getValue(row, 'ammoMaterials/volatiles'))
local ammoMetals = calculatePerAmmoResourceCost(getValue(row, 'ammoMass_kg'), getValue(row, 'ammoMaterials/metals'))
local ammoNobles = calculatePerAmmoResourceCost(getValue(row, 'ammoMass_kg'), getValue(row, 'ammoMaterials/nobleMetals'))
returnString = returnString .. '\n| ' .. round(ammoVolatiles, 5)
returnString = returnString .. '\n| ' .. round(ammoMetals, 5)
returnString = returnString .. '\n| ' .. round(ammoNobles, 5)
returnString = returnString .. '\n|-'
end
returnString = returnString .. '\n|}'
return returnString
end
--endregion
return SpaceBodyLister


