Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully support installing multiple weapons per ship #5991

Merged
merged 17 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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