Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Felinid Soft Thieving + Trait #500

Merged
merged 21 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Content.Client/Inventory/StrippableBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.Player;
using Robust.Shared.Input;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
Expand All @@ -31,6 +32,7 @@ namespace Content.Client.Inventory
public sealed class StrippableBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IUserInterfaceManager _ui = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
private readonly ExamineSystem _examine;
private readonly InventorySystem _inv;
private readonly SharedCuffableSystem _cuffable;
Expand Down Expand Up @@ -198,7 +200,8 @@ private void AddInventoryButton(EntityUid invUid, string slotId, InventoryCompon
var entity = container.ContainedEntity;

// If this is a full pocket, obscure the real entity
if (entity != null && slotDef.StripHidden)
if (entity != null && slotDef.StripHidden
&& !(EntMan.TryGetComponent<ThievingComponent>(_playerManager.LocalEntity, out var thiefcomponent) && thiefcomponent.IgnoreStripHidden))
entity = _virtualHiddenEntity;

var button = new SlotButton(new SlotData(slotDef, container));
Expand Down
51 changes: 30 additions & 21 deletions Content.Server/Strip/StrippableSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public sealed class StrippableSystem : SharedStrippableSystem
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;

[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly ThievingSystem _thieving = default!;

// TODO: ECS popups. Not all of these have ECS equivalents yet.

Expand Down Expand Up @@ -251,15 +252,17 @@ private void StartStripInsertInventory(

var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime);

if (!stealth)
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-insert", ("user", Identity.Entity(user, EntityManager)), ("item", user.Comp.ActiveHandEntity!.Value)), target, target, PopupType.Large);
bool hidden = stealth == ThievingStealth.Hidden;

var prefix = stealth ? "stealthily " : "";
if (!hidden)
StripPopup("strippable-component-alert-owner-insert", stealth, target, user: Identity.Entity(user, EntityManager), item: user.Comp.ActiveHandEntity!.Value);

var prefix = hidden ? "stealthily " : "";
_adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}place the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot");

var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(true, true, slot), user, target, held)
{
Hidden = stealth,
Hidden = hidden,
AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
Expand Down Expand Up @@ -340,20 +343,22 @@ private void StartStripRemoveInventory(

var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime);

if (!stealth)
bool hidden = stealth == ThievingStealth.Hidden;

if (!hidden)
{
if (slotDef.StripHidden)
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), target, target, PopupType.Large);
StripPopup("strippable-component-alert-owner-hidden", stealth, target, slot: slot);
else
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target, PopupType.Large);
StripPopup("strippable-component-alert-owner", stealth, target, user: Identity.Entity(user, EntityManager), item: item);
}

var prefix = stealth ? "stealthily " : "";
var prefix = hidden ? "stealthily " : "";
_adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot");

var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(false, true, slot), user, target, item)
{
Hidden = stealth,
Hidden = hidden,
AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
Expand All @@ -374,7 +379,7 @@ private void StripRemoveInventory(
EntityUid target,
EntityUid item,
string slot,
bool stealth)
bool hidden)
{
if (!CanStripRemoveInventory(user, target, item, slot))
return;
Expand All @@ -384,7 +389,7 @@ private void StripRemoveInventory(

RaiseLocalEvent(item, new DroppedEvent(user), true); // Gas tank internals etc.

_handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: stealth);
_handsSystem.PickupOrDrop(user, item, animateUser: hidden, animate: hidden);
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot");
}

Expand Down Expand Up @@ -446,12 +451,14 @@ private void StartStripInsertHand(

var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay);

var prefix = stealth ? "stealthily " : "";
bool hidden = stealth == ThievingStealth.Hidden;

var prefix = hidden ? "stealthily " : "";
_adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}place the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands");

var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(true, false, handName), user, target, held)
{
Hidden = stealth,
Hidden = hidden,
AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
Expand All @@ -471,7 +478,7 @@ private void StripInsertHand(
Entity<HandsComponent?> target,
EntityUid held,
string handName,
bool stealth)
bool hidden)
{
if (!Resolve(user, ref user.Comp) ||
!Resolve(target, ref target.Comp))
Expand All @@ -481,7 +488,7 @@ private void StripInsertHand(
return;

_handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: user.Comp);
_handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: stealth, animate: stealth, handsComp: target.Comp);
_handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: hidden, animate: hidden, handsComp: target.Comp);
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands");

// Hand update will trigger strippable update.
Expand Down Expand Up @@ -543,15 +550,17 @@ private void StartStripRemoveHand(

var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay);

if (!stealth)
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target);
bool hidden = stealth == ThievingStealth.Hidden;

if (!hidden)
StripPopup("strippable-component-alert-owner", stealth, target, user: Identity.Entity(user, EntityManager), item: item);

