using Content.Shared.PowerCell;
+using Content.Shared.PowerCell.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
SubscribeLocalEvent<PowerCellVisualsComponent, AppearanceChangeEvent>(OnPowerCellVisualsChange);
}
+ /// <inheritdoc/>
+ public override bool HasActivatableCharge(EntityUid uid, PowerCellDrawComponent? battery = null, PowerCellSlotComponent? cell = null,
+ EntityUid? user = null)
+ {
+ if (!Resolve(uid, ref battery, ref cell, false))
+ return true;
+
+ return battery.CanUse;
+ }
+
+ /// <inheritdoc/>
+ public override bool HasDrawCharge(
+ EntityUid uid,
+ PowerCellDrawComponent? battery = null,
+ PowerCellSlotComponent? cell = null,
+ EntityUid? user = null)
+ {
+ if (!Resolve(uid, ref battery, ref cell, false))
+ return true;
+
+ return battery.CanDraw;
+ }
+
private void OnPowerCellVisualsChange(EntityUid uid, PowerCellVisualsComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
+using Content.Shared.PowerCell;
using Content.Shared.Timing;
using Content.Shared.Toggleable;
using Robust.Shared.Player;
if (!comp.Drawing)
continue;
- if (_timing.CurTime < comp.NextUpdateTime)
+ if (Timing.CurTime < comp.NextUpdateTime)
continue;
comp.NextUpdateTime += Delay;
-using Content.Server.Administration.Logs;
-using Content.Server.Chemistry.EntitySystems;
-using Content.Server.Explosion.EntitySystems;
using Content.Server.Emp;
using Content.Server.Power.Components;
-using Content.Shared.Database;
using Content.Shared.Examine;
using Content.Shared.PowerCell;
using Content.Shared.PowerCell.Components;
using Content.Server.UserInterface;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Popups;
-using Robust.Shared.Timing;
namespace Content.Server.PowerCell;
/// </summary>
public sealed partial class PowerCellSystem : SharedPowerCellSystem
{
- [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ActivatableUISystem _activatable = default!;
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
}
#region Activatable
-
- /// <summary>
- /// Returns whether the entity has a slotted battery and <see cref="PowerCellDrawComponent.UseRate"/> charge.
- /// </summary>
- /// <param name="user">Popup to this user with the relevant detail if specified.</param>
- public bool HasActivatableCharge(EntityUid uid, PowerCellDrawComponent? battery = null, PowerCellSlotComponent? cell = null, EntityUid? user = null)
+ /// <inheritdoc/>
+ public override bool HasActivatableCharge(EntityUid uid, PowerCellDrawComponent? battery = null, PowerCellSlotComponent? cell = null, EntityUid? user = null)
{
// Default to true if we don't have the components.
if (!Resolve(uid, ref battery, ref cell, false))
return HasCharge(uid, battery.UseRate, cell, user);
}
+
/// <summary>
/// Tries to use the <see cref="PowerCellDrawComponent.UseRate"/> for this entity.
/// </summary>
return false;
}
- /// <summary>
- /// Whether the power cell has any power at all for the draw rate.
- /// </summary>
- public bool HasDrawCharge(EntityUid uid, PowerCellDrawComponent? battery = null,
- PowerCellSlotComponent? cell = null, EntityUid? user = null)
+ /// <inheritdoc/>
+ public override bool HasDrawCharge(
+ EntityUid uid,
+ PowerCellDrawComponent? battery = null,
+ PowerCellSlotComponent? cell = null,
+ EntityUid? user = null)
{
if (!Resolve(uid, ref battery, ref cell, false))
return true;
#endregion
- public void SetPowerCellDrawEnabled(EntityUid uid, bool enabled, PowerCellDrawComponent? component = null)
- {
- if (!Resolve(uid, ref component, false) || enabled == component.Drawing)
- return;
-
- component.Drawing = enabled;
- component.NextUpdateTime = _timing.CurTime;
- }
-
/// <summary>
/// Returns whether the entity has a slotted battery and charge for the requested action.
/// </summary>
using Content.Server.PowerCell;
+using Content.Shared.PowerCell;
using Content.Shared.Weapons.Misc;
using Robust.Shared.Physics.Components;
+using Content.Shared.Actions;
+using Content.Shared.Clothing.Components;
using Content.Shared.Examine;
+using Content.Shared.IdentityManagement;
using Content.Shared.Inventory;
using Content.Shared.Movement.Systems;
+using Content.Shared.PowerCell;
+using Content.Shared.Toggleable;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
public sealed class ClothingSpeedModifierSystem : EntitySystem
{
- [Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!;
+ [Dependency] private readonly SharedActionsSystem _actions = default!;
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly ClothingSpeedModifierSystem _clothingSpeedModifier = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
+ [Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!;
+ [Dependency] private readonly SharedPowerCellSystem _powerCell = default!;
public override void Initialize()
{
SubscribeLocalEvent<ClothingSpeedModifierComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<ClothingSpeedModifierComponent, InventoryRelayedEvent<RefreshMovementSpeedModifiersEvent>>(OnRefreshMoveSpeed);
SubscribeLocalEvent<ClothingSpeedModifierComponent, GetVerbsEvent<ExamineVerb>>(OnClothingVerbExamine);
+
+ SubscribeLocalEvent<ToggleClothingSpeedComponent, GetVerbsEvent<ActivationVerb>>(AddToggleVerb);
+ SubscribeLocalEvent<ToggleClothingSpeedComponent, GetItemActionsEvent>(OnGetActions);
+ SubscribeLocalEvent<ToggleClothingSpeedComponent, ToggleClothingSpeedEvent>(OnToggleSpeed);
+ SubscribeLocalEvent<ToggleClothingSpeedComponent, MapInitEvent>(OnMapInit);
+ SubscribeLocalEvent<ToggleClothingSpeedComponent, PowerCellSlotEmptyEvent>(OnPowerCellSlotEmpty);
}
// Public API
if (component.Enabled != enabled)
{
component.Enabled = enabled;
- Dirty(component);
+ Dirty(uid, component);
// inventory system will automatically hook into the event raised by this and update accordingly
if (_container.TryGetContainingContainer(uid, out var container))
_examine.AddDetailedExamineVerb(args, component, msg, Loc.GetString("clothing-speed-examinable-verb-text"), "/Textures/Interface/VerbIcons/outfit.svg.192dpi.png", Loc.GetString("clothing-speed-examinable-verb-message"));
}
+
+ private void OnMapInit(Entity<ToggleClothingSpeedComponent> uid, ref MapInitEvent args)
+ {
+ _actions.AddAction(uid, ref uid.Comp.ToggleActionEntity, uid.Comp.ToggleAction);
+ }
+
+ private void OnToggleSpeed(Entity<ToggleClothingSpeedComponent> uid, ref ToggleClothingSpeedEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ args.Handled = true;
+ SetSpeedToggleEnabled(uid, !uid.Comp.Enabled, args.Performer);
+ }
+
+ private void SetSpeedToggleEnabled(Entity<ToggleClothingSpeedComponent> uid, bool value, EntityUid? user)
+ {
+ if (uid.Comp.Enabled == value)
+ return;
+
+ TryComp<PowerCellDrawComponent>(uid, out var draw);
+ if (value && !_powerCell.HasDrawCharge(uid, draw, user: user))
+ return;
+
+ uid.Comp.Enabled = value;
+
+ _appearance.SetData(uid, ToggleVisuals.Toggled, uid.Comp.Enabled);
+ _actions.SetToggled(uid.Comp.ToggleActionEntity, uid.Comp.Enabled);
+ _clothingSpeedModifier.SetClothingSpeedModifierEnabled(uid.Owner, uid.Comp.Enabled);
+ _powerCell.SetPowerCellDrawEnabled(uid, uid.Comp.Enabled, draw);
+ Dirty(uid, uid.Comp);
+ }
+
+ private void AddToggleVerb(Entity<ToggleClothingSpeedComponent> uid, ref GetVerbsEvent<ActivationVerb> args)
+ {
+ if (!args.CanAccess || !args.CanInteract)
+ return;
+
+ var user = args.User;
+ ActivationVerb verb = new()
+ {
+ Text = Loc.GetString("toggle-clothing-verb-text",
+ ("entity", Identity.Entity(uid, EntityManager))),
+ Act = () => SetSpeedToggleEnabled(uid, !uid.Comp.Enabled, user)
+ };
+ args.Verbs.Add(verb);
+ }
+
+ private void OnGetActions(Entity<ToggleClothingSpeedComponent> uid, ref GetItemActionsEvent args)
+ {
+ args.AddAction(ref uid.Comp.ToggleActionEntity, uid.Comp.ToggleAction);
+ }
+
+ private void OnPowerCellSlotEmpty(Entity<ToggleClothingSpeedComponent> uid, ref PowerCellSlotEmptyEvent args)
+ {
+ SetSpeedToggleEnabled(uid, false, null);
+ }
}
--- /dev/null
+using Content.Shared.Actions;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Clothing.Components;
+
+/// <summary>
+/// This is used for a clothing item that gives a speed modification that is toggleable.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(ClothingSpeedModifierSystem)), AutoGenerateComponentState]
+public sealed partial class ToggleClothingSpeedComponent : Component
+{
+ /// <summary>
+ /// The action for toggling the clothing.
+ /// </summary>
+ [DataField]
+ public EntProtoId ToggleAction = "ActionToggleSpeedBoots";
+
+ /// <summary>
+ /// The action entity
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public EntityUid? ToggleActionEntity;
+
+ /// <summary>
+ /// The state of the toggle.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public bool Enabled;
+}
+
+public sealed partial class ToggleClothingSpeedEvent : InstantActionEvent
+{
+
+}
-namespace Content.Server.PowerCell;
+namespace Content.Shared.PowerCell;
/// <summary>
/// Raised directed on an entity when its active power cell has no more charge to supply.
using Content.Shared.PowerCell.Components;
using Content.Shared.Rejuvenate;
using Robust.Shared.Containers;
+using Robust.Shared.Timing;
namespace Content.Shared.PowerCell;
public abstract class SharedPowerCellSystem : EntitySystem
{
+ [Dependency] protected readonly IGameTiming Timing = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent<PowerCellSlotComponent, RejuvenateEvent>(OnRejuventate);
+ SubscribeLocalEvent<PowerCellSlotComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<PowerCellSlotComponent, EntInsertedIntoContainerMessage>(OnCellInserted);
SubscribeLocalEvent<PowerCellSlotComponent, EntRemovedFromContainerMessage>(OnCellRemoved);
SubscribeLocalEvent<PowerCellSlotComponent, ContainerIsInsertingAttemptEvent>(OnCellInsertAttempt);
}
- private void OnRejuventate(EntityUid uid, PowerCellSlotComponent component, RejuvenateEvent args)
+ private void OnRejuvenate(EntityUid uid, PowerCellSlotComponent component, RejuvenateEvent args)
{
if (!_itemSlots.TryGetSlot(uid, component.CellSlotId, out var itemSlot) || !itemSlot.Item.HasValue)
return;
_appearance.SetData(uid, PowerCellSlotVisuals.Enabled, false);
RaiseLocalEvent(uid, new PowerCellChangedEvent(true), false);
}
+
+ public void SetPowerCellDrawEnabled(EntityUid uid, bool enabled, PowerCellDrawComponent? component = null)
+ {
+ if (!Resolve(uid, ref component, false) || enabled == component.Drawing)
+ return;
+
+ component.Drawing = enabled;
+ component.NextUpdateTime = Timing.CurTime;
+ }
+
+ /// <summary>
+ /// Returns whether the entity has a slotted battery and <see cref="PowerCellDrawComponent.UseRate"/> charge.
+ /// </summary>
+ /// <param name="uid"></param>
+ /// <param name="battery"></param>
+ /// <param name="cell"></param>
+ /// <param name="user">Popup to this user with the relevant detail if specified.</param>
+ public abstract bool HasActivatableCharge(
+ EntityUid uid,
+ PowerCellDrawComponent? battery = null,
+ PowerCellSlotComponent? cell = null,
+ EntityUid? user = null);
+
+ /// <summary>
+ /// Whether the power cell has any power at all for the draw rate.
+ /// </summary>
+ public abstract bool HasDrawCharge(
+ EntityUid uid,
+ PowerCellDrawComponent? battery = null,
+ PowerCellSlotComponent? cell = null,
+ EntityUid? user = null);
}
+toggle-clothing-verb-text = Toggle {CAPITALIZE($entity)}
-toggleable-clothing-remove-first = You have to unequip {$entity} first.
\ No newline at end of file
+toggleable-clothing-remove-first = You have to unequip {$entity} first.
research-technology-honk-mech = H.O.N.K. Mech
research-technology-advanced-spray = Advanced Spray
research-technology-bluespace-cargo-transport = Bluespace Cargo Transport
+research-technology-quantum-fiber-weaving = Quantum Fiber Weaving
sprite: Clothing/Shoes/Misc/damedaneshoes.rsi
- type: Clothing
sprite: Clothing/Shoes/Misc/damedaneshoes.rsi
+
+- type: entity
+ parent: [ClothingShoesBase, PowerCellSlotSmallItem]
+ id: ClothingShoesBootsSpeed
+ name: speed boots
+ description: High-tech boots woven with quantum fibers, able to convert electricity into pure speed!
+ components:
+ - type: Sprite
+ sprite: Clothing/Shoes/Boots/speedboots.rsi
+ layers:
+ - state: icon
+ map: [ "enum.ToggleVisuals.Layer" ]
+ - type: Clothing
+ sprite: Clothing/Shoes/Boots/speedboots.rsi
+ - type: ToggleClothingSpeed
+ toggleAction: ActionToggleSpeedBoots
+ - type: ClothingSpeedModifier
+ walkModifier: 1.25
+ sprintModifier: 1.25
+ enabled: false
+ - type: Appearance
+ - type: GenericVisualizer
+ visuals:
+ enum.ToggleVisuals.Toggled:
+ enum.ToggleVisuals.Layer:
+ True: {state: icon-on}
+ False: {state: icon}
+ - type: StaticPrice
+ price: 500
+ - type: PowerCellDraw
+ drawRate: 4
+ - type: ItemSlots
+ slots:
+ cell_slot:
+ name: power-cell-slot-component-slot-name-default
+ - type: Tag
+ tags: []
+
+- type: entity
+ id: ActionToggleSpeedBoots
+ name: Toggle Speed Boots
+ description: Toggles the speed boots on and off.
+ noSpawn: true
+ components:
+ - type: InstantAction
+ itemIconStyle: NoItem
+ event: !type:ToggleClothingSpeedEvent
+ icon: { sprite: Clothing/Shoes/Boots/speedboots.rsi, state: icon }
+ iconOn: { sprite: Clothing/Shoes/Boots/speedboots.rsi, state: icon-on }
- SynthesizerInstrument
- RPED
- ClothingShoesBootsMag
+ - ClothingShoesBootsSpeed
- NodeScanner
- HolofanProjector
- BluespaceBeaker
Steel: 1000
Plastic: 500
+- type: latheRecipe
+ id: ClothingShoesBootsSpeed
+ result: ClothingShoesBootsSpeed
+ completetime: 2
+ materials:
+ Steel: 1500
+ Plastic: 1000
+ Silver: 500
+
- type: latheRecipe
id: ModularReceiver
result: ModularReceiver
cost: 15000
recipeUnlocks:
- CargoTelepadMachineCircuitboard
+
+- type: technology
+ id: QuantumFiberWeaving
+ name: research-technology-quantum-fiber-weaving
+ icon:
+ sprite: Clothing/Shoes/Boots/speedboots.rsi
+ state: icon
+ discipline: CivilianServices
+ tier: 3
+ cost: 10000
+ recipeUnlocks:
+ - ClothingShoesBootsSpeed
--- /dev/null
+{
+ "version": 1,
+ "license": "CC0-1.0",
+ "copyright": "Created by EmoGarbage404",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "equipped-FEET",
+ "directions": 4
+ },
+ {
+ "name": "on-equipped-FEET",
+ "directions": 4
+ },
+ {
+ "name": "icon"
+ },
+ {
+ "name": "icon-on"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "on-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "on-inhand-right",
+ "directions": 4
+ }
+ ]
+}