Skip to content

Commit 0d09553

Browse files
Merge branch 'master' into outercommand-drip
2 parents 6f3d78e + da001ad commit 0d09553

163 files changed

Lines changed: 2243 additions & 1181 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.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using Content.Goobstation.Shared.Tools;
2+
using Content.Shared.Tools.Components;
3+
using Robust.Client.Animations;
4+
using Robust.Client.GameObjects;
5+
using Robust.Client.Graphics;
6+
using Robust.Shared.Animations;
7+
using System.Numerics;
8+
9+
namespace Content.Goobstation.Client.Tools;
10+
11+
public sealed class WeldingSparksAnimationSystem : EntitySystem
12+
{
13+
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
14+
[Dependency] private readonly IEyeManager _eyeManager = default!;
15+
[Dependency] private readonly TransformSystem _transformSystem = default!;
16+
17+
private const string ANIM_KEY = "WeldAnim";
18+
19+
public override void Initialize()
20+
{
21+
base.Initialize();
22+
23+
SubscribeNetworkEvent<SpawnedWeldingSparksEvent>(OnSpawnedWeldingSparks);
24+
}
25+
26+
private void OnSpawnedWeldingSparks(SpawnedWeldingSparksEvent ev)
27+
{
28+
var targetEnt = GetEntity(ev.TargetEnt);
29+
if (!TryComp<WeldableComponent>(targetEnt, out var weldableComp) || !TryComp<WeldingSparksAnimationComponent>(targetEnt, out var sparksAnim))
30+
return;
31+
32+
if (!TryGetEntity(ev.SparksEnt, out var sparksEnt))
33+
// `targetEnt` is validated with the `TryComp()` calls, so that can just use `GetEntity()`.
34+
return;
35+
36+
var animationPlayer = EnsureComp<AnimationPlayerComponent>(targetEnt);
37+
if (_animation.HasRunningAnimation(targetEnt, animationPlayer, ANIM_KEY))
38+
return;
39+
40+
var (startOffset, endOffset) = GetOffsets((targetEnt, sparksAnim), weldableComp.IsWelded);
41+
42+
var animation = new Animation()
43+
{
44+
Length = ev.Duration,
45+
AnimationTracks =
46+
{
47+
new AnimationTrackComponentProperty()
48+
{
49+
ComponentType = typeof(SpriteComponent),
50+
Property = nameof(SpriteComponent.Offset),
51+
InterpolationMode = AnimationInterpolationMode.Linear,
52+
KeyFrames =
53+
{
54+
new AnimationTrackProperty.KeyFrame(startOffset, 0f),
55+
new AnimationTrackProperty.KeyFrame(endOffset, (float) ev.Duration.TotalSeconds),
56+
}
57+
}
58+
}
59+
};
60+
61+
_animation.Play(sparksEnt.Value, animation, ANIM_KEY);
62+
}
63+
64+
private (Vector2, Vector2) GetOffsets(Entity<WeldingSparksAnimationComponent> ent, bool isWelded)
65+
{
66+
var start = ent.Comp.StartingOffset;
67+
// If there's no manual `EndingOffset`, just go to the opposite of `StartingOffset`.
68+
var end = ent.Comp.EndingOffset ?? -ent.Comp.StartingOffset;
69+
70+
// Rotation
71+
// Honestly I don't understand all of RT's sprite/eye/world/cardinal rotation stuff. I just trial-and-error'd this into working.
72+
// (why isn't there a helper function for this) :(
73+
if (TryComp<SpriteComponent>(ent, out var sprite))
74+
{
75+
var worldRotation = _transformSystem.GetWorldRotation(ent);
76+
var eyeRotation = _eyeManager.CurrentEye.Rotation;
77+
78+
var relativeRotation = (worldRotation + eyeRotation).Reduced().FlipPositive();
79+
80+
var cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero;
81+
82+
var finalAngle = sprite.NoRotation ? relativeRotation : relativeRotation - cardinalSnapping;
83+
84+
start = finalAngle.RotateVec(start); // `RotateVec()` contains a `Theta == 0` check, so no need to check for it in here.
85+
end = finalAngle.RotateVec(end);
86+
}
87+
88+
// Welding.
89+
if (!isWelded)
90+
{
91+
return (start, end);
92+
}
93+
// Unwelding. (go backwards)
94+
else
95+
{
96+
return (end, start);
97+
}
98+
}
99+
}

