Shards damage barefoot users + steptrigger-related general cleanup (#9585)

This commit is contained in:
Kara
2022-07-10 02:28:37 -07:00
committed by GitHub
parent 37bf333674
commit 459f8d23eb
22 changed files with 220 additions and 92 deletions

View File

@@ -5,6 +5,7 @@ using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Slippery;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Systems;
using JetBrains.Annotations;
using Robust.Shared.Map;

View File

@@ -3,7 +3,7 @@ using Content.Shared.Damage;
namespace Content.Server.Damage.Components;
[RegisterComponent]
public sealed class DamageOnTriggerComponent : Component
public sealed class DamageUserOnTriggerComponent : Component
{
[DataField("ignoreResistances")] public bool IgnoreResistances;

View File

@@ -1,49 +0,0 @@
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, true);
_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,52 @@
using Content.Server.Damage.Components;
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Systems;
namespace Content.Server.Damage.Systems;
// System for damage that occurs on specific trigger, towards the user..
public sealed class DamageUserOnTriggerSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
public override void Initialize()
{
SubscribeLocalEvent<DamageUserOnTriggerComponent, TriggerEvent>(OnTrigger);
}
private void OnTrigger(EntityUid uid, DamageUserOnTriggerComponent component, TriggerEvent args)
{
if (args.User is null)
return;
args.Handled |= OnDamageTrigger(uid, args.User.Value, component);
}
private bool OnDamageTrigger(EntityUid source, EntityUid target, DamageUserOnTriggerComponent? component = null)
{
if (!Resolve(source, ref component))
{
return false;
}
var damage = new DamageSpecifier(component.Damage);
var ev = new BeforeDamageUserOnTriggerEvent(damage, target);
RaiseLocalEvent(source, ev);
return _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances) is not null;
}
}
public sealed class BeforeDamageUserOnTriggerEvent : EntityEventArgs
{
public DamageSpecifier Damage { get; set; }
public EntityUid Tripper { get; }
public BeforeDamageUserOnTriggerEvent(DamageSpecifier damage, EntityUid target)
{
Damage = damage;
Tripper = target;
}
}

View File

@@ -0,0 +1,10 @@
namespace Content.Server.Explosion.Components;
/// <summary>
/// This is used for entities that want the more generic 'trigger' behavior after a step trigger occurs.
/// Not done by default, since it's not useful for everything and might cause weird behavior. But it is useful for a lot of stuff like mousetraps.
/// </summary>
[RegisterComponent]
public sealed class TriggerOnStepTriggerComponent : Component
{
}

View File

@@ -14,6 +14,7 @@ using Content.Shared.Trigger;
using Content.Shared.Database;
using Content.Shared.Explosion;
using Content.Shared.Interaction;
using Content.Shared.StepTrigger.Systems;
namespace Content.Server.Explosion.EntitySystems
{
@@ -52,6 +53,7 @@ namespace Content.Server.Explosion.EntitySystems
SubscribeLocalEvent<TriggerOnCollideComponent, StartCollideEvent>(OnTriggerCollide);
SubscribeLocalEvent<TriggerOnActivateComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<TriggerOnStepTriggerComponent, StepTriggeredEvent>(OnStepTriggered);
SubscribeLocalEvent<DeleteOnTriggerComponent, TriggerEvent>(HandleDeleteTrigger);
SubscribeLocalEvent<ExplodeOnTriggerComponent, TriggerEvent>(HandleExplodeTrigger);
@@ -91,6 +93,11 @@ namespace Content.Server.Explosion.EntitySystems
args.Handled = true;
}
private void OnStepTriggered(EntityUid uid, TriggerOnStepTriggerComponent component, ref StepTriggeredEvent args)
{
Trigger(uid, args.Tripper);
}
public bool Trigger(EntityUid trigger, EntityUid? user = null)
{
var triggerEvent = new TriggerEvent(trigger, user);

View File

@@ -5,6 +5,8 @@ using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Fluids;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Components;
using Content.Shared.StepTrigger.Systems;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Player;

View File

@@ -3,6 +3,4 @@
[RegisterComponent]
public sealed class LandMineComponent : Component
{
[DataField("deleteOnActivate")]
public bool DeleteOnActivate = true;
}

View File

@@ -1,6 +1,7 @@
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Systems;
using Robust.Shared.Player;
namespace Content.Server.LandMines;
@@ -27,6 +28,8 @@ public sealed class LandMineSystem : EntitySystem
private void HandleTriggered(EntityUid uid, LandMineComponent component, ref StepTriggeredEvent args)
{
// This doesn't use TriggerOnStepTrigger since we don't want to display the popup if nothing happens
// and I didn't feel like making an `AfterTrigger` event
if (_trigger.Trigger(uid, args.Tripper))
{
_popupSystem.PopupCoordinates(
@@ -35,9 +38,6 @@ public sealed class LandMineSystem : EntitySystem
Filter.Entities(args.Tripper),
PopupType.LargeCaution);
}
if (component.DeleteOnActivate)
QueueDel(uid);
}
}

