Lavaland chasms (#19154)

This commit is contained in:
Kara
2023-08-14 19:29:24 -07:00
committed by GitHub
parent 71f5e38faf
commit cfccb5959a
20 changed files with 331 additions and 5 deletions

View File

@@ -0,0 +1,74 @@
using Content.Shared.Chasm;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.Animations;
namespace Content.Client.Chasm;
/// <summary>
/// Handles the falling animation for entities that fall into a chasm.
/// </summary>
public sealed class ChasmFallingVisualsSystem : EntitySystem
{
[Dependency] private readonly AnimationPlayerSystem _anim = default!;
private readonly string _chasmFallAnimationKey = "chasm_fall";
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ChasmFallingComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<ChasmFallingComponent, ComponentRemove>(OnComponentRemove);
}
private void OnComponentInit(EntityUid uid, ChasmFallingComponent component, ComponentInit args)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
component.OriginalScale = sprite.Scale;
var player = EnsureComp<AnimationPlayerComponent>(uid);
if (_anim.HasRunningAnimation(player, _chasmFallAnimationKey))
return;
_anim.Play(player, GetFallingAnimation(component), _chasmFallAnimationKey);
}
private void OnComponentRemove(EntityUid uid, ChasmFallingComponent component, ComponentRemove args)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
var player = EnsureComp<AnimationPlayerComponent>(uid);
if (_anim.HasRunningAnimation(player, _chasmFallAnimationKey))
_anim.Stop(player, _chasmFallAnimationKey);
sprite.Scale = component.OriginalScale;
}
private Animation GetFallingAnimation(ChasmFallingComponent component)
{
var length = component.AnimationTime;
return new Animation()
{
Length = length,
AnimationTracks =
{
new AnimationTrackComponentProperty()
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Scale),
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(component.OriginalScale, 0.0f),
new AnimationTrackProperty.KeyFrame(component.AnimationScale, length.Seconds),
},
InterpolationMode = AnimationInterpolationMode.Cubic
}
}
};
}
}

View File

@@ -0,0 +1,17 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared.Chasm;
/// <summary>
/// Marks a component that will cause entities to fall into them on a step trigger activation
/// </summary>
[NetworkedComponent, RegisterComponent, Access(typeof(ChasmSystem))]
public sealed class ChasmComponent : Component
{
/// <summary>
/// Sound that should be played when an entity falls into the chasm
/// </summary>
[DataField("fallingSound")]
public SoundSpecifier FallingSound = new SoundPathSpecifier("/Audio/Effects/falling.ogg");
}

View File

@@ -0,0 +1,37 @@
using System.Numerics;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Chasm;
/// <summary>
/// Added to entities which have started falling into a chasm.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed class ChasmFallingComponent : Component
{
/// <summary>
/// Time it should take for the falling animation (scaling down) to complete.
/// </summary>
[DataField("animationTime")]
public TimeSpan AnimationTime = TimeSpan.FromSeconds(1.5f);
/// <summary>
/// Time it should take in seconds for the entity to actually delete
/// </summary>
[DataField("deletionTime")]
public TimeSpan DeletionTime = TimeSpan.FromSeconds(1.8f);
[DataField("nextDeletionTime", customTypeSerializer:typeof(TimeOffsetSerializer))]
public TimeSpan NextDeletionTime = TimeSpan.Zero;
/// <summary>
/// Original scale of the object so it can be restored if the component is removed in the middle of the animation
/// </summary>
public Vector2 OriginalScale = Vector2.Zero;
/// <summary>
/// Scale that the animation should bring entities to.
/// </summary>
public Vector2 AnimationScale = new Vector2(0.01f, 0.01f);
}

View File

@@ -0,0 +1,78 @@
using Content.Shared.ActionBlocker;
using Content.Shared.Movement.Events;
using Content.Shared.StepTrigger.Systems;
using Robust.Shared.Network;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;
namespace Content.Shared.Chasm;
/// <summary>
/// Handles making entities fall into chasms when stepped on.
/// </summary>
public sealed class ChasmSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ChasmComponent, StepTriggeredEvent>(OnStepTriggered);
SubscribeLocalEvent<ChasmComponent, StepTriggerAttemptEvent>(OnStepTriggerAttempt);
SubscribeLocalEvent<ChasmFallingComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<ChasmFallingComponent, UpdateCanMoveEvent>(OnUpdateCanMove);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
// don't predict queuedels on client
if (_net.IsClient)
return;
var query = EntityQueryEnumerator<ChasmFallingComponent>();
while (query.MoveNext(out var uid, out var chasm))
{
if (_timing.CurTime < chasm.NextDeletionTime)
continue;
QueueDel(uid);
}
}
private void OnStepTriggered(EntityUid uid, ChasmComponent component, ref StepTriggeredEvent args)
{
// already doomed
if (HasComp<ChasmFallingComponent>(args.Tripper))
return;
var falling = AddComp<ChasmFallingComponent>(args.Tripper);
falling.NextDeletionTime = _timing.CurTime + falling.DeletionTime;
_blocker.UpdateCanMove(args.Tripper);
_audio.PlayPredicted(component.FallingSound, uid, args.Tripper);
}
private void OnStepTriggerAttempt(EntityUid uid, ChasmComponent component, ref StepTriggerAttemptEvent args)
{
if (TryComp<PhysicsComponent>(args.Tripper, out var physics) && physics.BodyStatus == BodyStatus.InAir)
return;
args.Continue = true;
}
private void OnUnpaused(EntityUid uid, ChasmFallingComponent component, ref EntityUnpausedEvent args)
{
component.NextDeletionTime += args.PausedTime;
}
private void OnUpdateCanMove(EntityUid uid, ChasmFallingComponent component, UpdateCanMoveEvent args)
{
args.Cancel();
}
}

View File

@@ -78,14 +78,15 @@ public sealed class StepTriggerSystem : EntitySystem
return false;
}
private void UpdateColliding(EntityUid uid, StepTriggerComponent component, TransformComponent ownerTransform, EntityUid otherUid, EntityQuery<PhysicsComponent> query)
private void UpdateColliding(EntityUid uid, StepTriggerComponent component, TransformComponent ownerXform, EntityUid otherUid, EntityQuery<PhysicsComponent> query)
{
if (!query.TryGetComponent(otherUid, out var otherPhysics))
return;
var otherXform = Transform(otherUid);
// TODO: This shouldn't be calculating based on world AABBs.
var ourAabb = _entityLookup.GetWorldAABB(uid, ownerTransform);
var otherAabb = _entityLookup.GetWorldAABB(otherUid);
var ourAabb = _entityLookup.GetAABBNoContainer(uid, ownerXform.LocalPosition, ownerXform.LocalRotation);
var otherAabb = _entityLookup.GetAABBNoContainer(otherUid, otherXform.LocalPosition, otherXform.LocalRotation);
if (!ourAabb.Intersects(otherAabb))
{
@@ -96,9 +97,13 @@ public sealed class StepTriggerSystem : EntitySystem
return;
}
// max 'area of enclosure' between the two aabbs
// this is hard to explain
var intersect = Box2.Area(otherAabb.Intersect(ourAabb));
var ratio = Math.Max(intersect / Box2.Area(otherAabb), intersect / Box2.Area(ourAabb));
if (otherPhysics.LinearVelocity.Length() < component.RequiredTriggerSpeed
|| component.CurrentlySteppedOn.Contains(otherUid)
|| otherAabb.IntersectPercentage(ourAabb) < component.IntersectRatio
|| ratio < component.IntersectRatio
|| !CanTrigger(uid, otherUid, component))
{
return;

View File

@@ -46,4 +46,9 @@
- files: ["fence_rattle1.ogg", "fence_rattle2.ogg", "fence_rattle3.ogg"]
license: "CC0-1.0"
copyright: "Taken from MWsfx via freesound.org and cropped + mixed from stereo to mono."
source: "https://freesound.org/people/MWsfx/sounds/575388/"
source: "https://freesound.org/people/MWsfx/sounds/575388/"
- files: ["falling.ogg"]
license: "CC0-1.0"
copyright: "Taken from MATRIXXX_ via freesound.org and mixed from stereo to mono."
source: "https://freesound.org/people/MATRIXXX_/sounds/415990/"

Binary file not shown.

View File

@@ -0,0 +1,47 @@
- type: entity
id: FloorChasmEntity
name: chasm
description: You can't even see the bottom.
placement:
mode: SnapgridCenter
snap:
- Wall
components:
- type: Chasm
- type: StepTrigger
requiredTriggeredSpeed: 0
intersectRatio: 0.4
blacklist:
tags:
- Catwalk
- type: Transform
anchored: true
- type: Clickable
- type: Sprite
sprite: Tiles/Planet/chasm.rsi
drawdepth: BelowFloor
layers:
- state: chasm
- type: Icon
sprite: Tiles/Planet/chasm.rsi
state: full
- type: IconSmooth
key: chasm
base: chasm
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.5,-0.5,0.5,0.5"
layer:
- WallLayer
mask:
- ItemMask
density: 1000
hard: false
- type: Tag
tags:
- HideContextMenu

View File

@@ -310,6 +310,20 @@
cellularReturnType: Distance2
entities:
- WallRockBasalt
# chasm time
- !type:BiomeEntityLayer
allowedTiles:
- FloorBasalt
threshold: 0.6
noise:
seed: 3
frequency: 0.02
fractalType: FBm
octaves: 5
lacunarity: 2
gain: 0.4
entities:
- FloorChasmEntity
- !type:BiomeDummyLayer
id: Loot
# Fill basalt

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

View File

@@ -0,0 +1,49 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from https://github.com/tgstation/tgstation/tree/f116442e34fe3e941a1df474bb57bb410dd177a3/icons/turf and modified",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "full"
},
{
"name": "chasm0",
"directions": 4
},
{
"name": "chasm1",
"directions": 4
},
{
"name": "chasm2",
"directions": 4
},
{
"name": "chasm3",
"directions": 4
},
{
"name": "chasm4",
"directions": 4
},
{
"name": "chasm5",
"directions": 4
},
{
"name": "chasm6",
"directions": 4
},
{
"name": "chasm7",
"directions": 4
},
{
"name": "chasm"
}
]
}