Skip to content

Commit

Permalink
Merge pull request #5991 from sturnclaw/gun-manager
Browse files Browse the repository at this point in the history
Fully support installing multiple weapons per ship
  • Loading branch information
sturnclaw authored Dec 7, 2024
2 parents 61ceb71 + e78994b commit 397e264
Show file tree
Hide file tree
Showing 30 changed files with 1,309 additions and 527 deletions.
43 changes: 35 additions & 8 deletions data/libs/EquipType.lua
Original file line number Diff line number Diff line change
Expand Up @@ -272,28 +272,55 @@ end
-- Base type for weapons
---@class Equipment.LaserType : EquipType
---@field laser_stats table
---@field weapon_data table
local LaserType = utils.inherits(EquipType, "Equipment.LaserType")

function LaserType.New(specs)
local item = setmetatable(EquipType.New(specs), LaserType.meta)
local ls = specs.laser_stats

-- NOTE: backwards-compatibility with old laser_stats definitions
if ls then

local projectile = {
lifespan = ls.lifespan,
speed = ls.speed,
damage = ls.damage,
beam = ls.beam == 1,
mining = ls.mining == 1,
length = ls.length,
width = ls.width,
color = Color(ls.rgba_r, ls.rgba_g, ls.rgba_b, ls.rgba_a),
}

item.weapon_data = {
rpm = 60 / ls.rechargeTime,
heatPerShot = ls.heatrate or 0.01,
cooling = ls.coolrate or 0.01,
overheat = 1.0,
projectile = projectile,
numBarrels = 1 + ls.dual
}

end

return item
end

---@param ship Ship
---@param slot HullConfig.Slot
function LaserType:OnInstall(ship, slot)
EquipType.OnInstall(self, ship, slot)

for k, v in pairs(self.laser_stats) do
-- TODO: allow installing more than one laser
ship:setprop('laser_front_' .. k, v)
end
ship:GetComponent('GunManager'):MountWeapon(slot.id, self.weapon_data)
end

---@param ship Ship
---@param slot HullConfig.Slot
function LaserType:OnRemove(ship, slot)
EquipType.OnRemove(self, ship, slot)

for k, v in pairs(self.laser_stats) do
-- TODO: allow installing more than one laser
ship:setprop('laser_front_' .. k, nil)
end
ship:GetComponent('GunManager'):UnmountWeapon(slot.id)
end

--==============================================================================
Expand Down
1 change: 1 addition & 0 deletions data/libs/HullConfig.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Slot.hardpoint = false
Slot.i18n_key = nil ---@type string?
Slot.i18n_res = "equipment-core"
Slot.count = nil ---@type integer?
Slot.gimbal = nil ---@type table?

-- Class: HullConfig
--
Expand Down
23 changes: 23 additions & 0 deletions data/libs/Ship.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ function Ship:Constructor()
self:SetComponent('CargoManager', CargoManager.New(self))
self:SetComponent('EquipSet', EquipSet.New(self))

self:UpdateWeaponSlots()

-- Timers cannot be started in ship constructors before Game is fully set,
-- so trigger a lazy event to setup gameplay timers.
--
Expand All @@ -40,6 +42,27 @@ end
function Ship:OnShipTypeChanged()
-- immediately update any needed components or properties
self:GetComponent('EquipSet'):OnShipTypeChanged()

self:UpdateWeaponSlots()
end

---@private
function Ship:UpdateWeaponSlots()
local equipSet = self:GetComponent('EquipSet')
local gunManager = self:GetComponent('GunManager')

for _, slot in ipairs(equipSet:GetAllSlotsOfType("weapon", true)) do
if not slot.gimbal then
logWarning('Missing hardpoint gimbal on ship {} for slot {}' % { self.shipId, slot.id })
end

local gimbal = Vector2(table.unpack(slot.gimbal or { 1, 1 }))
local ok = gunManager:AddWeaponMount(slot.id, slot.tag, gimbal)

