Speed Boots [Tier 3 Civ-Service] (#21438)

* Speed Boots

* validate

* monkey
This commit is contained in:
Nemanja
2023-11-07 20:25:43 -05:00
committed by GitHub
parent a6985e5b4b
commit 94368f1f00
24 changed files with 296 additions and 33 deletions

View File

@@ -1,4 +1,5 @@
using Content.Shared.PowerCell;
using Content.Shared.PowerCell.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
@@ -15,6 +16,29 @@ public sealed class PowerCellSystem : SharedPowerCellSystem
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)

View File

@@ -16,6 +16,7 @@ using Content.Shared.Mind;
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;

View File

@@ -22,7 +22,7 @@ public sealed partial class PowerCellSystem
if (!comp.Drawing)
continue;
if (_timing.CurTime < comp.NextUpdateTime)
if (Timing.CurTime < comp.NextUpdateTime)
continue;
comp.NextUpdateTime += Delay;

View File

@@ -1,9 +1,5 @@
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;
@@ -15,7 +11,6 @@ using Content.Server.Power.EntitySystems;
using Content.Server.UserInterface;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Popups;
using Robust.Shared.Timing;
namespace Content.Server.PowerCell;
@@ -24,7 +19,6 @@ 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!;
@@ -95,12 +89,8 @@ public sealed partial class PowerCellSystem : SharedPowerCellSystem
}
#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))
@@ -108,6 +98,7 @@ public sealed partial class PowerCellSystem : SharedPowerCellSystem
return HasCharge(uid, battery.UseRate, cell, user);
}
/// <summary>
/// Tries to use the <see cref="PowerCellDrawComponent.UseRate"/> for this entity.
/// </summary>
@@ -128,11 +119,12 @@ public sealed partial class PowerCellSystem : SharedPowerCellSystem
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;
@@ -142,15 +134,6 @@ public sealed partial class PowerCellSystem : SharedPowerCellSystem
#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>

View File

@@ -1,4 +1,5 @@
using Content.Server.PowerCell;
using Content.Shared.PowerCell;
using Content.Shared.Weapons.Misc;
using Robust.Shared.Physics.Components;

View File

@@ -1,6 +1,11 @@
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;
@@ -10,9 +15,13 @@ namespace Content.Shared.Clothing;
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()
{
@@ -22,6 +31,12 @@ public sealed class ClothingSpeedModifierSystem : EntitySystem
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
@@ -34,7 +49,7 @@ public sealed class ClothingSpeedModifierSystem : EntitySystem
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))
@@ -126,4 +141,61 @@ public sealed class ClothingSpeedModifierSystem : EntitySystem
_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);
}
}

View File

@@ -0,0 +1,35 @@
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
{
}

View File

@@ -1,4 +1,4 @@
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.

View File

@@ -2,24 +2,26 @@ using Content.Shared.Containers.ItemSlots;
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;
@@ -60,4 +62,35 @@ public abstract class SharedPowerCellSystem : EntitySystem
_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);
}

View File

@@ -1,2 +1,3 @@
toggle-clothing-verb-text = Toggle {CAPITALIZE($entity)}
toggleable-clothing-remove-first = You have to unequip {$entity} first.

View File

@@ -70,3 +70,4 @@ research-technology-meat-manipulation = Meat Manipulation
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

View File

@@ -69,3 +69,52 @@
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 }

View File

@@ -255,6 +255,7 @@
- SynthesizerInstrument
- RPED
- ClothingShoesBootsMag
- ClothingShoesBootsSpeed
- NodeScanner
- HolofanProjector
- BluespaceBeaker

View File

@@ -85,6 +85,15 @@
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

View File

@@ -204,3 +204,15 @@
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

View File

@@ -0,0 +1,41 @@
{
"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
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B