Rework the HoS's Energy Shotgun (Varying energy consumption depending on fire-mode + re-adds a toned down self recharge.) (#32104)
* Rebalance HoS's Energy Shotgun * SLIGHTLY Up the max charge so the gun properly recharges all of its charges, which matters a lot more with the self charge cooldown system. * Prevent recharge cooldown if 0 power is used. * Makes the clientside HUD actually update to reflect the changes in firecost and thus max/current charges. * Properly fix that recharging to just under full issue instead of applying a budget fix to only the eshotgun. * Clean up the client ammo UI fix. * Update the self recharger component to comply with maintainer request. Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Remove code that was made redundant by a hotfix from another PR. * Make the recharge pause on EMP, document things where needed, clean up code as per maintainer request, add a note to make the code better when power is moved to shared. * Fix another internal issue * Code cleanup + fix the rapid recharge verb to remove pause. * cleanup --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -77,6 +77,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
||||
base.Initialize();
|
||||
UpdatesOutsidePrediction = true;
|
||||
SubscribeLocalEvent<AmmoCounterComponent, ItemStatusCollectMessage>(OnAmmoCounterCollect);
|
||||
SubscribeLocalEvent<AmmoCounterComponent, UpdateClientAmmoEvent>(OnUpdateClientAmmo);
|
||||
SubscribeAllEvent<MuzzleFlashEvent>(OnMuzzleFlash);
|
||||
|
||||
// Plays animated effects on the client.
|
||||
@@ -86,6 +87,11 @@ public sealed partial class GunSystem : SharedGunSystem
|
||||
InitializeSpentAmmo();
|
||||
}
|
||||
|
||||
private void OnUpdateClientAmmo(EntityUid uid, AmmoCounterComponent ammoComp, ref UpdateClientAmmoEvent args)
|
||||
{
|
||||
UpdateAmmoCount(uid, ammoComp);
|
||||
}
|
||||
|
||||
private void OnMuzzleFlash(MuzzleFlashEvent args)
|
||||
{
|
||||
var gunUid = GetEntity(args.Uid);
|
||||
|
||||
@@ -204,6 +204,7 @@ public sealed partial class AdminVerbSystem
|
||||
var recharger = EnsureComp<BatterySelfRechargerComponent>(args.Target);
|
||||
recharger.AutoRecharge = true;
|
||||
recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
|
||||
recharger.AutoRechargePause = false; // No delay.
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-infinite-battery-object-description"),
|
||||
@@ -603,6 +604,7 @@ public sealed partial class AdminVerbSystem
|
||||
|
||||
recharger.AutoRecharge = true;
|
||||
recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
|
||||
recharger.AutoRechargePause = false; // No delay.
|
||||
}
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.Power.Components
|
||||
{
|
||||
/// <summary>
|
||||
@@ -6,8 +8,29 @@ namespace Content.Server.Power.Components
|
||||
[RegisterComponent]
|
||||
public sealed partial class BatterySelfRechargerComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("autoRecharge")] public bool AutoRecharge { get; set; }
|
||||
/// <summary>
|
||||
/// Does the entity auto recharge?
|
||||
/// </summary>
|
||||
[DataField] public bool AutoRecharge;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("autoRechargeRate")] public float AutoRechargeRate { get; set; }
|
||||
/// <summary>
|
||||
/// At what rate does the entity automatically recharge?
|
||||
/// </summary>
|
||||
[DataField] public float AutoRechargeRate;
|
||||
|
||||
/// <summary>
|
||||
/// Should this entity stop automatically recharging if a charge is used?
|
||||
/// </summary>
|
||||
[DataField] public bool AutoRechargePause = false;
|
||||
|
||||
/// <summary>
|
||||
/// How long should the entity stop automatically recharging if a charge is used?
|
||||
/// </summary>
|
||||
[DataField] public float AutoRechargePauseTime = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Do not auto recharge if this timestamp has yet to happen, set for the auto recharge pause system.
|
||||
/// </summary>
|
||||
[DataField] public TimeSpan NextAutoRecharge = TimeSpan.FromSeconds(0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,18 @@ using Content.Server.Emp;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Content.Shared.Timing;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Power.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class BatterySystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -84,6 +88,14 @@ namespace Content.Server.Power.EntitySystems
|
||||
while (query.MoveNext(out var uid, out var comp, out var batt))
|
||||
{
|
||||
if (!comp.AutoRecharge) continue;
|
||||
if (batt.IsFullyCharged) continue;
|
||||
|
||||
if (comp.AutoRechargePause)
|
||||
{
|
||||
if (comp.NextAutoRecharge > Timing.CurTime)
|
||||
continue;
|
||||
}
|
||||
|
||||
SetCharge(uid, batt.CurrentCharge + comp.AutoRechargeRate * frameTime, batt);
|
||||
}
|
||||
}
|
||||
@@ -100,6 +112,8 @@ namespace Content.Server.Power.EntitySystems
|
||||
{
|
||||
args.Affected = true;
|
||||
UseCharge(uid, args.EnergyConsumption, component);
|
||||
// Apply a cooldown to the entity's self recharge if needed to avoid it immediately self recharging after an EMP.
|
||||
TrySetChargeCooldown(uid);
|
||||
}
|
||||
|
||||
public float UseCharge(EntityUid uid, float value, BatteryComponent? battery = null)
|
||||
@@ -110,6 +124,10 @@ namespace Content.Server.Power.EntitySystems
|
||||
var newValue = Math.Clamp(0, battery.CurrentCharge - value, battery.MaxCharge);
|
||||
var delta = newValue - battery.CurrentCharge;
|
||||
battery.CurrentCharge = newValue;
|
||||
|
||||
// Apply a cooldown to the entity's self recharge if needed.
|
||||
TrySetChargeCooldown(uid);
|
||||
|
||||
var ev = new ChargeChangedEvent(battery.CurrentCharge, battery.MaxCharge);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
return delta;
|
||||
@@ -139,11 +157,47 @@ namespace Content.Server.Power.EntitySystems
|
||||
battery.CurrentCharge = MathHelper.Clamp(value, 0, battery.MaxCharge);
|
||||
if (MathHelper.CloseTo(battery.CurrentCharge, old) &&
|
||||
!(old != battery.CurrentCharge && battery.CurrentCharge == battery.MaxCharge))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ev = new ChargeChangedEvent(battery.CurrentCharge, battery.MaxCharge);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
}
|
||||
/// <summary>
|
||||
/// Checks if the entity has a self recharge and puts it on cooldown if applicable.
|
||||
/// </summary>
|
||||
public void TrySetChargeCooldown(EntityUid uid, float value = -1)
|
||||
{
|
||||
if (!TryComp<BatterySelfRechargerComponent>(uid, out var batteryself))
|
||||
return;
|
||||
|
||||
if (!batteryself.AutoRechargePause)
|
||||
return;
|
||||
|
||||
// If no answer or a negative is given for value, use the default from AutoRechargePauseTime.
|
||||
if (value < 0)
|
||||
value = batteryself.AutoRechargePauseTime;
|
||||
|
||||
if (Timing.CurTime + TimeSpan.FromSeconds(value) <= batteryself.NextAutoRecharge)
|
||||
return;
|
||||
|
||||
SetChargeCooldown(uid, batteryself.AutoRechargePauseTime, batteryself);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts the entity's self recharge on cooldown for the specified time.
|
||||
/// </summary>
|
||||
public void SetChargeCooldown(EntityUid uid, float value, BatterySelfRechargerComponent? batteryself = null)
|
||||
{
|
||||
if (!Resolve(uid, ref batteryself))
|
||||
return;
|
||||
|
||||
if (value >= 0)
|
||||
batteryself.NextAutoRecharge = Timing.CurTime + TimeSpan.FromSeconds(value);
|
||||
else
|
||||
batteryself.NextAutoRecharge = Timing.CurTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If sufficient charge is available on the battery, use it. Otherwise, don't.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Content.Shared.Weapons.Ranged.Events;
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct UpdateClientAmmoEvent();
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Weapons.Ranged.Systems;
|
||||
@@ -99,13 +100,21 @@ public sealed class BatteryWeaponFireModesSystem : EntitySystem
|
||||
component.CurrentFireMode = index;
|
||||
Dirty(uid, component);
|
||||
|
||||
if (TryComp(uid, out ProjectileBatteryAmmoProviderComponent? projectileBatteryAmmoProvider))
|
||||
if (TryComp(uid, out ProjectileBatteryAmmoProviderComponent? projectileBatteryAmmoProviderComponent))
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<EntityPrototype>(fireMode.Prototype, out var prototype))
|
||||
return;
|
||||
|
||||
projectileBatteryAmmoProvider.Prototype = fireMode.Prototype;
|
||||
projectileBatteryAmmoProvider.FireCost = fireMode.FireCost;
|
||||
// TODO: Have this get the info directly from the batteryComponent when power is moved to shared.
|
||||
var OldFireCost = projectileBatteryAmmoProviderComponent.FireCost;
|
||||
projectileBatteryAmmoProviderComponent.Prototype = fireMode.Prototype;
|
||||
projectileBatteryAmmoProviderComponent.FireCost = fireMode.FireCost;
|
||||
float FireCostDiff = (float)fireMode.FireCost / (float)OldFireCost;
|
||||
projectileBatteryAmmoProviderComponent.Shots = (int)Math.Round(projectileBatteryAmmoProviderComponent.Shots/FireCostDiff);
|
||||
projectileBatteryAmmoProviderComponent.Capacity = (int)Math.Round(projectileBatteryAmmoProviderComponent.Capacity/FireCostDiff);
|
||||
Dirty(uid, projectileBatteryAmmoProviderComponent);
|
||||
var updateClientAmmoEvent = new UpdateClientAmmoEvent();
|
||||
RaiseLocalEvent(uid, ref updateClientAmmoEvent);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
|
||||
@@ -740,15 +740,15 @@
|
||||
path: /Audio/Weapons/Guns/Gunshots/laser_cannon.ogg
|
||||
- type: ProjectileBatteryAmmoProvider
|
||||
proto: BulletLaserSpread
|
||||
fireCost: 100
|
||||
fireCost: 150
|
||||
- type: BatteryWeaponFireModes
|
||||
fireModes:
|
||||
- proto: BulletLaserSpread
|
||||
fireCost: 100
|
||||
fireCost: 150
|
||||
- proto: BulletLaserSpreadNarrow
|
||||
fireCost: 100
|
||||
fireCost: 200
|
||||
- proto: BulletDisablerSmgSpread
|
||||
fireCost: 100
|
||||
fireCost: 120
|
||||
- type: Item
|
||||
size: Large
|
||||
shape:
|
||||
@@ -762,5 +762,10 @@
|
||||
stealGroup: WeaponEnergyShotgun
|
||||
- type: GunRequiresWield #remove when inaccuracy on spreads is fixed
|
||||
- type: Battery
|
||||
maxCharge: 800
|
||||
startingCharge: 800
|
||||
maxCharge: 1200
|
||||
startingCharge: 1200
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 24
|
||||
autoRechargePause: true
|
||||
autoRechargePauseTime: 10
|
||||
Reference in New Issue
Block a user