using Content.Shared.Configurable;
using Content.Shared.Interaction;
using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
using Robust.Shared.Player;
public sealed class ConfigurationSystem : EntitySystem
{
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
public override void Initialize()
{
if (args.Handled)
return;
- if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.Contains(component.QualityNeeded))
+ if (!_toolSystem.HasQuality(args.Used, component.QualityNeeded))
return;
args.Handled = _uiSystem.TryOpenUi(uid, ConfigurationUiKey.Key, args.User);
private void OnInsert(EntityUid uid, ConfigurationComponent component, ContainerIsInsertingAttemptEvent args)
{
- if (!TryComp(args.EntityUid, out ToolComponent? tool) || !tool.Qualities.Contains(component.QualityNeeded))
+ if (!_toolSystem.HasQuality(args.EntityUid, component.QualityNeeded))
return;
args.Cancel();
using Content.Shared.Damage;
using Content.Shared.Tools;
-using Robust.Shared.Utility;
+using Robust.Shared.Prototypes;
-namespace Content.Server.Damage.Components
+namespace Content.Server.Damage.Components;
+
+[RegisterComponent]
+public sealed partial class DamageOnToolInteractComponent : Component
{
- [RegisterComponent]
- public sealed partial class DamageOnToolInteractComponent : Component
- {
- [DataField("tools")]
- public PrototypeFlags<ToolQualityPrototype> Tools { get; private set; } = new ();
+ [DataField]
+ public ProtoId<ToolQualityPrototype> Tools { get; private set; }
- // TODO: Remove this snowflake stuff, make damage per-tool quality perhaps?
- [DataField("weldingDamage")]
- [ViewVariables(VVAccess.ReadWrite)]
- public DamageSpecifier? WeldingDamage { get; private set; }
+ // TODO: Remove this snowflake stuff, make damage per-tool quality perhaps?
+ [DataField]
+ public DamageSpecifier? WeldingDamage { get; private set; }
- [DataField("defaultDamage")]
- [ViewVariables(VVAccess.ReadWrite)]
- public DamageSpecifier? DefaultDamage { get; private set; }
- }
+ [DataField]
+ public DamageSpecifier? DefaultDamage { get; private set; }
}
using Content.Shared.Database;
using Content.Shared.Interaction;
using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
using ItemToggleComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleComponent;
namespace Content.Server.Damage.Systems
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
public override void Initialize()
{
args.Handled = true;
}
else if (component.DefaultDamage is {} damage
- && EntityManager.TryGetComponent(args.Used, out ToolComponent? tool)
- && tool.Qualities.ContainsAny(component.Tools))
+ && _toolSystem.HasQuality(args.Used, component.Tools))
{
var dmg = _damageableSystem.TryChangeDamage(args.Target, damage, origin: args.User);
using Content.Shared.Interaction;
using Content.Shared.Tag;
using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
using Robust.Server.Containers;
using Robust.Shared.Containers;
{
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly TagSystem _tag = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
/// <inheritdoc/>
public override void Initialize()
private void OnInteractUsing(EntityUid uid, MechAssemblyComponent component, InteractUsingEvent args)
{
- if (TryComp<ToolComponent>(args.Used, out var toolComp) && toolComp.Qualities.Contains(component.QualityNeeded))
+ if (_toolSystem.HasQuality(args.Used, component.QualityNeeded))
{
foreach (var tag in component.RequiredParts.Keys)
{
using Content.Shared.Verbs;
using Content.Shared.Wires;
using Content.Server.Body.Systems;
+using Content.Shared.Tools.Systems;
using Robust.Server.Containers;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
/// <inheritdoc/>
public override void Initialize()
return;
}
- if (TryComp<ToolComponent>(args.Used, out var tool) && tool.Qualities.Contains("Prying") && component.BatterySlot.ContainedEntity != null)
+ if (_toolSystem.HasQuality(args.Used, "Prying") && component.BatterySlot.ContainedEntity != null)
{
var doAfterEventArgs = new DoAfterArgs(EntityManager, args.User, component.BatteryRemovalDelay,
new RemoveBatteryEvent(), uid, target: uid, used: args.Target)
using Content.Shared.Interaction;
using Content.Shared.PneumaticCannon;
using Content.Shared.StatusEffect;
-using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Weapons.Ranged.Systems;
[Dependency] private readonly GunSystem _gun = default!;
[Dependency] private readonly StunSystem _stun = default!;
[Dependency] private readonly ItemSlotsSystem _slots = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
public override void Initialize()
{
if (args.Handled)
return;
- if (!TryComp<ToolComponent>(args.Used, out var tool))
- return;
-
- if (!tool.Qualities.Contains(component.ToolModifyPower))
+ if (!_toolSystem.HasQuality(args.Used, component.ToolModifyPower))
return;
var val = (int) component.Power;
using Content.Shared.Light;
using Content.Shared.Light.Components;
using Content.Shared.Toggleable;
-using Content.Shared.Tools.Components;
-using Content.Shared.Item;
+using Content.Shared.Tools.Systems;
using Robust.Shared.Random;
namespace Content.Server.Weapons.Melee.EnergySword;
[Dependency] private readonly SharedRgbLightControllerSystem _rgbSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
public override void Initialize()
{
if (args.Handled)
return;
- if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.ContainsAny("Pulsing"))
+ if (!_toolSystem.HasQuality(args.Used, "Pulsing"))
return;
args.Handled = true;
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
using Content.Shared.Interaction;
using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
public sealed class ArtifactElectricityTriggerSystem : EntitySystem
{
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
+ [Dependency] private readonly SharedToolSystem _toolSystem = default!;
public override void Initialize()
{
if (args.Handled)
return;
- if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.ContainsAny("Pulsing"))
+ if (!_toolSystem.HasQuality(args.Used, "Pulsing"))
return;
args.Handled = _artifactSystem.TryActivateArtifact(uid, args.User);
return;
// If the used entity doesn't have a tool, return early.
- if (!TryComp(args.Used, out ToolComponent? usedTool) || !usedTool.Qualities.Contains(anchorable.Tool))
+ if (!TryComp(args.Used, out ToolComponent? usedTool) || !_tool.HasQuality(args.Used, anchorable.Tool, usedTool))
return;
args.Handled = true;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Radio.Components;
-using Content.Shared.Tools;
using Content.Shared.Tools.Components;
using Content.Shared.Wires;
-using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Network;
TryInsertKey(uid, component, args);
}
else if (TryComp<ToolComponent>(args.Used, out var tool)
- && tool.Qualities.Contains(component.KeysExtractionMethod)
+ && _tool.HasQuality(args.Used, component.KeysExtractionMethod, tool)
&& component.KeyContainer.ContainedEntities.Count > 0) // dont block deconstruction
{
args.Handled = true;
+using Content.Shared.Tools.Systems;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
-namespace Content.Shared.Tools.Components
-{
- [RegisterComponent, NetworkedComponent] // TODO move tool system to shared, and make it a friend.
- public sealed partial class ToolComponent : Component
- {
- [DataField("qualities")]
- public PrototypeFlags<ToolQualityPrototype> Qualities { get; set; } = new();
-
- /// <summary>
- /// For tool interactions that have a delay before action this will modify the rate, time to wait is divided by this value
- /// </summary>
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("speed")]
- public float SpeedModifier { get; set; } = 1;
+namespace Content.Shared.Tools.Components;
- [DataField("useSound")]
- public SoundSpecifier? UseSound { get; set; }
- }
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(SharedToolSystem))]
+public sealed partial class ToolComponent : Component
+{
+ [DataField]
+ public PrototypeFlags<ToolQualityPrototype> Qualities = [];
/// <summary>
- /// Attempt event called *before* any do afters to see if the tool usage should succeed or not.
- /// Raised on both the tool and then target.
+ /// For tool interactions that have a delay before action this will modify the rate, time to wait is divided by this value
/// </summary>
- public sealed class ToolUseAttemptEvent : CancellableEntityEventArgs
- {
- public EntityUid User { get; }
+ [DataField]
+ public float SpeedModifier = 1;
- public ToolUseAttemptEvent(EntityUid user)
- {
- User = user;
- }
- }
+ [DataField]
+ public SoundSpecifier? UseSound;
+}
- /// <summary>
- /// Event raised on the user of a tool to see if they can actually use it.
- /// </summary>
- [ByRefEvent]
- public struct ToolUserAttemptUseEvent
- {
- public EntityUid? Target;
- public bool Cancelled = false;
+/// <summary>
+/// Attempt event called *before* any do afters to see if the tool usage should succeed or not.
+/// Raised on both the tool and then target.
+/// </summary>
+public sealed class ToolUseAttemptEvent(EntityUid user, float fuel) : CancellableEntityEventArgs
+{
+ public EntityUid User { get; } = user;
+ public float Fuel = fuel;
+}
- public ToolUserAttemptUseEvent(EntityUid? target)
- {
- Target = target;
- }
- }
+/// <summary>
+/// Event raised on the user of a tool to see if they can actually use it.
+/// </summary>
+[ByRefEvent]
+public struct ToolUserAttemptUseEvent(EntityUid? target)
+{
+ public EntityUid? Target = target;
+ public bool Cancelled = false;
}
using Content.Shared.Storage;
-using Content.Shared.Tools;
+using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
+using Content.Shared.Tools.Systems;
-namespace Content.Server.Construction.Components;
+namespace Content.Shared.Tools.Components;
/// <summary>
/// Used for something that can be refined by welder.
/// For example, glass shard can be refined to glass sheet.
/// </summary>
-[RegisterComponent, Access(typeof(RefiningSystem))]
-public sealed partial class WelderRefinableComponent : Component
+[RegisterComponent, NetworkedComponent, Access(typeof(ToolRefinablSystem))]
+public sealed partial class ToolRefinableComponent : Component
{
/// <summary>
/// The items created when the item is refined.
/// The amount of fuel it takes to refine a given item.
/// </summary>
[DataField]
- public float RefineFuel;
+ public float RefineFuel = 3f;
/// <summary>
/// The tool type needed in order to refine this item.
{
SubscribeLocalEvent<WelderComponent, ExaminedEvent>(OnWelderExamine);
SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
- SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>(OnWelderToolUseAttempt);
+
+ SubscribeLocalEvent<WelderComponent, ToolUseAttemptEvent>((uid, comp, ev) => {
+ CanCancelWelderUse((uid, comp), ev.User, ev.Fuel, ev);
+ });
+ SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>((uid, comp, ev) => {
+ CanCancelWelderUse((uid, comp), ev.Event.User, ev.Event.Fuel, ev);
+ });
SubscribeLocalEvent<WelderComponent, ToolDoAfterEvent>(OnWelderDoAfter);
+
SubscribeLocalEvent<WelderComponent, ItemToggledEvent>(OnToggle);
SubscribeLocalEvent<WelderComponent, ItemToggleActivateAttemptEvent>(OnActivateAttempt);
}
}
}
- private void OnWelderToolUseAttempt(Entity<WelderComponent> entity, ref DoAfterAttemptEvent<ToolDoAfterEvent> args)
+ private void CanCancelWelderUse(Entity<WelderComponent> entity, EntityUid user, float requiredFuel, CancellableEntityEventArgs ev)
{
- var user = args.DoAfter.Args.User;
-
if (!ItemToggle.IsActivated(entity.Owner))
{
_popup.PopupClient(Loc.GetString("welder-component-welder-not-lit-message"), entity, user);
- args.Cancel();
- return;
+ ev.Cancel();
}
- var (fuel, _) = GetWelderFuelAndCapacity(entity);
+ var (currentFuel, _) = GetWelderFuelAndCapacity(entity);
- if (args.Event.Fuel > fuel)
+ if (requiredFuel > currentFuel)
{
_popup.PopupClient(Loc.GetString("welder-component-cannot-weld-message"), entity, user);
- args.Cancel();
+ ev.Cancel();
}
}
return false;
// check if the tool allows being used
- var beforeAttempt = new ToolUseAttemptEvent(user);
+ var beforeAttempt = new ToolUseAttemptEvent(user, fuel);
RaiseLocalEvent(tool, beforeAttempt);
if (beforeAttempt.Cancelled)
return false;
public sealed partial class CableCuttingFinishedEvent : SimpleDoAfterEvent;
#endregion
-
-using Content.Server.Construction.Components;
using Content.Shared.Construction;
using Content.Shared.Interaction;
using Content.Shared.Storage;
-using Content.Shared.Tools.Systems;
+using Content.Shared.Tools.Components;
+using Robust.Shared.Network;
using Robust.Shared.Random;
-namespace Content.Server.Construction;
+namespace Content.Shared.Tools.Systems;
-public sealed class RefiningSystem : EntitySystem
+public sealed class ToolRefinablSystem : EntitySystem
{
+ [Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent<WelderRefinableComponent, InteractUsingEvent>(OnInteractUsing);
- SubscribeLocalEvent<WelderRefinableComponent, WelderRefineDoAfterEvent>(OnDoAfter);
+ SubscribeLocalEvent<ToolRefinableComponent, InteractUsingEvent>(OnInteractUsing);
+ SubscribeLocalEvent<ToolRefinableComponent, WelderRefineDoAfterEvent>(OnDoAfter);
}
- private void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args)
+ private void OnInteractUsing(EntityUid uid, ToolRefinableComponent component, InteractUsingEvent args)
{
if (args.Handled)
return;
fuel: component.RefineFuel);
}
- private void OnDoAfter(EntityUid uid, WelderRefinableComponent component, WelderRefineDoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, ToolRefinableComponent component, WelderRefineDoAfterEvent args)
{
if (args.Cancelled)
return;
+ if (_net.IsClient)
+ return;
+
var xform = Transform(uid);
var spawns = EntitySpawnCollection.GetSpawns(component.RefineResult, _random);
foreach (var spawn in spawns)
- DoorBumpOpener
- FootstepSound
- type: Tool # Open door from xeno.yml.
- speed: 1.5
+ speedModifier: 1.5
qualities:
- Prying
useSound:
NavSmash: !type:Bool
true
- type: Tool
- speed: 1.5
+ speedModifier: 1.5
qualities:
- Prying
- type: Prying
- type: Tool
qualities:
- Rolling
- speed: 0.75 # not as good as a rolling pin but does the job
+ speedModifier: 0.75 # not as good as a rolling pin but does the job
- type: PhysicalComposition
materialComposition:
Glass: 100
- type: Tool
qualities:
- Rolling
- speed: 0.25 # its small so takes longer to roll the entire dough flat
+ speedModifier: 0.25 # its small so takes longer to roll the entire dough flat
- type: SpaceGarbage
- type: TrashOnSolutionEmpty
solution: drink
components:
- type: Sprite
color: "#bbeeff"
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- type: DamageUserOnTrigger
damage:
types:
Slash: 4.5
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: PartRodMetal1
damage:
types:
Slash: 5.5
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: SheetPlasma1
types:
Slash: 4.5
Radiation: 2
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: SheetUranium1
components:
- type: Sprite
color: "#e0aa36"
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: SheetBrass1
materialComposition:
Glass: 50
- type: SpaceGarbage
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- type: Tool
qualities:
- Rolling
- speed: 0.5 # its very big, akward to use
+ speedModifier: 0.5 # its very big, akward to use
- type: Appearance
- type: GenericVisualizer
visuals:
materialComposition:
Glass: 25
- type: SpaceGarbage
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- type: Construction
graph: CyanLight
node: icon
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: ShardCrystalCyan
- type: Construction
graph: BlueLight
node: icon
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: ShardCrystalBlue
- type: Construction
graph: PinkLight
node: icon
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: ShardCrystalPink
- type: Construction
graph: OrangeLight
node: icon
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: ShardCrystalOrange
- type: Construction
graph: RedLight
node: icon
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: ShardCrystalRed
- type: Construction
graph: GreenLight
node: icon
- - type: WelderRefinable
+ - type: ToolRefinable
refineResult:
- id: SheetGlass1
- id: ShardCrystalGreen
- type: Tool
qualities:
- Sawing
- speed: 1.0
+ speedModifier: 1.0
# No melee for regular saw because have you ever seen someone use a band saw as a weapon? It's dumb.
- type: entity
- type: Tool
qualities:
- Sawing
- speed: 0.5
+ speedModifier: 0.5
- type: entity
name: circular saw
- type: Tool
qualities:
- Sawing
- speed: 1.5
+ speedModifier: 1.5
- type: entity
name: advanced circular saw
- type: Tool
qualities:
- Sawing
- speed: 2.0
+ speedModifier: 2.0
- Cutting
useSound:
path: /Audio/Items/wirecutter.ogg
- speed: 0.05
+ speedModifier: 0.05
- type: Item
sprite: Objects/Tools/Cowtools/haycutters.rsi
- Screwing
useSound:
collection: Screwdriver
- speed: 0.05
+ speedModifier: 0.05
- type: entity
name: wronch
- Anchoring
useSound:
path: /Audio/Items/ratchet.ogg
- speed: 0.05
+ speedModifier: 0.05
- type: entity
name: cowbar
- Prying
useSound:
path: /Audio/Items/crowbar.ogg
- speed: 0.05
+ speedModifier: 0.05
- type: ToolTileCompatible
- type: Prying
size: Small
sprite: Objects/Tools/Cowtools/cowelder.rsi
- type: Tool
- speed: 0.05
+ speedModifier: 0.05
- type: entity
name: milkalyzer
- type: Tool
qualities:
- Rolling
- speed: 0.6 # fairly unwieldly but nice round surface
+ speedModifier: 0.6 # fairly unwieldly but nice round surface
- type: entity
parent: GasTankRoundBase
- type: Tool
qualities:
- Prying
- speed: 1.5
+ speedModifier: 1.5
useSound: /Audio/Items/jaws_pry.ogg
- type: Prying
pryPowered: true
- type: Tool
qualities:
- Prying
- speed: 3.0
+ speedModifier: 3.0
- type: MultipleTool
entries:
- behavior: Prying
- type: Tool
qualities:
- Screwing
- speed: 1.5
+ speedModifier: 1.5
useSound: /Audio/Items/drill_use.ogg
- type: MultipleTool
statusShowBehavior: true
- type: Tool
qualities:
- Screwing
- speed: 1.2 # Kept for future adjustments. Currently 1.2x for balance
+ speedModifier: 1.2 # Kept for future adjustments. Currently 1.2x for balance
useSound: /Audio/Items/drill_use.ogg
- type: ToolTileCompatible
- type: MultipleTool
Quantity: 250
maxVol: 250
- type: Tool
- speed: 1.3
+ speedModifier: 1.3
- type: entity
name: experimental welding tool
Quantity: 50
maxVol: 50
- type: Tool
- speed: 0.7
+ speedModifier: 0.7
- type: PointLight
enabled: false
radius: 1.0
- type: Tool
qualities:
- Rolling
- speed: 0.75 # a bit unwieldly but does the job
+ speedModifier: 0.75 # a bit unwieldly but does the job
- type: Clothing
quickEquip: false
slots:
- type: ReagentTank
tankType: Fuel
- type: DamageOnToolInteract
- tools:
- - Welding
+ tools: Welding
weldingDamage:
types:
Heat: 10
fillBaseName: watertank-2-
- type: ExaminableSolution
solution: tank
-
- type: ReagentTank
tankType: Fuel
- type: DamageOnToolInteract
- tools:
- - Welding
+ tools: Welding
weldingDamage:
types:
Heat: 20
- type: Tool
qualities:
- Screwing
- speed: 2 # Very powerful multitool to balance out the desire to sell or scrap for points
+ speedModifier: 2 # Very powerful multitool to balance out the desire to sell or scrap for points
useSound: /Audio/Items/drill_use.ogg
- type: Tag
tags: