Sentry turrets - Part 2: Basic prototype (#35031)

This commit is contained in:
chromiumboy
2025-02-23 07:39:44 -06:00
committed by GitHub
parent b742afbe2c
commit 066c773965
8 changed files with 500 additions and 263 deletions

View File

@@ -0,0 +1,49 @@
using Content.Server.Power.EntitySystems;
using Content.Shared.Power.EntitySystems;
namespace Content.Server.Power.Components;
/// <summary>
/// Attached to APC powered entities that possess a rechargeable internal battery.
/// If external power is interrupted, the entity will draw power from this battery instead.
/// Requires <see cref="ApcPowerReceiverComponent"/> and <see cref="BatteryComponent"/> to function.
/// </summary>
[RegisterComponent]
[Access([typeof(PowerNetSystem), typeof(SharedPowerReceiverSystem)])]
public sealed partial class ApcPowerReceiverBatteryComponent : Component
{
/// <summary>
/// Indicates whether power is currently being drawn from the battery.
/// </summary>
[DataField]
public bool Enabled = false;
/// <summary>
/// The passive load the entity places on the APC power network.
/// If not connected to an active APC power network, this amount
/// of power is drained from the battery every second.
/// </summary>
[DataField]
public float IdleLoad { get; set; } = 5f;
/// <summary>
/// Determines how much battery charge the entity's battery gains
/// per second when connected to an active APC power network.
/// </summary>
[DataField]
public float BatteryRechargeRate { get; set; } = 50f;
/// <summary>
/// While the battery is being recharged, the load this entity places on the APC
/// power network is increased by the <see cref="BatteryRechargeRate"/> multiplied
/// by this factor.
/// </summary>
[DataField]
public float BatteryRechargeEfficiency { get; set; } = 1f;
}
/// <summary>
/// Raised whenever an ApcPowerReceiverBattery starts / stops discharging
/// </summary>
[ByRefEvent]
public readonly record struct ApcPowerReceiverBatteryChangedEvent(bool Enabled);

View File

@@ -22,6 +22,7 @@ namespace Content.Server.Power.EntitySystems
[Dependency] private readonly PowerNetConnectorSystem _powerNetConnector = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IParallelManager _parMan = default!;
[Dependency] private readonly BatterySystem _battery = default!;
private readonly PowerState _powerState = new();
private readonly HashSet<PowerNet> _powerNetReconnectQueue = new();
@@ -278,7 +279,7 @@ namespace Content.Server.Power.EntitySystems
// Send events where necessary.
// TODO: Instead of querying ALL power components every tick, and then checking if an event needs to be
// raised, should probably assemble a list of entity Uids during the actual solver steps.
UpdateApcPowerReceiver();
UpdateApcPowerReceiver(frameTime);
UpdatePowerConsumer();
UpdateNetworkBattery();
}
@@ -306,10 +307,12 @@ namespace Content.Server.Power.EntitySystems
_powerNetReconnectQueue.Clear();
}
private void UpdateApcPowerReceiver()
private void UpdateApcPowerReceiver(float frameTime)
{
var appearanceQuery = GetEntityQuery<AppearanceComponent>();
var metaQuery = GetEntityQuery<MetaDataComponent>();
var apcBatteryQuery = GetEntityQuery<ApcPowerReceiverBatteryComponent>();
var enumerator = AllEntityQuery<ApcPowerReceiverComponent>();
while (enumerator.MoveNext(out var uid, out var apcReceiver))
{
@@ -318,6 +321,42 @@ namespace Content.Server.Power.EntitySystems
|| MathHelper.CloseToPercent(apcReceiver.NetworkLoad.ReceivingPower,
apcReceiver.Load));
// Check if the entity has an internal battery
if (apcBatteryQuery.TryComp(uid, out var apcBattery) && TryComp<BatteryComponent>(uid, out var battery))
{
apcReceiver.Load = apcBattery.IdleLoad;
// Try to draw power from the battery if there isn't sufficient external power
var requireBattery = !powered && !apcReceiver.PowerDisabled;
if (requireBattery)
{
_battery.SetCharge(uid, battery.CurrentCharge - apcBattery.IdleLoad * frameTime, battery);
}
// Otherwise try to charge the battery
else if (powered && !_battery.IsFull(uid, battery))
{
apcReceiver.Load += apcBattery.BatteryRechargeRate * apcBattery.BatteryRechargeEfficiency;
_battery.SetCharge(uid, battery.CurrentCharge + apcBattery.BatteryRechargeRate * frameTime, battery);
}
// Enable / disable the battery if the state changed
var enableBattery = requireBattery && battery.CurrentCharge > 0;
if (apcBattery.Enabled != enableBattery)
{
apcBattery.Enabled = enableBattery;
var apcBatteryEv = new ApcPowerReceiverBatteryChangedEvent(enableBattery);
RaiseLocalEvent(uid, ref apcBatteryEv);
_appearance.SetData(uid, PowerDeviceVisuals.BatteryPowered, enableBattery);
}
powered |= enableBattery;
}
// If new value is the same as the old, then exit
if (!apcReceiver.Recalculate && apcReceiver.Powered == powered)
continue;

View File

@@ -6,6 +6,7 @@ namespace Content.Shared.Power
public enum PowerDeviceVisuals : byte
{
VisualState,
Powered
Powered,
BatteryPowered
}
}