Content.Goobstation.Common/Silicons/Components/ExperimentalLawProviderComponent.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public sealed partial class ExperimentalLawProviderComponent : Component
1414
{
1515
[DataField] public string RandomLawsets = "IonStormLawsets";
1616

17-
// Numbers are equivalent to 83 points per second, so it's like running a dangerous anomaly for 2 minutes.
17+
// buffed point amounts 3x so people will actually use this; 30k in two minutes seems ok to me (triples points per second from ~80 to ~240)- strong but takes a lot of setup by RD (and stealing the AI upload console)
1818
[DataField] public float RewardTime = 120.0f;
1919

20-
[DataField] public int RewardPoints = 10000;
20+
[DataField] public int RewardPoints = 30000;
2121
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace Content.Goobstation.Common.Tools;
2+
3+
/// <summary>
4+
/// Event raised on a tool in `SharedToolSystem.UseTool()` if its DoAfter timer successfully started.
5+
/// </summary>
6+
public readonly record struct UseToolEvent
7+
{
8+
/// <summary>
9+
/// The entity using the tool.
10+
/// </summary>
11+
public readonly EntityUid User;
12+
13+
/// <summary>
14+
/// The entity that the tool is being used on. (May be null)
15+
/// </summary>
16+
public readonly EntityUid? Target;
17+
18+
/// <summary>
19+
/// The ID index of the DoAfter.
20+
/// </summary>
21+
/// <remarks>
22+
/// Ideally this would just be a <c>DoAfterIdx</c> instance and wouldn't need converting back, but this is in '.Common' so oh well.
23+
/// </remarks>
24+
public readonly ushort DoAfterIdx;
25+
26+
/// <summary>
27+
/// Duration of the DoAfter timer.
28+
/// </summary>
29+
public readonly TimeSpan DoAfterLength;
30+
31+
public UseToolEvent(EntityUid user, EntityUid? target, ushort doAfterIdx, TimeSpan doAfterLength)
32+
{
33+
User = user;
34+
Target = target;
35+
DoAfterIdx = doAfterIdx;
36+
DoAfterLength = doAfterLength;
37+
}
38+
}

Content.Goobstation.Server/Actions/ActionsProviderComponent.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

Content.Goobstation.Server/Actions/ActionsProviderSystem.cs

Lines changed: 0 additions & 29 deletions
This file was deleted.

Content.Goobstation.Server/Blob/GameTicking/BlobRuleSystem.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using Content.Server.Nuke;
2525
using Content.Server.Objectives;
2626
using Content.Server.RoundEnd;
27+
using Content.Server.Shuttles.Systems;
2728
using Content.Server.Station.Components;
2829
using Content.Server.Station.Systems;
2930
using Content.Shared.GameTicking.Components;
@@ -44,6 +45,7 @@ public sealed class BlobRuleSystem : GameRuleSystem<BlobRuleComponent>
4445
[Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!;
4546
[Dependency] private readonly IChatManager _chatManager = default!;
4647
[Dependency] private readonly IPlayerManager _player = default!;
48+
[Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
4749

4850
public override void Initialize()
4951
{
@@ -124,7 +126,8 @@ private void CheckChangeStage(
124126
var stationName = Name(stationUid);
125127

126128
if (blobTilesCount >= (stationUid.Comp?.StageBegin ?? StationBlobConfigComponent.DefaultStageBegin)
127-
&& _roundEndSystem.ExpectedCountdownEnd != null)
129+
&& _roundEndSystem.ExpectedCountdownEnd != null
130+
&& !_emergency.EmergencyShuttleArrived)
128131
{
129132
_roundEndSystem.CancelRoundEndCountdown(checkCooldown: false);
130133
_chatSystem.DispatchStationAnnouncement(stationUid,
@@ -134,7 +137,17 @@ private void CheckChangeStage(
134137
null,
135138
Color.Red);
136139
}
137-
140+
else if (blobTilesCount >= (stationUid.Comp?.StageBegin ?? StationBlobConfigComponent.DefaultStageBegin)
141+
&& _roundEndSystem.ExpectedCountdownEnd != null && _emergency.EmergencyShuttleArrived)
142+
{
143+
_chatSystem.DispatchStationAnnouncement(stationUid,
144+
Loc.GetString("blob-alert-shuttle-arrived"),
145+
Loc.GetString("Station"),
146+
false,
147+
null,
148+
Color.OrangeRed);
149+
}
150+
138151
switch (blobRuleComp.Stage)
139152
{
140153
case BlobStage.Default when blobTilesCount >= (stationUid.Comp?.StageBegin ?? StationBlobConfigComponent.DefaultStageBegin):

Content.Goobstation.Server/Sprinting/SprintingSystem.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// SPDX-License-Identifier: AGPL-3.0-or-later
66

77
using Content.Goobstation.Common.Standing;
8+
using Content.Goobstation.Server.Sandevistan;
89
using Content.Goobstation.Shared.Sprinting;
910
using Content.Server.Stunnable;
1011
using Content.Shared.CombatMode;
@@ -35,7 +36,9 @@ private void OnCollide(EntityUid uid, SprinterComponent sprinter, ref StartColli
3536
return;
3637
}
3738

38-
if (!TryComp(otherUid, out SprinterComponent? otherSprinter) || !otherSprinter.IsSprinting)
39+
if (!TryComp(otherUid, out SprinterComponent? otherSprinter)
40+
|| !otherSprinter.IsSprinting
41+
|| !HasComp<ActiveSandevistanUserComponent>(otherUid))
3942
{
4043
return;
4144
}

Content.Goobstation.Server/StationEvents/Components/GameDirectorComponent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace Content.Goobstation.Server.StationEvents.Components;
1414

15-
[RegisterComponent, Access(typeof(GameDirectorSystem))]
15+
[RegisterComponent, Access(typeof(GameDirector.GameDirectorSystem))]
1616
public sealed partial class GameDirectorComponent : Component
1717
{
1818

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Content.Goobstation.Server.StationEvents.Components;
2+
using Content.Goobstation.Server.StationEvents.Metric;
3+
4+
namespace Content.Goobstation.Server.StationEvents.GameDirector;
5+
6+
/// <summary>
7+
/// Pairs a PossibleEvent with the resultant chaos and a "score" for sorting by the GameDirector
8+
/// Temporary class used in processing and ranking the list of events.
9+
/// </summary>
10+
public sealed class RankedEvent(PossibleEvent possibleEvent, ChaosMetrics result, float score)
11+
{
12+
/// <summary>
13+
/// Contains the StationEvent and expected chaos delta
14+
/// </summary>
15+
public readonly PossibleEvent PossibleEvent = possibleEvent;
16+
17+
/// <summary>
18+
/// Current chaos + PossibleEvent.Chaos at time of creation
19+
/// </summary>
20+
public readonly ChaosMetrics Result = result;
21+
22+
/// <summary>
23+
/// Preference for this RankedEvent, lower is better.
24+
/// Essentially the "pain" of how far Result is from the StoryBeat.Goal
25+
/// </summary>
26+
public readonly float Score = score;
27+
}
28+
29+
public sealed class PlayerCount
30+
{
31+
public int Players;
32+
public int Ghosts;
33+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System.Linq;
2+
using Content.Shared.Mind;
3+
using Robust.Shared.Enums;
4+
using Robust.Shared.Player;
5+
6+
namespace Content.Goobstation.Server.StationEvents.GameDirector;
7+
8+
public sealed partial class GameDirectorSystem
9+
{
10+
11+
/// <summary>
12+
/// Count the active players and ghosts on the server.
13+
/// Players gates which stories and events are available
14+
/// Ghosts can be used to gate certain events (which require ghosts to occur)
15+
/// </summary>
16+
private PlayerCount CountActivePlayers()
17+
{
18+
var allPlayers = Enumerable.ToList<ICommonSession>(_playerManager.Sessions);
19+
var count = new PlayerCount();
20+
foreach (var player in allPlayers)
21+
{
22+
if (player.AttachedEntity == null)
23+
continue;
24+
var ev = new GetCharactedDeadIcEvent();
25+
RaiseLocalEvent(player.AttachedEntity.Value, ref ev);
26+
if (ev.Dead is not true)
27+
count.Players++;
28+
else
29+
count.Ghosts++;
30+
}
31+
32+
count.Players += _event.PlayerCountBias;
33+
34+
return count;
35+
}
36+
37+
/// <summary>
38+
/// Gets the player count for antag selection (debug or actual)
39+
/// </summary>
40+
private int GetPlayerCount()
41+
{
42+
#if DEBUG
43+
return _gameDirectorDebugPlayerCount;
44+
#else
45+
return GetTotalPlayerCount(_playerManager.Sessions);
46+
#endif
47+
}
48+
49+
/// <summary>
50+
/// Count all the players on the server.
51+
/// </summary>
52+
private int GetTotalPlayerCount(IList<ICommonSession> pool)
53+
{
54+
var count = 0;
55+
foreach (var session in pool)
56+
{
57+
if (session.Status is SessionStatus.Disconnected or SessionStatus.Zombie)
58+
continue;
59+
60+
count++;
61+
}
62+
63+
return count + _event.PlayerCountBias;
64+
}
65+
}

0 commit comments

Comments
 (0)