if not ok then
logWarning('Unable to add weapon mount slot {} on ship {}' % { slot.id, self.shipId })
end
end
end

-- class method
Expand Down
30 changes: 30 additions & 0 deletions data/meta/Components/GunManager.meta.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

-- This file implements type information about C++ classes for Lua static analysis

---@meta

---@class GunManager
local GunManager = {}

---@param id string
---@param tag string
---@param gimbal Vector2
function GunManager:AddWeaponMount(id, tag, gimbal) end

---@param id string
function GunManager:RemoveWeaponMount(id) end

---@param mount string
---@param weaponData table
---@return boolean
function GunManager:MountWeapon(mount, weaponData) end

---@param mount string
function GunManager:UnmountWeapon(mount) end

---@param mount string
function GunManager:IsWeaponMounted(mount) end

-- TODO...
1 change: 1 addition & 0 deletions data/pigui/modules/radar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ end)

-- reset radar to default at game end
Event.Register("onGameEnd", function()
player = nil
shouldDisplay2DRadar = false
radar2d:resetZoom()
radar3d:resetZoom()
Expand Down
1 change: 1 addition & 0 deletions src/Beam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "GameSaveError.h"
#include "JsonUtils.h"
#include "Pi.h"
#include "Projectile.h"
#include "Planet.h"
#include "Player.h"
#include "Sfx.h"
Expand Down
22 changes: 19 additions & 3 deletions src/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,20 +152,34 @@ class Body : public DeleteEmitter, public PropertiedObject {
T *GetComponent() const
{
auto *type = BodyComponentDB::GetComponentType<T>();
return m_components & (uint64_t(1) << uint8_t(type->componentIndex)) ? type->get(this) : nullptr;
return m_components & GetComponentBit(type->componentIndex) ? type->get(this) : nullptr;
}

// Add a component to this body if it is not already present.
// Returns a pointer to the existing component if a new one could not be added.
template <typename T>
T *AddComponent()
{
auto *type = BodyComponentDB::GetComponentType<T>();
if (m_components & (uint64_t(1) << uint8_t(type->componentIndex)))
if (m_components & GetComponentBit(type->componentIndex))
return type->get(this);

m_components |= (uint64_t(1) << uint8_t(type->componentIndex));
m_components |= GetComponentBit(type->componentIndex);
return type->newComponent(this);
}

// Remove a component from this body, destroying it.
template<typename T>
void RemoveComponent()
{
auto *type = BodyComponentDB::GetComponentType<T>();
if (!(m_components & GetComponentBit(type->componentIndex)))
return;

m_components ^= GetComponentBit(type->componentIndex);
type->deleteComponent(this);
}

// Returns the bitset of components attached to this body. Prefer using HasComponent<> or GetComponent<> instead.
uint64_t GetComponentList() const { return m_components; }

Expand Down Expand Up @@ -218,6 +232,8 @@ class Body : public DeleteEmitter, public PropertiedObject {
matrix3x3d m_interpOrient;

private:
uint64_t GetComponentBit(uint8_t bit) const { return uint64_t(1) << bit; }

vector3d m_pos;
matrix3x3d m_orient;
FrameId m_frame; // frame of reference
Expand Down
4 changes: 4 additions & 0 deletions src/ConnectionTicket.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ struct ConnectionTicket {
m_connection = c;
}

void disconnect() {
m_connection.disconnect();
}

sigc::connection m_connection;
};
1 change: 0 additions & 1 deletion src/DynamicBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "DynamicBody.h"

#include "FixedGuns.h"
#include "Frame.h"
#include "GameSaveError.h"
#include "JsonUtils.h"
Expand Down
2 changes: 0 additions & 2 deletions src/DynamicBody.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
#include "vector3.h"

class Propulsion;
class FixedGuns;
class Orbit;

class DynamicBody : public ModelBody {
private:
friend class Propulsion;
friend class FixedGuns;

public:
OBJDEF(DynamicBody, ModelBody, DYNAMICBODY);
Expand Down
Loading

0 comments on commit 397e264

Please sign in to comment.