Skip to content

Commit 5f47d7e

Browse files
committed
Merge branch 'how-to-cook-for-40-spacemen' of https://github.com/bynddark8/space-station-14 into how-to-cook-for-40-spacemen
2 parents 41fe104 + 563bf37 commit 5f47d7e

452 files changed

Lines changed: 155225 additions & 150563 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Content.Client/DoAfter/DoAfterOverlay.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ public sealed class DoAfterOverlay : Overlay
3737
private const float StartX = 2;
3838
private const float EndX = 22f;
3939

40+
// Time after which the doafter will lerp to max alpha.Add a comment on line R40Add diff commentMarkdown input: edit mode selected.WritePreviewAdd a suggestionHeadingBoldItalicQuoteCodeLinkUnordered listNumbered listTask listMentionReferenceMore itemsSaved repliesAdd FilesPaste, drop, or click to add filesCancelCommentStart a review
41+
private static readonly TimeSpan MaxAlphaTime = TimeSpan.FromSeconds(0.3f);
42+
43+
// After finishing, how long it takes to fade out to 0 alpha
44+
private static readonly TimeSpan FadeoutAlphaTime = TimeSpan.FromSeconds(0.2f);
45+
46+
// Time after which the doafter will lerp to its final y offset.
47+
private static readonly TimeSpan MaxYPosTime = TimeSpan.FromSeconds(0.5f);
48+
4049
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
4150

4251
public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager, IGameTiming timing, IPlayerManager player)
@@ -110,43 +119,52 @@ protected override void Draw(in OverlayDrawArgs args)
110119
foreach (var doAfter in comp.DoAfters.Values)
111120
{
112121
// Hide some DoAfters from other players for stealthy actions (ie: thieving gloves)
113-
var alpha = 1f;
122+
var maxAlpha = 1f;
114123
if (doAfter.Args.Hidden || isInContainer)
115124
{
116125
if (uid != localEnt)
117126
continue;
118127

119128
// Hints to the local player that this do-after is not visible to other players.
120-
alpha = 0.5f;
129+
maxAlpha = 0.5f;
121130
}
122131

132+
var elapsed = time - doAfter.StartTime;
133+
134+
var alpha = MathHelper.Lerp(0f, maxAlpha, (float)Math.Clamp(elapsed / MaxAlphaTime, 0.0, 1.0));
135+
// fade out if doafter finished
136+
if (elapsed >= doAfter.Args.Delay)
137+
alpha = MathHelper.Lerp(maxAlpha, 0f, (float)Math.Clamp((elapsed - doAfter.Args.Delay) / FadeoutAlphaTime, 0.0, 1.0));
138+
123139
// Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped
124140
// by the bar.
125-
var yOffset = _sprite.GetLocalBounds((uid, sprite)).Height / 2f + 0.05f;
141+
var spriteBounds = _sprite.GetLocalBounds((uid, sprite));
142+
var yFinished = spriteBounds.Height / 2f + 0.05f;
143+
var yStart = yFinished / 6f;
144+
var yOffset = MathHelper.Lerp(yStart, yFinished, Easings.OutSine((float)Math.Clamp(elapsed / MaxYPosTime, 0.0, 1.0)));
126145

127146
// Position above the entity (we've already applied the matrix transform to the entity itself)
128147
// Offset by the texture size for every do_after we have.
129148
var position = new Vector2(-_barTexture.Width / 2f / EyeManager.PixelsPerMeter,
130149
yOffset / scale + offset / EyeManager.PixelsPerMeter * scale);
131150

132151
// Draw the underlying bar texture
133-
handle.DrawTexture(_barTexture, position);
152+
handle.DrawTexture(_barTexture, position, Color.White.WithAlpha(alpha));
134153

135154
Color color;
136155
float elapsedRatio;
137156

138157
// if we're cancelled then flick red / off.
139158
if (doAfter.CancelledTime != null)
140159
{
141-
var elapsed = doAfter.CancelledTime.Value - doAfter.StartTime;
160+
elapsed = doAfter.CancelledTime.Value - doAfter.StartTime;
142161
elapsedRatio = (float)Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
143162
var cancelElapsed = (time - doAfter.CancelledTime.Value).TotalSeconds;
144163
var flash = Math.Floor(cancelElapsed / FlashTime) % 2 == 0;
145164
color = GetProgressColor(0, flash ? alpha : 0);
146165
}
147166
else
148167
{
149-
var elapsed = time - doAfter.StartTime;
150168
elapsedRatio = (float)Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
151169
color = GetProgressColor(elapsedRatio, alpha);
152170
}

Content.Client/Doors/DoorSystem.cs

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ public override void Initialize()
1818
{
1919
base.Initialize();
2020
SubscribeLocalEvent<DoorComponent, AppearanceChangeEvent>(OnAppearanceChange);
21+
SubscribeLocalEvent<DoorComponent, AnimationCompletedEvent>(OnAnimationCompleted);
22+
}
23+
24+
private void OnAnimationCompleted(Entity<DoorComponent> entity, ref AnimationCompletedEvent args)
25+
{
26+
if (args.Key != DoorComponent.OpenKey && args.Key != DoorComponent.CloseKey)
27+
return;
28+
29+
if (!TryComp<SpriteComponent>(entity, out var sprite)) // Starlight
30+
return;
31+
32+
switch (entity.Comp.State)
33+
{
34+
case DoorState.Open:
35+
foreach (var (layer, layerState) in entity.Comp.OpenSpriteStates)
36+
{
37+
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
38+
}
39+
40+
break;
41+
case DoorState.Closed:
42+
foreach (var (layer, layerState) in entity.Comp.ClosedSpriteStates)
43+
{
44+
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
45+
}
46+
47+
break;
48+
}
2149
}
2250

2351
protected override void OnComponentInit(Entity<DoorComponent> ent, ref ComponentInit args)
@@ -89,8 +117,11 @@ private void OnAppearanceChange(Entity<DoorComponent> entity, ref AppearanceChan
89117
if (AppearanceSystem.TryGetData<string>(entity, PaintableVisuals.Prototype, out var prototype, args.Component))
90118
UpdateSpriteLayers((entity.Owner, args.Sprite), prototype);
91119

92-
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.AnimationKey))
93-
_animationSystem.Stop(entity.Owner, DoorComponent.AnimationKey);
120+
// ES START
121+
// dont stop all animations for no reason
122+
//if (_animationSystem.HasRunningAnimation(entity, DoorComponent.AnimationKey))
123+
// _animationSystem.Stop(entity.Owner, DoorComponent.AnimationKey);
124+
// ES END
94125