View File

@@ -17,6 +17,34 @@
- HideContextMenu
- type: AnimationPlayer
- type: entity
parent: MuzzleFlashEffect
id: MuzzleFlashEffectOmnilaser
categories: [ HideSpawnMenu ]
components:
- type: Sprite
drawdepth: BelowMobs
offset: 0.15, 0
layers:
- shader: unshaded
map: ["enum.EffectLayers.Unshaded"]
sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi
state: omnilaser_flash
- type: entity
parent: MuzzleFlashEffect
id: MuzzleFlashEffectHeavyLaser
categories: [ HideSpawnMenu ]
components:
- type: Sprite
drawdepth: BelowMobs
offset: 0.15, 0
layers:
- shader: unshaded
map: ["enum.EffectLayers.Unshaded"]
sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi
state: heavylaser_flash
# One bullet to bring them all into the darkness and bind them
- type: entity
id: BaseBullet
@@ -949,6 +977,81 @@
collection: WeakHit
forceSound: true
- type: entity
name : energy bolt
id: BulletEnergyTurretBase
parent: BaseBullet
categories: [ HideSpawnMenu ]
components:
- type: Reflective
reflective:
- Energy
- type: FlyBySound
sound:
collection: EnergyMiss
params:
volume: 5
- type: Sprite
sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi
layers:
- state: heavylaser
shader: unshaded
- type: Physics
- type: Fixtures
fixtures:
projectile:
shape:
!type:PhysShapeAabb
bounds: "-0.15,-0.3,0.15,0.3"
hard: false
mask:
- Opaque
fly-by: *flybyfixture
- type: Ammo
- type: entity
name : laser bolt
id: BulletEnergyTurretLaser
parent: BulletEnergyTurretBase
categories: [ HideSpawnMenu ]
components:
- type: Ammo
muzzleFlash: MuzzleFlashEffectHeavyLaser
- type: Sprite
sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi
layers:
- state: heavylaser
shader: unshaded
- type: Projectile
impactEffect: BulletImpactEffectOrangeDisabler
damage:
types:
Heat: 28
- type: entity
name : disabler bolt
id: BulletEnergyTurretDisabler
parent: BulletEnergyTurretBase
categories: [ HideSpawnMenu ]
components:
- type: Ammo
muzzleFlash: MuzzleFlashEffectOmnilaser
- type: Sprite
sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi
layers:
- state: omnilaser
shader: unshaded
- type: StaminaDamageOnCollide
damage: 30
- type: Projectile
impactEffect: BulletImpactEffectDisabler
damage:
types:
Heat: 0
soundHit:
collection: WeakHit
forceSound: true
- type: entity
name: tesla gun lightning
id: TeslaGunBullet

View File

@@ -0,0 +1,138 @@
- type: entity
parent: [BaseWeaponBallisticTurret, BaseSyndicateContraband]
id: WeaponTurretSyndicate
suffix: Syndicate
components:
- type: NpcFactionMember
factions:
- Syndicate
- type: entity
parent: BaseWeaponBallisticTurret
id: WeaponTurretSyndicateDisposable
name: disposable ballistic turret
suffix: Syndicate, Disposable
components:
- type: NpcFactionMember
factions:
- Syndicate
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 600
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:TriggerBehavior
- type: Gun
fireRate: 2
selectedMode: FullAuto
availableModes:
- FullAuto
soundGunshot: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg
- type: BallisticAmmoProvider
proto: CartridgePistol
capacity: 50
- type: Construction
deconstructionTarget: null
graph: WeaponTurretSyndicateDisposable
node: disposableTurret
- type: Repairable
qualityNeeded: "Anchoring"
doAfterDelay: 3
- type: TriggerWhenEmpty
- type: ExplodeOnTrigger
- type: Explosive
explosionType: Default
maxIntensity: 10
intensitySlope: 1.5
totalIntensity: 30
canCreateVacuum: false
- type: entity
parent: BaseWeaponBallisticTurret
id: WeaponTurretNanoTrasen
suffix: NanoTrasen
components:
- type: NpcFactionMember
factions:
- NanoTrasen
- type: entity
parent: BaseWeaponBallisticTurret
id: WeaponTurretHostile
suffix: Hostile
components:
- type: NpcFactionMember
factions:
- SimpleHostile
- type: entity
parent: BaseWeaponBallisticTurret
id: WeaponTurretAllHostile
suffix: All hostile
components:
- type: NpcFactionMember
factions:
- AllHostile
- type: entity
parent: BaseWeaponBallisticTurret
id: WeaponTurretXeno
name: xeno turret
suffix: Xeno
description: Shoots 9mm acid projectiles.
components:
- type: NpcFactionMember
factions:
- Xeno
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/xenoturret.rsi
noRot: true
layers:
- state: acid_turret
- type: BallisticAmmoProvider
proto: BulletAcid
capacity: 500
- type: Gun
fireRate: 1
selectedMode: FullAuto
soundGunshot: /Audio/Weapons/Xeno/alien_spitacid.ogg
- type: HTN
rootTask:
task: TurretCompound
blackboard:
SoundTargetInLOS: !type:SoundPathSpecifier
path: /Audio/Animals/snake_hiss.ogg
- type: Damageable
damageContainer: Biological
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/gib1.ogg
- !type:SpawnEntitiesBehavior
spawn:
FoodMeatXeno:
min: 3
max: 5
- type: InteractionPopup
interactDelay: 1.0
successChance: 0.8
interactSuccessString: petting-success-generic
interactFailureString: petting-failure-generic
interactSuccessSound:
path: /Audio/Animals/snake_hiss.ogg