View File

@@ -15,7 +15,4 @@ public sealed class MousetrapComponent : Component
[ViewVariables(VVAccess.ReadWrite)]
[DataField("massBalance")]
public int MassBalance = 10;
[DataField("ignoreDamageIfInventorySlotsFilled")]
public List<string> IgnoreDamageIfSlotFilled = new();
}

View File

@@ -5,6 +5,7 @@ using Content.Shared.Interaction.Events;
using Content.Shared.Inventory;
using Content.Shared.Mousetrap;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Systems;
using Robust.Shared.Player;
namespace Content.Server.Mousetrap;
@@ -18,9 +19,9 @@ public sealed class MousetrapSystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<MousetrapComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<MousetrapComponent, BeforeDamageOnTriggerEvent>(BeforeDamageOnTrigger);
SubscribeLocalEvent<MousetrapComponent, BeforeDamageUserOnTriggerEvent>(BeforeDamageOnTrigger);
SubscribeLocalEvent<MousetrapComponent, StepTriggerAttemptEvent>(OnStepTriggerAttempt);
SubscribeLocalEvent<MousetrapComponent, StepTriggeredEvent>(OnStepTrigger);
SubscribeLocalEvent<MousetrapComponent, TriggerEvent>(OnTrigger);
}
private void OnUseInHand(EntityUid uid, MousetrapComponent component, UseInHandEvent args)
@@ -37,27 +38,11 @@ public sealed class MousetrapSystem : EntitySystem
private void OnStepTriggerAttempt(EntityUid uid, MousetrapComponent component, ref StepTriggerAttemptEvent args)
{
args.Continue = component.IsActive;
args.Continue |= component.IsActive;
}
private void BeforeDamageOnTrigger(EntityUid uid, MousetrapComponent component, BeforeDamageOnTriggerEvent args)
private void BeforeDamageOnTrigger(EntityUid uid, MousetrapComponent component, BeforeDamageUserOnTriggerEvent 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) && physics.Mass != 0)
{
// The idea here is inverse,
@@ -69,11 +54,9 @@ public sealed class MousetrapSystem : EntitySystem
}
}
private void OnStepTrigger(EntityUid uid, MousetrapComponent component, ref StepTriggeredEvent args)
private void OnTrigger(EntityUid uid, MousetrapComponent component, TriggerEvent args)
{
component.IsActive = false;
_triggerSystem.Trigger(uid);
UpdateVisuals(uid);
}

View File

@@ -2,7 +2,7 @@ using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Inventory;
using Content.Shared.StatusEffect;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Systems;
using Content.Shared.Stunnable;
using JetBrains.Annotations;
using Robust.Shared.Containers;

View File

@@ -1,5 +1,6 @@
using Content.Shared.Sound;
using Content.Shared.StepTrigger;
using Content.Shared.StepTrigger.Components;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;

View File

@@ -0,0 +1,11 @@
using Robust.Shared.GameStates;
namespace Content.Shared.StepTrigger.Components;
/// <summary>
/// This is used for cancelling step trigger events if the user is wearing shoes, such as for glass shards.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed class ShoesRequiredStepTriggerComponent : Component
{
}

View File

@@ -1,7 +1,8 @@
using Content.Shared.StepTrigger.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.StepTrigger;
namespace Content.Shared.StepTrigger.Components;
[RegisterComponent]
[NetworkedComponent]

View File

@@ -0,0 +1,33 @@
using Content.Shared.Examine;
using Content.Shared.Inventory;
using Content.Shared.StepTrigger.Components;
namespace Content.Shared.StepTrigger.Systems;
public sealed class ShoesRequiredStepTriggerSystem : EntitySystem
{
[Dependency] private readonly InventorySystem _inventory = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<ShoesRequiredStepTriggerComponent, StepTriggerAttemptEvent>(OnStepTriggerAttempt);
SubscribeLocalEvent<ShoesRequiredStepTriggerComponent, ExaminedEvent>(OnExamined);
}
private void OnStepTriggerAttempt(EntityUid uid, ShoesRequiredStepTriggerComponent component, ref StepTriggerAttemptEvent args)
{
if (!TryComp<InventoryComponent>(args.Tripper, out var inventory))
return;
if (_inventory.TryGetSlotEntity(args.Tripper, "shoes", out _, inventory))
{
args.Cancelled = true;
}
}
private void OnExamined(EntityUid uid, ShoesRequiredStepTriggerComponent component, ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("shoes-required-step-trigger-examine"));
}
}

View File

@@ -1,8 +1,9 @@
using Content.Shared.StepTrigger.Components;
using Robust.Shared.Collections;
using Robust.Shared.GameStates;
using Robust.Shared.Physics.Dynamics;
namespace Content.Shared.StepTrigger;
namespace Content.Shared.StepTrigger.Systems;
public sealed class StepTriggerSystem : EntitySystem
{
@@ -93,7 +94,7 @@ public sealed class StepTriggerSystem : EntitySystem
RaiseLocalEvent(uid, ref msg, true);
return msg.Continue;
return msg.Continue && !msg.Cancelled;
}
private void HandleCollide(EntityUid uid, StepTriggerComponent component, StartCollideEvent args)
@@ -177,6 +178,10 @@ public struct StepTriggerAttemptEvent
public EntityUid Source;
public EntityUid Tripper;
public bool Continue;
/// <summary>
/// Set by systems which wish to cancel the step trigger event, regardless of event ordering.
/// </summary>
public bool Cancelled;
}
[ByRefEvent]

View File

@@ -0,0 +1 @@
shoes-required-step-trigger-examine = You probably shouldn't step on this barefoot.

View File

@@ -2,6 +2,7 @@
name: mousetrap
parent: BaseItem
id: Mousetrap
description: Useful for catching rodents sneaking into your kitchen.
components:
- type: Sprite
sprite: Objects/Devices/mousetrap.rsi
@@ -13,9 +14,9 @@
intersectRatio: 0.2
requiredTriggeredSpeed: 0
- type: Mousetrap
ignoreDamageIfInventorySlotsFilled:
- shoes # shoes
- type: DamageOnTrigger
- type: TriggerOnStepTrigger
- type: ShoesRequiredStepTrigger
- type: DamageUserOnTrigger
damage:
types:
Blunt: 2 # base damage, scales based on mass

View File

@@ -92,3 +92,33 @@
sides: 4
- type: Sprite
state: d44
- 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: StepTrigger
intersectRatio: 0.2
requiredTriggeredSpeed: 0
- type: TriggerOnStepTrigger
- type: ShoesRequiredStepTrigger
- type: Slippery
slipSound:
path: /Audio/Effects/glass_step.ogg
launchForwardsMultiplier: 0
- type: DamageUserOnTrigger
damage:
types:
Piercing: 5

View File

@@ -19,6 +19,23 @@
Slash: 5
- type: Item
sprite: Objects/Materials/Shards/shard.rsi
- 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: DamageOtherOnHit
damage:
types:
@@ -39,12 +56,25 @@
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: StepTrigger
intersectRatio: 0.2
requiredTriggeredSpeed: 0
- type: ShoesRequiredStepTrigger
- type: Slippery
slipSound:
path: /Audio/Effects/glass_step.ogg
launchForwardsMultiplier: 0
- type: TriggerOnStepTrigger
- type: DamageUserOnTrigger
damage:
types:
Piercing: 5
- type: entity
parent: ShardBase
id: ShardGlass
name: glass shard
description: A small piece of glass. It looks sharp, you wouldn't want to step on it barefoot.
description: A small piece of glass.
components:
- type: Sprite
color: "#bbeeff"
@@ -53,12 +83,16 @@
- type: WelderRefinable
refineResult:
- SheetGlass1
- type: DamageUserOnTrigger
damage:
types:
Piercing: 5
- type: entity
parent: ShardBase
id: ShardGlassReinforced
name: reinforced glass shard
description: A small piece of reinforced glass. It looks sharp, you wouldn't want to step on it barefoot.
description: A small piece of reinforced glass.
components:
- type: Sprite
color: "#96cdef"
@@ -68,12 +102,16 @@
refineResult:
- SheetGlass1
- SheetSteel1
- type: DamageUserOnTrigger
damage:
types:
Piercing: 10
- type: entity
parent: ShardBase
id: ShardGlassPlasma
name: plasma glass shard
description: A small piece of plasma glass. It looks sharp, you wouldn't want to step on it barefoot.
description: A small piece of plasma glass.
components:
- type: Sprite
color: "#f3b489"
@@ -83,3 +121,7 @@
refineResult:
- SheetGlass1
- SheetPlasma1
- type: DamageUserOnTrigger
damage:
types:
Piercing: 15

View File

@@ -35,6 +35,7 @@
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: LandMine
- type: TriggerOnStepTrigger
- type: StepTrigger
requiredTriggeredSpeed: 0
@@ -44,6 +45,7 @@
id: LandMineKick
components:
- type: GhostKickUserOnTrigger
- type: DeleteOnTrigger
- type: entity
name: modular mine
@@ -56,7 +58,6 @@
graph: ModularMineGraph
node: emptyCase
- type: LandMine
deleteOnActivate: false
- type: entity
name: explosive mine
@@ -70,3 +71,4 @@
intensitySlope: 3
totalIntensity: 120 # about a ~4 tile radius
canCreateVacuum: false
- type: DeleteOnTrigger