95126
// We are checking beforehand since some doors may not have an emagging visual layer, and we don't want LayerSetVisible to throw an error.
96127
if (_sprite.TryGetLayer(entity.Owner, DoorVisualLayers.BaseEmagging, out var _, false))
@@ -106,13 +137,37 @@ private void UpdateAppearanceForDoorState(Entity<DoorComponent> entity, SpriteCo
106137
switch (state)
107138
{
108139
case DoorState.Open:
140+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.OpenKey))
141+
return;
142+
143+
// Moffstation - Start - Don't stop animations
144+
/*
145+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.CloseKey))
146+
{
147+
_animationSystem.Stop(entity, null, DoorComponent.CloseKey);
148+
_animationSystem.Play(entity, (Animation)entity.Comp.OpeningAnimation, DoorComponent.OpenKey);
149+
}
150+
*/ // Moffstation - End
151+
109152
foreach (var (layer, layerState) in entity.Comp.OpenSpriteStates)
110153
{
111154
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
112155
}
113156

114157
return;
115158
case DoorState.Closed:
159+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.CloseKey))
160+
return;
161+
162+
// Moffstation - Start - Don't stop animations
163+
/*
164+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.OpenKey))
165+
{
166+
_animationSystem.Stop(entity, null, DoorComponent.OpenKey);
167+
_animationSystem.Play(entity, (Animation)entity.Comp.OpeningAnimation, DoorComponent.OpenKey);
168+
}
169+
*/ // Moffstation - End
170+
116171
foreach (var (layer, layerState) in entity.Comp.ClosedSpriteStates)
117172
{
118173
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
@@ -123,24 +178,34 @@ private void UpdateAppearanceForDoorState(Entity<DoorComponent> entity, SpriteCo
123178
if (entity.Comp.OpeningAnimationTime == TimeSpan.Zero)
124179
return;
125180

126-
_animationSystem.Play(entity, (Animation)entity.Comp.OpeningAnimation, DoorComponent.AnimationKey);
181+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.OpenKey))
182+
return;
183+
184+
_animationSystem.Play(entity, (Animation)entity.Comp.OpeningAnimation, DoorComponent.OpenKey);
127185

128186
return;
129187
case DoorState.Closing:
130188
if (entity.Comp.ClosingAnimationTime == TimeSpan.Zero || entity.Comp.CurrentlyCrushing.Count != 0)
131189
return;
132190

133-
_animationSystem.Play(entity, (Animation)entity.Comp.ClosingAnimation, DoorComponent.AnimationKey);
191+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.CloseKey))
192+
return;
193+
194+
_animationSystem.Play(entity, (Animation)entity.Comp.ClosingAnimation, DoorComponent.CloseKey);
134195

135196
return;
136197
case DoorState.Denying:
137-
_animationSystem.Play(entity, (Animation)entity.Comp.DenyingAnimation, DoorComponent.AnimationKey);
198+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.DenyKey))
199+
return;
200+
201+
_animationSystem.Play(entity, (Animation)entity.Comp.DenyingAnimation, DoorComponent.DenyKey);
138202

