Mousetraps (#8440)

Co-authored-by: Kara <lunarautomaton6@gmail.com>
This commit is contained in:
Flipp Syder
2022-05-25 13:16:34 -07:00
committed by GitHub
parent bd6725e9d9
commit a8f1ffd435
16 changed files with 315 additions and 15 deletions

View File

@@ -359,6 +359,8 @@ namespace Content.Client.Entry
"Thirst",
"CanEscapeInventory",
"PowerSink",
"Mousetrap",
"DamageOnTrigger",
"Wires",
};
}

View File

@@ -0,0 +1,12 @@
using Content.Shared.Damage;
namespace Content.Server.Damage.Components;
[RegisterComponent]
public sealed class DamageOnTriggerComponent : Component
{
[DataField("ignoreResistances")] public bool IgnoreResistances;
[DataField("damage", required: true)]
public DamageSpecifier Damage = default!;
}

View File

@@ -0,0 +1,49 @@
using Content.Server.Damage.Components;
using Content.Shared.Damage;
using Content.Shared.StepTrigger;
namespace Content.Server.Damage.Systems;
// System for damage that occurs on specific triggers.
// This is originally meant for mousetraps, but could
// probably be extended to fit other triggers as well.
public sealed class DamageOnTriggerSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
public override void Initialize()
{
SubscribeLocalEvent<DamageOnTriggerComponent, StepTriggeredEvent>(OnStepTrigger);
}
private void OnStepTrigger(EntityUid uid, DamageOnTriggerComponent component, ref StepTriggeredEvent args)
{
OnDamageTrigger(uid, args.Tripper, component);
}
private void OnDamageTrigger(EntityUid source, EntityUid target, DamageOnTriggerComponent? component = null)
{
if (!Resolve(source, ref component))
{
return;
}
var damage = new DamageSpecifier(component.Damage);
var ev = new BeforeDamageOnTriggerEvent(damage, target);
RaiseLocalEvent(source, ev);
_damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances);
}
}
public sealed class BeforeDamageOnTriggerEvent : EntityEventArgs
{
public DamageSpecifier Damage { get; set; }
public EntityUid Tripper { get; }
public BeforeDamageOnTriggerEvent(DamageSpecifier damage, EntityUid target)
{
Damage = damage;
Tripper = target;
}
}

View File

@@ -0,0 +1,21 @@
namespace Content.Server.Mousetrap;
[RegisterComponent]
public sealed class MousetrapComponent : Component
{
[ViewVariables]
public bool IsActive;
/// <summary>
/// Set this to change where the
/// inflection point in the scaling
/// equation will occur.
/// The default is 10.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("massBalance")]
public int MassBalance = 10;
[DataField("ignoreDamageIfInventorySlotsFilled")]
public List<string> IgnoreDamageIfSlotFilled = new();
}

View File

@@ -0,0 +1,82 @@
using Content.Server.Damage.Systems;
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory;
using Content.Shared.Mousetrap;
using Content.Shared.StepTrigger;
namespace Content.Server.Mousetrap;
public sealed class MousetrapSystem : EntitySystem
{
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly TriggerSystem _triggerSystem = default!;
public override void Initialize()
{
SubscribeLocalEvent<MousetrapComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<MousetrapComponent, BeforeDamageOnTriggerEvent>(BeforeDamageOnTrigger);
SubscribeLocalEvent<MousetrapComponent, StepTriggerAttemptEvent>(OnStepTriggerAttempt);
SubscribeLocalEvent<MousetrapComponent, StepTriggeredEvent>(OnStepTrigger);
}
private void OnUseInHand(EntityUid uid, MousetrapComponent component, UseInHandEvent args)
{
component.IsActive = !component.IsActive;
UpdateVisuals(uid);
}
private void OnStepTriggerAttempt(EntityUid uid, MousetrapComponent component, ref StepTriggerAttemptEvent args)
{
args.Continue = component.IsActive;
}
private void BeforeDamageOnTrigger(EntityUid uid, MousetrapComponent component, BeforeDamageOnTriggerEvent args)
{
foreach (var slot in component.IgnoreDamageIfSlotFilled)
{
if (!_inventorySystem.TryGetSlotContainer(args.Tripper, slot, out var container, out _))
{
continue;
}
// This also means that wearing slippers won't
// hurt the entity.
if (container.ContainedEntity != null)
{
args.Damage *= 0;
return;
}
}
if (TryComp(args.Tripper, out PhysicsComponent? physics))
{
// The idea here is inverse,
// Small - big damage,
// Large - small damage
// yes i punched numbers into a calculator until the graph looked right
var scaledDamage = -50 * Math.Atan(physics.Mass - component.MassBalance) + (25 * Math.PI);
args.Damage *= scaledDamage;
}
}
private void OnStepTrigger(EntityUid uid, MousetrapComponent component, ref StepTriggeredEvent args)
{
component.IsActive = false;
_triggerSystem.Trigger(uid);
UpdateVisuals(uid);
}
private void UpdateVisuals(EntityUid uid, MousetrapComponent? mousetrap = null, AppearanceComponent? appearance = null)
{
if (!Resolve(uid, ref mousetrap, ref appearance, false))
{
return;
}
appearance.SetData(MousetrapVisuals.Visual,
mousetrap.IsActive ? MousetrapVisuals.Armed : MousetrapVisuals.Unarmed);
}
}

