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

Port Drop on Slip #54

Merged
merged 9 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions Content.Server/Parkstation/Slippery/DropOnSlipComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Content.Server.Parkstation.Slippery;

/// <summary>
/// Marks this item as one that may be dropped when its wearer slips with it equipped.
/// </summary>
[RegisterComponent]
public sealed partial class DropOnSlipComponent : Component
{
/// <summary>
/// Percent chance to drop this item when slipping
/// </summary>
[DataField("chance")]
[ViewVariables(VVAccess.ReadWrite)]
public int Chance = 20;
}
96 changes: 96 additions & 0 deletions Content.Server/Parkstation/Slippery/DropOnSlipSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System.Numerics;
using Content.Server.Popups;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Interaction.Components;
using Content.Shared.Inventory;
using Content.Shared.Popups;
using Content.Shared.Slippery;
using Content.Shared.Throwing;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Random;

namespace Content.Server.Parkstation.Slippery;

public sealed class DropOnSlipSystem : EntitySystem
{
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;

public float PocketDropChance = 10f;
public float PocketThrowChance = 5f;

public float ClumsyDropChance = 5f;
public float ClumsyThrowChance = 90f;


public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<InventoryComponent, ParkSlipEvent>(HandleSlip);
}


private void HandleSlip(EntityUid entity, InventoryComponent invComp, ParkSlipEvent args)
{
if (!_inventory.TryGetSlots(entity, out var slotDefinitions))
return;

foreach (var slot in slotDefinitions)
{
if (!_inventory.TryGetSlotEntity(entity, slot.Name, out var item))
continue;

if (ShouldBeDropped(entity, slot, item))
{
var popupString = Loc.GetString("system-drop-on-slip-text-component", ("name", entity), ("item", item));

Drop(entity, item.Value, slot.Name, popupString);
}
}
}

private bool ShouldBeDropped(EntityUid entity, SlotDefinition slot, EntityUid? item)
{
// Check for any items in pockets or other criteria
if (slot.SlotFlags == SlotFlags.POCKET && _random.NextFloat(0, 100) < PocketDropChance)
return true;

// Check for DropOnSlipComponent
if (EntityManager.TryGetComponent<Parkstation.Slippery.DropOnSlipComponent>(item, out var dropComp) && _random.NextFloat(0, 100) < dropComp.Chance)
return true;

// Check for ClumsyComponent
if (slot.Name != "jumpsuit" && _random.NextFloat(0, 100) < ClumsyDropChance && HasComp<ClumsyComponent>(entity))
return true;

return false;
}

private void Drop(EntityUid entity, EntityUid item, string slot, string popupString)
{
if (!_inventory.TryUnequip(entity, slot, false, true))
return;

EntityManager.TryGetComponent<PhysicsComponent>(entity, out var entPhysComp);

if (entPhysComp != null)
{
var strength = entPhysComp.LinearVelocity.Length() / 1.5f;
Vector2 direction = new Vector2(_random.Next(-8, 8), _random.Next(-8, 8));

_throwing.TryThrow(item, direction, strength, entity);
}

_popup.PopupEntity(popupString, item, PopupType.MediumCaution);

var logMessage = Loc.GetString("system-drop-on-slip-log", ("entity", ToPrettyString(entity)), ("item", ToPrettyString(item)));
_adminLogger.Add(LogType.Slip, LogImpact.Low, $"{logMessage}");
}
}
9 changes: 9 additions & 0 deletions Content.Shared/Slippery/SlipperySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ private void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other

_stun.TryParalyze(other, TimeSpan.FromSeconds(component.ParalyzeTime), true);

RaiseLocalEvent(other, new ParkSlipEvent(uid)); // Parkstation-DropOnSlip

// Preventing from playing the slip sound when you are already knocked down.
if (playSound)
{
Expand Down Expand Up @@ -131,3 +133,10 @@ public record struct SlipCausingAttemptEvent (bool Cancelled);
/// <param name="Slipped">The entity being slipped</param>
[ByRefEvent]
public readonly record struct SlipEvent(EntityUid Slipped);

// Parkstation-DropOnSlip-Start
/// <summary>
/// This is an event raised on an entity after they slip. Duh.
/// </summary>
public readonly record struct ParkSlipEvent(EntityUid Tripper);
// Parkstation-DropOnSlip-End
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
system-drop-on-slip-text-component = {$name}'s {$item} slips off!
system-drop-on-slip-text-pocket = Something falls out of {$name}'s pocket!
system-drop-on-slip-text-clumsy = The {$item} tumbles off of {$name}!

system-drop-on-slip-log = {$entity} dropped {$item} when slipping.
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Clothing/Ears/headsets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
- type: GuideHelp
guides:
- Radio
- type: DropOnSlip
chance: 5

- type: entity
parent: ClothingHeadset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
state: icon_alt
- type: Clothing
equippedPrefix: alt
- type: DropOnSlip
chance: 0

- type: entity
parent: ClothingHeadsetAlt
Expand Down
8 changes: 8 additions & 0 deletions Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
- type: Tag
tags:
- SecDogWearable # DeltaV - let Laika wear meson goggles
- type: DropOnSlip
chance: 30

- type: entity
parent: ClothingEyesBase
Expand All @@ -83,6 +85,8 @@
- HamsterWearable
- WhitelistChameleon
- GlassesNearsight # SimpleStation14 NearsightedTrait
- type: DropOnSlip
chance: 30

- type: entity
parent: ClothingEyesBase
Expand Down Expand Up @@ -144,6 +148,8 @@
- SecDogWearable # DeltaV - let Laika wear sunglasses
- type: IdentityBlocker
coverage: EYES
- type: DropOnSlip
chance: 30

- type: entity
parent: ClothingEyesGlassesCheapSunglasses
Expand Down Expand Up @@ -210,6 +216,8 @@
coefficients:
Heat: 0.95
- type: GroupExamine
- type: DropOnSlip
chance: 30

- type: entity
parent: ClothingEyesBase
Expand Down
6 changes: 6 additions & 0 deletions Resources/Prototypes/Entities/Clothing/Eyes/hud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
damageContainers:
- Inorganic
- Silicon
- type: DropOnSlip
chance: 25

- type: entity
parent: ClothingEyesBase
Expand All @@ -32,6 +34,8 @@
- type: Tag
tags:
- HudMedical
- type: DropOnSlip
chance: 25

- type: entity
parent: ClothingEyesBase
Expand All @@ -47,6 +51,8 @@
- type: Tag
tags:
- HudSecurity
- type: DropOnSlip
chance: 25

- type: entity
parent: ClothingEyesBase
Expand Down
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Clothing/Head/hardhats.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
- type: Tag
tags:
- WhitelistChameleon
- type: DropOnSlip
chance: 15

- type: entity
parent: ClothingHeadHatHardhatBase
Expand Down
Loading
Loading