Skip to content

Commit

Permalink
Rework the HoS's Energy Shotgun (Varying energy consumption depending…
Browse files Browse the repository at this point in the history
… on fire-mode + re-adds a toned down self recharge.) (space-wizards#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 <[email protected]>

* 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 <[email protected]>
Co-authored-by: metalgearsloth <[email protected]>
  • Loading branch information
3 people authored Dec 11, 2024
1 parent 5ba868a commit ce9fc82
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 11 deletions.
6 changes: 6 additions & 0 deletions Content.Client/Weapons/Ranged/Systems/GunSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public override void Initialize()
base.Initialize();
UpdatesOutsidePrediction = true;
SubscribeLocalEvent<AmmoCounterComponent, ItemStatusCollectMessage>(OnAmmoCounterCollect);
SubscribeLocalEvent<AmmoCounterComponent, UpdateClientAmmoEvent>(OnUpdateClientAmmo);
SubscribeAllEvent<MuzzleFlashEvent>(OnMuzzleFlash);

// Plays animated effects on the client.
Expand All @@ -86,6 +87,11 @@ public override void Initialize()
InitializeSpentAmmo();
}

private void OnUpdateClientAmmo(EntityUid uid, AmmoCounterComponent ammoComp, ref UpdateClientAmmoEvent args)
{
UpdateAmmoCount(uid, ammoComp);
}

private void OnMuzzleFlash(MuzzleFlashEvent args)
{
var gunUid = GetEntity(args.Uid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ private void AddTricksVerbs(GetVerbsEvent<Verb> args)
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"),
Expand Down Expand Up @@ -603,6 +604,7 @@ private void AddTricksVerbs(GetVerbsEvent<Verb> args)

recharger.AutoRecharge = true;
recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
recharger.AutoRechargePause = false; // No delay.
}
},
Impact = LogImpact.Extreme,
Expand Down
27 changes: 25 additions & 2 deletions Content.Server/Power/Components/BatterySelfRechargerComponent.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;

namespace Content.Server.Power.Components
{
/// <summary>
Expand All @@ -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;

/// <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;

[ViewVariables(VVAccess.ReadWrite)] [DataField("autoRechargeRate")] public float AutoRechargeRate { get; set; }
/// <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);
}
}
54 changes: 54 additions & 0 deletions Content.Server/Power/EntitySystems/BatterySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
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();
Expand Down Expand Up @@ -84,6 +88,14 @@ public override void Update(float frameTime)
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);
}
}
Expand All @@ -100,6 +112,8 @@ private void OnEmpPulse(EntityUid uid, BatteryComponent component, ref EmpPulseE
{
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)
Expand All @@ -110,6 +124,10 @@ public float UseCharge(EntityUid uid, float value, BatteryComponent? battery = n
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;
Expand Down Expand Up @@ -139,11 +157,47 @@ public void SetCharge(EntityUid uid, float value, BatteryComponent? battery = nu
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.
Expand Down
4 changes: 4 additions & 0 deletions Content.Shared/Weapons/Ranged/Events/UpdateClientAmmoEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Content.Shared.Weapons.Ranged.Events;

[ByRefEvent]
public readonly record struct UpdateClientAmmoEvent();
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;
Expand Down Expand Up @@ -99,13 +100,21 @@ private void SetFireMode(EntityUid uid, BatteryWeaponFireModesComponent componen
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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

0 comments on commit ce9fc82

Please sign in to comment.