diff --git a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs new file mode 100644 index 0000000000..62f7aa3255 --- /dev/null +++ b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs @@ -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 _slipped = new List(); + + /// + /// How many seconds the mob will be paralyzed for. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float ParalyzeTime { get; set; } = 3f; + + /// + /// Percentage of shape intersection for a slip to occur. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float IntersectPercentage { get; set; } = 0.3f; + + /// + /// Entities will only be slipped if their speed exceeds this limit. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float RequiredSlipSpeed { get; set; } = 0f; + + /// + /// Path to the sound to be played when a mob slips. + /// + [ViewVariables] + public string SlipSound { get; set; } = "/Audio/Effects/slip.ogg"; + + public override void Initialize() + { + base.Initialize(); + var collidable = Owner.GetComponent(); + + 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().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(); + var otherCollidable = entity.GetComponent(); + + if (!collidable.WorldAABB.Intersects(otherCollidable.WorldAABB)) + _slipped.Remove(uid); + } + } + } +} diff --git a/Content.Server/GameObjects/EntitySystems/SlipperySystem.cs b/Content.Server/GameObjects/EntitySystems/SlipperySystem.cs new file mode 100644 index 0000000000..064e34ad92 --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/SlipperySystem.cs @@ -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().Update(frameTime); + } + } + } +} diff --git a/Resources/Audio/Effects/slip.ogg b/Resources/Audio/Effects/slip.ogg new file mode 100644 index 0000000000..2ac7e157e6 Binary files /dev/null and b/Resources/Audio/Effects/slip.ogg differ diff --git a/Resources/Prototypes/Entities/Items/Consumables/food.yml b/Resources/Prototypes/Entities/Items/Consumables/food.yml index af3c8ade0f..df87e17021 100644 --- a/Resources/Prototypes/Entities/Items/Consumables/food.yml +++ b/Resources/Prototypes/Entities/Items/Consumables/food.yml @@ -3027,3 +3027,21 @@ sprite: Objects/Consumable/Food/milkape.rsi - type: Icon 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 diff --git a/Resources/Prototypes/Entities/Items/Consumables/trash.yml b/Resources/Prototypes/Entities/Items/Consumables/trash.yml index 31a6c07fda..462cbb9a6c 100644 --- a/Resources/Prototypes/Entities/Items/Consumables/trash.yml +++ b/Resources/Prototypes/Entities/Items/Consumables/trash.yml @@ -200,3 +200,16 @@ sprite: Objects/Consumable/Trash/waffles.rsi - type: Icon 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 diff --git a/Resources/Prototypes/Entities/janitor.yml b/Resources/Prototypes/Entities/janitor.yml index 5f5fbf172d..152a1a35e9 100644 --- a/Resources/Prototypes/Entities/janitor.yml +++ b/Resources/Prototypes/Entities/janitor.yml @@ -104,3 +104,92 @@ - type: Item 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 diff --git a/Resources/Textures/Objects/Consumable/Food/banana.rsi/icon.png b/Resources/Textures/Objects/Consumable/Food/banana.rsi/icon.png new file mode 100644 index 0000000000..fc117d8623 Binary files /dev/null and b/Resources/Textures/Objects/Consumable/Food/banana.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Consumable/Food/banana.rsi/meta.json b/Resources/Textures/Objects/Consumable/Food/banana.rsi/meta.json new file mode 100644 index 0000000000..2374895ce2 --- /dev/null +++ b/Resources/Textures/Objects/Consumable/Food/banana.rsi/meta.json @@ -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 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Consumable/Food/banana.rsi/peel.png b/Resources/Textures/Objects/Consumable/Food/banana.rsi/peel.png new file mode 100644 index 0000000000..46bd5c0979 Binary files /dev/null and b/Resources/Textures/Objects/Consumable/Food/banana.rsi/peel.png differ diff --git a/Resources/Textures/Objects/Fun/banana.png b/Resources/Textures/Objects/Fun/banana.png deleted file mode 100644 index df4c416e95..0000000000 Binary files a/Resources/Textures/Objects/Fun/banana.png and /dev/null differ diff --git a/Resources/Textures/Objects/Fun/bananapeel.png b/Resources/Textures/Objects/Fun/bananapeel.png deleted file mode 100644 index f2891d4268..0000000000 Binary files a/Resources/Textures/Objects/Fun/bananapeel.png and /dev/null differ diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json new file mode 100644 index 0000000000..73934a51bf --- /dev/null +++ b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json @@ -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 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap.png new file mode 100644 index 0000000000..3f82c55990 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap.png differ diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapdeluxe.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapdeluxe.png new file mode 100644 index 0000000000..f5e0a9c951 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapdeluxe.png differ diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapgibs.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapgibs.png new file mode 100644 index 0000000000..5640e0e836 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapgibs.png differ diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapnt.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapnt.png new file mode 100644 index 0000000000..1f02e35820 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapnt.png differ diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapomega.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapomega.png new file mode 100644 index 0000000000..06bb48131b Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapomega.png differ diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapsyndie.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapsyndie.png new file mode 100644 index 0000000000..1886ea2481 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soapsyndie.png differ