Gun + PKA fixes (#16244)

This commit is contained in:
metalgearsloth
2023-05-08 22:37:40 +10:00
committed by GitHub
parent 892eb24c51
commit 84e1b6f695
10 changed files with 141 additions and 114 deletions

View File

@@ -62,7 +62,9 @@ public sealed partial class GunSystem
// share as much code as possible // share as much code as possible
if (!Timing.IsFirstTimePredicted || if (!Timing.IsFirstTimePredicted ||
!TryComp<AmmoCounterComponent>(uid, out var clientComp)) !TryComp<AmmoCounterComponent>(uid, out var clientComp))
{
return; return;
}
UpdateAmmoCount(uid, clientComp); UpdateAmmoCount(uid, clientComp);
} }

View File

@@ -1,32 +0,0 @@
using Robust.Shared.Audio;
namespace Content.Server.Weapons.Ranged.Components;
/// <summary>
/// Responsible for handling recharging a basic entity ammo provider over time.
/// </summary>
[RegisterComponent]
public sealed class RechargeBasicEntityAmmoComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("minRechargeCooldown")]
public float MinRechargeCooldown = 30f;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("maxRechargeCooldown")]
public float MaxRechargeCooldown = 45f;
[DataField("rechargeSound")]
public SoundSpecifier RechargeSound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg")
{
Params = AudioParams.Default.WithVolume(-5f)
};
[DataField("accumulatedFrametime")]
public float AccumulatedFrameTime;
/// <summary>
/// Number of seconds until the next recharge.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float NextRechargeTime = 0f;
}

View File

@@ -1,73 +0,0 @@
using Content.Server.Weapons.Ranged.Components;
using Content.Shared.Examine;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Systems;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Random;
namespace Content.Server.Weapons.Ranged.Systems;
public sealed class RechargeBasicEntityAmmoSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedGunSystem _gun = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, ExaminedEvent>(OnExamined);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var (recharge, ammo) in
EntityQuery<RechargeBasicEntityAmmoComponent, BasicEntityAmmoProviderComponent>())
{
if (ammo.Count is null || ammo.Count == ammo.Capacity)
continue;
recharge.AccumulatedFrameTime += frameTime;
if (recharge.AccumulatedFrameTime < recharge.NextRechargeTime)
continue;
recharge.AccumulatedFrameTime -= recharge.NextRechargeTime;
UpdateCooldown(recharge);
if (_gun.UpdateBasicEntityAmmoCount(ammo.Owner, ammo.Count.Value + 1, ammo))
{
SoundSystem.Play(recharge.RechargeSound.GetSound(), Filter.Pvs(recharge.Owner), recharge.Owner,
recharge.RechargeSound.Params);
}
}
}
private void OnInit(EntityUid uid, RechargeBasicEntityAmmoComponent component, ComponentInit args)
{
UpdateCooldown(component);
}
private void OnExamined(EntityUid uid, RechargeBasicEntityAmmoComponent component, ExaminedEvent args)
{
if (!TryComp<BasicEntityAmmoProviderComponent>(uid, out var ammo)
|| ammo.Count == ammo.Capacity)
{
args.PushMarkup(Loc.GetString("recharge-basic-entity-ammo-full"));
return;
}
var timeLeft = component.NextRechargeTime - component.AccumulatedFrameTime;
args.PushMarkup(Loc.GetString("recharge-basic-entity-ammo-can-recharge", ("seconds", Math.Round(timeLeft, 1))));
}
private void UpdateCooldown(RechargeBasicEntityAmmoComponent component)
{
component.NextRechargeTime = _random.NextFloat(component.MinRechargeCooldown, component.MaxRechargeCooldown);
}
}

View File

