diff --git a/Content.Client/Items/Systems/ItemToggleSystem.cs b/Content.Client/Items/Systems/ItemToggleSystem.cs
new file mode 100644
index 0000000000..46d6f1b464
--- /dev/null
+++ b/Content.Client/Items/Systems/ItemToggleSystem.cs
@@ -0,0 +1,9 @@
+using Content.Shared.Item.ItemToggle;
+
+namespace Content.Shared.Item;
+
+///
+public sealed class ItemToggleSystem : SharedItemToggleSystem
+{
+
+}
diff --git a/Content.Client/Tools/ToolSystem.cs b/Content.Client/Tools/ToolSystem.cs
index 966f37146e..a305fd5bb2 100644
--- a/Content.Client/Tools/ToolSystem.cs
+++ b/Content.Client/Tools/ToolSystem.cs
@@ -1,7 +1,7 @@
using Content.Client.Items;
using Content.Client.Tools.Components;
using Content.Client.Tools.UI;
-using Content.Shared.Tools;
+using Content.Shared.Item;
using Content.Shared.Tools.Components;
using Robust.Client.GameObjects;
using Robust.Shared.GameStates;
@@ -50,7 +50,7 @@ namespace Content.Client.Tools
private void OnWelderGetStatusMessage(EntityUid uid, WelderComponent component, ItemStatusCollectMessage args)
{
- args.Controls.Add(new WelderStatusControl(component));
+ args.Controls.Add(new WelderStatusControl(component, uid));
}
private void OnWelderHandleState(EntityUid uid, WelderComponent welder, ref ComponentHandleState args)
@@ -60,7 +60,6 @@ namespace Content.Client.Tools
welder.FuelCapacity = state.FuelCapacity;
welder.Fuel = state.Fuel;
- welder.Lit = state.Lit;
welder.UiUpdateNeeded = true;
}
diff --git a/Content.Client/Tools/UI/WelderStatusControl.cs b/Content.Client/Tools/UI/WelderStatusControl.cs
index c8d4df2b8f..8da7a1448b 100644
--- a/Content.Client/Tools/UI/WelderStatusControl.cs
+++ b/Content.Client/Tools/UI/WelderStatusControl.cs
@@ -1,6 +1,7 @@
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Client.Tools.Components;
+using Content.Shared.Item;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
@@ -9,13 +10,19 @@ namespace Content.Client.Tools.UI;
public sealed class WelderStatusControl : Control
{
+ [Dependency] private readonly IEntityManager _entMan = default!;
+
private readonly WelderComponent _parent;
+ private readonly ItemToggleComponent? _toggleComponent;
private readonly RichTextLabel _label;
- public WelderStatusControl(WelderComponent parent)
+ public WelderStatusControl(WelderComponent parent, EntityUid? uid = null)
{
_parent = parent;
- _label = new RichTextLabel {StyleClasses = {StyleNano.StyleClassItemStatus}};
+ _entMan = IoCManager.Resolve();
+ if (_entMan.TryGetComponent(uid, out var itemToggle))
+ _toggleComponent = itemToggle;
+ _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
AddChild(_label);
UpdateDraw();
@@ -39,7 +46,11 @@ public sealed class WelderStatusControl : Control
var fuelCap = _parent.FuelCapacity;
var fuel = _parent.Fuel;
- var lit = _parent.Lit;
+ var lit = false;
+ if (_toggleComponent != null)
+ {
+ lit = _toggleComponent.Activated;
+ }
_label.SetMarkup(Loc.GetString("welder-component-on-examine-detailed-message",
("colorName", fuel < fuelCap / 4f ? "darkorange" : "orange"),
diff --git a/Content.Client/Tools/Visualizers/WelderVisualizerSystem.cs b/Content.Client/Tools/Visualizers/WelderVisualizerSystem.cs
deleted file mode 100644
index 02df7d98b0..0000000000
--- a/Content.Client/Tools/Visualizers/WelderVisualizerSystem.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using Content.Client.Tools.Components;
-using Content.Shared.Tools.Components;
-using Robust.Client.GameObjects;
-
-namespace Content.Client.Tools.Visualizers;
-
-public sealed class WelderVisualizerSystem : VisualizerSystem
-{
- protected override void OnAppearanceChange(EntityUid uid, WelderComponent component, ref AppearanceChangeEvent args)
- {
- if (args.Sprite == null)
- return;
-
- if (AppearanceSystem.TryGetData(uid, WelderVisuals.Lit, out var isLit, args.Component))
- {
- args.Sprite.LayerSetVisible(WelderLayers.Flame, isLit);
- }
- }
-}
diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs
index 6c842f0082..695de4461d 100644
--- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs
+++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs
@@ -10,8 +10,8 @@ using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Construction.Components;
using Content.Server.Gravity;
+using Content.Server.Item;
using Content.Server.Power.Components;
-using Content.Server.Tools.Components;
using Content.Shared.Atmos;
using Content.Shared.Construction.Prototypes;
using Content.Shared.Gravity;
@@ -164,7 +164,7 @@ public abstract partial class InteractionTest
// spawn and pick up the new item
var item = await SpawnEntity(entity, SEntMan.GetCoordinates(PlayerCoords));
- WelderComponent? welder = null;
+ ItemToggleComponent? itemToggle = null;
await Server.WaitPost(() =>
{
@@ -173,14 +173,16 @@ public abstract partial class InteractionTest
Assert.That(HandSys.TryPickup(playerEnt, item, Hands.ActiveHand, false, false, Hands));
// turn on welders
- if (enableWelder && SEntMan.TryGetComponent(item, out welder) && !welder.Lit)
- Assert.That(ToolSys.TryTurnWelderOn(item, playerEnt, welder));
+ if (enableWelder && SEntMan.TryGetComponent(item, out itemToggle) && !itemToggle.Activated)
+ {
+ Assert.That(ItemToggleSys.TryActivate(item, playerEnt, itemToggle: itemToggle));
+ }
});
await RunTicks(1);
Assert.That(Hands.ActiveHandEntity, Is.EqualTo(item));
- if (enableWelder && welder != null)
- Assert.That(welder.Lit);
+ if (enableWelder && itemToggle != null)
+ Assert.That(itemToggle.Activated);
return item;
}
diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs
index 58076454c1..f54d772881 100644
--- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs
+++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs
@@ -12,6 +12,7 @@ using Content.Shared.DoAfter;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
+using Content.Server.Item;
using Content.Shared.Mind;
using Content.Shared.Players;
using Robust.Client.Input;
@@ -23,6 +24,7 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.UnitTesting;
+using Content.Shared.Item.ItemToggle;
namespace Content.IntegrationTests.Tests.Interaction;
@@ -97,6 +99,7 @@ public abstract partial class InteractionTest
protected Content.Server.Construction.ConstructionSystem SConstruction = default!;
protected SharedDoAfterSystem DoAfterSys = default!;
protected ToolSystem ToolSys = default!;
+ protected SharedItemToggleSystem ItemToggleSys = default!;
protected InteractionTestSystem STestSystem = default!;
protected SharedTransformSystem Transform = default!;
protected ISawmill SLogger = default!;
@@ -152,6 +155,7 @@ public abstract partial class InteractionTest
HandSys = SEntMan.System();
InteractSys = SEntMan.System();
ToolSys = SEntMan.System();
+ ItemToggleSys = SEntMan.System();
DoAfterSys = SEntMan.System();
Transform = SEntMan.System();
SConstruction = SEntMan.System();
diff --git a/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs b/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs
index 2abd6fdf86..c12c71a850 100644
--- a/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs
+++ b/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs
@@ -1,6 +1,7 @@
using Content.Server.Administration.Logs;
using Content.Server.Damage.Components;
using Content.Server.Tools.Components;
+using Content.Shared.Item;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Interaction;
@@ -11,7 +12,7 @@ namespace Content.Server.Damage.Systems
public sealed class DamageOnToolInteractSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
- [Dependency] private readonly IAdminLogManager _adminLogger= default!;
+ [Dependency] private readonly IAdminLogManager _adminLogger = default!;
public override void Initialize()
{
@@ -25,16 +26,19 @@ namespace Content.Server.Damage.Systems
if (args.Handled)
return;
+ if (!TryComp(uid, out var itemToggle))
+ return;
+
if (component.WeldingDamage is {} weldingDamage
- && EntityManager.TryGetComponent(args.Used, out WelderComponent? welder)
- && welder.Lit
- && !welder.TankSafe)
+ && EntityManager.TryGetComponent(args.Used, out WelderComponent? welder)
+ && itemToggle.Activated
+ && !welder.TankSafe)
{
var dmg = _damageableSystem.TryChangeDamage(args.Target, weldingDamage, origin: args.User);
if (dmg != null)
_adminLogger.Add(LogType.Damaged,
- $"{ToPrettyString(args.User):user} used {ToPrettyString(args.Used):used} as a welder to deal {dmg.Total:damage} damage to {ToPrettyString(args.Target):target}");
+ $"{ToPrettyString(args.User):user} used {ToPrettyString(args.Used):used} as a welder to deal {dmg.GetTotal():damage} damage to {ToPrettyString(args.Target):target}");
args.Handled = true;
}
@@ -46,7 +50,7 @@ namespace Content.Server.Damage.Systems
if (dmg != null)
_adminLogger.Add(LogType.Damaged,
- $"{ToPrettyString(args.User):user} used {ToPrettyString(args.Used):used} as a tool to deal {dmg.Total:damage} damage to {ToPrettyString(args.Target):target}");
+ $"{ToPrettyString(args.User):user} used {ToPrettyString(args.Used):used} as a tool to deal {dmg.GetTotal():damage} damage to {ToPrettyString(args.Target):target}");
args.Handled = true;
}
diff --git a/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs b/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs
index d31f9eeed6..1b6a5bb930 100644
--- a/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs
+++ b/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs
@@ -1,10 +1,10 @@
-using Content.Shared.Eye.Blinding;
using Content.Shared.StatusEffect;
using Content.Shared.Inventory;
-using Content.Server.Tools;
+using Content.Shared.Item;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Tools.Components;
+using Content.Shared.Item.ItemToggle;
namespace Content.Server.Eye.Blinding.EyeProtection
{
@@ -12,11 +12,13 @@ namespace Content.Server.Eye.Blinding.EyeProtection
{
[Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
[Dependency] private readonly BlindableSystem _blindingSystem = default!;
+ [Dependency] private readonly SharedItemToggleSystem _itemToggle = default!;
+
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnUseAttempt);
- SubscribeLocalEvent(OnWelderToggled);
+ SubscribeLocalEvent(OnWelderToggled);
SubscribeLocalEvent(OnGetProtection);
SubscribeLocalEvent>(OnGetRelayedProtection);
@@ -44,7 +46,7 @@ namespace Content.Server.Eye.Blinding.EyeProtection
var ev = new GetEyeProtectionEvent();
RaiseLocalEvent(args.User, ev);
- var time = (float) (component.StatusEffectTime- ev.Protection).TotalSeconds;
+ var time = (float) (component.StatusEffectTime - ev.Protection).TotalSeconds;
if (time <= 0)
return;
@@ -55,9 +57,9 @@ namespace Content.Server.Eye.Blinding.EyeProtection
_statusEffectsSystem.TryAddStatusEffect(args.User, TemporaryBlindnessSystem.BlindingStatusEffect,
statusTimeSpan, false, TemporaryBlindnessSystem.BlindingStatusEffect);
}
- private void OnWelderToggled(EntityUid uid, RequiresEyeProtectionComponent component, WelderToggledEvent args)
+ private void OnWelderToggled(EntityUid uid, RequiresEyeProtectionComponent component, ItemToggleDoneEvent args)
{
- component.Toggled = args.WelderOn;
+ component.Toggled = _itemToggle.IsActivated(uid);
}
}
}
diff --git a/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs b/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs
new file mode 100644
index 0000000000..923a10b22a
--- /dev/null
+++ b/Content.Server/Item/ItemToggle/Components/ItemToggleDisarmMalusComponent.cs
@@ -0,0 +1,20 @@
+namespace Content.Server.Item;
+
+///
+/// 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.
+ ///
+ [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.
+ ///
+ [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
new file mode 100644
index 0000000000..ea2efae147
--- /dev/null
+++ b/Content.Server/Item/ItemToggle/Components/ItemToggleSharpComponent.cs
@@ -0,0 +1,14 @@
+namespace Content.Server.Item;
+
+///
+/// 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
new file mode 100644
index 0000000000..8a6903dd49
--- /dev/null
+++ b/Content.Server/Item/ItemToggle/ItemToggleSystem.cs
@@ -0,0 +1,57 @@
+using Content.Shared.Item;
+using Content.Server.CombatMode.Disarm;
+using Content.Server.Kitchen.Components;
+using Content.Shared.Item.ItemToggle;
+
+namespace Content.Server.Item;
+
+public sealed class ItemToggleSystem : SharedItemToggleSystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(Toggle);
+ }
+
+ private void Toggle(EntityUid uid, ItemToggleComponent comp, ref ItemToggleDoneEvent 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;
+ }
+ }
+ else
+ {
+ 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;
+ }
+ }
+ }
+}
diff --git a/Content.Server/Item/ItemToggleSystem.cs b/Content.Server/Item/ItemToggleSystem.cs
deleted file mode 100644
index fb72148b88..0000000000
--- a/Content.Server/Item/ItemToggleSystem.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using Content.Server.CombatMode.Disarm;
-using Content.Shared.Interaction;
-using Content.Shared.Interaction.Events;
-using Content.Shared.Item;
-using Content.Shared.Toggleable;
-using Content.Shared.Tools.Components;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Player;
-
-namespace Content.Server.Weapons.Melee.ItemToggle;
-
-public sealed class ItemToggleSystem : EntitySystem
-{
- [Dependency] private readonly SharedItemSystem _item = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent(OnUseInHand);
- SubscribeLocalEvent(OnInteractUsing);
- SubscribeLocalEvent(TurnOff);
- SubscribeLocalEvent(TurnOn);
- }
-
- private void OnUseInHand(EntityUid uid, ItemToggleComponent comp, UseInHandEvent args)
- {
- if (args.Handled)
- return;
-
- args.Handled = true;
-
- if (comp.Activated)
- {
- var ev = new ItemToggleDeactivatedEvent();
- RaiseLocalEvent(uid, ref ev);
- }
- else
- {
- var ev = new ItemToggleActivatedEvent();
- RaiseLocalEvent(uid, ref ev);
- }
-
- UpdateAppearance(uid, comp);
- }
-
- private void TurnOff(EntityUid uid, ItemToggleComponent comp, ref ItemToggleDeactivatedEvent args)
- {
- if (TryComp(uid, out ItemComponent? item))
- _item.SetSize(uid, comp.OffSize, item);
-
- if (TryComp(uid, out var malus))
- malus.Malus -= comp.ActivatedDisarmMalus;
-
- _audio.PlayEntity(comp.DeActivateSound, Filter.Pvs(uid, entityManager: EntityManager), uid, true, comp.DeActivateSound.Params);
-
- comp.Activated = false;
- }
-
- private void TurnOn(EntityUid uid, ItemToggleComponent comp, ref ItemToggleActivatedEvent args)
- {
- if (TryComp(uid, out ItemComponent? item))
- _item.SetSize(uid, comp.OnSize, item);
-
- if (TryComp(uid, out var malus))
- malus.Malus += comp.ActivatedDisarmMalus;
-
- _audio.PlayEntity(comp.ActivateSound, Filter.Pvs(uid, entityManager: EntityManager), uid, true, comp.ActivateSound.Params);
-
- comp.Activated = true;
- }
-
- private void UpdateAppearance(EntityUid uid, ItemToggleComponent component)
- {
- if (!TryComp(uid, out AppearanceComponent? appearanceComponent))
- return;
-
- _appearance.SetData(uid, ToggleableLightVisuals.Enabled, component.Activated, appearanceComponent);
- }
-
- private void OnInteractUsing(EntityUid uid, ItemToggleComponent comp, InteractUsingEvent args)
- {
- if (args.Handled)
- return;
-
- if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.ContainsAny("Pulsing"))
- return;
-
- args.Handled = true;
- }
-}
diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs
index da2391a86b..2ed30d8942 100644
--- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs
+++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs
@@ -2,45 +2,39 @@ using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Power.Events;
using Content.Server.Stunnable.Components;
-using Content.Shared.Audio;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage.Events;
using Content.Shared.Examine;
-using Content.Shared.Interaction.Events;
using Content.Shared.Item;
+using Content.Shared.Item.ItemToggle;
using Content.Shared.Popups;
using Content.Shared.Stunnable;
-using Content.Shared.Toggleable;
-using Robust.Server.GameObjects;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Player;
namespace Content.Server.Stunnable.Systems
{
public sealed class StunbatonSystem : SharedStunbatonSystem
{
[Dependency] private readonly SharedItemSystem _item = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly RiggableSystem _riggableSystem = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly BatterySystem _battery = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly SharedItemToggleSystem _itemToggle = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent(OnUseInHand);
- SubscribeLocalEvent(OnExamined);
+ SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnSolutionChange);
SubscribeLocalEvent(OnStaminaHitAttempt);
+ SubscribeLocalEvent(TryTurnOn);
+ SubscribeLocalEvent(ToggleDone);
}
private void OnStaminaHitAttempt(EntityUid uid, StunbatonComponent component, ref StaminaDamageOnHitAttemptEvent args)
{
- if (!component.Activated ||
- !TryComp(uid, out var battery) || !_battery.TryUseCharge(uid, component.EnergyPerUse, battery))
+ if (!_itemToggle.IsActivated(uid) ||
+ !TryComp(uid, out var battery) || !_battery.TryUseCharge(uid, component.EnergyPerUse, battery))
{
args.Cancelled = true;
return;
@@ -48,93 +42,56 @@ namespace Content.Server.Stunnable.Systems
if (battery.CurrentCharge < component.EnergyPerUse)
{
- _audio.PlayPvs(component.SparksSound, uid, AudioHelpers.WithVariation(0.25f));
- TurnOff(uid, component);
+ _itemToggle.Toggle(uid, predicted: false);
}
}
- private void OnUseInHand(EntityUid uid, StunbatonComponent comp, UseInHandEvent args)
+ private void OnExamined(EntityUid uid, BatteryComponent battery, ExaminedEvent args)
{
- if (comp.Activated)
- {
- TurnOff(uid, comp);
- }
- else
- {
- TurnOn(uid, comp, args.User);
- }
+ var onMsg = _itemToggle.IsActivated(uid)
+ ? Loc.GetString("comp-stunbaton-examined-on")
+ : Loc.GetString("comp-stunbaton-examined-off");
+ args.PushMarkup(onMsg);
+
+ var chargeMessage = Loc.GetString("stunbaton-component-on-examine-charge",
+ ("charge", (int) (battery.CurrentCharge / battery.MaxCharge * 100)));
+ args.PushMarkup(chargeMessage);
}
- private void OnExamined(EntityUid uid, StunbatonComponent comp, ExaminedEvent args)
+ private void ToggleDone(EntityUid uid, StunbatonComponent comp, ref ItemToggleDoneEvent args)
{
- var msg = comp.Activated
- ? Loc.GetString("comp-stunbaton-examined-on")
- : Loc.GetString("comp-stunbaton-examined-off");
- args.PushMarkup(msg);
- if (TryComp(uid, out var battery))
- {
- args.PushMarkup(Loc.GetString("stunbaton-component-on-examine-charge",
- ("charge", (int)((battery.CurrentCharge/battery.MaxCharge) * 100))));
- }
- }
-
- private void TurnOff(EntityUid uid, StunbatonComponent comp)
- {
- if (!comp.Activated)
+ if (!TryComp(uid, out var item))
return;
-
- if (TryComp(uid, out var appearance) &&
- TryComp(uid, out var item))
- {
- _item.SetHeldPrefix(uid, "off", item);
- _appearance.SetData(uid, ToggleVisuals.Toggled, false, appearance);
- }
-
- _audio.PlayPvs(comp.SparksSound, uid, AudioHelpers.WithVariation(0.25f));
-
- comp.Activated = false;
- Dirty(uid, comp);
+ _item.SetHeldPrefix(uid, args.Activated ? "on" : "off", item);
}
- private void TurnOn(EntityUid uid, StunbatonComponent comp, EntityUid user)
+ private void TryTurnOn(EntityUid uid, StunbatonComponent comp, ref ItemToggleActivateAttemptEvent args)
{
- if (comp.Activated)
- return;
-
if (!TryComp(uid, out var battery) || battery.CurrentCharge < comp.EnergyPerUse)
{
-
- _audio.PlayPvs(comp.TurnOnFailSound, uid, AudioHelpers.WithVariation(0.25f));
- _popup.PopupEntity(Loc.GetString("stunbaton-component-low-charge"), user, user);
+ args.Cancelled = true;
+ if (args.User != null)
+ {
+ _popup.PopupEntity(Loc.GetString("stunbaton-component-low-charge"), (EntityUid) args.User, (EntityUid) args.User);
+ }
return;
}
if (TryComp(uid, out var rig) && rig.IsRigged)
{
- _riggableSystem.Explode(uid, battery, user);
+ _riggableSystem.Explode(uid, battery, args.User);
}
-
-
- if (EntityManager.TryGetComponent(uid, out var appearance) &&
- EntityManager.TryGetComponent(uid, out var item))
- {
- _item.SetHeldPrefix(uid, "on", item);
- _appearance.SetData(uid, ToggleVisuals.Toggled, true, appearance);
- }
-
- _audio.PlayPvs(comp.SparksSound, uid, AudioHelpers.WithVariation(0.25f));
- comp.Activated = true;
- Dirty(uid, comp);
}
// https://github.com/space-wizards/space-station-14/pull/17288#discussion_r1241213341
private void OnSolutionChange(EntityUid uid, StunbatonComponent component, SolutionChangedEvent args)
{
// Explode if baton is activated and rigged.
- if (!TryComp(uid, out var riggable) || !TryComp(uid, out var battery))
+ if (!TryComp(uid, out var riggable) ||
+ !TryComp(uid, out var battery))
return;
- if (component.Activated && riggable.IsRigged)
+ if (_itemToggle.IsActivated(uid) && riggable.IsRigged)
_riggableSystem.Explode(uid, battery);
}
diff --git a/Content.Server/Tools/Components/WelderComponent.cs b/Content.Server/Tools/Components/WelderComponent.cs
index 48fbd3640a..a620fa2ef4 100644
--- a/Content.Server/Tools/Components/WelderComponent.cs
+++ b/Content.Server/Tools/Components/WelderComponent.cs
@@ -1,9 +1,8 @@
using Content.Shared.Chemistry.Reagent;
-using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.Tools.Components;
using Robust.Shared.Audio;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Prototypes;
namespace Content.Server.Tools.Components
{
@@ -13,56 +12,37 @@ namespace Content.Server.Tools.Components
///
/// Solution on the entity that contains the fuel.
///
- [DataField("fuelSolution"), ViewVariables(VVAccess.ReadWrite)]
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
public string FuelSolution { get; private set; } = "Welder";
///
/// Reagent that will be used as fuel for welding.
///
- [DataField("fuelReagent", customTypeSerializer:typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)]
- public string FuelReagent { get; private set; } = "WeldingFuel";
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public ProtoId FuelReagent { get; private set; } = "WeldingFuel";
///
- /// Fuel consumption per second, while the welder is active.
+ /// Fuel consumption per second while the welder is active.
///
- [DataField("fuelConsumption"), ViewVariables(VVAccess.ReadWrite)]
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
public FixedPoint2 FuelConsumption { get; private set; } = FixedPoint2.New(2.0f);
///
/// A fuel amount to be consumed when the welder goes from being unlit to being lit.
///
- [DataField("fuelLitCost"), ViewVariables(VVAccess.ReadWrite)]
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
public FixedPoint2 FuelLitCost { get; private set; } = FixedPoint2.New(0.5f);
///
- /// Sound played when the welder is turned off.
+ /// Sound played when refilling the welder.
///
- [DataField("welderOffSounds")]
- public SoundSpecifier WelderOffSounds { get; private set; } = new SoundCollectionSpecifier("WelderOff");
-
- ///
- /// Sound played when the tool is turned on.
- ///
- [DataField("welderOnSounds")]
- public SoundSpecifier WelderOnSounds { get; private set; } = new SoundCollectionSpecifier("WelderOn");
-
- [DataField("welderRefill")]
+ [DataField]
public SoundSpecifier WelderRefill { get; private set; } = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
- ///
- /// When the welder is lit, this damage is added to the base melee weapon damage.
- ///
- ///
- /// If this is a standard welder, this damage bonus should probably subtract the entity's standard melee weapon damage
- /// and replace it all with heat damage.
- ///
- [DataField("litMeleeDamageBonus")]
- public DamageSpecifier LitMeleeDamageBonus = new();
-
///
/// Whether the item is safe to refill while lit without exploding the tank.
///
- [DataField("tankSafe")]
+ [DataField]
public bool TankSafe = false; //I have no idea what I'm doing
}
diff --git a/Content.Server/Tools/ToolSystem.Welder.cs b/Content.Server/Tools/ToolSystem.Welder.cs
index e0dc341a16..7827cbdfc5 100644
--- a/Content.Server/Tools/ToolSystem.Welder.cs
+++ b/Content.Server/Tools/ToolSystem.Welder.cs
@@ -2,24 +2,21 @@ using System.Linq;
using Content.Server.Chemistry.Components;
using Content.Server.Tools.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
-using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Item;
-using Content.Shared.Temperature;
-using Content.Shared.Toggleable;
+using Content.Shared.Item.ItemToggle;
using Content.Shared.Tools.Components;
-using Content.Shared.Weapons.Melee.Events;
-using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Server.Tools
{
public sealed partial class ToolSystem
{
+ [Dependency] private readonly SharedItemToggleSystem _itemToggle = default!;
private readonly HashSet _activeWelders = new();
private const float WelderUpdateTimer = 1f;
@@ -27,106 +24,51 @@ namespace Content.Server.Tools
public void InitializeWelders()
{
- SubscribeLocalEvent(OnWelderStartup);
- SubscribeLocalEvent(OnWelderIsHotEvent);
SubscribeLocalEvent(OnWelderExamine);
- SubscribeLocalEvent(OnWelderSolutionChange);
- SubscribeLocalEvent(OnWelderActivate);
SubscribeLocalEvent(OnWelderAfterInteract);
SubscribeLocalEvent>(OnWelderToolUseAttempt);
SubscribeLocalEvent(OnWelderShutdown);
SubscribeLocalEvent(OnWelderGetState);
- SubscribeLocalEvent(OnGetMeleeDamage);
- }
-
- private void OnGetMeleeDamage(EntityUid uid, WelderComponent component, ref GetMeleeDamageEvent args)
- {
- if (component.Lit)
- args.Damage += component.LitMeleeDamageBonus;
+ SubscribeLocalEvent(TryTurnOn);
+ SubscribeLocalEvent(TurnOff);
}
public (FixedPoint2 fuel, FixedPoint2 capacity) GetWelderFuelAndCapacity(EntityUid uid, WelderComponent? welder = null, SolutionContainerManagerComponent? solutionContainer = null)
{
if (!Resolve(uid, ref welder, ref solutionContainer)
- || !_solutionContainerSystem.TryGetSolution(uid, welder.FuelSolution, out var fuelSolution, solutionContainer))
+ || !_solutionContainer.TryGetSolution(uid, welder.FuelSolution, out var fuelSolution, solutionContainer))
return (FixedPoint2.Zero, FixedPoint2.Zero);
- return (_solutionContainerSystem.GetTotalPrototypeQuantity(uid, welder.FuelReagent), fuelSolution.MaxVolume);
+ return (_solutionContainer.GetTotalPrototypeQuantity(uid, welder.FuelReagent), fuelSolution.MaxVolume);
}
- public bool TryToggleWelder(EntityUid uid, EntityUid? user,
- WelderComponent? welder = null,
- SolutionContainerManagerComponent? solutionContainer = null,
- ItemComponent? item = null,
- SharedPointLightComponent? light = null,
- AppearanceComponent? appearance = null)
+ public void TryTurnOn(EntityUid uid, WelderComponent welder, ref ItemToggleActivateAttemptEvent args)
{
- // Right now, we only need the welder.
- // So let's not unnecessarily resolve components
- if (!Resolve(uid, ref welder))
- return false;
-
- return !welder.Lit
- ? TryTurnWelderOn(uid, user, welder, solutionContainer, item, light, appearance)
- : TryTurnWelderOff(uid, user, welder, item, light, appearance);
- }
-
- public bool TryTurnWelderOn(EntityUid uid, EntityUid? user,
- WelderComponent? welder = null,
- SolutionContainerManagerComponent? solutionContainer = null,
- ItemComponent? item = null,
- SharedPointLightComponent? light = null,
- AppearanceComponent? appearance = null,
- TransformComponent? transform = null)
- {
- if (!Resolve(uid, ref welder, ref solutionContainer, ref transform))
- return false;
-
- // Optional components.
- Resolve(uid, ref item, ref appearance, false);
-
- _light.ResolveLight(uid, ref light);
-
- if (!_solutionContainerSystem.TryGetSolution(uid, welder.FuelSolution, out var solution, solutionContainer))
- return false;
-
+ if (!_solutionContainer.TryGetSolution(uid, welder.FuelSolution, out var solution) ||
+ !TryComp(uid, out var transform))
+ {
+ args.Cancelled = true;
+ return;
+ }
var fuel = solution.GetTotalPrototypeQuantity(welder.FuelReagent);
// Not enough fuel to lit welder.
if (fuel == FixedPoint2.Zero || fuel < welder.FuelLitCost)
{
- if(user != null)
- _popupSystem.PopupEntity(Loc.GetString("welder-component-no-fuel-message"), uid, user.Value);
- return false;
+ if (args.User != null)
+ {
+ _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-message"), uid, (EntityUid) args.User);
+ }
+ args.Cancelled = true;
+ return;
}
solution.RemoveReagent(welder.FuelReagent, welder.FuelLitCost);
- welder.Lit = true;
-
// Logging
- if (user != null)
- _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user.Value):user} toggled {ToPrettyString(uid):welder} on");
- else
- _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(uid):welder} toggled on");
+ _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(uid):welder} on");
- var ev = new WelderToggledEvent(true);
- RaiseLocalEvent(uid, ev);
-
- var hotEvent = new IsHotEvent() {IsHot = true};
- RaiseLocalEvent(uid, hotEvent);
-
- _appearanceSystem.SetData(uid, WelderVisuals.Lit, true);
- _appearanceSystem.SetData(uid, ToggleableLightVisuals.Enabled, true);
-
- if (light != null)
- {
- _light.SetEnabled(uid, true, light);
- }
-
- _audioSystem.PlayPvs(welder.WelderOnSounds, uid, AudioParams.Default.WithVariation(0.125f).WithVolume(-5f));
-
- if (transform.GridUid is {} gridUid)
+ if (transform.GridUid is { } gridUid)
{
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
_atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, uid, true);
@@ -135,68 +77,21 @@ namespace Content.Server.Tools
Dirty(uid, welder);
_activeWelders.Add(uid);
- return true;
}
- public bool TryTurnWelderOff(EntityUid uid, EntityUid? user,
- WelderComponent? welder = null,
- ItemComponent? item = null,
- SharedPointLightComponent? light = null,
- AppearanceComponent? appearance = null)
+ public void TurnOff(EntityUid uid, WelderComponent welder, ref ItemToggleDeactivateAttemptEvent args)
{
- if (!Resolve(uid, ref welder))
- return false;
-
- // Optional components.
- Resolve(uid, ref item, ref appearance, false);
-
- _light.ResolveLight(uid, ref light);
-
- welder.Lit = false;
-
// Logging
- if (user != null)
- _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user.Value):user} toggled {ToPrettyString(uid):welder} off");
- else
- _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(uid):welder} toggled off");
-
- var ev = new WelderToggledEvent(false);
- RaiseLocalEvent(uid, ev);
-
- var hotEvent = new IsHotEvent() {IsHot = false};
- RaiseLocalEvent(uid, hotEvent);
-
- // Layer 1 is the flame.
- _appearanceSystem.SetData(uid, WelderVisuals.Lit, false);
- _appearanceSystem.SetData(uid, ToggleableLightVisuals.Enabled, false);
-
- if (light != null)
- {
- _light.SetEnabled(uid, false, light);
- }
-
- _audioSystem.PlayPvs(welder.WelderOffSounds, uid, AudioParams.Default.WithVariation(0.125f).WithVolume(-5f));
+ _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(uid):welder} off");
Dirty(uid, welder);
_activeWelders.Remove(uid);
- return true;
- }
-
- private void OnWelderStartup(EntityUid uid, WelderComponent welder, ComponentStartup args)
- {
- // TODO: Delete this shit what
- Dirty(uid, welder);
- }
-
- private void OnWelderIsHotEvent(EntityUid uid, WelderComponent welder, IsHotEvent args)
- {
- args.IsHot = welder.Lit;
}
private void OnWelderExamine(EntityUid uid, WelderComponent welder, ExaminedEvent args)
{
- if (welder.Lit)
+ if (_itemToggle.IsActivated(uid))
{
args.PushMarkup(Loc.GetString("welder-component-on-examine-welder-lit-message"));
}
@@ -217,50 +112,34 @@ namespace Content.Server.Tools
}
}
- private void OnWelderSolutionChange(EntityUid uid, WelderComponent welder, SolutionChangedEvent args)
- {
- // TODO what
- // ????
- Dirty(uid, welder);
- }
-
- private void OnWelderActivate(EntityUid uid, WelderComponent welder, ActivateInWorldEvent args)
- {
- args.Handled = TryToggleWelder(uid, args.User, welder);
- if (args.Handled)
- args.WasLogged = true;
- }
-
private void OnWelderAfterInteract(EntityUid uid, WelderComponent welder, AfterInteractEvent args)
{
if (args.Handled)
return;
- if (args.Target is not {Valid: true} target || !args.CanReach)
+ if (args.Target is not { Valid: true } target || !args.CanReach)
return;
- // TODO: Clean up this inherited oldcode.
-
- if (EntityManager.TryGetComponent(target, out ReagentTankComponent? tank)
+ if (TryComp(target, out ReagentTankComponent? tank)
&& tank.TankType == ReagentTankType.Fuel
- && _solutionContainerSystem.TryGetDrainableSolution(target, out var targetSolution)
- && _solutionContainerSystem.TryGetSolution(uid, welder.FuelSolution, out var welderSolution))
+ && _solutionContainer.TryGetDrainableSolution(target, out var targetSolution)
+ && _solutionContainer.TryGetSolution(uid, welder.FuelSolution, out var welderSolution))
{
var trans = FixedPoint2.Min(welderSolution.AvailableVolume, targetSolution.Volume);
if (trans > 0)
{
- var drained = _solutionContainerSystem.Drain(target, targetSolution, trans);
- _solutionContainerSystem.TryAddSolution(uid, welderSolution, drained);
- _audioSystem.PlayPvs(welder.WelderRefill, uid);
- _popupSystem.PopupEntity(Loc.GetString("welder-component-after-interact-refueled-message"), uid, args.User);
+ var drained = _solutionContainer.Drain(target, targetSolution, trans);
+ _solutionContainer.TryAddSolution(uid, welderSolution, drained);
+ _audio.PlayPvs(welder.WelderRefill, uid);
+ _popup.PopupEntity(Loc.GetString("welder-component-after-interact-refueled-message"), uid, args.User);
}
else if (welderSolution.AvailableVolume <= 0)
{
- _popupSystem.PopupEntity(Loc.GetString("welder-component-already-full"), uid, args.User);
+ _popup.PopupEntity(Loc.GetString("welder-component-already-full"), uid, args.User);
}
else
{
- _popupSystem.PopupEntity(Loc.GetString("welder-component-no-fuel-in-tank", ("owner", args.Target)), uid, args.User);
+ _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-in-tank", ("owner", args.Target)), uid, args.User);
}
}
@@ -271,11 +150,10 @@ namespace Content.Server.Tools
{
var user = args.DoAfter.Args.User;
- if (!welder.Lit)
+ if (!_itemToggle.IsActivated(uid))
{
- _popupSystem.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), uid, user);
+ _popup.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), uid, user);
args.Cancel();
- return;
}
}
@@ -287,7 +165,7 @@ namespace Content.Server.Tools
private void OnWelderGetState(EntityUid uid, WelderComponent welder, ref ComponentGetState args)
{
var (fuel, capacity) = GetWelderFuelAndCapacity(uid, welder);
- args.State = new WelderComponentState(capacity.Float(), fuel.Float(), welder.Lit);
+ args.State = new WelderComponentState(capacity.Float(), fuel.Float());
}
private void UpdateWelders(float frameTime)
@@ -297,37 +175,26 @@ namespace Content.Server.Tools
if (_welderTimer < WelderUpdateTimer)
return;
-
// TODO Use an "active welder" component instead, EntityQuery over that.
foreach (var tool in _activeWelders.ToArray())
{
- if (!EntityManager.TryGetComponent(tool, out WelderComponent? welder)
- || !EntityManager.TryGetComponent(tool, out SolutionContainerManagerComponent? solutionContainer)
- || !EntityManager.TryGetComponent(tool, out TransformComponent? transform))
+ if (!TryComp(tool, out WelderComponent? welder)
+ || !TryComp(tool, out SolutionContainerManagerComponent? solutionContainer))
continue;
- if (!_solutionContainerSystem.TryGetSolution(tool, welder.FuelSolution, out var solution, solutionContainer))
+ if (!_solutionContainer.TryGetSolution(tool, welder.FuelSolution, out var solution, solutionContainer))
continue;
solution.RemoveReagent(welder.FuelReagent, welder.FuelConsumption * _welderTimer);
if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero)
- TryTurnWelderOff(tool, null, welder);
+ {
+ _itemToggle.Toggle(tool, predicted: false);
+ }
Dirty(tool, welder);
}
-
_welderTimer -= WelderUpdateTimer;
}
}
-
- public sealed class WelderToggledEvent : EntityEventArgs
- {
- public bool WelderOn;
-
- public WelderToggledEvent(bool welderOn)
- {
- WelderOn = welderOn;
- }
- }
}
diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs
index de6a7fefc1..7366bfce40 100644
--- a/Content.Server/Tools/ToolSystem.cs
+++ b/Content.Server/Tools/ToolSystem.cs
@@ -19,10 +19,10 @@ namespace Content.Server.Tools
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
- [Dependency] private readonly PopupSystem _popupSystem = default!;
- [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+ [Dependency] private readonly PopupSystem _popup = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPointLightSystem _light = default!;
- [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
+ [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
public override void Initialize()
diff --git a/Content.Server/Weapons/Melee/EnergySword/EnergySwordComponent.cs b/Content.Server/Weapons/Melee/EnergySword/EnergySwordComponent.cs
index f699ef7b34..458c88af3e 100644
--- a/Content.Server/Weapons/Melee/EnergySword/EnergySwordComponent.cs
+++ b/Content.Server/Weapons/Melee/EnergySword/EnergySwordComponent.cs
@@ -1,44 +1,14 @@
-using Content.Shared.Damage;
-using Robust.Shared.Audio;
-
namespace Content.Server.Weapons.Melee.EnergySword;
[RegisterComponent]
internal sealed partial class EnergySwordComponent : Component
{
- public Color BladeColor = Color.DodgerBlue;
-
- public bool Hacked = false;
-
- public bool Activated = false;
-
- [DataField("isSharp")]
- public bool IsSharp = true;
+ [ViewVariables(VVAccess.ReadWrite), DataField("activatedColor"), AutoNetworkedField]
+ public Color ActivatedColor = Color.DodgerBlue;
///
- /// Does this become hidden when deactivated
+ /// A color option list for the random color picker.
///
- [DataField("secret")]
- public bool Secret { get; set; } = false;
-
- ///
- /// RGB cycle rate for hacked e-swords.
- ///
- [DataField("cycleRate")]
- public float CycleRate = 1f;
-
- [DataField("activateSound")]
- public SoundSpecifier ActivateSound { get; set; } = new SoundPathSpecifier("/Audio/Weapons/ebladeon.ogg");
-
- [DataField("deActivateSound")]
- public SoundSpecifier DeActivateSound { get; set; } = new SoundPathSpecifier("/Audio/Weapons/ebladeoff.ogg");
-
- [DataField("onHitOn")]
- public SoundSpecifier OnHitOn { get; set; } = new SoundPathSpecifier("/Audio/Weapons/eblade1.ogg");
-
- [DataField("onHitOff")]
- public SoundSpecifier OnHitOff { get; set; } = new SoundPathSpecifier("/Audio/Weapons/genhit1.ogg");
-
[DataField("colorOptions")]
public List ColorOptions = new()
{
@@ -49,15 +19,10 @@ internal sealed partial class EnergySwordComponent : Component
Color.MediumOrchid
};
- [DataField("litDamageBonus")]
- public DamageSpecifier LitDamageBonus = new();
-
- [DataField("litDisarmMalus")]
- public float LitDisarmMalus = 0.6f;
+ public bool Hacked = false;
+ ///
+ /// RGB cycle rate for hacked e-swords.
+ ///
+ [DataField("cycleRate")]
+ public float CycleRate = 1f;
}
-
-[ByRefEvent]
-public readonly record struct EnergySwordActivatedEvent();
-
-[ByRefEvent]
-public readonly record struct EnergySwordDeactivatedEvent();
diff --git a/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs b/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs
index a08ff17ec8..e8897781f5 100644
--- a/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs
+++ b/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs
@@ -1,164 +1,38 @@
-using Content.Server.CombatMode.Disarm;
-using Content.Server.Kitchen.Components;
using Content.Shared.Interaction;
-using Content.Shared.Interaction.Events;
-using Content.Shared.Item;
using Content.Shared.Light;
using Content.Shared.Light.Components;
-using Content.Shared.Temperature;
using Content.Shared.Toggleable;
using Content.Shared.Tools.Components;
-using Content.Shared.Weapons.Melee;
-using Content.Shared.Weapons.Melee.Events;
-using Content.Shared.Wieldable;
-using Content.Shared.Wieldable.Components;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Player;
+using Content.Shared.Item;
using Robust.Shared.Random;
namespace Content.Server.Weapons.Melee.EnergySword;
public sealed class EnergySwordSystem : EntitySystem
{
- [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedRgbLightControllerSystem _rgbSystem = default!;
- [Dependency] private readonly SharedItemSystem _item = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnMapInit);
- SubscribeLocalEvent(OnGetMeleeDamage);
- SubscribeLocalEvent(OnUseInHand);
SubscribeLocalEvent(OnInteractUsing);
- SubscribeLocalEvent(OnIsHotEvent);
- SubscribeLocalEvent(TurnOff);
- SubscribeLocalEvent(TurnOn);
-
- SubscribeLocalEvent(TurnOffonUnwielded);
- SubscribeLocalEvent(TurnOnonWielded);
}
-
+ // Used to pick a random color for the blade on map init.
private void OnMapInit(EntityUid uid, EnergySwordComponent comp, MapInitEvent args)
{
if (comp.ColorOptions.Count != 0)
- comp.BladeColor = _random.Pick(comp.ColorOptions);
- }
+ comp.ActivatedColor = _random.Pick(comp.ColorOptions);
- private void OnGetMeleeDamage(EntityUid uid, EnergySwordComponent comp, ref GetMeleeDamageEvent args)
- {
- if (!comp.Activated)
- return;
-
- // Adjusts base damage when the energy blade is active, by values set in yaml
- args.Damage += comp.LitDamageBonus;
- }
-
- private void OnUseInHand(EntityUid uid, EnergySwordComponent comp, UseInHandEvent args)
- {
- if (args.Handled)
- return;
-
- args.Handled = true;
-
- if (TryComp(uid, out var wieldableComp))
- return;
-
- if (comp.Activated)
- {
- var ev = new EnergySwordDeactivatedEvent();
- RaiseLocalEvent(uid, ref ev);
- }
- else
- {
- var ev = new EnergySwordActivatedEvent();
- RaiseLocalEvent(uid, ref ev);
- }
-
- UpdateAppearance(uid, comp);
- }
-
- private void TurnOffonUnwielded(EntityUid uid, EnergySwordComponent comp, ItemUnwieldedEvent args)
- {
- var ev = new EnergySwordDeactivatedEvent();
- RaiseLocalEvent(uid, ref ev);
- UpdateAppearance(uid, comp);
- }
-
- private void TurnOnonWielded(EntityUid uid, EnergySwordComponent comp, ref ItemWieldedEvent args)
- {
- var ev = new EnergySwordActivatedEvent();
- RaiseLocalEvent(uid, ref ev);
- UpdateAppearance(uid, comp);
- }
-
- private void TurnOff(EntityUid uid, EnergySwordComponent comp, ref EnergySwordDeactivatedEvent args)
- {
- if (TryComp(uid, out ItemComponent? item))
- {
- _item.SetSize(uid, "Small", item);
- }
-
- if (TryComp(uid, out var malus))
- {
- malus.Malus -= comp.LitDisarmMalus;
- }
-
- if (TryComp(uid, out var weaponComp))
- {
- weaponComp.HitSound = comp.OnHitOff;
- if (comp.Secret)
- weaponComp.Hidden = true;
- }
-
- if (comp.IsSharp)
- RemComp(uid);
-
- _audio.PlayEntity(comp.DeActivateSound, Filter.Pvs(uid, entityManager: EntityManager), uid, true, comp.DeActivateSound.Params);
-
- comp.Activated = false;
- }
-
- private void TurnOn(EntityUid uid, EnergySwordComponent comp, ref EnergySwordActivatedEvent args)
- {
- if (TryComp(uid, out ItemComponent? item))
- {
- _item.SetSize(uid, "Huge", item);
- }
-
- if (comp.IsSharp)
- EnsureComp(uid);
-
- if (TryComp(uid, out var weaponComp))
- {
- weaponComp.HitSound = comp.OnHitOn;
- if (comp.Secret)
- weaponComp.Hidden = false;
- }
-
- if (TryComp(uid, out var malus))
- {
- malus.Malus += comp.LitDisarmMalus;
- }
-
- _audio.PlayEntity(comp.ActivateSound, Filter.Pvs(uid, entityManager: EntityManager), uid, true, comp.ActivateSound.Params);
-
- comp.Activated = true;
- }
-
- private void UpdateAppearance(EntityUid uid, EnergySwordComponent component)
- {
if (!TryComp(uid, out AppearanceComponent? appearanceComponent))
return;
-
- _appearance.SetData(uid, ToggleableLightVisuals.Enabled, component.Activated, appearanceComponent);
- _appearance.SetData(uid, ToggleableLightVisuals.Color, component.BladeColor, appearanceComponent);
+ _appearance.SetData(uid, ToggleableLightVisuals.Color, comp.ActivatedColor, appearanceComponent);
}
+ // Used to make the make the blade multicolored when using a multitool on it.
private void OnInteractUsing(EntityUid uid, EnergySwordComponent comp, InteractUsingEvent args)
{
if (args.Handled)
@@ -178,9 +52,4 @@ public sealed class EnergySwordSystem : EntitySystem
else
RemComp(uid);
}
-
- private void OnIsHotEvent(EntityUid uid, EnergySwordComponent energySword, IsHotEvent args)
- {
- args.IsHot = energySword.Activated;
- }
}
diff --git a/Content.Server/Weapons/Reflect/ReflectSystem.cs b/Content.Server/Weapons/Reflect/ReflectSystem.cs
index 48dffd87e3..5c1939478e 100644
--- a/Content.Server/Weapons/Reflect/ReflectSystem.cs
+++ b/Content.Server/Weapons/Reflect/ReflectSystem.cs
@@ -1,5 +1,4 @@
-using Content.Server.Weapons.Melee.EnergySword;
-using Content.Server.Weapons.Melee.ItemToggle;
+using Content.Shared.Item;
using Content.Shared.Weapons.Reflect;
namespace Content.Server.Weapons.Reflect;
@@ -10,33 +9,12 @@ public sealed class ReflectSystem : SharedReflectSystem
{
base.Initialize();
- SubscribeLocalEvent(EnableReflect);
- SubscribeLocalEvent(DisableReflect);
- SubscribeLocalEvent(ShieldEnableReflect);
- SubscribeLocalEvent(ShieldDisableReflect);
+ SubscribeLocalEvent(ToggleReflect);
}
- private void EnableReflect(EntityUid uid, ReflectComponent comp, ref EnergySwordActivatedEvent args)
+ private void ToggleReflect(EntityUid uid, ReflectComponent comp, ref ItemToggleReflectUpdateEvent args)
{
- comp.Enabled = true;
- Dirty(comp);
- }
-
- private void DisableReflect(EntityUid uid, ReflectComponent comp, ref EnergySwordDeactivatedEvent args)
- {
- comp.Enabled = false;
- Dirty(comp);
- }
-
- private void ShieldEnableReflect(EntityUid uid, ReflectComponent comp, ref ItemToggleActivatedEvent args)
- {
- comp.Enabled = true;
- Dirty(comp);
- }
-
- private void ShieldDisableReflect(EntityUid uid, ReflectComponent comp, ref ItemToggleDeactivatedEvent args)
- {
- comp.Enabled = false;
- Dirty(comp);
+ comp.Enabled = args.Activated;
+ Dirty(uid, comp);
}
}
diff --git a/Content.Shared/Damage/DamageSpecifier.cs b/Content.Shared/Damage/DamageSpecifier.cs
index b7181e297f..702b6fe3e9 100644
--- a/Content.Shared/Damage/DamageSpecifier.cs
+++ b/Content.Shared/Damage/DamageSpecifier.cs
@@ -5,6 +5,7 @@ using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
using Robust.Shared.Utility;
+using Robust.Shared.Serialization;
namespace Content.Shared.Damage
{
@@ -15,7 +16,7 @@ namespace Content.Shared.Damage
/// The actual damage information is stored in . This class provides
/// functions to apply resistance sets and supports basic math operations to modify this dictionary.
///
- [DataDefinition]
+ [DataDefinition, Serializable, NetSerializable]
public sealed partial class DamageSpecifier : IEquatable
{
// These exist solely so the wiki works. Please do not touch them or use them.
diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleActiveSoundComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleActiveSoundComponent.cs
new file mode 100644
index 0000000000..eb992975b3
--- /dev/null
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleActiveSoundComponent.cs
@@ -0,0 +1,34 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Item;
+
+///
+/// Handles the active sound being played continuously with some items that are activated (ie e-sword hum).
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ItemToggleActiveSoundComponent : Component
+{
+ ///
+ /// The continuous noise this item makes when it's activated (like an e-sword's hum). This loops.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? ActiveSound;
+
+ ///
+ /// Used when the item emits sound while active.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public EntityUid? PlayingStream;
+}
+
+///
+/// Raised in order to effect changes upon the ActiveSound of the entity.
+///
+[ByRefEvent]
+public record struct ItemToggleActiveSoundUpdateEvent(bool Activated, bool Predicted, EntityUid? User)
+{
+ public bool Activated = Activated;
+ public bool Predicted = Predicted;
+ public EntityUid? User = User;
+}
diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs
new file mode 100644
index 0000000000..6d27d9ee12
--- /dev/null
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs
@@ -0,0 +1,126 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Item;
+
+///
+/// Handles generic item toggles, like a welder turning on and off, or an e-sword.
+///
+///
+/// If you need extended functionality (e.g. requiring power) then add a new component and use events:
+/// ItemToggleActivateAttemptEvent, ItemToggleDeactivateAttemptEvent or ItemToggleForceToggleEvent.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class ItemToggleComponent : Component
+{
+ ///
+ /// The item's toggle state.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public bool Activated = false;
+
+ ///
+ /// Whether the item's toggle can be predicted by the client.
+ ///
+ /// ///
+ /// If server-side systems affect the item's toggle, like charge/fuel systems, then the item is not predictable.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public bool Predictable = true;
+
+ ///
+ /// The noise this item makes when it is toggled on.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? SoundActivate;
+
+ ///
+ /// The noise this item makes when it is toggled off.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? SoundDeactivate;
+
+ ///
+ /// The noise this item makes when it is toggled on.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? SoundFailToActivate;
+}
+
+///
+/// Raised directed on an entity when its ItemToggle is attempted to be activated.
+///
+[ByRefEvent]
+public record struct ItemToggleActivateAttemptEvent(EntityUid? User)
+{
+ public bool Cancelled = false;
+ public EntityUid? User = User;
+}
+
+///
+/// Raised directed on an entity when its ItemToggle is attempted to be deactivated.
+///
+[ByRefEvent]
+public record struct ItemToggleDeactivateAttemptEvent(EntityUid? User)
+{
+ public bool Cancelled = false;
+ public EntityUid? User = User;
+}
+
+///
+/// Raised directed on an entity any sort of toggle is complete.
+///
+[ByRefEvent]
+public record struct ItemToggleDoneEvent(bool Activated, EntityUid? User)
+{
+ public bool Activated = Activated;
+ public EntityUid? User = User;
+}
+
+///
+/// Raised in order to play a toggle sound effect.
+///
+[ByRefEvent]
+public record struct ItemTogglePlayToggleSoundEvent(bool Activated, bool Predicted, EntityUid? User)
+{
+ public bool Activated = Activated;
+ public bool Predicted = Predicted;
+ public EntityUid? User = User;
+}
+
+///
+/// Raised in order to play a failure to toggle sound effect.
+///
+[ByRefEvent]
+public record struct ItemTogglePlayFailSoundEvent(bool Predicted, EntityUid? User)
+{
+ public bool Predicted = Predicted;
+ public EntityUid? User = User;
+}
+
+///
+/// Raised in order to effect changes upon the Light component of the entity.
+///
+[ByRefEvent]
+public record struct ItemToggleLightUpdateEvent(bool Activated)
+{
+ public bool Activated = Activated;
+}
+
+///
+/// Raised in order to effect changes upon the Appearance component of the entity.
+///
+[ByRefEvent]
+public record struct ItemToggleAppearanceUpdateEvent(bool Activated)
+{
+ public bool Activated = Activated;
+}
+
+///
+/// Raised in order to effect changes upon the Reflect component of the entity.
+///
+[ByRefEvent]
+public record struct ItemToggleReflectUpdateEvent(bool Activated)
+{
+ public bool Activated = Activated;
+}
diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs
new file mode 100644
index 0000000000..b35adfadac
--- /dev/null
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleHotComponent.cs
@@ -0,0 +1,16 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Item;
+
+///
+/// Handles whether the item is hot when toggled on.
+///
+[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/Components/ItemToggleMeleeWeaponComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleMeleeWeaponComponent.cs
new file mode 100644
index 0000000000..5e57491af0
--- /dev/null
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleMeleeWeaponComponent.cs
@@ -0,0 +1,79 @@
+using Robust.Shared.GameStates;
+using Robust.Shared.Audio;
+using Content.Shared.Damage;
+
+namespace Content.Shared.Item;
+
+///
+/// Handles the changes to the melee weapon component when the item is toggled.
+///
+///
+/// You can change the damage, sound on hit, on swing, as well as hidden status while activated.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ItemToggleMeleeWeaponComponent : Component
+{
+ ///
+ /// The noise this item makes when hitting something with it on.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? ActivatedSoundOnHit;
+
+ ///
+ /// The noise this item makes when hitting something with it off.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? DeactivatedSoundOnHit;
+
+ ///
+ /// The noise this item makes when hitting something with it on and it does no damage.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? ActivatedSoundOnHitNoDamage;
+
+ ///
+ /// The noise this item makes when hitting something with it off and it does no damage.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? DeactivatedSoundOnHitNoDamage;
+
+ ///
+ /// The noise this item makes when swinging at nothing while activated.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? ActivatedSoundOnSwing;
+
+ ///
+ /// The noise this item makes when swinging at nothing while not activated.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public SoundSpecifier? DeactivatedSoundOnSwing;
+
+ ///
+ /// Damage done by this item when activated.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public DamageSpecifier? ActivatedDamage = null;
+
+ ///
+ /// Damage done by this item when deactivated.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public DamageSpecifier? DeactivatedDamage = null;
+
+ ///
+ /// Does this become hidden when deactivated
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public bool DeactivatedSecret = false;
+}
+
+///
+/// Raised in order to effect changes upon the MeleeWeaponComponent of the entity.
+///
+[ByRefEvent]
+public record struct ItemToggleMeleeWeaponUpdateEvent(bool Activated)
+{
+ public bool Activated = Activated;
+}
+
diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleSizeComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleSizeComponent.cs
new file mode 100644
index 0000000000..f280934f1b
--- /dev/null
+++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleSizeComponent.cs
@@ -0,0 +1,35 @@
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Item;
+
+///
+/// Handles the changes to the item size when toggled.
+///
+///
+/// You can change the size when activated or not. By default the sizes are copied from the item.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ItemToggleSizeComponent : Component
+{
+ ///
+ /// Item's size when activated
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public ProtoId? ActivatedSize = null;
+
+ ///
+ /// Item's size when deactivated. If none is mentioned, it uses the item's default size instead.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ public ProtoId? DeactivatedSize = null;
+}
+
+///
+/// Raised in order to effect changes upon the MeleeWeaponComponent of the entity.
+///
+[ByRefEvent]
+public record struct ItemToggleSizeUpdateEvent(bool Activated)
+{
+ public bool Activated = Activated;
+}
diff --git a/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs b/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs
new file mode 100644
index 0000000000..e44d135bf2
--- /dev/null
+++ b/Content.Shared/Item/ItemToggle/SharedItemToggleSystem.cs
@@ -0,0 +1,293 @@
+using Content.Shared.Interaction.Events;
+using Content.Shared.Toggleable;
+using Content.Shared.Temperature;
+using Content.Shared.Wieldable;
+using Content.Shared.Wieldable.Components;
+using Robust.Shared.Audio;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Network;
+
+namespace Content.Shared.Item.ItemToggle;
+///
+/// Handles generic item toggles, like a welder turning on and off, or an e-sword.
+///
+///
+/// If you need extended functionality (e.g. requiring power) then add a new component and use events.
+///
+public abstract class SharedItemToggleSystem : EntitySystem
+{
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly SharedPointLightSystem _light = default!;
+ [Dependency] private readonly INetManager _netManager = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(TurnOffonUnwielded);
+ SubscribeLocalEvent(TurnOnonWielded);
+ SubscribeLocalEvent(OnUseInHand);
+ SubscribeLocalEvent(OnIsHotEvent);
+ SubscribeLocalEvent(UpdateActiveSound);
+ SubscribeLocalEvent(UpdateAppearance);
+ SubscribeLocalEvent(UpdateLight);
+ SubscribeLocalEvent(PlayToggleSound);
+ SubscribeLocalEvent(PlayFailToggleSound);
+ }
+
+ private void OnUseInHand(EntityUid uid, ItemToggleComponent itemToggle, UseInHandEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ args.Handled = true;
+
+ Toggle(uid, args.User, predicted: itemToggle.Predictable, itemToggle: itemToggle);
+ }
+
+ ///
+ /// Used when an item is attempted to be toggled.
+ ///
+ public void Toggle(EntityUid uid, EntityUid? user = null, bool predicted = true, ItemToggleComponent? itemToggle = null)
+ {
+ if (!Resolve(uid, ref itemToggle))
+ return;
+
+ if (itemToggle.Activated)
+ {
+ TryDeactivate(uid, user, itemToggle: itemToggle, predicted: predicted);
+ }
+ else
+ {
+ TryActivate(uid, user, itemToggle: itemToggle, predicted: predicted);
+ }
+ }
+
+ ///
+ /// Used when an item is attempting to be activated. It returns false if the attempt fails any reason, interrupting the activation.
+ ///
+ public bool TryActivate(EntityUid uid, EntityUid? user = null, bool predicted = true, ItemToggleComponent? itemToggle = null)
+ {
+ if (!Resolve(uid, ref itemToggle))
+ return false;
+
+ if (itemToggle.Activated)
+ return true;
+
+ var attempt = new ItemToggleActivateAttemptEvent(user);
+ RaiseLocalEvent(uid, ref attempt);
+
+ if (attempt.Cancelled)
+ {
+ //Raises the event to play the failure to activate noise.
+ var evPlayFailToggleSound = new ItemTogglePlayFailSoundEvent(Predicted: predicted, user);
+ RaiseLocalEvent(uid, ref evPlayFailToggleSound);
+
+ 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);
+
+ var evPlayToggleSound = new ItemTogglePlayToggleSoundEvent(Activated: true, Predicted: predicted, user);
+ RaiseLocalEvent(uid, ref evPlayToggleSound);
+
+ var evActiveSound = new ItemToggleActiveSoundUpdateEvent(Activated: true, Predicted: predicted, user);
+ RaiseLocalEvent(uid, ref evActiveSound);
+
+ var toggleUsed = new ItemToggleDoneEvent(Activated: true, user);
+ RaiseLocalEvent(uid, ref toggleUsed);
+
+ return true;
+ }
+
+ ///
+ /// Used when an item is attempting to be deactivated. It returns false if the attempt fails any reason, interrupting the deactivation.
+ ///
+ public bool TryDeactivate(EntityUid uid, EntityUid? user = null, bool predicted = true, ItemToggleComponent? itemToggle = null)
+ {
+ if (!Resolve(uid, ref itemToggle))
+ return false;
+
+ if (!itemToggle.Activated)
+ return true;
+
+ var attempt = new ItemToggleDeactivateAttemptEvent(user);
+ RaiseLocalEvent(uid, ref attempt);
+
+ if (attempt.Cancelled)
+ {
+ 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);
+
+ var evPlayToggleSound = new ItemTogglePlayToggleSoundEvent(Activated: false, Predicted: predicted, user);
+ RaiseLocalEvent(uid, ref evPlayToggleSound);
+
+ var evActiveSound = new ItemToggleActiveSoundUpdateEvent(Activated: false, Predicted: predicted, user);
+ RaiseLocalEvent(uid, ref evActiveSound);
+
+ var toggleUsed = new ItemToggleDoneEvent(Activated: false, user);
+ RaiseLocalEvent(uid, ref toggleUsed);
+
+ return true;
+ }
+
+ ///
+ /// Used to make the actual changes to the item's components on activation.
+ ///
+ private void Activate(EntityUid uid, ItemToggleComponent itemToggle)
+ {
+ UpdateComponents(uid, itemToggle.Activated = true);
+
+ Dirty(uid, itemToggle);
+ }
+
+ ///
+ /// Used to make the actual changes to the item's components on deactivation.
+ ///
+ private void Deactivate(EntityUid uid, ItemToggleComponent itemToggle)
+ {
+ UpdateComponents(uid, itemToggle.Activated = false);
+
+ Dirty(uid, itemToggle);
+ }
+
+ ///
+ /// Used to raise events to update components on toggle.
+ ///
+ private void UpdateComponents(EntityUid uid, bool activated)
+ {
+ var evSize = new ItemToggleSizeUpdateEvent(activated);
+ RaiseLocalEvent(uid, ref evSize);
+
+ var evMelee = new ItemToggleMeleeWeaponUpdateEvent(activated);
+ RaiseLocalEvent(uid, ref evMelee);
+
+ var evAppearance = new ItemToggleAppearanceUpdateEvent(activated);
+ RaiseLocalEvent(uid, ref evAppearance);
+
+ var evLight = new ItemToggleLightUpdateEvent(activated);
+ RaiseLocalEvent(uid, ref evLight);
+
+ var evReflect = new ItemToggleReflectUpdateEvent(activated);
+ RaiseLocalEvent(uid, ref evReflect);
+ }
+
+ ///
+ /// 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.
+ ///
+ private void TurnOffonUnwielded(EntityUid uid, ItemToggleComponent itemToggle, ItemUnwieldedEvent args)
+ {
+ if (itemToggle.Activated)
+ TryDeactivate(uid, args.User, itemToggle: itemToggle);
+ }
+
+ ///
+ /// Wieldable items will automatically turn on when wielded.
+ ///
+ private void TurnOnonWielded(EntityUid uid, ItemToggleComponent itemToggle, ref ItemWieldedEvent args)
+ {
+ if (!itemToggle.Activated)
+ TryActivate(uid, itemToggle: itemToggle);
+ }
+
+ public bool IsActivated(EntityUid uid, ItemToggleComponent? comp = null)
+ {
+ if (!Resolve(uid, ref comp, false))
+ return true; // assume always activated if no component
+
+ return comp.Activated;
+ }
+
+ ///
+ /// Used to make the item hot when activated.
+ ///
+ private void OnIsHotEvent(EntityUid uid, ItemToggleHotComponent itemToggleHot, IsHotEvent args)
+ {
+ if (itemToggleHot.IsHotWhenActivated)
+ args.IsHot = IsActivated(uid);
+ }
+
+ ///
+ /// Used to update item appearance.
+ ///
+ private void UpdateAppearance(EntityUid uid, AppearanceComponent appearance, ref ItemToggleAppearanceUpdateEvent args)
+ {
+ _appearance.SetData(uid, ToggleableLightVisuals.Enabled, args.Activated, appearance);
+ _appearance.SetData(uid, ToggleVisuals.Toggled, args.Activated, appearance);
+ }
+
+ ///
+ /// Used to update light settings.
+ ///
+ private void UpdateLight(EntityUid uid, ItemToggleComponent comp, ref ItemToggleLightUpdateEvent args)
+ {
+ if (!_light.TryGetLight(uid, out var light))
+ return;
+
+ _light.SetEnabled(uid, args.Activated, light);
+ }
+
+ ///
+ /// Used to update the looping active sound linked to the entity.
+ ///
+ private void UpdateActiveSound(EntityUid uid, ItemToggleActiveSoundComponent activeSound, ref ItemToggleActiveSoundUpdateEvent args)
+ {
+ if (args.Activated)
+ {
+ if (activeSound.ActiveSound != null && activeSound.PlayingStream == null)
+ {
+ if (args.Predicted)
+ activeSound.PlayingStream = _audio.PlayPredicted(activeSound.ActiveSound, uid, args.User, AudioParams.Default.WithLoop(true)).Value.Entity;
+ else
+ activeSound.PlayingStream = _audio.PlayPvs(activeSound.ActiveSound, uid, AudioParams.Default.WithLoop(true)).Value.Entity;
+ }
+ }
+ else
+ {
+ activeSound.PlayingStream = _audio.Stop(activeSound.PlayingStream);
+ }
+ }
+
+ ///
+ /// Used to play a toggle sound.
+ ///
+ private void PlayToggleSound(EntityUid uid, ItemToggleComponent itemToggle, ref ItemTogglePlayToggleSoundEvent args)
+ {
+ SoundSpecifier? soundToPlay;
+ if (args.Activated)
+ soundToPlay = itemToggle.SoundActivate;
+ else
+ soundToPlay = itemToggle.SoundDeactivate;
+
+ if (soundToPlay == null)
+ return;
+
+ if (args.Predicted)
+ _audio.PlayPredicted(soundToPlay, uid, args.User);
+ else
+ _audio.PlayPvs(soundToPlay, uid);
+ }
+
+ ///
+ /// Used to play a failure to toggle sound.
+ ///
+ private void PlayFailToggleSound(EntityUid uid, ItemToggleComponent itemToggle, ref ItemTogglePlayFailSoundEvent args)
+ {
+ if (args.Predicted)
+ _audio.PlayPredicted(itemToggle.SoundFailToActivate, uid, args.User);
+ else
+ _audio.PlayPvs(itemToggle.SoundFailToActivate, uid);
+ }
+}
diff --git a/Content.Shared/Item/ItemToggleComponent.cs b/Content.Shared/Item/ItemToggleComponent.cs
deleted file mode 100644
index eb25f259ae..0000000000
--- a/Content.Shared/Item/ItemToggleComponent.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using Content.Shared.Item;
-using Robust.Shared.Audio;
-using Robust.Shared.GameStates;
-using Robust.Shared.Prototypes;
-
-namespace Content.Server.Weapons.Melee.ItemToggle;
-
-[RegisterComponent, NetworkedComponent]
-public sealed partial class ItemToggleComponent : Component
-{
- public bool Activated = false;
-
- [DataField("activateSound")]
- public SoundSpecifier ActivateSound { get; set; } = default!;
-
- [DataField("deActivateSound")]
- public SoundSpecifier DeActivateSound { get; set; } = default!;
-
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("activatedDisarmMalus")]
- public float ActivatedDisarmMalus = 0.6f;
-
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("offSize")]
- public ProtoId OffSize = "Small";
-
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("onSize")]
- public ProtoId OnSize = "Huge";
-}
-
-[ByRefEvent]
-public readonly record struct ItemToggleActivatedEvent();
-
-[ByRefEvent]
-public readonly record struct ItemToggleDeactivatedEvent();
diff --git a/Content.Shared/Item/SharedItemSystem.cs b/Content.Shared/Item/SharedItemSystem.cs
index c718b21e0f..fe925c5547 100644
--- a/Content.Shared/Item/SharedItemSystem.cs
+++ b/Content.Shared/Item/SharedItemSystem.cs
@@ -27,6 +27,8 @@ public abstract class SharedItemSystem : EntitySystem
SubscribeLocalEvent(OnHandleState);
SubscribeLocalEvent(OnExamine);
+
+ SubscribeLocalEvent(OnItemToggle);
}
#region Public API
@@ -205,4 +207,32 @@ public abstract class SharedItemSystem : EntitySystem
return adjustedShapes;
}
+
+ ///
+ /// Used to update the Item component on item toggle (specifically size).
+ ///
+ private void OnItemToggle(EntityUid uid, ItemToggleSizeComponent itemToggleSize, ItemToggleSizeUpdateEvent args)
+ {
+ if (!TryComp(uid, out ItemComponent? item))
+ return;
+
+ if (args.Activated)
+ {
+ if (itemToggleSize.ActivatedSize != null)
+ {
+ // Set the deactivated size to the default item's size before it gets changed.
+ itemToggleSize.DeactivatedSize ??= item.Size;
+ SetSize(uid, (ProtoId) itemToggleSize.ActivatedSize, item);
+ }
+ }
+ else
+ {
+ if (itemToggleSize.DeactivatedSize != null)
+ {
+ SetSize(uid, (ProtoId) itemToggleSize.DeactivatedSize, item);
+ }
+ }
+
+ Dirty(uid, item);
+ }
}
diff --git a/Content.Shared/Stunnable/SharedStunbatonSystem.cs b/Content.Shared/Stunnable/SharedStunbatonSystem.cs
index c964a9427d..28b68553b3 100644
--- a/Content.Shared/Stunnable/SharedStunbatonSystem.cs
+++ b/Content.Shared/Stunnable/SharedStunbatonSystem.cs
@@ -1,7 +1,3 @@
-using Content.Server.Stunnable.Components;
-using Content.Shared.Damage;
-using Content.Shared.Weapons.Melee.Events;
-
namespace Content.Shared.Stunnable;
public abstract class SharedStunbatonSystem : EntitySystem
@@ -9,16 +5,5 @@ public abstract class SharedStunbatonSystem : EntitySystem
public override void Initialize()
{
base.Initialize();
-
- SubscribeLocalEvent(OnGetMeleeDamage);
- }
-
- private void OnGetMeleeDamage(EntityUid uid, StunbatonComponent component, ref GetMeleeDamageEvent args)
- {
- if (!component.Activated)
- return;
-
- // Don't apply damage if it's activated; just do stamina damage.
- args.Damage = new DamageSpecifier();
}
}
diff --git a/Content.Shared/Stunnable/StunbatonComponent.cs b/Content.Shared/Stunnable/StunbatonComponent.cs
index 1cbba641be..1df009f780 100644
--- a/Content.Shared/Stunnable/StunbatonComponent.cs
+++ b/Content.Shared/Stunnable/StunbatonComponent.cs
@@ -9,17 +9,10 @@ namespace Content.Server.Stunnable.Components;
[Access(typeof(SharedStunbatonSystem))]
public sealed partial class StunbatonComponent : Component
{
- [DataField("activated"), ViewVariables(VVAccess.ReadWrite)]
- [AutoNetworkedField]
- public bool Activated = false;
-
[DataField("energyPerUse"), ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public float EnergyPerUse = 350;
[DataField("sparksSound")]
public SoundSpecifier SparksSound = new SoundCollectionSpecifier("sparks");
-
- [DataField("turnOnFailSound")]
- public SoundSpecifier TurnOnFailSound = new SoundPathSpecifier("/Audio/Machines/button.ogg");
}
diff --git a/Content.Shared/Tools/Components/SharedWelderComponent.cs b/Content.Shared/Tools/Components/SharedWelderComponent.cs
index 735aef88c1..78c1cde201 100644
--- a/Content.Shared/Tools/Components/SharedWelderComponent.cs
+++ b/Content.Shared/Tools/Components/SharedWelderComponent.cs
@@ -4,36 +4,18 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Tools.Components
{
[NetworkedComponent]
- public abstract partial class SharedWelderComponent : Component
- {
- public bool Lit { get; set; }
- }
+ public abstract partial class SharedWelderComponent : Component { }
[NetSerializable, Serializable]
public sealed class WelderComponentState : ComponentState
{
public float FuelCapacity { get; }
public float Fuel { get; }
- public bool Lit { get; }
- public WelderComponentState(float fuelCapacity, float fuel, bool lit)
+ public WelderComponentState(float fuelCapacity, float fuel)
{
FuelCapacity = fuelCapacity;
Fuel = fuel;
- Lit = lit;
}
}
-
- [Serializable, NetSerializable]
- public enum WelderVisuals : byte
- {
- Lit
- }
-
- [Serializable, NetSerializable]
- public enum WelderLayers : byte
- {
- Base,
- Flame
- }
}
diff --git a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
index 54db0b8c67..d76d7340ff 100644
--- a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
+++ b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
@@ -63,8 +63,8 @@ public sealed partial class MeleeWeaponComponent : Component
///
/// Base damage for this weapon. Can be modified via heavy damage or other means.
///
- [DataField(required:true)]
- [ViewVariables(VVAccess.ReadWrite)]
+ [DataField(required: true)]
+ [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public DamageSpecifier Damage = default!;
[DataField]
@@ -113,7 +113,7 @@ public sealed partial class MeleeWeaponComponent : Component
/// This gets played whenever a melee attack is done. This is predicted by the client.
///
[ViewVariables(VVAccess.ReadWrite)]
- [DataField("soundSwing")]
+ [DataField("soundSwing"), AutoNetworkedField]
public SoundSpecifier SwingSound { get; set; } = new SoundPathSpecifier("/Audio/Weapons/punchmiss.ogg")
{
Params = AudioParams.Default.WithVolume(-3f).WithVariation(0.025f),
@@ -124,14 +124,14 @@ public sealed partial class MeleeWeaponComponent : Component
// If overwatch and apex do this then we probably should too.
[ViewVariables(VVAccess.ReadWrite)]
- [DataField("soundHit")]
+ [DataField("soundHit"), AutoNetworkedField]
public SoundSpecifier? HitSound;
///
/// Plays if no damage is done to the target entity.
///
[ViewVariables(VVAccess.ReadWrite)]
- [DataField("soundNoDamage")]
+ [DataField("soundNoDamage"), AutoNetworkedField]
public SoundSpecifier NoDamageSound { get; set; } = new SoundPathSpecifier("/Audio/Weapons/tap.ogg");
}
diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs
index 5eac283ef1..3505149564 100644
--- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs
+++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs
@@ -12,6 +12,7 @@ using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
+using Content.Shared.Item;
using Content.Shared.Physics;
using Content.Shared.Popups;
using Content.Shared.Weapons.Melee.Components;
@@ -72,6 +73,8 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
SubscribeLocalEvent(OnGetBonusHeavyDamageModifier);
SubscribeLocalEvent(OnGetBonusMeleeAttackRate);
+ SubscribeLocalEvent(OnItemToggle);
+
SubscribeAllEvent(OnHeavyAttack);
SubscribeAllEvent(OnLightAttack);
SubscribeAllEvent(OnDisarmAttack);
@@ -849,4 +852,60 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
}
public abstract void DoLunge(EntityUid user, EntityUid weapon, Angle angle, Vector2 localPos, string? animation, bool predicted = true);
+
+ ///
+ /// Used to update the MeleeWeapon component on item toggle.
+ ///
+ private void OnItemToggle(EntityUid uid, ItemToggleMeleeWeaponComponent itemToggleMelee, ItemToggleMeleeWeaponUpdateEvent args)
+ {
+ if (!TryComp(uid, out MeleeWeaponComponent? meleeWeapon))
+ return;
+
+ if (args.Activated)
+ {
+ if (itemToggleMelee.ActivatedDamage != null)
+ {
+ //Setting deactivated damage to the weapon's regular value before changing it.
+ itemToggleMelee.DeactivatedDamage ??= meleeWeapon.Damage;
+ meleeWeapon.Damage = itemToggleMelee.ActivatedDamage;
+ }
+
+ meleeWeapon.HitSound = itemToggleMelee.ActivatedSoundOnHit;
+
+ if (itemToggleMelee.ActivatedSoundOnHitNoDamage != null)
+ {
+ //Setting the deactivated sound on no damage hit to the weapon's regular value before changing it.
+ itemToggleMelee.DeactivatedSoundOnHitNoDamage ??= meleeWeapon.NoDamageSound;
+ meleeWeapon.NoDamageSound = itemToggleMelee.ActivatedSoundOnHitNoDamage;
+ }
+
+ if (itemToggleMelee.ActivatedSoundOnSwing != null)
+ {
+ //Setting the deactivated sound on no damage hit to the weapon's regular value before changing it.
+ itemToggleMelee.DeactivatedSoundOnSwing ??= meleeWeapon.SwingSound;
+ meleeWeapon.SwingSound = itemToggleMelee.ActivatedSoundOnSwing;
+ }
+
+ if (itemToggleMelee.DeactivatedSecret)
+ meleeWeapon.Hidden = false;
+ }
+ else
+ {
+ if (itemToggleMelee.DeactivatedDamage != null)
+ meleeWeapon.Damage = itemToggleMelee.DeactivatedDamage;
+
+ meleeWeapon.HitSound = itemToggleMelee.DeactivatedSoundOnHit;
+
+ if (itemToggleMelee.DeactivatedSoundOnHitNoDamage != null)
+ meleeWeapon.NoDamageSound = itemToggleMelee.DeactivatedSoundOnHitNoDamage;
+
+ if (itemToggleMelee.DeactivatedSoundOnSwing != null)
+ meleeWeapon.SwingSound = itemToggleMelee.DeactivatedSoundOnSwing;
+
+ if (itemToggleMelee.DeactivatedSecret)
+ meleeWeapon.Hidden = true;
+ }
+
+ Dirty(uid, meleeWeapon);
+ }
}
diff --git a/Resources/Audio/Weapons/attributions.yml b/Resources/Audio/Weapons/attributions.yml
index 02b1c13d53..b29f498fee 100644
--- a/Resources/Audio/Weapons/attributions.yml
+++ b/Resources/Audio/Weapons/attributions.yml
@@ -33,6 +33,11 @@
copyright: "User Nimfar11 on GitHub."
source: "https://github.com/Nimfar11"
+- files: ["ebladehum.ogg", "eblademiss.ogg"]
+ license: "CC0-1.0"
+ copyright: "User gyzhor on freesound.org. Modified by Darkenson on github."
+ source: "https://freesound.org/people/gyzhor/sounds/47123/"
+
- files: ["dodgeball.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from tgstation"
diff --git a/Resources/Audio/Weapons/ebladehum.ogg b/Resources/Audio/Weapons/ebladehum.ogg
new file mode 100644
index 0000000000..aa885b14d2
Binary files /dev/null and b/Resources/Audio/Weapons/ebladehum.ogg differ
diff --git a/Resources/Audio/Weapons/eblademiss.ogg b/Resources/Audio/Weapons/eblademiss.ogg
new file mode 100644
index 0000000000..5ebdbaef2a
Binary files /dev/null and b/Resources/Audio/Weapons/eblademiss.ogg differ
diff --git a/Resources/Prototypes/Entities/Objects/Shields/shields.yml b/Resources/Prototypes/Entities/Objects/Shields/shields.yml
index 4596085f34..c7fda9779a 100644
--- a/Resources/Prototypes/Entities/Objects/Shields/shields.yml
+++ b/Resources/Prototypes/Entities/Objects/Shields/shields.yml
@@ -1,4 +1,4 @@
-- type: entity
+- type: entity
name: base shield
parent: BaseItem
id: BaseShield
@@ -316,7 +316,11 @@
state: mirror-icon
- type: Item
heldPrefix: mirror
- - type: Blocking #Mirror shield should reflect heat/laser eventually, but be relatively weak to everything else.
+ - type: Reflect
+ reflectProb: 0.95
+ reflects:
+ - Energy
+ - type: Blocking #Mirror shield reflects heat/laser, but is relatively weak to everything else.
passiveBlockModifier:
coefficients:
Blunt: 1.2
@@ -356,12 +360,17 @@
description: Exotic energy shield, when folded, can even fit in your pocket.
components:
- type: ItemToggle
- activatedDisarmMalus: 0.6
- activateSound:
+ soundActivate:
path: /Audio/Weapons/ebladeon.ogg
- deActivateSound:
+ soundDeactivate:
path: /Audio/Weapons/ebladeoff.ogg
- offSize: Small
+ - type: ItemToggleActiveSound
+ activeSound:
+ path: /Audio/Weapons/ebladehum.ogg
+ - type: ItemToggleSize
+ activatedSize: Huge
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.6
- type: Sprite
sprite: Objects/Weapons/Melee/e_shield.rsi
layers:
@@ -461,16 +470,18 @@
description: An advanced riot shield made of lightweight materials that collapses for easy storage.
components:
- type: ItemToggle
- activatedDisarmMalus: 0.6
- activateSound:
+ soundActivate:
path: /Audio/Weapons/telescopicon.ogg
params:
volume: -5
- deActivateSound:
+ soundDeactivate:
path: /Audio/Weapons/telescopicoff.ogg
params:
volume: -5
- offSize: Small
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.6
+ - type: ItemToggleSize
+ activatedSize: Huge
- type: Sprite
sprite: Objects/Weapons/Melee/teleriot_shield.rsi
layers:
diff --git a/Resources/Prototypes/Entities/Objects/Tools/lighters.yml b/Resources/Prototypes/Entities/Objects/Tools/lighters.yml
index a3b6b3fd6e..7d3ede8eaf 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/lighters.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/lighters.yml
@@ -4,45 +4,73 @@
id: Lighter
description: "A simple plastic cigarette lighter."
components:
- # Sloth: What is this comment ?????????
- - type: RandomSprite #this has to be before sprite component for the flame to toggle right because weldercomponent behaves weird (and i dont trust myself to fix it right)
- available:
- - enum.WelderLayers.Base:
- basic_icon_base-1: ""
- - enum.WelderLayers.Base:
- basic_icon_base-2: ""
- - enum.WelderLayers.Base:
- basic_icon_base-3: ""
- - enum.WelderLayers.Base:
- basic_icon_base-4: ""
- - enum.WelderLayers.Base:
- basic_icon_base-5: ""
- - enum.WelderLayers.Base:
- basic_icon_base-6: ""
- - enum.WelderLayers.Base:
- basic_icon_base-7: ""
- - enum.WelderLayers.Base:
- basic_icon_base-8: ""
- - enum.WelderLayers.Base:
- basic_icon_base-9: ""
- - enum.WelderLayers.Base:
- basic_icon_base-10: ""
- - enum.WelderLayers.Base:
- basic_icon_base-11: ""
+ - type: ItemToggle
+ predictable: false
+ soundActivate:
+ collection: lighterOnSounds
+ soundDeactivate:
+ collection: lighterOffSounds
+ - type: ItemToggleMeleeWeapon
+ activatedDamage:
+ types:
+ Heat: 1
+ - type: ItemToggleSize
+ activatedSize: Small
+ - type: ItemToggleHot
- type: Sprite
sprite: Objects/Tools/lighters.rsi
layers:
- state: icon_map
- map: ["enum.WelderLayers.Base"]
- - state: lighter_flame
- map: ["enum.WelderLayers.Flame"]
- shader: unshaded
- visible: false
+ - state: cheap_icon_base
+ map: [ "skin" ]
- state: basic_icon_top
+ - state: lighter_flame
+ visible: false
+ shader: unshaded
+ map: [ "flame" ]
+ - type: Appearance
+ - type: RandomSprite
+ available:
+ - skin:
+ basic_icon_base-1: ""
+ - skin:
+ basic_icon_base-2: ""
+ - skin:
+ basic_icon_base-3: ""
+ - skin:
+ basic_icon_base-4: ""
+ - skin:
+ basic_icon_base-5: ""
+ - skin:
+ basic_icon_base-6: ""
+ - skin:
+ basic_icon_base-7: ""
+ - skin:
+ basic_icon_base-8: ""
+ - skin:
+ basic_icon_base-9: ""
+ - skin:
+ basic_icon_base-10: ""
+ - skin:
+ basic_icon_base-11: ""
+ - type: GenericVisualizer
+ visuals:
+ enum.ToggleVisuals.Toggled:
+ flame:
+ True: { visible: true }
+ False: { visible: false }
+ - type: ToggleableLightVisuals
+ spriteLayer: lighter_flame
+ inhandVisuals:
+ left:
+ - state: inhand-left-flame
+ shader: unshaded
+ right:
+ - state: inhand-right-flame
+ shader: unshaded
- type: Item
size: Tiny
sprite: Objects/Tools/lighters.rsi
- heldPrefix: off
- type: ItemCooldown
- type: RefillableSolution
solution: Welder
@@ -56,24 +84,16 @@
- type: MeleeWeapon
damage:
types:
- Blunt: 0 #this feels hacky, but is needed for burn damage while active (i think)
+ Blunt: 0
- type: Welder
fuelConsumption: 0.01
fuelLitCost: 0.1
- litMeleeDamageBonus:
- types:
- Heat: 1
tankSafe: true
- welderOnSounds:
- collection: lighterOnSounds
- welderOffSounds:
- collection: lighterOffSounds
- type: PointLight
enabled: false
+ netsync: false
radius: 1.1 #smallest possible
color: orange
- - type: Appearance
-
- type: entity
name: cheap lighter
@@ -81,20 +101,21 @@
id: CheapLighter
description: "A dangerously inexpensive plastic lighter, don't burn your thumb!"
components:
- - type: RandomSprite
- available:
- - enum.WelderLayers.Base:
- cheap_icon_base: Rainbow
- type: Sprite
sprite: Objects/Tools/lighters.rsi
layers:
- state: icon_map
- map: ["enum.WelderLayers.Base"]
- - state: lighter_flame
- map: ["enum.WelderLayers.Flame"]
- shader: unshaded
- visible: false
+ - state: cheap_icon_base
+ map: [ "skin" ]
- state: cheap_icon_top
+ - state: lighter_flame
+ visible: false
+ shader: unshaded
+ map: [ "flame" ]
+ - type: RandomSprite
+ available:
+ - skin:
+ cheap_icon_base: Rainbow
- type: SolutionContainerManager
solutions:
Welder:
@@ -102,5 +123,3 @@
- ReagentId: WeldingFuel
Quantity: 4
maxVol: 4 #uses less fuel than a welder, so this isnt as bad as it looks
-
- #TODO: zippos
diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml
index caa0d4c208..ccfbca8246 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/welders.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml
@@ -11,14 +11,50 @@
sprite: Objects/Tools/welder.rsi
layers:
- state: icon
- map: ["enum.WelderLayers.Base"]
- state: welder_flame
- map: ["enum.WelderLayers.Flame"]
- shader: unshaded
visible: false
+ shader: unshaded
+ map: ["enum.ToggleVisuals.Layer"]
+ - type: GenericVisualizer
+ visuals:
+ enum.ToggleVisuals.Toggled:
+ enum.ToggleVisuals.Layer:
+ True: { visible: true }
+ False: { visible: false }
- type: Item
size: Small
sprite: Objects/Tools/welder.rsi
+ - type: ItemToggle
+ predictable: false
+ soundActivate:
+ collection: WelderOn
+ params:
+ variation: 0.125
+ volume: -5
+ soundDeactivate:
+ collection: WelderOff
+ params:
+ variation: 0.125
+ volume: -5
+ - type: ItemToggleMeleeWeapon
+ activatedSoundOnHit:
+ path: /Audio/Weapons/eblade1.ogg
+ params:
+ variation: 0.250
+ volume: -10
+ activatedSoundOnHitNoDamage:
+ path: /Audio/Weapons/eblade1.ogg
+ params:
+ variation: 0.250
+ volume: -12
+ activatedDamage:
+ types:
+ Heat: 8
+ - type: ItemToggleSize
+ activatedSize: Large
+ - type: ItemToggleHot
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.6
- type: ToggleableLightVisuals
spriteLayer: flame
inhandVisuals:
@@ -48,10 +84,6 @@
collection: Welder
qualities: Welding
- type: Welder
- litMeleeDamageBonus:
- types:
- Heat: 8
- Blunt: -5
- type: PointLight
enabled: false
radius: 1.5
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml
index b2b7bfd20c..a070a55199 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml
@@ -5,13 +5,39 @@
description: A very loud & dangerous sword with a beam made of pure, concentrated plasma. Cuts through unarmored targets like butter.
components:
- type: EnergySword
- litDamageBonus:
+ - type: ItemToggle
+ soundActivate:
+ path: /Audio/Weapons/ebladeon.ogg
+ soundDeactivate:
+ path: /Audio/Weapons/ebladeoff.ogg
+ - type: ItemToggleActiveSound
+ activeSound:
+ path: /Audio/Weapons/ebladehum.ogg
+ - type: ItemToggleSharp
+ - type: ItemToggleHot
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.6
+ - type: ItemToggleSize
+ activatedSize: Huge
+ - type: ItemToggleMeleeWeapon
+ activatedSoundOnHit:
+ path: /Audio/Weapons/eblade1.ogg
+ params:
+ variation: 0.250
+ activatedSoundOnHitNoDamage:
+ path: /Audio/Weapons/eblade1.ogg
+ params:
+ variation: 0.250
+ volume: -10
+ activatedSoundOnSwing:
+ path: /Audio/Weapons/eblademiss.ogg
+ params:
+ variation: 0.125
+ activatedDamage:
types:
Slash: 15
Heat: 15
Structural: 20
- Blunt: -4.5
- litDisarmMalus: 0.6
- type: Sprite
sprite: Objects/Weapons/Melee/e_sword.rsi
layers:
@@ -24,8 +50,6 @@
- type: MeleeWeapon
wideAnimationRotation: -135
attackRate: 1
- soundHit:
- path: /Audio/Weapons/eblade1.ogg
damage:
types:
Blunt: 4.5
@@ -63,21 +87,33 @@
description: 'A dark ink pen.'
components:
- type: EnergySword
- secret: true
- litDamageBonus:
- types:
- Slash: 10
- Heat: 10
- Blunt: -1
- litDisarmMalus: 0.4
- activateSound: !type:SoundPathSpecifier
+ - type: ItemToggle
+ soundActivate:
path: /Audio/Weapons/ebladeon.ogg
params:
volume: -6
- deActivateSound: !type:SoundPathSpecifier
+ soundDeactivate:
path: /Audio/Weapons/ebladeoff.ogg
params:
volume: -6
+ - type: ItemToggleMeleeWeapon
+ activatedSoundOnSwing:
+ path: /Audio/Weapons/eblademiss.ogg
+ params:
+ volume: -6
+ variation: 0.250
+ activatedDamage:
+ types:
+ Slash: 10
+ Heat: 10
+ deactivatedSecret: true
+ - type: ItemToggleActiveSound
+ activeSound:
+ path: /Audio/Weapons/ebladehum.ogg
+ params:
+ volume: -6
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.4
- type: Sprite
sprite: Objects/Weapons/Melee/e_dagger.rsi
layers:
@@ -146,13 +182,14 @@
description: An exotic energy weapon.
components:
- type: EnergySword
- secret: true
- litDamageBonus:
+ - type: ItemToggleMeleeWeapon
+ activatedDamage:
types:
Slash: 10
Heat: 12
- Blunt: -1
- litDisarmMalus: 0.6
+ deactivatedSecret: true
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.6
- type: Sprite
sprite: Objects/Weapons/Melee/e_cutlass.rsi
layers:
@@ -181,21 +218,39 @@
id: EnergySwordDouble
description: Syndicate Command Interns thought that having one blade on the energy sword was not enough. This can be stored in pockets.
components:
- - type: Wieldable
- type: EnergySword
- litDamageBonus:
+ - type: ItemToggle
+ soundActivate:
+ path: /Audio/Weapons/ebladeon.ogg
+ params:
+ volume: 3
+ soundDeactivate:
+ path: /Audio/Weapons/ebladeoff.ogg
+ params:
+ volume: 3
+ - type: ItemToggleMeleeWeapon
+ activatedSoundOnSwing:
+ path: /Audio/Weapons/eblademiss.ogg
+ params:
+ volume: 3
+ variation: 0.250
+ activatedDamage:
types:
Slash: 12
Heat: 12
Structural: 15
- Blunt: -4.5
- litDisarmMalus: 0.7
+ - type: ItemToggleActiveSound
+ activeSound:
+ path: /Audio/Weapons/ebladehum.ogg
+ params:
+ volume: 3
+ - type: ItemToggleDisarmMalus
+ activatedDisarmMalus: 0.7
+ - type: Wieldable
- type: MeleeWeapon
wideAnimationRotation: -135
attackRate: 1.5
angle: 100
- soundHit:
- path: /Audio/Weapons/eblade1.ogg
damage:
types:
Blunt: 4.5
@@ -212,7 +267,6 @@
size: Small
sprite: Objects/Weapons/Melee/e_sword_double-inhands.rsi
- type: Reflect
- enabled: true
reflectProb: .75
spread: 75
- type: UseDelay
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml
index b43ea5059c..e6ecbe059f 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml
@@ -9,6 +9,23 @@
layers:
- state: stunprod_off
map: [ "enum.ToggleVisuals.Layer" ]
+ - type: ItemToggle
+ soundActivate:
+ collection: sparks
+ params:
+ variation: 0.250
+ soundDeactivate:
+ collection: sparks
+ params:
+ variation: 0.250
+ soundFailToActivate:
+ path: /Audio/Machines/button.ogg
+ params:
+ variation: 0.250
+ - type: ItemToggleMeleeWeapon
+ activatedDamage:
+ types:
+ Blunt: 0
- type: Stunbaton
energyPerUse: 70
- type: MeleeWeapon
@@ -37,7 +54,7 @@
- type: Appearance
- type: GenericVisualizer
visuals:
- enum.ToggleVisuals.Toggled:
+ enum.ToggleVisuals.Toggled:
enum.ToggleVisuals.Layer:
True: {state: stunprod_on}
False: {state: stunprod_off}
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/security.yml b/Resources/Prototypes/Entities/Objects/Weapons/security.yml
index bf4a155ee4..d55a396164 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/security.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/security.yml
@@ -11,6 +11,24 @@
map: [ "enum.ToggleVisuals.Layer" ]
- type: Stunbaton
energyPerUse: 50
+ - type: ItemToggle
+ predictable: false
+ soundActivate:
+ collection: sparks
+ params:
+ variation: 0.250
+ soundDeactivate:
+ collection: sparks
+ params:
+ variation: 0.250
+ soundFailToActivate:
+ path: /Audio/Machines/button.ogg
+ params:
+ variation: 0.250
+ - type: ItemToggleMeleeWeapon
+ activatedDamage:
+ types:
+ Blunt: 0
- type: MeleeWeapon
wideAnimationRotation: -135
damage:
diff --git a/Resources/Textures/Objects/Tools/lighters.rsi/on-inhand-left.png b/Resources/Textures/Objects/Tools/lighters.rsi/inhand-left-flame.png
similarity index 100%
rename from Resources/Textures/Objects/Tools/lighters.rsi/on-inhand-left.png
rename to Resources/Textures/Objects/Tools/lighters.rsi/inhand-left-flame.png
diff --git a/Resources/Textures/Objects/Tools/lighters.rsi/off-inhand-left.png b/Resources/Textures/Objects/Tools/lighters.rsi/inhand-left.png
similarity index 100%
rename from Resources/Textures/Objects/Tools/lighters.rsi/off-inhand-left.png
rename to Resources/Textures/Objects/Tools/lighters.rsi/inhand-left.png
diff --git a/Resources/Textures/Objects/Tools/lighters.rsi/on-inhand-right.png b/Resources/Textures/Objects/Tools/lighters.rsi/inhand-right-flame.png
similarity index 100%
rename from Resources/Textures/Objects/Tools/lighters.rsi/on-inhand-right.png
rename to Resources/Textures/Objects/Tools/lighters.rsi/inhand-right-flame.png
diff --git a/Resources/Textures/Objects/Tools/lighters.rsi/off-inhand-right.png b/Resources/Textures/Objects/Tools/lighters.rsi/inhand-right.png
similarity index 100%
rename from Resources/Textures/Objects/Tools/lighters.rsi/off-inhand-right.png
rename to Resources/Textures/Objects/Tools/lighters.rsi/inhand-right.png
diff --git a/Resources/Textures/Objects/Tools/lighters.rsi/meta.json b/Resources/Textures/Objects/Tools/lighters.rsi/meta.json
index e1c6d6e749..7617a25de9 100644
--- a/Resources/Textures/Objects/Tools/lighters.rsi/meta.json
+++ b/Resources/Textures/Objects/Tools/lighters.rsi/meta.json
@@ -71,19 +71,19 @@
"name": "zippo_top"
},
{
- "name": "off-inhand-left",
+ "name": "inhand-left",
"directions": 4
},
{
- "name": "off-inhand-right",
+ "name": "inhand-right",
"directions": 4
},
{
- "name": "on-inhand-left",
+ "name": "inhand-left-flame",
"directions": 4
},
{
- "name": "on-inhand-right",
+ "name": "inhand-right-flame",
"directions": 4
}