Adds slippery items (#1321)
* Start work on Slippery Component * Slips work * Add banana peel * Add required slip speed * Add slip sound * Adds soap * Make soapnt, soapsyndie and soapdeluxe inherit soap * Adds homemade soap and omega soap * Fix slipping not taking into account the entity being in a container
@@ -0,0 +1,115 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Timers;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.Throw;
|
||||||
|
using Content.Shared.Audio;
|
||||||
|
using Content.Shared.Physics;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Components;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using Timer = Robust.Shared.Timers.Timer;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Movement
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class SlipperyComponent : Component, ICollideBehavior
|
||||||
|
{
|
||||||
|
[Dependency] private IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
|
public override string Name => "Slippery";
|
||||||
|
|
||||||
|
private List<EntityUid> _slipped = new List<EntityUid>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How many seconds the mob will be paralyzed for.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float ParalyzeTime { get; set; } = 3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Percentage of shape intersection for a slip to occur.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float IntersectPercentage { get; set; } = 0.3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entities will only be slipped if their speed exceeds this limit.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float RequiredSlipSpeed { get; set; } = 0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the sound to be played when a mob slips.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public string SlipSound { get; set; } = "/Audio/Effects/slip.ogg";
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
var collidable = Owner.GetComponent<ICollidableComponent>();
|
||||||
|
|
||||||
|
collidable.Hard = false;
|
||||||
|
var shape = collidable.PhysicsShapes[0];
|
||||||
|
shape.CollisionLayer |= (int) CollisionGroup.MobImpassable;
|
||||||
|
shape.CollisionMask = (int)CollisionGroup.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
serializer.DataField(this, x => ParalyzeTime, "paralyzeTime", 3f);
|
||||||
|
serializer.DataField(this, x => IntersectPercentage, "intersectPercentage", 0.3f);
|
||||||
|
serializer.DataField(this, x => RequiredSlipSpeed, "requiredSlipSpeed", 0f);
|
||||||
|
serializer.DataField(this, x => SlipSound, "slipSound", "/Audio/Effects/slip.ogg");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollideWith(IEntity collidedWith)
|
||||||
|
{
|
||||||
|
if (ContainerHelpers.IsInContainer(Owner)
|
||||||
|
|| _slipped.Contains(collidedWith.Uid)
|
||||||
|
|| !collidedWith.TryGetComponent(out StunnableComponent stun)
|
||||||
|
|| !collidedWith.TryGetComponent(out ICollidableComponent otherBody)
|
||||||
|
|| !collidedWith.TryGetComponent(out PhysicsComponent otherPhysics)
|
||||||
|
|| !Owner.TryGetComponent(out ICollidableComponent body))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (otherPhysics.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);
|
||||||
|
|
||||||
|
if (percentage < IntersectPercentage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
stun.Paralyze(5f);
|
||||||
|
_slipped.Add(collidedWith.Uid);
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(SlipSound))
|
||||||
|
EntitySystem.Get<AudioSystem>().PlayFromEntity(SlipSound, Owner, AudioHelpers.WithVariation(0.2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(float frameTime)
|
||||||
|
{
|
||||||
|
foreach (var uid in _slipped.ToArray())
|
||||||
|
{
|
||||||
|
if(!uid.IsValid() || !_entityManager.EntityExists(uid)) continue;
|
||||||
|
|
||||||
|
var entity = _entityManager.GetEntity(uid);
|
||||||
|
var collidable = Owner.GetComponent<ICollidableComponent>();
|
||||||
|
var otherCollidable = entity.GetComponent<ICollidableComponent>();
|
||||||
|
|
||||||
|
if (!collidable.WorldAABB.Intersects(otherCollidable.WorldAABB))
|
||||||
|
_slipped.Remove(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Content.Server/GameObjects/EntitySystems/SlipperySystem.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Movement;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
|
{
|
||||||
|
public class SlipperySystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
EntityQuery = new TypeEntityQuery(typeof(SlipperyComponent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
foreach (var entity in RelevantEntities)
|
||||||
|
{
|
||||||
|
entity.GetComponent<SlipperyComponent>().Update(frameTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Resources/Audio/Effects/slip.ogg
Normal file
@@ -3027,3 +3027,21 @@
|
|||||||
sprite: Objects/Consumable/Food/milkape.rsi
|
sprite: Objects/Consumable/Food/milkape.rsi
|
||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Objects/Consumable/Food/milkape.rsi
|
sprite: Objects/Consumable/Food/milkape.rsi
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: banana
|
||||||
|
parent: FoodBase
|
||||||
|
id: FoodBanana
|
||||||
|
description: Rich in potassium.
|
||||||
|
components:
|
||||||
|
- type: Food
|
||||||
|
trash: TrashBananaPeel
|
||||||
|
- type: Solution
|
||||||
|
contents:
|
||||||
|
reagents:
|
||||||
|
- ReagentId: chem.Nutriment
|
||||||
|
Quantity: 6
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Consumable/Food/banana.rsi
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Consumable/Food/banana.rsi
|
||||||
|
|||||||
@@ -200,3 +200,16 @@
|
|||||||
sprite: Objects/Consumable/Trash/waffles.rsi
|
sprite: Objects/Consumable/Trash/waffles.rsi
|
||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Objects/Consumable/Trash/waffles.rsi
|
sprite: Objects/Consumable/Trash/waffles.rsi
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: banana peel
|
||||||
|
parent: TrashBase
|
||||||
|
id: TrashBananaPeel
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Consumable/Food/banana.rsi
|
||||||
|
state: peel
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Consumable/Food/banana.rsi
|
||||||
|
state: peel
|
||||||
|
- type: Slippery
|
||||||
|
|||||||
@@ -104,3 +104,92 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Specific/Janitorial/wet_floor_sign.rsi
|
sprite: Objects/Specific/Janitorial/wet_floor_sign.rsi
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: soap
|
||||||
|
id: Soap
|
||||||
|
parent: BaseItem
|
||||||
|
description: A cheap bar of soap. Doesn't smell.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Specific/Janitorial/soap.rsi
|
||||||
|
state: soap
|
||||||
|
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Specific/Janitorial/soap.rsi
|
||||||
|
state: soap
|
||||||
|
|
||||||
|
- type: Item
|
||||||
|
sprite: Objects/Specific/Janitorial/soap.rsi
|
||||||
|
|
||||||
|
- type: Slippery
|
||||||
|
paralyzeTime: 2.5
|
||||||
|
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: soap
|
||||||
|
id: SoapNT
|
||||||
|
parent: Soap
|
||||||
|
description: A Nanotrasen brand bar of soap. Smells of phoron.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: soapnt
|
||||||
|
|
||||||
|
- type: Icon
|
||||||
|
state: soapnt
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: soap
|
||||||
|
id: SoapDeluxe
|
||||||
|
parent: Soap
|
||||||
|
description: A deluxe Waffle Co. brand bar of soap. Smells of condoms.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: soapdeluxe
|
||||||
|
|
||||||
|
- type: Icon
|
||||||
|
state: soapdeluxe
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: soap
|
||||||
|
id: SoapSyndie
|
||||||
|
parent: Soap
|
||||||
|
description: An untrustworthy bar of soap. Smells of fear.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: soapsyndie
|
||||||
|
|
||||||
|
- type: Icon
|
||||||
|
state: soapsyndie
|
||||||
|
|
||||||
|
- type: Slippery
|
||||||
|
paralyzeTime: 5
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: soap
|
||||||
|
id: SoapHomemade
|
||||||
|
parent: Soap
|
||||||
|
description: A homemade bar of soap. Smells of... well....
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: soapgibs
|
||||||
|
|
||||||
|
- type: Icon
|
||||||
|
state: soapgibs
|
||||||
|
|
||||||
|
- type: Slippery
|
||||||
|
paralyzeTime: 2
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: omega soap
|
||||||
|
id: SoapOmega
|
||||||
|
parent: Soap
|
||||||
|
description: The most advanced soap known to mankind. Smells of bluespace.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: soapomega
|
||||||
|
|
||||||
|
- type: Icon
|
||||||
|
state: soapomega
|
||||||
|
|
||||||
|
- type: Slippery
|
||||||
|
paralyzeTime: 7
|
||||||
|
|||||||
BIN
Resources/Textures/Objects/Consumable/Food/banana.rsi/icon.png
Normal file
|
After Width: | Height: | Size: 488 B |
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"license": "CC-BY-SA 3.0",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "peel",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Objects/Consumable/Food/banana.rsi/peel.png
Normal file
|
After Width: | Height: | Size: 445 B |
|
Before Width: | Height: | Size: 575 B |
|
Before Width: | Height: | Size: 527 B |
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"license": "CC-BY-SA 3.0",
|
||||||
|
"copyright": "Taken from https://github.com/vgstation-coders/vgstation13 at a407fc1f5c25cbce8b653c553f53be294d15b071 and https://github.com/tgstation/tgstation at 259acc8c81054d89f7b6bcd9ff702fdf587a19ed. soapomega.png modified by Zumorica",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "soap",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "soapdeluxe",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "soapgibs",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "soapnt",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "soapomega",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "soapsyndie",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap.png
Normal file
|
After Width: | Height: | Size: 688 B |
|
After Width: | Height: | Size: 573 B |
|
After Width: | Height: | Size: 773 B |
|
After Width: | Height: | Size: 630 B |
|
After Width: | Height: | Size: 598 B |
|
After Width: | Height: | Size: 470 B |