var prefix = stealth ? "stealthily " : "";
var prefix = hidden ? "stealthily " : "";
_adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands");

var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(false, false, handName), user, target, item)
{
Hidden = stealth,
Hidden = hidden,
AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
Expand All @@ -572,7 +581,7 @@ private void StripRemoveHand(
Entity<HandsComponent?> target,
EntityUid item,
string handName,
bool stealth)
bool hidden)
{
if (!Resolve(user, ref user.Comp) ||
!Resolve(target, ref target.Comp))
Expand All @@ -582,7 +591,7 @@ private void StripRemoveHand(
return;

_handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: target.Comp);
_handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: stealth, handsComp: user.Comp);
_handsSystem.PickupOrDrop(user, item, animateUser: hidden, animate: hidden, handsComp: user.Comp);
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands");

// Hand update will trigger strippable update.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public sealed class ToggleableClothingSystem : EntitySystem
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedStrippableSystem _strippable = default!;
[Dependency] private readonly ThievingSystem _thieving = default!;

public override void Initialize()
{
Expand Down Expand Up @@ -97,6 +98,8 @@ private void StartDoAfter(EntityUid user, EntityUid item, EntityUid wearer, Togg

var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, component.StripDelay.Value);

bool hidden = (stealth == ThievingStealth.Hidden);

var args = new DoAfterArgs(EntityManager, user, time, new ToggleClothingDoAfterEvent(), item, wearer, item)
{
BreakOnDamage = true,
Expand All @@ -110,11 +113,8 @@ private void StartDoAfter(EntityUid user, EntityUid item, EntityUid wearer, Togg
if (!_doAfter.TryStartDoAfter(args))
return;

if (!stealth)
{
var popup = Loc.GetString("strippable-component-alert-owner-interact", ("user", Identity.Entity(user, EntityManager)), ("item", item));
_popupSystem.PopupEntity(popup, wearer, wearer, PopupType.Large);
}
if (!hidden)
_strippable.StripPopup("strippable-component-alert-owner-interact", stealth, wearer, user: Identity.Entity(user, EntityManager), item: item);
}

private void OnGetAttachedStripVerbsEvent(EntityUid uid, AttachedClothingComponent component, GetVerbsEvent<EquipmentVerb> args)
Expand Down
8 changes: 4 additions & 4 deletions Content.Shared/Strip/Components/StrippableComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public sealed class StrippingSlotButtonPressed(string slot, bool isHand) : Bound
public sealed class StrippingEnsnareButtonPressed : BoundUserInterfaceMessage;

[ByRefEvent]
public abstract class BaseBeforeStripEvent(TimeSpan initialTime, bool stealth = false) : EntityEventArgs, IInventoryRelayEvent
public abstract class BaseBeforeStripEvent(TimeSpan initialTime, ThievingStealth stealth = ThievingStealth.Obvious) : EntityEventArgs, IInventoryRelayEvent
{
public readonly TimeSpan InitialTime = initialTime;
public float Multiplier = 1f;
public TimeSpan Additive = TimeSpan.Zero;
public bool Stealth = stealth;
public ThievingStealth Stealth = stealth;

public TimeSpan Time => TimeSpan.FromSeconds(MathF.Max(InitialTime.Seconds * Multiplier + Additive.Seconds, 0f));

Expand All @@ -51,7 +51,7 @@ public abstract class BaseBeforeStripEvent(TimeSpan initialTime, bool stealth =
/// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player.
/// </remarks>
[ByRefEvent]
public sealed class BeforeStripEvent(TimeSpan initialTime, bool stealth = false) : BaseBeforeStripEvent(initialTime, stealth);
public sealed class BeforeStripEvent(TimeSpan initialTime, ThievingStealth stealth = ThievingStealth.Obvious) : BaseBeforeStripEvent(initialTime, stealth);

/// <summary>
/// Used to modify strip times. Raised directed at the target.
Expand All @@ -60,7 +60,7 @@ public sealed class BeforeStripEvent(TimeSpan initialTime, bool stealth = false)
/// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player.
/// </remarks>
[ByRefEvent]
public sealed class BeforeGettingStrippedEvent(TimeSpan initialTime, bool stealth = false) : BaseBeforeStripEvent(initialTime, stealth);
public sealed class BeforeGettingStrippedEvent(TimeSpan initialTime, ThievingStealth stealth = ThievingStealth.Obvious) : BaseBeforeStripEvent(initialTime, stealth);

/// <summary>
/// Organizes the behavior of DoAfters for <see cref="StrippableSystem">.
Expand Down
20 changes: 15 additions & 5 deletions Content.Shared/Strip/Components/ThievingComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,24 @@ public sealed partial class ThievingComponent : Component
/// <summary>
/// How much the strip time should be shortened by
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("stripTimeReduction")]
[DataField]
public TimeSpan StripTimeReduction = TimeSpan.FromSeconds(0.5f);

/// <summary>
/// A multiplier coefficient for strip time
/// </summary>
[DataField]
public float StripTimeMultiplier = 1f;

/// <summary>
/// Should it notify the user if they're stripping a pocket?
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("stealthy")]
public bool Stealthy;
[DataField]
public ThievingStealth Stealth = ThievingStealth.Hidden;

/// <summary>
/// Should the user be able to see hidden items? (i.e pockets)
/// </summary>
[DataField]
public bool IgnoreStripHidden;
}
18 changes: 17 additions & 1 deletion Content.Shared/Strip/SharedStrippableSystem.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using Content.Shared.DragDrop;
using Content.Shared.Hands.Components;
using Content.Shared.Popups;
using Content.Shared.Strip.Components;

namespace Content.Shared.Strip;

public abstract class SharedStrippableSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly ThievingSystem _thieving = default!;
public override void Initialize()
{
base.Initialize();
Expand All @@ -14,7 +17,7 @@ public override void Initialize()
SubscribeLocalEvent<StrippableComponent, DragDropDraggedEvent>(OnDragDrop);
}

public (TimeSpan Time, bool Stealth) GetStripTimeModifiers(EntityUid user, EntityUid target, TimeSpan initialTime)
public (TimeSpan Time, ThievingStealth Stealth) GetStripTimeModifiers(EntityUid user, EntityUid target, TimeSpan initialTime)
{
var userEv = new BeforeStripEvent(initialTime);
RaiseLocalEvent(user, ref userEv);
Expand Down Expand Up @@ -55,4 +58,17 @@ private void OnCanDrop(EntityUid uid, StrippableComponent component, ref CanDrop
if (args.CanDrop)
args.Handled = true;
}

public void StripPopup(string messageId, ThievingStealth stealth, EntityUid target, EntityUid? user = null, EntityUid? item = null, string slot = "")
{
bool subtle = stealth == ThievingStealth.Subtle;
PopupType? popupSize = _thieving.GetPopupTypeFromStealth(stealth);

if (popupSize.HasValue) // We should always have a value if we're not hidden
_popup.PopupEntity(Loc.GetString(messageId,
("user", subtle ? Loc.GetString("thieving-component-user") : user ?? EntityUid.Invalid),
("item", subtle ? Loc.GetString("thieving-component-item") : item ?? EntityUid.Invalid),
("slot", slot)),
target, target, popupSize.Value);
}
}
39 changes: 37 additions & 2 deletions Content.Shared/Strip/ThievingSystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Content.Shared.Inventory;
using Content.Shared.Strip;
using Content.Shared.Popups;
using Content.Shared.Strip.Components;
using Robust.Shared.Serialization;

namespace Content.Shared.Strip;

Expand All @@ -17,7 +18,41 @@ public override void Initialize()

private void OnBeforeStrip(EntityUid uid, ThievingComponent component, BeforeStripEvent args)
{
args.Stealth |= component.Stealthy;
args.Stealth = (ThievingStealth) Math.Max((sbyte) args.Stealth, (sbyte) component.Stealth);
args.Additive -= component.StripTimeReduction;
args.Multiplier *= component.StripTimeMultiplier;
}

public PopupType? GetPopupTypeFromStealth(ThievingStealth stealth)
{
switch (stealth)
{
case ThievingStealth.Hidden:
return null;

case ThievingStealth.Subtle:
return PopupType.Small;

default:
return PopupType.Large;
}
}
}
[Serializable, NetSerializable]
public enum ThievingStealth : sbyte
{
/// <summary>
/// Target sees a large popup indicating that an item is being stolen by who
/// </summary>
Obvious = 0,

/// <summary>
/// Target sees a small popup indicating that an item is being stolen
/// </summary>
Subtle = 1,

/// <summary>
/// Target does not see any popup regarding the stealing of an item
/// </summary>
Hidden = 2
}
6 changes: 5 additions & 1 deletion Resources/Locale/en-US/strip/strippable-component.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ strip-verb-get-data-text = Strip
## UI

strippable-bound-user-interface-stripping-menu-title = {$ownerName}'s inventory
strippable-bound-user-interface-stripping-menu-ensnare-button = Remove Leg Restraints
strippable-bound-user-interface-stripping-menu-ensnare-button = Remove Leg Restraints

# Stealth
thieving-component-user = Someone
thieving-component-item = something
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/traits/traits.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ trait-description-SocialAnxiety = You are anxious when you speak and stutter.

trait-name-Snoring = Snoring
trait-description-Snoring = You will snore while sleeping.

trait-name-Thieving = Thieving
trait-description-Thieving =
You are deft with your hands, and talented at convincing people of their belongings.
You can identify pocketed items, steal them quieter, and steal ~33% faster.
Loading
Loading