View File

@@ -0,0 +1,135 @@
- type: entity
parent: BaseStructure
id: BaseWeaponTurret
name: turret
abstract: true
components:
- type: Clickable
- type: InteractionOutline
- type: Actions
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.45,-0.45,0.45,0.45"
density: 60
mask:
- MachineMask
layer:
- MachineLayer
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/turrets.rsi
drawdepth: Mobs
layers:
- state: syndie_lethal
- type: InteractionPopup
interactDelay: 0.2
successChance: 0.8
interactSuccessString: petting-success-generic
interactFailureString: petting-failure-generic
interactSuccessSound:
path: /Audio/Effects/double_beep.ogg
- type: CombatMode
toggleMouseRotator: false
- type: Damageable
damageContainer: Inorganic
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 600
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalGlassBreak
- trigger:
!type:DamageTrigger
damage: 300
# TODO: Construction graph
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalGlassBreak
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel1:
min: 3
max: 5
- type: HTN
rootTask:
task: TurretCompound
blackboard:
RotateSpeed: !type:Single
3.141
SoundTargetInLOS: !type:SoundPathSpecifier
path: /Audio/Effects/double_beep.ogg
- type: MouseRotator
angleTolerance: 5
rotationSpeed: 180
simple4DirMode: false
- type: NoRotateOnInteract
- type: NoRotateOnMove
- type: Input
context: "human"
- type: entity
parent: BaseWeaponTurret
id: BaseWeaponBallisticTurret
description: A ballistic machine gun auto-turret.
name: ballistic turret
abstract: true
components:
- type: ContainerContainer
containers:
ballistic-ammo: !type:Container
- type: Gun
fireRate: 6
selectedMode: FullAuto
availableModes:
- FullAuto
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg
- type: BallisticAmmoProvider
proto: CartridgeCaselessRifle
capacity: 500
- type: entity
parent: BaseWeaponTurret
id: BaseWeaponEnergyTurret
name: laser turret
description: An auto-turret armed with a heavy laser. Its weapon will recharge while connected to an active power grid.
abstract: true
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/sentry_turret.rsi
drawdepth: FloorObjects
granularLayersRendering: true
layers:
- state: support
renderingStrategy: NoRotation
- state: base
- state: lethal
shader: unshaded
- type: Gun
projectileSpeed: 15
fireRate: 1.5
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/taser2.ogg
- type: ProjectileBatteryAmmoProvider
proto: BulletEnergyTurretLaser
fireCost: 100
- type: Battery
maxCharge: 2000
startingCharge: 0
- type: ApcPowerReceiverBattery
idlePowerUse: 5
batteryRechargeRate: 200
batteryRechargeEfficiency: 1.225
- type: ApcPowerReceiver
powerLoad: 5
- type: ExtensionCableReceiver

View File

@@ -0,0 +1,31 @@
- type: entity
parent: BaseStructure
id: WeaponTurretSyndicateBroken
name: ballistic turret (broken)
description: A ballistic machine gun auto-turret.
components:
- type: Clickable
- type: InteractionOutline
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/turrets.rsi
drawdepth: Mobs
layers:
- state: syndie_broken
- type: Damageable
damageContainer: Inorganic
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 450
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalGlassBreak
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel1:
min: 2
max: 4

View File