139203
return;
140204
case DoorState.Emagging:
141-
// We are checking beforehand since some doors may not have an emagging visual layer.
142-
if (_sprite.TryGetLayer(entity.Owner, DoorVisualLayers.BaseEmagging, out var _, false))
143-
_animationSystem.Play(entity, (Animation)entity.Comp.EmaggingAnimation, DoorComponent.AnimationKey);
205+
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.EmagKey))
206+
return;
207+
208+
_animationSystem.Play(entity, (Animation)entity.Comp.EmaggingAnimation, DoorComponent.EmagKey);
144209

145210
return;
146211
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Content.Shared._ES.Core.Timer.Components;
2+
3+
namespace Content.Client._ES.Lighting.Components;
4+
5+
/// <summary>
6+
/// Handles a point light that fades out while synced to a <see cref="ESTimedDespawnComponent"/>
7+
/// </summary>
8+
[RegisterComponent]
9+
[Access(typeof(ESTimedDespawnLightFadeSystem))]
10+
public sealed partial class ESTimedDespawnLightFadeComponent : Component
11+
{
12+
[DataField]
13+
public TimeSpan FadeTime = TimeSpan.FromSeconds(1);
14+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using Content.Client._ES.Lighting.Components;
2+
using Content.Shared._ES.Core.Timer.Components;
3+
using Robust.Client.Animations;
4+
using Robust.Client.GameObjects;
5+
using Robust.Shared.Animations;
6+
using Robust.Shared.Timing;
7+
8+
namespace Content.Client._ES.Lighting;
9+
10+
public sealed partial class ESTimedDespawnLightFadeSystem : VisualizerSystem<ESTimedDespawnLightFadeComponent>
11+
{
12+
[Dependency] private IGameTiming _timing = default!;
13+
[Dependency] private AnimationPlayerSystem _animationPlayer = default!;
14+
15+
private const string FadeTrack = "light-fade";
16+
17+
protected override void OnAppearanceChange(EntityUid uid, ESTimedDespawnLightFadeComponent component, ref AppearanceChangeEvent args)
18+
{
19+
base.OnAppearanceChange(uid, component, ref args);
20+
21+
if (_animationPlayer.HasRunningAnimation(uid, FadeTrack))
22+
return;
23+
24+
if (!AppearanceSystem.TryGetData<TimeSpan>(uid, ESTimedDespawnVisuals.DespawnTime, out var time, args.Component) ||
25+
!TryComp<PointLightComponent>(uid, out var light))
26+
return;
27+
28+
var duration = time - _timing.CurTime;
29+
30+
var animation = new Animation
31+
{
32+
Length = duration,
33+
AnimationTracks =
34+
{
35+
new AnimationTrackComponentProperty
36+
{
37+
Property = nameof(PointLightComponent.Energy),
38+
ComponentType = typeof(PointLightComponent),
39+
InterpolationMode = AnimationInterpolationMode.Linear,
40+
KeyFrames =
41+
{
42+
new AnimationTrackProperty.KeyFrame(light.Energy, 0f),
43+
new AnimationTrackProperty.KeyFrame(light.Energy, (float) (duration - component.FadeTime).TotalSeconds),
44+
new AnimationTrackProperty.KeyFrame(0f, (float) component.FadeTime.TotalSeconds, Easings.OutSine),
45+
}
46+
}
47+
}
48+
};
49+
50+
_animationPlayer.Play(uid, animation, FadeTrack);
51+
}
52+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Content.Shared._ES.Core.Timer.Components;
2+
3+
namespace Content.Client._ES.Sprite.Components;
4+
5+
/// <summary>
6+
/// Handles a sprite that fades out while synced to a <see cref="ESTimedDespawnComponent"/>
7+
/// </summary>
8+
[RegisterComponent]
9+
[Access(typeof(ESTimedDespawnSpriteFadeSystem))]
10+
public sealed partial class ESTimedDespawnSpriteFadeComponent : Component
11+
{
12+
[DataField]
13+
public TimeSpan FadeTime = TimeSpan.FromSeconds(1);
14+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using Content.Client._ES.Sprite.Components;
2+
using Content.Shared._ES.Core.Timer.Components;
3+
using Robust.Client.Animations;
4+
using Robust.Client.GameObjects;
5+
using Robust.Shared.Animations;
6+
using Robust.Shared.Timing;
7+
8+
namespace Content.Client._ES.Sprite;
9+
10+
/// <summary>
11+
/// This handles <see cref="ESTimedDespawnSpriteFadeComponent"/>
12+
/// </summary>
13+
public sealed partial class ESTimedDespawnSpriteFadeSystem : VisualizerSystem<ESTimedDespawnSpriteFadeComponent>
14+
{
15+
[Dependency] private IGameTiming _timing = default!;
16+
[Dependency] private AnimationPlayerSystem _animationPlayer = default!;
17+
18+
private const string FadeTrack = "es-sprite-fade";
19+
20+
protected override void OnAppearanceChange(EntityUid uid, ESTimedDespawnSpriteFadeComponent component, ref AppearanceChangeEvent args)
21+
{
22+
base.OnAppearanceChange(uid, component, ref args);
23+
24+
if (args.Sprite is not { } sprite)
25+
return;
26+
27+
if (_animationPlayer.HasRunningAnimation(uid, FadeTrack))
28+
return;
29+
30+
if (!AppearanceSystem.TryGetData<TimeSpan>(uid, ESTimedDespawnVisuals.DespawnTime, out var time, args.Component))
31+
return;
32+
33+
var duration = time - _timing.CurTime;
34+
35+
var animation = new Animation
36+
{
37+
Length = duration,
38+
AnimationTracks =
39+
{
40+
new AnimationTrackComponentProperty
41+
{
42+
Property = nameof(SpriteComponent.Color),
43+
ComponentType = typeof(SpriteComponent),
44+
InterpolationMode = AnimationInterpolationMode.Linear,
45+
KeyFrames =
46+
{
47+
new AnimationTrackProperty.KeyFrame(sprite.Color, 0f),
48+
new AnimationTrackProperty.KeyFrame(sprite.Color, MathF.Max((float) (duration - component.FadeTime).TotalSeconds, 0f)),
49+
new AnimationTrackProperty.KeyFrame(sprite.Color.WithAlpha(0f), (float) component.FadeTime.TotalSeconds, Easings.OutSine),
50+
},
51+
},
52+
},
53+
};
54+
55+
_animationPlayer.Play(uid, animation, FadeTrack);
56+
}
57+
}

Content.Client/_FarHorizons/Power/Generation/FissionGenerator/ReactorPartSystem.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Content.Shared._FarHorizons.Power.Generation.FissionGenerator;
22
using Robust.Client.GameObjects;
3+
using Robust.Client.Graphics;
34
using Robust.Shared.Prototypes;
45

56
namespace Content.Client._FarHorizons.Power.Generation.FissionGenerator;
@@ -9,10 +10,15 @@ public sealed partial class ReactorPartSystem : EntitySystem
910
[Dependency] private IPrototypeManager _proto = default!;
1011
[Dependency] private SpriteSystem _sprite = default!;
1112

13+
private static readonly ProtoId<ShaderPrototype> _shaderID = "HeatDistortionFH";
14+
private ShaderInstance _heatShader = default!;
15+
1216
public override void Initialize()
1317
{
1418
base.Initialize();
1519

20+
_heatShader = _proto.Index(_shaderID).InstanceUnique();
21+
1622
SubscribeLocalEvent<ReactorPartComponent, AppearanceChangeEvent>(OnAppearanceChange);
1723
SubscribeLocalEvent<ReactorPartComponent, ComponentInit>(OnComponentInit);
1824
}
@@ -27,8 +33,11 @@ private void OnAppearanceChange(EntityUid uid, ReactorPartComponent component, r
2733
// return;
2834

2935
_sprite.LayerSetColor((uid, args.Sprite), 0, _proto.Index(component.Material).Color);
36+
37+
if (args.AppearanceData.TryGetValue(ReactorPartVisuals.HeatDistort, out var value) && value is bool enabled)
38+
args.Sprite.PostShader = enabled ? _heatShader : null;
3039
}
3140

3241
private void OnComponentInit(Entity<ReactorPartComponent> ent, ref ComponentInit args)
33-
=> _sprite.LayerSetColor((ent.Owner, EntityManager.GetComponent<SpriteComponent>(ent.Owner)), 0, _proto.Index(ent.Comp.Material).Color);
42+
=> _sprite.LayerSetColor((ent.Owner, Comp<SpriteComponent>(ent.Owner)), 0, _proto.Index(ent.Comp.Material).Color);
3443
}

Content.Client/_FarHorizons/Power/UI/NuclearReactorBoundUserInterface.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ protected override void Open()
4242
_window.ItemActionButtonPressed += OnActionButtonPressed;
4343
_window.EjectButtonPressed += OnEjectButtonPressed;
4444
_window.ControlRodModify += OnControlRodModify;
45+
_window.AckButtonPressed += OnAckButtonPressed;
4546

4647
Update();
4748
}
@@ -74,4 +75,11 @@ private void OnControlRodModify(float amount)
7475

7576
SendPredictedMessage(new ReactorControlRodModifyMessage(amount));
7677
}
78+
79+
private void OnAckButtonPressed()
80+
{
81+
if (_window is null) return;
82+
83+
SendPredictedMessage(new ReactorAlarmAckMessage());
84+
}
7785
}

0 commit comments

Comments
 (0)