stealth clothing (#19397)
Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -20,6 +20,11 @@ public sealed class GetItemActionsEvent : EntityEventArgs
|
|||||||
{
|
{
|
||||||
public SortedSet<ActionType> Actions = new();
|
public SortedSet<ActionType> Actions = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User equipping the item.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid User;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Slot flags for the inventory slot that this item got equipped to. Null if not in a slot (i.e., if equipped to hands).
|
/// Slot flags for the inventory slot that this item got equipped to. Null if not in a slot (i.e., if equipped to hands).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -30,8 +35,9 @@ public sealed class GetItemActionsEvent : EntityEventArgs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool InHands => SlotFlags == null;
|
public bool InHands => SlotFlags == null;
|
||||||
|
|
||||||
public GetItemActionsEvent(SlotFlags? slotFlags = null)
|
public GetItemActionsEvent(EntityUid user, SlotFlags? slotFlags = null)
|
||||||
{
|
{
|
||||||
|
User = user;
|
||||||
SlotFlags = slotFlags;
|
SlotFlags = slotFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -410,7 +410,7 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
#region EquipHandlers
|
#region EquipHandlers
|
||||||
private void OnDidEquip(EntityUid uid, ActionsComponent component, DidEquipEvent args)
|
private void OnDidEquip(EntityUid uid, ActionsComponent component, DidEquipEvent args)
|
||||||
{
|
{
|
||||||
var ev = new GetItemActionsEvent(args.SlotFlags);
|
var ev = new GetItemActionsEvent(args.Equipee, args.SlotFlags);
|
||||||
RaiseLocalEvent(args.Equipment, ev);
|
RaiseLocalEvent(args.Equipment, ev);
|
||||||
|
|
||||||
if (ev.Actions.Count == 0)
|
if (ev.Actions.Count == 0)
|
||||||
@@ -421,7 +421,7 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnHandEquipped(EntityUid uid, ActionsComponent component, DidEquipHandEvent args)
|
private void OnHandEquipped(EntityUid uid, ActionsComponent component, DidEquipHandEvent args)
|
||||||
{
|
{
|
||||||
var ev = new GetItemActionsEvent();
|
var ev = new GetItemActionsEvent(args.User);
|
||||||
RaiseLocalEvent(args.Equipped, ev);
|
RaiseLocalEvent(args.Equipped, ev);
|
||||||
|
|
||||||
if (ev.Actions.Count == 0)
|
if (ev.Actions.Count == 0)
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Actions.ActionTypes;
|
||||||
|
using Content.Shared.Clothing.EntitySystems;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Clothing.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds StealthComponent to the user when enabled, either by an action or the system's SetEnabled method.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(StealthClothingSystem))]
|
||||||
|
public sealed partial class StealthClothingComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether stealth effect is enabled.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("enabled"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||||
|
public bool Enabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number added to MinVisibility when stealthed, to make the user not fully invisible.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("visibility"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||||
|
public float Visibility;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The action for enabling and disabling stealth.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("toggleAction")]
|
||||||
|
public InstantAction ToggleAction = new()
|
||||||
|
{
|
||||||
|
Event = new ToggleStealthEvent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When stealth is enabled, disables it.
|
||||||
|
/// When it is disabled, raises <see cref="AttemptStealthEvent"/> before enabling.
|
||||||
|
/// Put any checks in a handler for that event to cancel it.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class ToggleStealthEvent : InstantActionEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
137
Content.Shared/Clothing/EntitySystems/StealthClothingSystem.cs
Normal file
137
Content.Shared/Clothing/EntitySystems/StealthClothingSystem.cs
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Clothing.Components;
|
||||||
|
using Content.Shared.Inventory.Events;
|
||||||
|
using Content.Shared.Stealth;
|
||||||
|
using Content.Shared.Stealth.Components;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Clothing.EntitySystems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the toggle action and disables stealth when clothing is unequipped.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class StealthClothingSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedStealthSystem _stealth = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StealthClothingComponent, GetItemActionsEvent>(OnGetItemActions);
|
||||||
|
SubscribeLocalEvent<StealthClothingComponent, ToggleStealthEvent>(OnToggleStealth);
|
||||||
|
SubscribeLocalEvent<StealthClothingComponent, AfterAutoHandleStateEvent>(OnHandleState);
|
||||||
|
SubscribeLocalEvent<StealthClothingComponent, GotUnequippedEvent>(OnUnequipped);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the clothing's stealth effect for the user.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if it was changed, false otherwise</returns>
|
||||||
|
public bool SetEnabled(EntityUid uid, EntityUid user, bool enabled, StealthClothingComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp) || comp.Enabled == enabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO remove this when clothing unequip on delete is less sus
|
||||||
|
// prevent debug assert when ending round and its disabled
|
||||||
|
if (MetaData(user).EntityLifeStage >= EntityLifeStage.Terminating)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
comp.Enabled = enabled;
|
||||||
|
Dirty(uid, comp);
|
||||||
|
|
||||||
|
var stealth = EnsureComp<StealthComponent>(user);
|
||||||
|
// slightly visible, but doesn't change when moving so it's ok
|
||||||
|
var visibility = enabled ? stealth.MinVisibility + comp.Visibility : stealth.MaxVisibility;
|
||||||
|
_stealth.SetVisibility(user, visibility, stealth);
|
||||||
|
_stealth.SetEnabled(user, enabled, stealth);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise <see cref="AddStealthActionEvent"/> then add the toggle action if it was not cancelled.
|
||||||
|
/// </summary>
|
||||||
|
private void OnGetItemActions(EntityUid uid, StealthClothingComponent comp, GetItemActionsEvent args)
|
||||||
|
{
|
||||||
|
var ev = new AddStealthActionEvent(args.User);
|
||||||
|
RaiseLocalEvent(uid, ev);
|
||||||
|
if (ev.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Actions.Add(comp.ToggleAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises <see cref="AttemptStealthEvent"/> if enabling.
|
||||||
|
/// </summary>
|
||||||
|
private void OnToggleStealth(EntityUid uid, StealthClothingComponent comp, ToggleStealthEvent args)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
var user = args.Performer;
|
||||||
|
if (comp.Enabled)
|
||||||
|
{
|
||||||
|
SetEnabled(uid, user, false, comp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ev = new AttemptStealthEvent(user);
|
||||||
|
RaiseLocalEvent(uid, ev);
|
||||||
|
if (ev.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetEnabled(uid, user, true, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls <see cref="SetEnabled"/> when server sends new state.
|
||||||
|
/// </summary>
|
||||||
|
private void OnHandleState(EntityUid uid, StealthClothingComponent comp, ref AfterAutoHandleStateEvent args)
|
||||||
|
{
|
||||||
|
// SetEnabled checks if it is the same, so change it to before state was received from the server
|
||||||
|
var enabled = comp.Enabled;
|
||||||
|
comp.Enabled = !enabled;
|
||||||
|
var user = Transform(uid).ParentUid;
|
||||||
|
SetEnabled(uid, user, enabled, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Force unstealths the user, doesnt remove StealthComponent since other things might use it
|
||||||
|
/// </summary>
|
||||||
|
private void OnUnequipped(EntityUid uid, StealthClothingComponent comp, GotUnequippedEvent args)
|
||||||
|
{
|
||||||
|
SetEnabled(uid, args.Equipee, false, comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on the stealth clothing when attempting to add an action.
|
||||||
|
/// </summary>
|
||||||
|
public class AddStealthActionEvent : CancellableEntityEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// User that equipped the stealth clothing.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid User;
|
||||||
|
|
||||||
|
public AddStealthActionEvent(EntityUid user)
|
||||||
|
{
|
||||||
|
User = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on the stealth clothing when the user is attemping to enable it.
|
||||||
|
/// </summary>
|
||||||
|
public class AttemptStealthEvent : CancellableEntityEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// User that is attempting to enable the stealth clothing.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid User;
|
||||||
|
|
||||||
|
public AttemptStealthEvent(EntityUid user)
|
||||||
|
{
|
||||||
|
User = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,6 +101,20 @@
|
|||||||
sprite: Clothing/OuterClothing/Suits/spaceninja.rsi
|
sprite: Clothing/OuterClothing/Suits/spaceninja.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/OuterClothing/Suits/spaceninja.rsi
|
sprite: Clothing/OuterClothing/Suits/spaceninja.rsi
|
||||||
|
- type: StealthClothing
|
||||||
|
visibility: 0.3
|
||||||
|
toggleAction:
|
||||||
|
# have to plan (un)cloaking ahead of time
|
||||||
|
useDelay: 5
|
||||||
|
name: action-name-toggle-phase-cloak
|
||||||
|
description: action-desc-toggle-phase-cloak
|
||||||
|
priority: -9
|
||||||
|
event: !type:ToggleStealthEvent
|
||||||
|
- type: PressureProtection
|
||||||
|
highPressureMultiplier: 0.6
|
||||||
|
lowPressureMultiplier: 1000
|
||||||
|
- type: TemperatureProtection
|
||||||
|
coefficient: 0.01
|
||||||
- type: Armor
|
- type: Armor
|
||||||
modifiers:
|
modifiers:
|
||||||
coefficients:
|
coefficients:
|
||||||
|
|||||||
Reference in New Issue
Block a user