@@ -1,6 +1,5 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Weapons.Ranged.Components; namespace Content.Shared.Weapons.Ranged.Components;
@@ -9,7 +8,7 @@ namespace Content.Shared.Weapons.Ranged.Components;
/// Simply provides a certain capacity of entities that cannot be reloaded through normal means and have /// Simply provides a certain capacity of entities that cannot be reloaded through normal means and have
/// no special behavior like cycling, magazine /// no special behavior like cycling, magazine
/// </summary> /// </summary>
[RegisterComponent, AutoGenerateComponentState] [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class BasicEntityAmmoProviderComponent : AmmoProviderComponent public sealed partial class BasicEntityAmmoProviderComponent : AmmoProviderComponent
{ {
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]

View File

@@ -0,0 +1,29 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Weapons.Ranged.Components;
/// <summary>
/// Responsible for handling recharging a basic entity ammo provider over time.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class RechargeBasicEntityAmmoComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("rechargeCooldown")]
[AutoNetworkedField]
public float RechargeCooldown = 1.5f;
[DataField("rechargeSound")]
[AutoNetworkedField]
public SoundSpecifier RechargeSound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg")
{
Params = AudioParams.Default.WithVolume(-5f)
};
[ViewVariables(VVAccess.ReadWrite),
DataField("nextCharge", customTypeSerializer:typeof(TimeOffsetSerializer)),
AutoNetworkedField]
public TimeSpan? NextCharge;
}

View File

@@ -0,0 +1,97 @@
using Content.Shared.Examine;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Shared.Weapons.Ranged.Systems;
public sealed class RechargeBasicEntityAmmoSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedGunSystem _gun = default!;
[Dependency] private readonly MetaDataSystem _metadata = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, ExaminedEvent>(OnExamined);
}
private void OnUnpaused(EntityUid uid, RechargeBasicEntityAmmoComponent component, ref EntityUnpausedEvent args)
{
if (component.NextCharge == null)
return;
component.NextCharge = component.NextCharge.Value + args.PausedTime;
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<RechargeBasicEntityAmmoComponent, BasicEntityAmmoProviderComponent>();
while (query.MoveNext(out var uid, out var recharge, out var ammo))
{
if (ammo.Count is null || ammo.Count == ammo.Capacity || recharge.NextCharge == null)
continue;
if (recharge.NextCharge > _timing.CurTime)
continue;
if (_gun.UpdateBasicEntityAmmoCount(uid, ammo.Count.Value + 1, ammo))
{
if (_netManager.IsClient && _timing.IsFirstTimePredicted)
_audio.Play(recharge.RechargeSound, Filter.Local(), uid, true);
}
if (ammo.Count == ammo.Capacity)
{
recharge.NextCharge = null;
Dirty(recharge);
continue;
}
recharge.NextCharge = recharge.NextCharge.Value + TimeSpan.FromSeconds(recharge.RechargeCooldown);
Dirty(recharge);
}
}
private void OnInit(EntityUid uid, RechargeBasicEntityAmmoComponent component, MapInitEvent args)
{
component.NextCharge = _timing.CurTime;
Dirty(component);
}
private void OnExamined(EntityUid uid, RechargeBasicEntityAmmoComponent component, ExaminedEvent args)
{
if (!TryComp<BasicEntityAmmoProviderComponent>(uid, out var ammo)
|| ammo.Count == ammo.Capacity ||
component.NextCharge == null)
{
args.PushMarkup(Loc.GetString("recharge-basic-entity-ammo-full"));
return;
}
var timeLeft = component.NextCharge + _metadata.GetPauseTime(uid) - _timing.CurTime;
args.PushMarkup(Loc.GetString("recharge-basic-entity-ammo-can-recharge", ("seconds", Math.Round(timeLeft.Value.TotalSeconds, 1))));
}
public void Reset(EntityUid uid, RechargeBasicEntityAmmoComponent? recharge = null)
{
if (!Resolve(uid, ref recharge, false))
return;
if (recharge.NextCharge == null || recharge.NextCharge < _timing.CurTime)
{
recharge.NextCharge = _timing.CurTime + TimeSpan.FromSeconds(recharge.RechargeCooldown);
Dirty(recharge);
}
}
}

View File

