ninja hotfixes (#20032)

* check that slot is power cell slot

* add BatteryChangedEvent

* use BatteryChangedEvent when enabling gloves and replacing battery

* sort gloves dependencies

* increase stun duration and cooldown

* play sound when stunning people

* remove dirty for non networked field

* NinjaBatteryChangedEvent

* real

* fake

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-09-12 21:54:18 +01:00
committed by GitHub
parent ef869b1cff
commit b53e5d6661
6 changed files with 58 additions and 11 deletions

View File

@@ -0,0 +1,7 @@
namespace Content.Server.Ninja.Events;
/// <summary>
/// Raised on the ninja when the suit has its powercell changed.
/// </summary>
[ByRefEvent]
public record struct NinjaBatteryChangedEvent(EntityUid Battery, EntityUid BatteryHolder);

View File

@@ -1,3 +1,4 @@
using Content.Server.Ninja.Events;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.DoAfter;
@@ -24,6 +25,7 @@ public sealed class BatteryDrainerSystem : SharedBatteryDrainerSystem
base.Initialize();
SubscribeLocalEvent<BatteryDrainerComponent, BeforeInteractHandEvent>(OnBeforeInteractHand);
SubscribeLocalEvent<BatteryDrainerComponent, NinjaBatteryChangedEvent>(OnBatteryChanged);
}
/// <summary>
@@ -56,6 +58,11 @@ public sealed class BatteryDrainerSystem : SharedBatteryDrainerSystem
_doAfter.TryStartDoAfter(doAfterArgs);
}
private void OnBatteryChanged(EntityUid uid, BatteryDrainerComponent comp, ref NinjaBatteryChangedEvent args)
{
SetBattery(uid, args.Battery, comp);
}
/// <inheritdoc/>
protected override void OnDoAfterAttempt(EntityUid uid, BatteryDrainerComponent comp, DoAfterAttemptEvent<DrainDoAfterEvent> args)
{

View File

@@ -1,7 +1,7 @@
using Content.Server.Communications;
using Content.Server.DoAfter;
using Content.Server.Mind;
using Content.Server.Ninja.Systems;
using Content.Server.Ninja.Events;
using Content.Server.Power.Components;
using Content.Server.Roles;
using Content.Shared.Communications;
@@ -22,11 +22,10 @@ namespace Content.Server.Ninja.Systems;
public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
{
[Dependency] private readonly EmagProviderSystem _emagProvider = default!;
[Dependency] private readonly SharedBatteryDrainerSystem _drainer = default!;
[Dependency] private readonly SharedStunProviderSystem _stunProvider = default!;
[Dependency] private readonly SpaceNinjaSystem _ninja = default!;
[Dependency] private readonly CommsHackerSystem _commsHacker = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly SharedStunProviderSystem _stunProvider = default!;
[Dependency] private readonly SpaceNinjaSystem _ninja = default!;
public override void Initialize()
{
@@ -73,6 +72,10 @@ public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
private void EnableGloves(EntityUid uid, NinjaGlovesComponent comp, EntityUid user, SpaceNinjaComponent ninja)
{
// can't use abilities if suit is not equipped, this is checked elsewhere but just making sure to satisfy nullability
if (ninja.Suit == null)
return;
comp.User = user;
Dirty(uid, comp);
_ninja.AssignGloves(user, uid, ninja);
@@ -82,8 +85,8 @@ public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
_stunProvider.SetNoPowerPopup(user, "ninja-no-power", stun);
if (_ninja.GetNinjaBattery(user, out var battery, out var _))
{
_drainer.SetBattery(user, battery, drainer);
_stunProvider.SetBattery(user, battery, stun);
var ev = new NinjaBatteryChangedEvent(battery.Value, ninja.Suit.Value);
RaiseLocalEvent(user, ref ev);
}
var emag = EnsureComp<EmagProviderComponent>(user);

View File

@@ -1,4 +1,5 @@
using Content.Server.Emp;
using Content.Server.Ninja.Events;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.PowerCell;
@@ -8,6 +9,7 @@ using Content.Shared.Hands.EntitySystems;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
using Content.Shared.Popups;
using Content.Shared.PowerCell.Components;
using Robust.Shared.Containers;
namespace Content.Server.Ninja.Systems;
@@ -47,6 +49,11 @@ public sealed class NinjaSuitSystem : SharedNinjaSuitSystem
// TODO: or put MaxCharge in shared along with powercellslot
private void OnSuitInsertAttempt(EntityUid uid, NinjaSuitComponent comp, ContainerIsInsertingAttemptEvent args)
{
// this is for handling battery upgrading, not stopping actions from being added
// if another container like ActionsContainer is specified, don't handle it
if (TryComp<PowerCellSlotComponent>(uid, out var slot) && args.Container.ID != slot.CellSlotId)
return;
// no power cell for some reason??? allow it
if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery))
return;
@@ -57,7 +64,13 @@ public sealed class NinjaSuitSystem : SharedNinjaSuitSystem
args.Cancel();
}
// TODO: raise event on ninja telling it to update battery
// tell ninja abilities that use battery to update it so they don't use charge from the old one
var user = Transform(uid).ParentUid;
if (!HasComp<SpaceNinjaComponent>(user))
return;
var ev = new NinjaBatteryChangedEvent(args.EntityUid, uid);
RaiseLocalEvent(user, ref ev);
}
private void OnEmpAttempt(EntityUid uid, NinjaSuitComponent comp, EmpAttemptEvent args)

View File

@@ -1,10 +1,12 @@
using Content.Server.Ninja.Events;
using Content.Server.Power.EntitySystems;
using Content.Shared.Electrocution;
using Content.Shared.Interaction;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
using Content.Shared.Popups;
using Content.Shared.Whitelist;
using Content.Server.Power.EntitySystems;
using Robust.Shared.Audio;
using Robust.Shared.Timing;
namespace Content.Server.Ninja.Systems;
@@ -16,6 +18,7 @@ public sealed class StunProviderSystem : SharedStunProviderSystem
{
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedElectrocutionSystem _electrocution = default!;
[Dependency] private readonly SharedNinjaGlovesSystem _gloves = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
@@ -25,6 +28,7 @@ public sealed class StunProviderSystem : SharedStunProviderSystem
base.Initialize();
SubscribeLocalEvent<StunProviderComponent, BeforeInteractHandEvent>(OnBeforeInteractHand);
SubscribeLocalEvent<StunProviderComponent, NinjaBatteryChangedEvent>(OnBatteryChanged);
}
/// <summary>
@@ -49,12 +53,18 @@ public sealed class StunProviderSystem : SharedStunProviderSystem
return;
}
_audio.PlayPvs(comp.Sound, target);
// not holding hands with target so insuls don't matter
_electrocution.TryDoElectrocution(target, uid, comp.StunDamage, comp.StunTime, false, ignoreInsulation: true);
// short cooldown to prevent instant stunlocking
comp.NextStun = _timing.CurTime + comp.Cooldown;
Dirty(uid, comp);
args.Handled = true;
}
private void OnBatteryChanged(EntityUid uid, StunProviderComponent comp, ref NinjaBatteryChangedEvent args)
{
SetBattery(uid, args.Battery, comp);
}
}

View File

@@ -1,5 +1,6 @@
using Content.Shared.Ninja.Systems;
using Content.Shared.Whitelist;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
@@ -19,6 +20,12 @@ public sealed partial class StunProviderComponent : Component
[DataField("batteryUid"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public EntityUid? BatteryUid;
/// <summary>
/// Sound played when stunning someone.
/// </summary>
[DataField("sound"), ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier Sound = new SoundCollectionSpecifier("sparks");
/// <summary>
/// Joules required in the battery to stun someone. Defaults to 10 uses on a small battery.
/// </summary>
@@ -35,13 +42,13 @@ public sealed partial class StunProviderComponent : Component
/// Time that someone is stunned for, stacks if done multiple times.
/// </summary>
[DataField("stunTime"), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan StunTime = TimeSpan.FromSeconds(3);
public TimeSpan StunTime = TimeSpan.FromSeconds(5);
/// <summary>
/// How long stunning is disabled after stunning something.
/// </summary>
[DataField("cooldown"), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Cooldown = TimeSpan.FromSeconds(1);
public TimeSpan Cooldown = TimeSpan.FromSeconds(2);
/// <summary>
/// Locale string to popup when there is no power