diff --git a/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs b/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs
index 923a10b22a..30fa84ed90 100644
--- a/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs
+++ b/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs
@@ -1,19 +1,21 @@
namespace Content.Server.Item;
///
-/// Handles whether this item applies a disarm malus when active.
+/// Handles whether this item applies a disarm malus when active.
///
[RegisterComponent]
public sealed partial class ItemToggleDisarmMalusComponent : Component
{
///
/// Item has this modifier to the chance to disarm when activated.
+ /// If null, the value will be inferred from the current malus just before the malus is first deactivated.
///
[ViewVariables(VVAccess.ReadOnly), DataField]
public float? ActivatedDisarmMalus = null;
///
/// Item has this modifier to the chance to disarm when deactivated. If none is mentioned, it uses the item's default disarm modifier.
+ /// If null, the value will be inferred from the current malus just before the malus is first activated.
///
[ViewVariables(VVAccess.ReadOnly), DataField]
public float? DeactivatedDisarmMalus = null;
diff --git a/Content.Server/Item/ItemToggle/Components/ItemToggleSharpComponent.cs b/Content.Server/Item/ItemToggle/Components/ItemToggleSharpComponent.cs
index ea2efae147..227491b16c 100644
--- a/Content.Server/Item/ItemToggle/Components/ItemToggleSharpComponent.cs
+++ b/Content.Server/Item/ItemToggle/Components/ItemToggleSharpComponent.cs
@@ -1,14 +1,9 @@
namespace Content.Server.Item;
///
-/// Handles whether this item is sharp when toggled on.
+/// Handles whether this item is sharp when toggled on.
///
[RegisterComponent]
public sealed partial class ItemToggleSharpComponent : Component
{
- ///
- /// Item can be used to butcher when activated.
- ///
- [ViewVariables(VVAccess.ReadOnly), DataField]
- public bool ActivatedSharp = true;
}
diff --git a/Content.Server/Item/ItemToggle/ItemToggleSystem.cs b/Content.Server/Item/ItemToggle/ItemToggleSystem.cs
index 4507ace9d2..f98415eb08 100644
--- a/Content.Server/Item/ItemToggle/ItemToggleSystem.cs
+++ b/Content.Server/Item/ItemToggle/ItemToggleSystem.cs
@@ -1,9 +1,7 @@
-using Content.Shared.Item;
using Content.Server.CombatMode.Disarm;
using Content.Server.Kitchen.Components;
using Content.Shared.Item.ItemToggle;
using Content.Shared.Item.ItemToggle.Components;
-using ItemToggleComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleComponent;
namespace Content.Server.Item;
@@ -13,47 +11,34 @@ public sealed class ItemToggleSystem : SharedItemToggleSystem
{
base.Initialize();
- SubscribeLocalEvent(Toggle);
+ SubscribeLocalEvent(ToggleSharp);
+ SubscribeLocalEvent(ToggleMalus);
}
- private void Toggle(EntityUid uid, ItemToggleComponent comp, ref ItemToggledEvent args)
+ private void ToggleSharp(Entity ent, ref ItemToggledEvent args)
{
- if (args.Activated == true)
- {
- if (TryComp(uid, out var itemSharpness))
- {
- if (itemSharpness.ActivatedSharp)
- EnsureComp(uid);
- }
-
- if (!TryComp(uid, out var itemToggleDisarmMalus) ||
- !TryComp(uid, out var malus))
- return;
-
- //Default the deactivated DisarmMalus to the item's value before activation happens.
- itemToggleDisarmMalus.DeactivatedDisarmMalus ??= malus.Malus;
-
- if (itemToggleDisarmMalus.ActivatedDisarmMalus != null)
- {
- malus.Malus = (float) itemToggleDisarmMalus.ActivatedDisarmMalus;
- }
- }
+ // TODO generalize this into a "ToggleComponentComponent", though probably with a better name
+ if (args.Activated)
+ EnsureComp(ent);
else
+ RemCompDeferred(ent);
+ }
+
+ private void ToggleMalus(Entity ent, ref ItemToggledEvent args)
+ {
+ if (!TryComp(ent, out var malus))
+ return;
+
+ if (args.Activated)
{
- if (TryComp(uid, out var itemSharpness))
- {
- if (itemSharpness.ActivatedSharp)
- RemCompDeferred(uid);
- }
-
- if (!TryComp(uid, out var itemToggleDisarmMalus) ||
- !TryComp(uid, out var malus))
- return;
-
- if (itemToggleDisarmMalus.DeactivatedDisarmMalus != null)
- {
- malus.Malus = (float) itemToggleDisarmMalus.DeactivatedDisarmMalus;
- }
+ ent.Comp.DeactivatedDisarmMalus ??= malus.Malus;
+ if (ent.Comp.ActivatedDisarmMalus is {} activatedMalus)
+ malus.Malus = activatedMalus;
+ return;
}
+
+ ent.Comp.ActivatedDisarmMalus ??= malus.Malus;
+ if (ent.Comp.DeactivatedDisarmMalus is {} deactivatedMalus)
+ malus.Malus = deactivatedMalus;
}
}
diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs
index 5f019490b5..c1782efaba 100644
--- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs
+++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs
@@ -58,10 +58,7 @@ namespace Content.Server.Stunnable.Systems
private void ToggleDone(Entity entity, ref ItemToggledEvent args)
{
- if (!TryComp(entity, out var item))
- return;
-
- _item.SetHeldPrefix(entity.Owner, args.Activated ? "on" : "off", component: item);
+ _item.SetHeldPrefix(entity.Owner, args.Activated ? "on" : "off");
}
private void TryTurnOn(Entity entity, ref ItemToggleActivateAttemptEvent args)
diff --git a/Content.Server/Tools/ToolSystem.Welder.cs b/Content.Server/Tools/ToolSystem.Welder.cs
index 1eabd6c6d2..727526b398 100644
--- a/Content.Server/Tools/ToolSystem.Welder.cs
+++ b/Content.Server/Tools/ToolSystem.Welder.cs
@@ -7,7 +7,6 @@ using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
-using Content.Shared.Item;
using Content.Shared.Item.ItemToggle;
using Content.Shared.Tools.Components;
using Robust.Shared.GameStates;
@@ -32,8 +31,8 @@ namespace Content.Server.Tools
SubscribeLocalEvent>(OnWelderToolUseAttempt);
SubscribeLocalEvent(OnWelderShutdown);
SubscribeLocalEvent(OnWelderGetState);
- SubscribeLocalEvent(TryTurnOn);
- SubscribeLocalEvent(TurnOff);
+ SubscribeLocalEvent(OnToggle);
+ SubscribeLocalEvent(OnActivateAttempt);
}
public (FixedPoint2 fuel, FixedPoint2 capacity) GetWelderFuelAndCapacity(EntityUid uid, WelderComponent? welder = null, SolutionContainerManagerComponent? solutionContainer = null)
@@ -45,55 +44,54 @@ namespace Content.Server.Tools
return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume);
}
- public void TryTurnOn(Entity entity, ref ItemToggleActivateAttemptEvent args)
+ private void OnToggle(Entity entity, ref ItemToggledEvent args)
{
- if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var solution) ||
- !TryComp(entity, out var transform))
+ if (args.Activated)
+ TurnOn(entity, args.User);
+ else
+ TurnOff(entity, args.User);
+ }
+
+ private void OnActivateAttempt(Entity entity, ref ItemToggleActivateAttemptEvent args)
+ {
+ if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var solution))
{
args.Cancelled = true;
+ args.Popup = Loc.GetString("welder-component-no-fuel-message");
return;
}
var fuel = solution.GetTotalPrototypeQuantity(entity.Comp.FuelReagent);
-
- // Not enough fuel to lit welder.
if (fuel == FixedPoint2.Zero || fuel < entity.Comp.FuelLitCost)
{
- if (args.User != null)
- {
- _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-message"), entity, (EntityUid) args.User);
- }
+ args.Popup = Loc.GetString("welder-component-no-fuel-message");
args.Cancelled = true;
- return;
}
+ }
+
+ public void TurnOn(Entity entity, EntityUid? user)
+ {
+ if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution))
+ return;
_solutionContainer.RemoveReagent(entity.Comp.FuelSolution.Value, entity.Comp.FuelReagent, entity.Comp.FuelLitCost);
+ AdminLogger.Add(LogType.InteractActivate, LogImpact.Low,
+ $"{ToPrettyString(user):user} toggled {ToPrettyString(entity.Owner):welder} on");
- // Logging
- AdminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(entity.Owner):welder} on");
-
- _ignitionSource.SetIgnited(entity.Owner);
-
- if (transform.GridUid is { } gridUid)
+ var xform = Transform(entity);
+ if (xform.GridUid is { } gridUid)
{
- var position = _transformSystem.GetGridOrMapTilePosition(entity.Owner, transform);
+ var position = _transformSystem.GetGridOrMapTilePosition(entity.Owner, xform);
_atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, entity.Owner, true);
}
- Dirty(entity);
-
_activeWelders.Add(entity);
}
- public void TurnOff(Entity entity, ref ItemToggleDeactivateAttemptEvent args)
+ public void TurnOff(Entity entity, EntityUid? user)
{
- // Logging
- AdminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(entity.Owner):welder} off");
-
- _ignitionSource.SetIgnited(entity.Owner, false);
-
- Dirty(entity);
-
+ AdminLogger.Add(LogType.InteractActivate, LogImpact.Low,
+ $"{ToPrettyString(user):user} toggled {ToPrettyString(entity.Owner):welder} off");
_activeWelders.Remove(entity);
}
@@ -186,7 +184,9 @@ namespace Content.Server.Tools
if (_welderTimer < WelderUpdateTimer)
return;
- // TODO Use an "active welder" component instead, EntityQuery over that.
+ // TODO Serialization. _activeWelders is not serialized.
+ // Need to use some "active" component, and EntityQuery over that.
+ // Probably best to generalize it to a "ToggleableFuelDrain" component.
foreach (var tool in _activeWelders.ToArray())
{
if (!TryComp(tool, out WelderComponent? welder)
diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs
index 3ea80ec735..620ddfd194 100644
--- a/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs
@@ -16,7 +16,7 @@ public sealed partial class ItemToggleComponent : Component
///
/// The item's toggle state.
///
- [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ [DataField, AutoNetworkedField]
public bool Activated = false;
///
@@ -45,6 +45,12 @@ public sealed partial class ItemToggleComponent : Component
///
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public SoundSpecifier? SoundFailToActivate;
+
+ ///
+ /// Whether or not to toggle the entity's lights on or off.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public bool ToggleLight = true;
}
///
@@ -55,6 +61,11 @@ public record struct ItemToggleActivateAttemptEvent(EntityUid? User)
{
public bool Cancelled = false;
public readonly EntityUid? User = User;
+
+ ///
+ /// Pop-up that gets shown to users explaining why the attempt was cancelled.
+ ///
+ public string? Popup { get; set; }
}
///
@@ -77,21 +88,3 @@ public readonly record struct ItemToggledEvent(bool Predicted, bool Activated, E
public readonly bool Activated = Activated;
public readonly EntityUid? User = User;
}
-
-///
-/// Raised directed on an entity when an itemtoggle is activated.
-///
-[ByRefEvent]
-public readonly record struct ItemToggleActivatedEvent(EntityUid? User)
-{
- public readonly EntityUid? User = User;
-}
-
-///
-/// Raised directed on an entity when an itemtoggle is deactivated.
-///
-[ByRefEvent]
-public readonly record struct ItemToggleDeactivatedEvent(EntityUid? User)
-{
- public readonly EntityUid? User = User;
-}
diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs
index c3eb1d1e58..4bcd6e25c0 100644
--- a/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs
@@ -5,12 +5,7 @@ namespace Content.Shared.Item.ItemToggle.Components;
///
/// Handles whether the item is hot when toggled on.
///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[RegisterComponent, NetworkedComponent]
public sealed partial class ItemToggleHotComponent : Component
{
- ///
- /// Item becomes hot when active.
- ///
- [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
- public bool IsHotWhenActivated = true;
}
diff --git a/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs b/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs
index e2e5fc2e3c..523f67bac3 100644
--- a/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs
+++ b/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs
@@ -1,5 +1,6 @@
using Content.Shared.Interaction.Events;
using Content.Shared.Item.ItemToggle.Components;
+using Content.Shared.Popups;
using Content.Shared.Temperature;
using Content.Shared.Toggleable;
using Content.Shared.Wieldable;
@@ -20,11 +21,13 @@ public abstract class SharedItemToggleSystem : EntitySystem
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedPointLightSystem _light = default!;
[Dependency] private readonly INetManager _netManager = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
+ SubscribeLocalEvent(OnStartup);
SubscribeLocalEvent(TurnOffonUnwielded);
SubscribeLocalEvent(TurnOnonWielded);
SubscribeLocalEvent(OnUseInHand);
@@ -34,6 +37,11 @@ public abstract class SharedItemToggleSystem : EntitySystem
SubscribeLocalEvent(UpdateActiveSound);
}
+ private void OnStartup(Entity ent, ref ComponentStartup args)
+ {
+ UpdateVisuals(ent);
+ }
+
private void OnUseInHand(EntityUid uid, ItemToggleComponent itemToggle, UseInHandEvent args)
{
if (args.Handled)
@@ -73,6 +81,9 @@ public abstract class SharedItemToggleSystem : EntitySystem
if (itemToggle.Activated)
return true;
+ if (!itemToggle.Predictable && _netManager.IsClient)
+ return true;
+
var attempt = new ItemToggleActivateAttemptEvent(user);
RaiseLocalEvent(uid, ref attempt);
@@ -83,12 +94,16 @@ public abstract class SharedItemToggleSystem : EntitySystem
else
_audio.PlayPvs(itemToggle.SoundFailToActivate, uid);
+ if (attempt.Popup != null && user != null)
+ {
+ if (predicted)
+ _popup.PopupClient(attempt.Popup, uid, user.Value);
+ else
+ _popup.PopupEntity(attempt.Popup, uid, user.Value);
+ }
+
return false;
}
- // If the item's toggle is unpredictable because of something like requiring fuel or charge, then clients exit here.
- // Otherwise you get stuff like an item activating client-side and then turning back off when it synchronizes with the server.
- if (predicted == false && _netManager.IsClient)
- return true;
Activate(uid, itemToggle, predicted, user);
@@ -103,6 +118,9 @@ public abstract class SharedItemToggleSystem : EntitySystem
if (!Resolve(uid, ref itemToggle))
return false;
+ if (!itemToggle.Predictable && _netManager.IsClient)
+ return true;
+
if (!itemToggle.Activated)
return true;
@@ -114,10 +132,6 @@ public abstract class SharedItemToggleSystem : EntitySystem
return false;
}
- // If the item's toggle is unpredictable because of something like requiring fuel or charge, then clients exit here.
- if (predicted == false && _netManager.IsClient)
- return true;
-
Deactivate(uid, itemToggle, predicted, user);
return true;
}
@@ -135,7 +149,6 @@ public abstract class SharedItemToggleSystem : EntitySystem
}
var soundToPlay = itemToggle.SoundActivate;
-
if (predicted)
_audio.PlayPredicted(soundToPlay, uid, user);
else
@@ -146,10 +159,8 @@ public abstract class SharedItemToggleSystem : EntitySystem
var toggleUsed = new ItemToggledEvent(predicted, Activated: true, user);
RaiseLocalEvent(uid, ref toggleUsed);
- var activev = new ItemToggleActivatedEvent(user);
- RaiseLocalEvent(uid, ref activev);
-
itemToggle.Activated = true;
+ UpdateVisuals((uid, itemToggle));
Dirty(uid, itemToggle);
}
@@ -158,35 +169,38 @@ public abstract class SharedItemToggleSystem : EntitySystem
///
private void Deactivate(EntityUid uid, ItemToggleComponent itemToggle, bool predicted, EntityUid? user = null)
{
- // TODO: Fix this hardcoding
- TryComp(uid, out AppearanceComponent? appearance);
- _appearance.SetData(uid, ToggleableLightVisuals.Enabled, false, appearance);
- _appearance.SetData(uid, ToggleVisuals.Toggled, false, appearance);
-
- if (_light.TryGetLight(uid, out var light))
- {
- _light.SetEnabled(uid, false, light);
- }
-
var soundToPlay = itemToggle.SoundDeactivate;
-
if (predicted)
_audio.PlayPredicted(soundToPlay, uid, user);
else
_audio.PlayPvs(soundToPlay, uid);
-
// END FIX HARDCODING
var toggleUsed = new ItemToggledEvent(predicted, Activated: false, user);
RaiseLocalEvent(uid, ref toggleUsed);
- var activev = new ItemToggleDeactivatedEvent(user);
- RaiseLocalEvent(uid, ref activev);
-
itemToggle.Activated = false;
+ UpdateVisuals((uid, itemToggle));
Dirty(uid, itemToggle);
}
+ private void UpdateVisuals(Entity ent)
+ {
+ if (TryComp(ent, out AppearanceComponent? appearance))
+ {
+ _appearance.SetData(ent, ToggleVisuals.Toggled, ent.Comp.Activated, appearance);
+
+ if (ent.Comp.ToggleLight)
+ _appearance.SetData(ent, ToggleableLightVisuals.Enabled, ent.Comp.Activated, appearance);
+ }
+
+ if (!ent.Comp.ToggleLight)
+ return;
+
+ if (_light.TryGetLight(ent, out var light))
+ _light.SetEnabled(ent, ent.Comp.Activated, light);
+ }
+
///
/// Used for items that require to be wielded in both hands to activate. For instance the dual energy sword will turn off if not wielded.
///
@@ -218,8 +232,7 @@ public abstract class SharedItemToggleSystem : EntitySystem
///
private void OnIsHotEvent(EntityUid uid, ItemToggleHotComponent itemToggleHot, IsHotEvent args)
{
- if (itemToggleHot.IsHotWhenActivated)
- args.IsHot = IsActivated(uid);
+ args.IsHot |= IsActivated(uid);
}
///