View File

@@ -0,0 +1,11 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Mousetrap;
[Serializable, NetSerializable]
public enum MousetrapVisuals : byte
{
Visual,
Armed,
Unarmed
}

View File

@@ -22,6 +22,18 @@
category: Service
group: market
- type: cargoProduct
name: "mousetraps crate"
id: MousetrapBoxes
description: "Mousetraps, for when all of service is being haunted by an entire horde of rats. Use sparingly... or not."
icon:
sprite: Objects/Devices/mousetrap.rsi
state: normal
product: CrateMousetrapBoxes
cost: 1000
category: Service
group: market
- type: cargoProduct
name: "lung cancer crate"
id: ServiceSmokeables
@@ -57,7 +69,7 @@
cost: 1000
category: Service
group: market
- type: cargoProduct
name: "personnel crate"
id: ServicePersonnel

View File

@@ -7,6 +7,21 @@
- type: Sprite
state: box
- type: entity
name: mousetrap box
parent: BoxCardboard
id: BoxMousetrap
description: This box is filled with mousetraps. Try not to get your hand stuck in one.
components:
- type: StorageFill
contents:
- id: Mousetrap
amount: 6
- type: Sprite
layers:
- state: box
- state: mousetraps
- type: entity
name: lightbulb box
parent: BoxCardboard

View File

@@ -34,6 +34,17 @@
- id: BoxLightbulb
amount: 1
- type: entity
id: CrateMousetrapBoxes
name: mousetraps crate
description: Mousetraps, for when all of service is being haunted by an entire horde of rats. Use sparingly... or not.
parent: CrateGenericSteel
components:
- type: StorageFill
contents:
- id: BoxMousetrap
amount: 1
- type: entity
id: CrateServiceSmokeables
name: smokeables crate

View File

@@ -30,6 +30,8 @@
contents:
- id: CrowbarRed
- id: MonkeyCubeBox
- id: BoxMousetrap
amount: 2
- id: SprayBottleWater
- id: ReagentContainerFlour
amount: 2
@@ -49,6 +51,8 @@
- type: StorageFill
contents:
- id: MopItem
- id: BoxMousetrap
amount: 2
- id: WetFloorSign
amount: 3
- id: TrashBag

View File

@@ -507,7 +507,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.48
mass: 20
mass: 60
mask:
- MobMask
layer:
@@ -560,7 +560,7 @@
crit: kangaroo-dead
dead: kangaroo-dead
- type: Puller
- type: entity
name: boxing kangaroo
parent: MobKangaroo
@@ -997,7 +997,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.25
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -1213,7 +1213,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -1269,7 +1269,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -1325,7 +1325,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:

View File

@@ -19,7 +19,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -138,7 +138,7 @@
spawned:
- id: FoodMeatCorgi
amount: 2
- type: entity
name: Old Ian
parent: MobCorgi
@@ -225,7 +225,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -375,7 +375,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -418,7 +418,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -472,7 +472,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -515,7 +515,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:
@@ -592,7 +592,7 @@
- shape:
!type:PhysShapeCircle
radius: 0.35
mass: 10
mass: 20
mask:
- MobMask
layer:

View File

@@ -0,0 +1,58 @@
- type: entity
name: mousetrap
parent: BaseItem
id: Mousetrap
components:
- type: Sprite
sprite: Objects/Devices/mousetrap.rsi
netsync: false
drawdepth: SmallMobs # if mice can hide under tables, so can mousetraps
layers:
- state: mousetrap
- type: StepTrigger
intersectRatio: 0.2
requiredTriggeredSpeed: 0
- type: Mousetrap
ignoreDamageIfInventorySlotsFilled:
- shoes # shoes
- type: DamageOnTrigger
damage:
types:
Blunt: 2 # base damage, scales based on mass
- type: EmitSoundOnUse
sound: "/Audio/Items/Handcuffs/cuff_end.ogg"
- type: EmitSoundOnTrigger
sound: "/Audio/Items/snap.ogg"
- type: Item
sprite: Objects/Devices/mousetrap.rsi
- type: Appearance
visuals:
- type: GenericEnumVisualizer
key: enum.MousetrapVisuals.Visual
layer: 0
states:
enum.MousetrapVisuals.Armed: mousetraparmed
enum.MousetrapVisuals.Unarmed: mousetrap
- type: Physics
bodyType: Dynamic
- type: CollisionWake
enabled: false
- type: Fixtures
fixtures:
- shape:
!type:PhysShapeAabb
bounds: "-0.2,-0.2,0.2,0.2"
id: "slips"
hard: false
layer:
- LowImpassable
- shape:
!type:PhysShapeAabb
bounds: "-0.2,-0.2,0.2,0.2"
mass: 5
mask:
- ItemMask
- type: Rotatable
- type: Tag
tags:
- DroneUsable

View File

@@ -0,0 +1,23 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from https://github.com/tgstation/tgstation/commit/4323540b6bec3ae93bbf13d685c2dbe0cb40a36e",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "mousetrap",
"directions": 4
},
{
"name": "mousetraparmed",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB