--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Effects;
+
+/// <summary>
+/// Launches the owner of this component when triggered.
+/// If TargetUser is true, this launches the entity that was collided with instead (because the "user" is the thing that's caused the collision, i.e. the other object).
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class LaunchOnTriggerComponent : BaseXOnTriggerComponent
+{
+ [DataField, AutoNetworkedField]
+ public float Speed = 10.0f;
+}
--- /dev/null
+using System.Numerics;
+using Content.Shared.Trigger.Components.Effects;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Systems;
+
+namespace Content.Shared.Trigger.Systems;
+
+public sealed class LaunchOnTriggerSystem : EntitySystem
+{
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly SharedPhysicsSystem _physics = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<LaunchOnTriggerComponent, TriggerEvent>(OnTrigger);
+ }
+
+ private void OnTrigger(Entity<LaunchOnTriggerComponent> ent, ref TriggerEvent args)
+ {
+ if (args.Key != null && !ent.Comp.KeysIn.Contains(args.Key))
+ return;
+
+ var target = ent.Comp.TargetUser ? args.User : ent.Owner;
+
+ if (target is null)
+ return;
+
+ if (!TryComp(target, out PhysicsComponent? phys))
+ return;
+
+ var linearVelocity = _physics.GetMapLinearVelocity(target.Value);
+ // If the linear velocity is length 0, this means it's not moving. Given we want to move it in some direction...
+ if (linearVelocity.IsLengthZero())
+ // An object that isn't moving is launched in the direction its facing, not the direction it's rotated (objects face away from their rotation).
+ linearVelocity = _transform.GetWorldRotation(target.Value).RotateVec(Vector2.UnitY) * -1;
+
+ // When triggered, take the direction the target is moving in (the normalized vector) and multiply it by the speed.
+ // Then apply an impulse to the target on the new vector.
+ // (If the target is moving NE at 10 m/s, this impulses it NE at speed m/s)
+ _physics.ApplyLinearImpulse(target.Value,
+ linearVelocity.Normalized() * ent.Comp.Speed,
+ body: phys);
+
+ args.Handled = true;
+ }
+}
name: beach ball
description: The simple beach ball is one of Nanotrasen's most popular products. 'Why do we make beach balls? Because we can! (TM)' - Nanotrasen
components:
- - type: Sprite
- sprite: Objects/Fun/Balls/beach_ball.rsi
- state: icon
- - type: Fixtures
- fixtures:
- fix1:
- shape: !type:PhysShapeCircle
- radius: 0.3
- position: "0,-0.2"
- density: 20
- mask:
- - ItemMask
- restitution: 0.1 # not bouncy
- friction: 0.2
- - type: Catchable
- catchChance: 0.8
- catchSuccessSound:
- path: /Audio/Effects/Footsteps/bounce.ogg
- - type: EmitSoundOnCollide
- sound:
- path: /Audio/Effects/Footsteps/bounce.ogg
- - type: Item
- size: Normal
- sprite: Objects/Fun/Balls/beach_ball.rsi
- - type: TileFrictionModifier
- modifier: 0.05
+ - type: Sprite
+ sprite: Objects/Fun/Balls/beach_ball.rsi
+ state: icon
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape: !type:PhysShapeCircle
+ radius: 0.3
+ position: "0,-0.2"
+ density: 20
+ mask:
+ - ThrownItem
+ restitution: 0.2 # not bouncy
+ friction: 0.2
+ - type: Catchable
+ catchChance: 0.8
+ catchSuccessSound:
+ path: /Audio/Effects/Footsteps/bounce.ogg
+ - type: Item
+ size: Normal
+ sprite: Objects/Fun/Balls/beach_ball.rsi
+ - type: TileFrictionModifier
+ modifier: 0.05
+ - type: TriggerOnCollide
+ fixtureID: fix1
+ keyOut: OnCollide
+ - type: EmitSoundOnTrigger
+ sound:
+ path: /Audio/Effects/Footsteps/bounce.ogg
+ keysIn:
+ - OnCollide
+
+- type: entity
+ parent: BeachBall
+ id: EvilBeachBall
+ suffix: evil
+ name: beach ball
+ description: Someone's drawn ">:3c" on the side of this beach ball in indelible ink.
+ components:
+ - type: LaunchOnTrigger
+ speed: 100.0
+ keysIn:
+ - OnCollide
+ - type: StaminaDamageOnTrigger
+ stamina: 25.0
+ keysIn:
+ - OnCollide
+ targetUser: true
+ - type: DamageOnTrigger
+ damage:
+ types:
+ Blunt: 20
+ keysIn:
+ - OnCollide
+ targetUser: true
- type: entity
parent: BaseItem