Skip to content

Commit

Permalink
Merge pull request #6027 from sturnclaw/missile-api
Browse files Browse the repository at this point in the history
Improve Naval and Smart missiles
  • Loading branch information
sturnclaw authored Jan 21, 2025
2 parents 465f6db + 45e7431 commit 6b63d37
Show file tree
Hide file tree
Showing 17 changed files with 199 additions and 122 deletions.
9 changes: 9 additions & 0 deletions data/libs/EquipType.lua
Original file line number Diff line number Diff line change
Expand Up @@ -548,13 +548,20 @@ local ThrusterType = utils.inherits(EquipType, "Equipment.ThrusterType")

--==============================================================================

---@class Equipment.MissileType : EquipType
---@field missile_stats table
local MissileType = utils.inherits(EquipType, "Equipment.MissileType")

--==============================================================================

Serializer:RegisterClass("EquipType", EquipType)
Serializer:RegisterClass("Equipment.LaserType", LaserType)
Serializer:RegisterClass("Equipment.HyperdriveType", HyperdriveType)
Serializer:RegisterClass("Equipment.SensorType", SensorType)
Serializer:RegisterClass("Equipment.BodyScannerType", BodyScannerType)
Serializer:RegisterClass("Equipment.CabinType", CabinType)
Serializer:RegisterClass("Equipment.ThrusterType", ThrusterType)
Serializer:RegisterClass("Equipment.MissileType", MissileType)

EquipType:SetupPrototype()
LaserType:SetupPrototype()
Expand All @@ -563,6 +570,7 @@ SensorType:SetupPrototype()
BodyScannerType:SetupPrototype()
CabinType:SetupPrototype()
ThrusterType:SetupPrototype()
MissileType:SetupPrototype()

