Adds IThrowCollide, Creaming people with cream pies and tactical stun baton throws (#2122)
@@ -0,0 +1,33 @@
|
|||||||
|
using Content.Shared.GameObjects.Components.Nutrition;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Interfaces.GameObjects.Components;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Nutrition
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public class CreamPiedVisualizer : AppearanceVisualizer
|
||||||
|
{
|
||||||
|
public override void OnChangeData(AppearanceComponent component)
|
||||||
|
{
|
||||||
|
base.OnChangeData(component);
|
||||||
|
|
||||||
|
if (component.TryGetData<bool>(CreamPiedVisuals.Creamed, out var pied))
|
||||||
|
{
|
||||||
|
SetPied(component, pied);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPied(AppearanceComponent component, bool pied)
|
||||||
|
{
|
||||||
|
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||||
|
|
||||||
|
sprite.LayerSetVisible(CreamPiedVisualLayers.Pie, pied);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CreamPiedVisualLayers
|
||||||
|
{
|
||||||
|
Pie,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
namespace Content.Server.GameObjects.Components.Fluids
|
namespace Content.Server.GameObjects.Components.Fluids
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
class SprayComponent : SharedSprayComponent, IAfterInteract, IUse, IActivate
|
class SprayComponent : SharedSprayComponent, IAfterInteract, IUse, IActivate, IDropped
|
||||||
{
|
{
|
||||||
public const float SprayDistance = 3f;
|
public const float SprayDistance = 3f;
|
||||||
|
|
||||||
@@ -211,5 +211,11 @@ namespace Content.Server.GameObjects.Components.Fluids
|
|||||||
if(Owner.TryGetComponent(out AppearanceComponent appearance))
|
if(Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||||
appearance.SetData(SprayVisuals.Safety, _safety);
|
appearance.SetData(SprayVisuals.Safety, _safety);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dropped(DroppedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if(_hasSafety && Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||||
|
appearance.SetData(SprayVisuals.Safety, _safety);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Chemistry;
|
||||||
|
using Content.Server.GameObjects.Components.Fluids;
|
||||||
|
using Content.Shared.Audio;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Nutrition
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class CreamPieComponent : Component, ILand
|
||||||
|
{
|
||||||
|
public override string Name => "CreamPie";
|
||||||
|
|
||||||
|
public void PlaySound()
|
||||||
|
{
|
||||||
|
EntitySystem.Get<AudioSystem>()
|
||||||
|
.PlayFromEntity(AudioHelpers.GetRandomFileFromSoundCollection("desecration"), Owner,
|
||||||
|
AudioHelpers.WithVariation(0.125f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Land(LandEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
PlaySound();
|
||||||
|
|
||||||
|
if (Owner.TryGetComponent(out SolutionContainerComponent solution))
|
||||||
|
{
|
||||||
|
solution.Solution.SpillAt(Owner, "PuddleSmear", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Owner.Delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.Chemistry;
|
||||||
|
using Content.Shared.GameObjects.Components.Nutrition;
|
||||||
|
using Content.Shared.Interfaces;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Nutrition
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class CreamPiedComponent : SharedCreamPiedComponent, IReagentReaction, IThrowCollide
|
||||||
|
{
|
||||||
|
private bool _creamPied;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public bool CreamPied
|
||||||
|
{
|
||||||
|
get => _creamPied;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
_creamPied = value;
|
||||||
|
if (Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||||
|
{
|
||||||
|
appearance.SetData(CreamPiedVisuals.Creamed, CreamPied);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Wash()
|
||||||
|
{
|
||||||
|
if(CreamPied)
|
||||||
|
CreamPied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReagentUnit ReagentReactTouch(ReagentPrototype reagent, ReagentUnit volume)
|
||||||
|
{
|
||||||
|
switch (reagent.ID)
|
||||||
|
{
|
||||||
|
case "chem.SpaceCleaner":
|
||||||
|
case "chem.H2O":
|
||||||
|
Wash();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReagentUnit.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HitBy(ThrowCollideEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!eventArgs.Thrown.TryGetComponent(out CreamPieComponent creamPie) || CreamPied) return;
|
||||||
|
|
||||||
|
CreamPied = true;
|
||||||
|
Owner.PopupMessage(Loc.GetString("You have been creamed by {0:theName}!", eventArgs.Thrown));
|
||||||
|
Owner.PopupMessageOtherClients(Loc.GetString("{0:theName} has been creamed by {1:theName}!", Owner, eventArgs.Thrown));
|
||||||
|
|
||||||
|
if (Owner.TryGetComponent(out StunnableComponent stun))
|
||||||
|
{
|
||||||
|
stun.Paralyze(1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,9 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_shouldStop = true; // hit something hard => stop after this collision
|
_shouldStop = true; // hit something hard => stop after this collision
|
||||||
|
|
||||||
|
// Raise an event.
|
||||||
|
EntitySystem.Get<InteractionSystem>().ThrowCollideInteraction(User, Owner, entity, Owner.Transform.Coordinates);
|
||||||
}
|
}
|
||||||
if (entity.TryGetComponent(out IDamageableComponent damage))
|
if (entity.TryGetComponent(out IDamageableComponent damage))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ using Robust.Shared.ViewVariables;
|
|||||||
namespace Content.Server.GameObjects.Components.Weapon.Melee
|
namespace Content.Server.GameObjects.Components.Weapon.Melee
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class StunbatonComponent : MeleeWeaponComponent, IUse, IExamine, IMapInit, IInteractUsing
|
public class StunbatonComponent : MeleeWeaponComponent, IUse, IExamine, IMapInit, IInteractUsing, IThrowCollide
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
|
|
||||||
@@ -282,5 +282,15 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
|||||||
component.EjectCell(user);
|
component.EjectCell(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DoHit(ThrowCollideEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!Activated || Cell == null || !Cell.TryUseCharge(EnergyPerUse) || !eventArgs.Target.TryGetComponent(out StunnableComponent stunnable))
|
||||||
|
return;
|
||||||
|
|
||||||
|
EntitySystem.Get<AudioSystem>().PlayAtCoords("/Audio/Weapons/egloves.ogg", Owner.Transform.Coordinates, AudioHelpers.WithVariation(0.25f));
|
||||||
|
|
||||||
|
stunnable.Paralyze(_paralyzeTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -625,6 +625,32 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls ThrowCollide on all components that implement the IThrowCollide interface
|
||||||
|
/// on a thrown entity and the target entity it hit.
|
||||||
|
/// </summary>
|
||||||
|
public void ThrowCollideInteraction(IEntity user, IEntity thrown, IEntity target, EntityCoordinates location)
|
||||||
|
{
|
||||||
|
var collideMsg = new ThrowCollideMessage(user, thrown, target, location);
|
||||||
|
RaiseLocalEvent(collideMsg);
|
||||||
|
if (collideMsg.Handled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventArgs = new ThrowCollideEventArgs(user, thrown, target, location);
|
||||||
|
|
||||||
|
foreach (var comp in thrown.GetAllComponents<IThrowCollide>().ToArray())
|
||||||
|
{
|
||||||
|
comp.DoHit(eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var comp in target.GetAllComponents<IThrowCollide>().ToArray())
|
||||||
|
{
|
||||||
|
comp.HitBy(eventArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls Equipped on all components that implement the IEquipped interface
|
/// Calls Equipped on all components that implement the IEquipped interface
|
||||||
/// on an entity that has been equipped.
|
/// on an entity that has been equipped.
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components.Nutrition
|
||||||
|
{
|
||||||
|
public class SharedCreamPiedComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "CreamPied";
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum CreamPiedVisuals
|
||||||
|
{
|
||||||
|
Creamed,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Shared.Interfaces.GameObjects.Components
|
||||||
|
{
|
||||||
|
public interface IThrowCollide
|
||||||
|
{
|
||||||
|
void HitBy(ThrowCollideEventArgs eventArgs) {}
|
||||||
|
void DoHit(ThrowCollideEventArgs eventArgs) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ThrowCollideEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The entity that threw <see cref="Thrown"/> and hit <see cref="Target"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IEntity User { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity thrown by <see cref="User"/> that hit <see cref="Target"/>
|
||||||
|
/// </summary>
|
||||||
|
public IEntity Thrown { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity hit with <see cref="Thrown"/> by <see cref="User"/>
|
||||||
|
/// </summary>
|
||||||
|
public IEntity Target { get; }
|
||||||
|
public EntityCoordinates Location { get; }
|
||||||
|
|
||||||
|
public ThrowCollideEventArgs(IEntity user, IEntity thrown, IEntity target, EntityCoordinates location)
|
||||||
|
{
|
||||||
|
User = user;
|
||||||
|
Thrown = thrown;
|
||||||
|
Target = target;
|
||||||
|
Location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ThrowCollideMessage : EntitySystemMessage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// If this message has already been "handled" by a previous system.
|
||||||
|
/// </summary>
|
||||||
|
public bool Handled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity that threw <see cref="Thrown"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IEntity User { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity thrown by <see cref="User"/> that hit <see cref="Target"/>
|
||||||
|
/// </summary>
|
||||||
|
public IEntity Thrown { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity hit with <see cref="Thrown"/> by <see cref="User"/>
|
||||||
|
/// </summary>
|
||||||
|
public IEntity Target { get; }
|
||||||
|
public EntityCoordinates Location { get; }
|
||||||
|
|
||||||
|
public ThrowCollideMessage(IEntity user, IEntity thrown, IEntity target, EntityCoordinates location)
|
||||||
|
{
|
||||||
|
User = user;
|
||||||
|
Thrown = thrown;
|
||||||
|
Target = target;
|
||||||
|
Location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Resources/Audio/Effects/desecration-01.ogg
Normal file
BIN
Resources/Audio/Effects/desecration-02.ogg
Normal file
BIN
Resources/Audio/Effects/desecration-03.ogg
Normal file
@@ -112,6 +112,10 @@
|
|||||||
sprite: Mobs/Customization/human_hair.rsi
|
sprite: Mobs/Customization/human_hair.rsi
|
||||||
- map: ["enum.Slots.MASK"]
|
- map: ["enum.Slots.MASK"]
|
||||||
- map: ["enum.Slots.HEAD"]
|
- map: ["enum.Slots.HEAD"]
|
||||||
|
- map: ["enum.CreamPiedVisualLayers.Pie"]
|
||||||
|
sprite: Effects/creampie.rsi
|
||||||
|
state: creampie_human
|
||||||
|
visible: false
|
||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Mobs/Species/Human/parts.rsi
|
sprite: Mobs/Species/Human/parts.rsi
|
||||||
state: full
|
state: full
|
||||||
@@ -159,6 +163,7 @@
|
|||||||
visuals:
|
visuals:
|
||||||
- type: RotationVisualizer
|
- type: RotationVisualizer
|
||||||
- type: BuckleVisualizer
|
- type: BuckleVisualizer
|
||||||
|
- type: CreamPiedVisualizer
|
||||||
- type: CombatMode
|
- type: CombatMode
|
||||||
- type: Climbing
|
- type: Climbing
|
||||||
- type: Cuffable
|
- type: Cuffable
|
||||||
@@ -176,6 +181,7 @@
|
|||||||
proper: true
|
proper: true
|
||||||
- type: Pullable
|
- type: Pullable
|
||||||
- type: DoAfter
|
- type: DoAfter
|
||||||
|
- type: CreamPied
|
||||||
- type: Strippable
|
- type: Strippable
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
|
|||||||
@@ -231,6 +231,7 @@
|
|||||||
components:
|
components:
|
||||||
- type: Food
|
- type: Food
|
||||||
trash: TrashPlate
|
trash: TrashPlate
|
||||||
|
- type: CreamPie
|
||||||
- type: SolutionContainer
|
- type: SolutionContainer
|
||||||
contents:
|
contents:
|
||||||
reagents:
|
reagents:
|
||||||
|
|||||||
6
Resources/Prototypes/SoundCollections/desceration.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
- type: soundCollection
|
||||||
|
id: desecration
|
||||||
|
files:
|
||||||
|
- /Audio/Effects/desecration-01.ogg
|
||||||
|
- /Audio/Effects/desecration-02.ogg
|
||||||
|
- /Audio/Effects/desecration-03.ogg
|
||||||
BIN
Resources/Textures/Effects/creampie.rsi/creampie_ai.png
Normal file
|
After Width: | Height: | Size: 613 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_corgi.png
Normal file
|
After Width: | Height: | Size: 478 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_drone.png
Normal file
|
After Width: | Height: | Size: 558 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_engborg.png
Normal file
|
After Width: | Height: | Size: 429 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_hardsuit.png
Normal file
|
After Width: | Height: | Size: 452 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_helmet.png
Normal file
|
After Width: | Height: | Size: 386 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_human.png
Normal file
|
After Width: | Height: | Size: 412 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_janborg.png
Normal file
|
After Width: | Height: | Size: 575 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_lizard.png
Normal file
|
After Width: | Height: | Size: 412 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_medborg.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_monkey.png
Normal file
|
After Width: | Height: | Size: 368 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_secborg.png
Normal file
|
After Width: | Height: | Size: 372 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_standborg.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_xeno_crit.png
Normal file
|
After Width: | Height: | Size: 225 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_xeno_dead.png
Normal file
|
After Width: | Height: | Size: 225 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_xeno_sleep.png
Normal file
|
After Width: | Height: | Size: 292 B |
BIN
Resources/Textures/Effects/creampie.rsi/creampie_xenomorph.png
Normal file
|
After Width: | Height: | Size: 374 B |
1
Resources/Textures/Effects/creampie.rsi/meta.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA 3.0", "copyright": "Taken from https://github.com/tgstation/tgstation at 0d9c9a8233dfc3fc55edc538955a761a6328bee0", "states": [{"name": "creampie_ai", "directions": 1, "delays": [[1.0]]}, {"name": "creampie_corgi", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_drone", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_engborg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_hardsuit", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_helmet", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_human", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_janborg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_lizard", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_medborg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_monkey", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_secborg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_standborg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_xeno_crit", "directions": 1, "delays": [[1.0]]}, {"name": "creampie_xeno_dead", "directions": 1, "delays": [[1.0]]}, {"name": "creampie_xeno_sleep", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "creampie_xenomorph", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||||