@@ -1,259 +0,0 @@
- type: entity
parent: BaseStructure
id: WeaponTurretSyndicateBroken
name: ballistic turret (broken)
description: A ballistic machine gun auto-turret.
components:
- type: Clickable
- type: InteractionOutline
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/turrets.rsi
drawdepth: Mobs
layers:
- state: syndie_broken
- type: Damageable
damageContainer: Inorganic
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 450
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalGlassBreak
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel1:
min: 2
max: 4
- type: entity
parent: BaseStructure
id: BaseWeaponTurret
name: ballistic turret
abstract: true
components:
- type: Clickable
- type: InteractionOutline
- type: Actions
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.45,-0.45,0.45,0.45"
density: 60
mask:
- MachineMask
layer:
- MachineLayer
- type: ContainerContainer
containers:
ballistic-ammo: !type:Container
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/turrets.rsi
drawdepth: Mobs
layers:
- state: syndie_lethal
- type: InteractionPopup
interactDelay: 0.2
successChance: 0.8
interactSuccessString: petting-success-generic
interactFailureString: petting-failure-generic
interactSuccessSound:
path: /Audio/Effects/double_beep.ogg
- type: CombatMode
toggleMouseRotator: false
- type: Damageable
damageContainer: Inorganic
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 600
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTrigger
damage: 300
# TODO: Construction graph
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
collection: MetalGlassBreak
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel1:
min: 3
max: 5
- type: Gun
fireRate: 6
selectedMode: FullAuto
availableModes:
- FullAuto
soundGunshot: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg
# TODO: Power ammo provider?
- type: BallisticAmmoProvider
proto: CartridgeCaselessRifle
capacity: 500
- type: HTN
rootTask:
task: TurretCompound
blackboard:
RotateSpeed: !type:Single
3.141
SoundTargetInLOS: !type:SoundPathSpecifier
path: /Audio/Effects/double_beep.ogg
- type: MouseRotator
angleTolerance: 5
rotationSpeed: 180
simple4DirMode: false
- type: NoRotateOnInteract
- type: NoRotateOnMove
- type: Input
context: "human"
- type: entity
parent: [BaseWeaponTurret, BaseSyndicateContraband]
id: WeaponTurretSyndicate
suffix: Syndicate
components:
- type: NpcFactionMember
factions:
- Syndicate
- type: entity
parent: BaseWeaponTurret
name: disposable ballistic turret
id: WeaponTurretSyndicateDisposable
suffix: Syndicate, Disposable
components:
- type: NpcFactionMember
factions:
- Syndicate
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 600
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:TriggerBehavior
- type: Gun
fireRate: 2
selectedMode: FullAuto
availableModes:
- FullAuto
soundGunshot: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg
- type: BallisticAmmoProvider
proto: CartridgePistol
capacity: 50
- type: Construction
deconstructionTarget: null
graph: WeaponTurretSyndicateDisposable
node: disposableTurret
- type: Repairable
qualityNeeded: "Anchoring"
doAfterDelay: 3
- type: TriggerWhenEmpty
- type: ExplodeOnTrigger
- type: Explosive
explosionType: Default
maxIntensity: 10
intensitySlope: 1.5
totalIntensity: 30
canCreateVacuum: false
- type: entity
parent: BaseWeaponTurret
id: WeaponTurretNanoTrasen
suffix: NanoTrasen
components:
- type: NpcFactionMember
factions:
- NanoTrasen
- type: entity
parent: BaseWeaponTurret
id: WeaponTurretHostile
suffix: Hostile
components:
- type: NpcFactionMember
factions:
- SimpleHostile
- type: entity
parent: BaseWeaponTurret
id: WeaponTurretAllHostile
suffix: All hostile
components:
- type: NpcFactionMember
factions:
- AllHostile
- type: entity
name: xeno turret
description: Shoots 9mm acid projectiles.
parent: BaseWeaponTurret
id: WeaponTurretXeno
suffix: Xeno
components:
- type: NpcFactionMember
factions:
- Xeno
- type: Sprite
sprite: Objects/Weapons/Guns/Turrets/xenoturret.rsi
noRot: true
layers:
- state: acid_turret
- type: BallisticAmmoProvider
proto: BulletAcid
capacity: 500
- type: Gun
fireRate: 1
selectedMode: FullAuto
soundGunshot: /Audio/Weapons/Xeno/alien_spitacid.ogg
- type: HTN
rootTask:
task: TurretCompound
blackboard:
SoundTargetInLOS: !type:SoundPathSpecifier
path: /Audio/Animals/snake_hiss.ogg
- type: Damageable
damageContainer: Biological
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/gib1.ogg
- !type:SpawnEntitiesBehavior
spawn:
FoodMeatXeno:
min: 3
max: 5
- type: InteractionPopup
interactDelay: 1.0
successChance: 0.8
interactSuccessString: petting-success-generic
interactFailureString: petting-failure-generic
interactSuccessSound:
path: /Audio/Animals/snake_hiss.ogg