return {
laser = laser,
Expand All @@ -575,4 +583,5 @@ return {
BodyScannerType = BodyScannerType,
CabinType = CabinType,
ThrusterType = ThrusterType,
MissileType = MissileType,
}
3 changes: 1 addition & 2 deletions data/libs/Ship.lua
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,10 @@ function Ship:FireMissileAt(missile, target)
-- FIXME: handle multiple-count missile mounts
equipSet:Remove(missile)

local missile_object = self:SpawnMissile(missile.missile_type)
local missile_object = self:SpawnMissile(missile.missile_stats, target)

if missile_object then
if target then
missile_object:AIKamikaze(target)
Event.Queue("onShipFiring", self)
end
-- Let's keep a safe distance before activating this device, shall we ?
Expand Down
6 changes: 6 additions & 0 deletions data/meta/CoreObject/Ship.meta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,9 @@ function Ship:IsLanded() end
-- Get the starport this ship is docked with, if any
---@return SpaceStation?
function Ship:GetDockedWith() end

-- Spawn a new missile from this ship
---@param stats table Information about the missile to spawn. Must include a shipType: string field
---@param target Body? Optional body to target with the missile
---@return Body? missile The spawned missile if valid
function Ship:SpawnMissile(stats, target) end
32 changes: 20 additions & 12 deletions data/modules/Debug/DebugShip.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,19 @@ local templateOptions = {
}

local missileOptions = {
"Guided Missile",
"Unguided Missile",
"Smart Missile",
"Naval Missile"
"S1 Guided Missile",
"S1 Unguided Missile",
"S2 Guided Missile",
"S3 Smart Missile",
"S4 Naval Missile"
}

local missileTypes = {
"missile_guided",
"missile_unguided",
"missile_smart",
"missile_naval",
"missile.guided_s1",
"missile.unguided_s1",
"missile.guided_s2",
"missile.smart_s3",
"missile.naval_s4",
}

---@type HullConfig[]
Expand Down Expand Up @@ -221,15 +223,21 @@ end

function DebugShipTool:onSpawnMissile()

local missile_type = missileTypes[self.missileIdx]
local missile_type = require 'Equipment'.Get(missileTypes[self.missileIdx]) --[[@as Equipment.MissileType?]]

if missile_type ~= "missile_unguided" and not Game.player:GetCombatTarget() then
if not missile_type then
Notification.add(Notification.Type.Error, "No missile equipment {}" % { missileTypes[self.missileIdx] })
return
end

if missile_type.missile_stats.guided and not Game.player:GetCombatTarget() then
Notification.add(Notification.Type.Error, "Debug: no target for {}" % { missileOptions[self.missileIdx] })
return
end

local missile = Game.player:SpawnMissile(missile_type)
missile:AIKamikaze(Game.player:GetCombatTarget())
local missile = Game.player:SpawnMissile(missile_type.missile_stats, Game.player:GetCombatTarget())

if not missile then return end

Timer:CallAt(Game.time + 1, function()
if missile:exists() then
Expand Down
21 changes: 11 additions & 10 deletions data/modules/Equipment/Weapons.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local Slot = require 'HullConfig'.Slot

local EquipType = EquipTypes.EquipType
local LaserType = EquipTypes.LaserType
local MissileType = EquipTypes.MissileType

--===============================================
-- Pulse Cannons
Expand Down Expand Up @@ -199,46 +200,46 @@ Equipment.Register("laser.miningcannon_17mw", LaserType.New {
-- Missiles
--===============================================

Equipment.Register("missile.unguided_s1", EquipType.New {
Equipment.Register("missile.unguided_s1", MissileType.New {
l10n_key="MISSILE_UNGUIDED",
price=30, purchasable=true, tech_level=1,
missile_type="missile_unguided",
missile_stats = { shipType="missile_unguided", guided=false, warheadSize=200.0, fuzeRadius=100.0, effectiveRadius=1000.0, chargeEffectiveness=1.0, ecmResist=5.0 },
volume=0, mass=0.045,
slot = { type="missile", size=1, hardpoint=true },
icon_name="equip_missile_unguided"
})
-- Approximately equivalent in size to an R60M / AA-8 'Aphid'
Equipment.Register("missile.guided_s1", EquipType.New {
Equipment.Register("missile.guided_s1", MissileType.New {
l10n_key="MISSILE_GUIDED",
price=45, purchasable=true, tech_level=5,
missile_type="missile_guided",
missile_stats = { shipType="missile_guided", guided=true, warheadSize=125.0, fuzeRadius=30.0, effectiveRadius=800.0, chargeEffectiveness=3.0, ecmResist=1.0 },
volume=0, mass=0.065,
slot = { type="missile", size=1, hardpoint=true },
icon_name="equip_missile_guided"
})
-- Approximately equivalent in size to an R73 / AA-11 'Archer'
Equipment.Register("missile.guided_s2", EquipType.New {
Equipment.Register("missile.guided_s2", MissileType.New {
l10n_key="MISSILE_GUIDED",
price=60, purchasable=true, tech_level=5,
missile_type="missile_guided",
missile_stats = { shipType="missile_guided", guided=true, warheadSize=200.0, fuzeRadius=40.0, effectiveRadius=1500.0, chargeEffectiveness=3.5, ecmResist=1.0 },
volume=0, mass=0.145,
slot = { type="missile", size=2, hardpoint=true },
icon_name="equip_missile_guided"
})
-- Approximately equivalent in size to an R77 / AA-12 'Adder'
Equipment.Register("missile.smart_s3", EquipType.New {
Equipment.Register("missile.smart_s3", MissileType.New {
l10n_key="MISSILE_SMART",
price=95, purchasable=true, tech_level=9,
missile_type="missile_smart",
missile_stats = { shipType="missile_smart", guided=true, warheadSize=320.0, fuzeRadius=35.0, effectiveRadius=2000.0, chargeEffectiveness=4.0, ecmResist=2.0 },
volume=0, mass=0.5,
slot = { type="missile", size=3, hardpoint=true },
icon_name="equip_missile_smart"
})
-- TBD
Equipment.Register("missile.naval_s4", EquipType.New {
Equipment.Register("missile.naval_s4", MissileType.New {
l10n_key="MISSILE_NAVAL",
price=160, purchasable=true, tech_level="MILITARY",
missile_type="missile_naval",
missile_stats = { shipType="missile_naval", guided=true, warheadSize=580.0, fuzeRadius=40.0, effectiveRadius=2000.0, chargeEffectiveness=4.5, ecmResist=3.0 },
volume=0, mass=1,
slot = { type="missile", size=4, hardpoint=true },
icon_name="equip_missile_naval"
Expand Down
56 changes: 31 additions & 25 deletions data/pigui/modules/equipment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

local Engine = require 'Engine'
local Equipment = require 'Equipment'
local Game = require 'Game'
local utils = require 'utils'
local Event = require 'Event'
Expand Down Expand Up @@ -72,16 +73,9 @@ local function displayECM(uiPos)
return uiPos
end

local function getMissileIcon(missile)
if icons[missile.missile_type] then
return icons[missile.missile_type]
else
print("no icon for missile " .. missile.missile_type)
return icons.bullseye
end
end

local function fireMissile(missile)
---@param player Player
---@param missile Equipment.MissileType
local function fireMissile(player, missile)
if not player:GetCombatTarget() then
Game.AddCommsLogLine(lc.SELECT_A_TARGET, "", 1)
else
Expand All @@ -90,28 +84,40 @@ local function fireMissile(missile)
end

local function displayMissiles(uiPos)
player = Game.player
local current_view = Game.CurrentView()
if Game.CurrentView() == "WorldView" then

if current_view == "WorldView" then
local paused = Game.paused
local docked = Game.player:GetDockedWith()

local missiles = Game.player:GetComponent("EquipSet"):GetInstalledOfType("missile") --[[@as Equipment.MissileType[] ]]

local groups = utils.automagic()

local missiles = player:GetComponent("EquipSet"):GetInstalledOfType("missile")
local count = {}
local types = {}
for i, missile in ipairs(missiles) do
local group = groups[missile.id]

for i,missile in ipairs(missiles) do
count[missile.missile_type] = (count[missile.missile_type] or 0) + 1
types[missile.missile_type] = missile
group.count = (group.count or 0) + 1
group.size = missile.slot.size
group.proto = missile:GetPrototype()
group.index = i
end

for t,missile in pairs(types) do
local c = count[t]
local size,clicked = iconEqButton(uiPos, getMissileIcon(missile), true, mainWideIconSize, c, c == 0, mainBackgroundColor, mainForegroundColor, mainHoverColor, mainPressedColor, lec[missile.l10n_key])
local display = utils.build_array(pairs(groups))
table.sort(display, function(a, b) return
a.size < b.size or (a.size == b.size and (not a.guided and b.guided))
end)

for _, group in ipairs(display) do
local count = tostring(group.count)

-- TODO: slot size indicators should have a translated string at some point
local tooltip = "{} (S{})" % { group.proto:GetName(), group.size }
local size, clicked = iconEqButton(uiPos, icons[group.proto.icon_name], false, mainIconSize,
count, false, mainBackgroundColor, mainForegroundColor, mainHoverColor, mainPressedColor, tooltip)
uiPos.y = uiPos.y + size.y + 10

if clicked then
print("firing missile " .. t)
fireMissile(missile)
if clicked and not paused and not docked then
fireMissile(Game.player, missiles[group.index])
end
end

Expand Down
Loading

0 comments on commit 6b63d37

Please sign in to comment.