@@ -8,12 +8,12 @@ public abstract partial class SharedGunSystem
{ {
protected virtual void InitializeBasicEntity() protected virtual void InitializeBasicEntity()
{ {
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, ComponentInit>(OnBasicEntityInit); SubscribeLocalEvent<BasicEntityAmmoProviderComponent, MapInitEvent>(OnBasicEntityMapInit);
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, TakeAmmoEvent>(OnBasicEntityTakeAmmo); SubscribeLocalEvent<BasicEntityAmmoProviderComponent, TakeAmmoEvent>(OnBasicEntityTakeAmmo);
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, GetAmmoCountEvent>(OnBasicEntityAmmoCount); SubscribeLocalEvent<BasicEntityAmmoProviderComponent, GetAmmoCountEvent>(OnBasicEntityAmmoCount);
} }
private void OnBasicEntityInit(EntityUid uid, BasicEntityAmmoProviderComponent component, ComponentInit args) private void OnBasicEntityMapInit(EntityUid uid, BasicEntityAmmoProviderComponent component, MapInitEvent args)
{ {
if (component.Count is null) if (component.Count is null)
{ {
@@ -26,7 +26,7 @@ public abstract partial class SharedGunSystem
private void OnBasicEntityTakeAmmo(EntityUid uid, BasicEntityAmmoProviderComponent component, TakeAmmoEvent args) private void OnBasicEntityTakeAmmo(EntityUid uid, BasicEntityAmmoProviderComponent component, TakeAmmoEvent args)
{ {
for (int i = 0; i < args.Shots; i++) for (var i = 0; i < args.Shots; i++)
{ {
if (component.Count <= 0) if (component.Count <= 0)
return; return;
@@ -40,6 +40,7 @@ public abstract partial class SharedGunSystem
args.Ammo.Add((ent, EnsureComp<AmmoComponent>(ent))); args.Ammo.Add((ent, EnsureComp<AmmoComponent>(ent)));
} }
_recharge.Reset(uid);
UpdateBasicEntityAppearance(uid, component); UpdateBasicEntityAppearance(uid, component);
Dirty(component); Dirty(component);
} }
@@ -73,6 +74,7 @@ public abstract partial class SharedGunSystem
component.Count = count; component.Count = count;
Dirty(component); Dirty(component);
UpdateBasicEntityAppearance(uid, component); UpdateBasicEntityAppearance(uid, component);
UpdateAmmoCount(uid);
return true; return true;
} }

View File

@@ -41,6 +41,7 @@ public abstract partial class SharedGunSystem : EntitySystem
[Dependency] protected readonly DamageableSystem Damageable = default!; [Dependency] protected readonly DamageableSystem Damageable = default!;
[Dependency] protected readonly ExamineSystemShared Examine = default!; [Dependency] protected readonly ExamineSystemShared Examine = default!;
[Dependency] private readonly ItemSlotsSystem _slots = default!; [Dependency] private readonly ItemSlotsSystem _slots = default!;
[Dependency] private readonly RechargeBasicEntityAmmoSystem _recharge = default!;
[Dependency] protected readonly SharedActionsSystem Actions = default!; [Dependency] protected readonly SharedActionsSystem Actions = default!;
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!; [Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
[Dependency] private readonly SharedCombatModeSystem _combatMode = default!; [Dependency] private readonly SharedCombatModeSystem _combatMode = default!;
@@ -243,6 +244,9 @@ public abstract partial class SharedGunSystem : EntitySystem
shots++; shots++;
} }
// NextFire has been touched regardless so need to dirty the gun.
Dirty(gun);
// Get how many shots we're actually allowed to make, due to clip size or otherwise. // Get how many shots we're actually allowed to make, due to clip size or otherwise.
// Don't do this in the loop so we still reset NextFire. // Don't do this in the loop so we still reset NextFire.
switch (gun.SelectedMode) switch (gun.SelectedMode)
@@ -288,7 +292,6 @@ public abstract partial class SharedGunSystem : EntitySystem
// May cause prediction issues? Needs more tweaking // May cause prediction issues? Needs more tweaking
gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds)); gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
Audio.PlayPredicted(gun.SoundEmpty, gunUid, user); Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
Dirty(gun);
return; return;
} }

View File

@@ -9,7 +9,7 @@
sprite: Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi sprite: Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi
size: 30 size: 30
- type: Gun - type: Gun
fireRate: 1 fireRate: 0.75
selectedMode: SemiAuto selectedMode: SemiAuto
availableModes: availableModes:
- SemiAuto - SemiAuto
@@ -24,8 +24,7 @@
True: { visible: False } True: { visible: False }
False: { visible: True } False: { visible: True }
- type: RechargeBasicEntityAmmo - type: RechargeBasicEntityAmmo
minRechargeCooldown: 1.5 rechargeCooldown: 1
maxRechargeCooldown: 1.5
rechargeSound: rechargeSound:
path: /Audio/Weapons/Guns/MagIn/kinetic_reload.ogg path: /Audio/Weapons/Guns/MagIn/kinetic_reload.ogg
- type: BasicEntityAmmoProvider - type: BasicEntityAmmoProvider

View File

@@ -16,6 +16,7 @@
- type: AmmoCounter - type: AmmoCounter
# All staves recharge. Wands are not. # All staves recharge. Wands are not.
- type: RechargeBasicEntityAmmo - type: RechargeBasicEntityAmmo
rechargeCooldown: 30
- type: Tag - type: Tag
tags: tags:
- WizardStaff - WizardStaff