Gun + PKA fixes (#16244)
This commit is contained in:
@@ -62,7 +62,9 @@ public sealed partial class GunSystem
|
||||
// share as much code as possible
|
||||
if (!Timing.IsFirstTimePredicted ||
|
||||
!TryComp<AmmoCounterComponent>(uid, out var clientComp))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateAmmoCount(uid, clientComp);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
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
|
||||
/// no special behavior like cycling, magazine
|
||||
/// </summary>
|
||||
[RegisterComponent, AutoGenerateComponentState]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class BasicEntityAmmoProviderComponent : AmmoProviderComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,12 @@ public abstract partial class SharedGunSystem
|
||||
{
|
||||
protected virtual void InitializeBasicEntity()
|
||||
{
|
||||
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, ComponentInit>(OnBasicEntityInit);
|
||||
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, MapInitEvent>(OnBasicEntityMapInit);
|
||||
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, TakeAmmoEvent>(OnBasicEntityTakeAmmo);
|
||||
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)
|
||||
{
|
||||
@@ -26,7 +26,7 @@ public abstract partial class SharedGunSystem
|
||||
|
||||
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)
|
||||
return;
|
||||
@@ -40,6 +40,7 @@ public abstract partial class SharedGunSystem
|
||||
args.Ammo.Add((ent, EnsureComp<AmmoComponent>(ent)));
|
||||
}
|
||||
|
||||
_recharge.Reset(uid);
|
||||
UpdateBasicEntityAppearance(uid, component);
|
||||
Dirty(component);
|
||||
}
|
||||
@@ -73,6 +74,7 @@ public abstract partial class SharedGunSystem
|
||||
component.Count = count;
|
||||
Dirty(component);
|
||||
UpdateBasicEntityAppearance(uid, component);
|
||||
UpdateAmmoCount(uid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
[Dependency] protected readonly DamageableSystem Damageable = default!;
|
||||
[Dependency] protected readonly ExamineSystemShared Examine = default!;
|
||||
[Dependency] private readonly ItemSlotsSystem _slots = default!;
|
||||
[Dependency] private readonly RechargeBasicEntityAmmoSystem _recharge = default!;
|
||||
[Dependency] protected readonly SharedActionsSystem Actions = default!;
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] private readonly SharedCombatModeSystem _combatMode = default!;
|
||||
@@ -243,6 +244,9 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
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.
|
||||
// Don't do this in the loop so we still reset NextFire.
|
||||
switch (gun.SelectedMode)
|
||||
@@ -288,7 +292,6 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
// May cause prediction issues? Needs more tweaking
|
||||
gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
|
||||
Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
|
||||
Dirty(gun);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
sprite: Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi
|
||||
size: 30
|
||||
- type: Gun
|
||||
fireRate: 1
|
||||
fireRate: 0.75
|
||||
selectedMode: SemiAuto
|
||||
availableModes:
|
||||
- SemiAuto
|
||||
@@ -24,8 +24,7 @@
|
||||
True: { visible: False }
|
||||
False: { visible: True }
|
||||
- type: RechargeBasicEntityAmmo
|
||||
minRechargeCooldown: 1.5
|
||||
maxRechargeCooldown: 1.5
|
||||
rechargeCooldown: 1
|
||||
rechargeSound:
|
||||
path: /Audio/Weapons/Guns/MagIn/kinetic_reload.ogg
|
||||
- type: BasicEntityAmmoProvider
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
- type: AmmoCounter
|
||||
# All staves recharge. Wands are not.
|
||||
- type: RechargeBasicEntityAmmo
|
||||
rechargeCooldown: 30
|
||||
- type: Tag
|
||||
tags:
|
||||
- WizardStaff
|
||||
|
||||
Reference in New Issue
Block a user