diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
index 4707a69f1e..bab8dcd237 100644
--- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
+++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
@@ -4,6 +4,7 @@ using System.Numerics;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
using Content.Server.Station.Events;
+using Content.Shared.Atmos.Components;
using Content.Shared.Body.Components;
using Content.Shared.CCVar;
using Content.Shared.Database;
@@ -51,6 +52,7 @@ public sealed partial class ShuttleSystem
private float FTLCooldown;
public float FTLMassLimit;
private TimeSpan _hyperspaceKnockdownTime = TimeSpan.FromSeconds(5);
+ private const float _ftlThrowForce = 20.0f;
///
/// Left-side of the station we're allowed to use
@@ -74,6 +76,7 @@ public sealed partial class ShuttleSystem
private EntityQuery _bodyQuery;
private EntityQuery _immuneQuery;
private EntityQuery _statusQuery;
+ private EntityQuery _movedByPressureQuery;
private void InitializeFTL()
{
@@ -83,6 +86,7 @@ public sealed partial class ShuttleSystem
_bodyQuery = GetEntityQuery();
_immuneQuery = GetEntityQuery();
_statusQuery = GetEntityQuery();
+ _movedByPressureQuery = GetEntityQuery();
_cfg.OnValueChanged(CCVars.FTLStartupTime, time => DefaultStartupTime = time, true);
_cfg.OnValueChanged(CCVars.FTLTravelTime, time => DefaultTravelTime = time, true);
@@ -375,7 +379,8 @@ public sealed partial class ShuttleSystem
var uid = entity.Owner;
var comp = entity.Comp1;
var xform = _xformQuery.GetComponent(entity);
- DoTheDinosaur(xform);
+ // Sunrise-Edit
+ //DoTheDinosaur(xform);
comp.State = FTLState.Travelling;
var fromMapUid = xform.MapUid;
@@ -429,6 +434,10 @@ public sealed partial class ShuttleSystem
var wowdio = _audio.PlayPvs(comp.TravelSound, uid);
comp.TravelStream = wowdio?.Entity;
_audio.SetGridAudio(wowdio);
+
+ // Sunrise-Start
+ DoTheDinosaur(xform, Direction.South.ToVec());
+ // Sunrise-End
}
///
@@ -441,6 +450,16 @@ public sealed partial class ShuttleSystem
comp.StateTime = StartEndTime.FromCurTime(_gameTiming, DefaultArrivalTime);
comp.State = FTLState.Arriving;
+ // Sunrise-Start
+ // Почему оно здесь а не в UpdateFTLArriving?
+ // Ну потому что когда шаттл выходит из фтл он телепортируется
+ // к докам и меняет угол поворота. А вот брошеная сущность все еще летит
+ // в том направлении когда шаттл был в фтл зоне,
+ // как итог полет будет не назад или вперед а в бок.
+ var xform = _xformQuery.GetComponent(entity.Owner);
+ DoTheDinosaur(xform, Direction.North.ToVec());
+ // Sunrise-End
+
if (entity.Comp1.VisualizerProto != null)
{
comp.VisualizerEntity = SpawnAttachedTo(entity.Comp1.VisualizerProto, entity.Comp1.TargetCoordinates);
@@ -467,7 +486,8 @@ public sealed partial class ShuttleSystem
var xform = _xformQuery.GetComponent(uid);
var body = _physicsQuery.GetComponent(uid);
var comp = entity.Comp1;
- DoTheDinosaur(xform);
+ // Sunrise-Edit
+ //DoTheDinosaur(xform);
_dockSystem.SetDockBolts(entity, false);
_physics.SetLinearVelocity(uid, Vector2.Zero, body: body);
@@ -610,7 +630,7 @@ public sealed partial class ShuttleSystem
///
/// Puts everyone unbuckled on the floor, paralyzed.
///
- private void DoTheDinosaur(TransformComponent xform)
+ private void DoTheDinosaur(TransformComponent xform, Vector2 throwDirection) // Sunrise-Edit
{
// Get enumeration exceptions from people dropping things if we just paralyze as we go
var toKnock = new ValueList();
@@ -626,6 +646,22 @@ public sealed partial class ShuttleSystem
_stuns.TryParalyze(child, _hyperspaceKnockdownTime, true, status);
+ // Sunrise-Start
+ if (_physicsQuery.TryGetComponent(child, out var physics))
+ {
+ if ((physics.BodyType & BodyType.Static) != 0)
+ continue;
+
+ _throwing.TryThrow(child,
+ throwDirection * _ftlThrowForce,
+ physics,
+ Transform(child),
+ _projQuery,
+ _ftlThrowForce,
+ playSound: false);
+ }
+ // Sunrise-End
+
// If the guy we knocked down is on a spaced tile, throw them too
if (grid != null)
TossIfSpaced((xform.GridUid.Value, grid, shuttleBody), child);
@@ -667,6 +703,11 @@ public sealed partial class ShuttleSystem
if (!_buckleQuery.TryGetComponent(child, out var buckle) || buckle.Buckled)
continue;
+ // Sunrise-Start
+ if (_movedByPressureQuery.TryComp(child, out var moved) && !moved.Enabled)
+ continue;
+ // Sunrise-End
+
toKnock.Add(child);
}
}
diff --git a/Content.Shared/Buckle/BuckleDoafterEvent.cs b/Content.Shared/Buckle/BuckleDoafterEvent.cs
index 268ddfe261..f5c846b38a 100644
--- a/Content.Shared/Buckle/BuckleDoafterEvent.cs
+++ b/Content.Shared/Buckle/BuckleDoafterEvent.cs
@@ -9,3 +9,11 @@ public sealed partial class BuckleDoAfterEvent : SimpleDoAfterEvent
{
}
+
+// Sunrise-Start
+[Serializable, NetSerializable]
+public sealed partial class UnbuckleDoAfterEvent : SimpleDoAfterEvent
+{
+
+}
+// Sunrise-End
diff --git a/Content.Shared/Buckle/Components/BuckleComponent.cs b/Content.Shared/Buckle/Components/BuckleComponent.cs
index 1518ccea9b..9b0a157bdf 100644
--- a/Content.Shared/Buckle/Components/BuckleComponent.cs
+++ b/Content.Shared/Buckle/Components/BuckleComponent.cs
@@ -70,6 +70,11 @@ public sealed partial class BuckleComponent : Component
/// Used for client rendering
///
[ViewVariables] public int? OriginalDrawDepth;
+
+ // Sunrise-Start
+ [DataField]
+ public float UnbuckleDoafterTime = 2f;
+ // Sunrise-End
}
public sealed partial class UnbuckleAlertEvent : BaseAlertEvent;
diff --git a/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs b/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs
index 198f9d127a..89ea294c3f 100644
--- a/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs
+++ b/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs
@@ -60,6 +60,14 @@ public abstract partial class SharedBuckleSystem
{
BuckleDoafterEarly((uid, comp), ev.Event, ev);
});
+
+ // Sunrise-Start
+ SubscribeLocalEvent(OnUnbuckleDoafter);
+ SubscribeLocalEvent>((uid, comp, ev) =>
+ {
+ UnbuckleDoafterEarly((uid, comp), ev.Event, ev);
+ });
+ // Sunrise-End
}
private void OnBuckleComponentShutdown(Entity ent, ref ComponentShutdown args)
@@ -74,6 +82,11 @@ public abstract partial class SharedBuckleSystem
// Prevent people pulling the chair they're on, etc.
if (ent.Comp.BuckledTo == args.Pulled && !ent.Comp.PullStrap)
args.Cancel();
+
+ // Sunrise-Start
+ if (ent.Comp.Buckled)
+ args.Cancel();
+ // Sunrise-End
}
private void OnBeingPulledAttempt(Entity ent, ref BeingPulledAttemptEvent args)
@@ -282,7 +295,7 @@ public abstract partial class SharedBuckleSystem
return false;
}
- if (buckleComp.Buckled && !TryUnbuckle(buckleUid, user, buckleComp))
+ if (buckleComp.Buckled) // && !TryUnbuckle(buckleUid, user, buckleComp) Sunrise-Edit
{
if (popup)
{
@@ -604,4 +617,27 @@ public abstract partial class SharedBuckleSystem
TryBuckle(args.Target.Value, args.User, args.Used.Value, popup: false);
}
}
+
+ // Sunrise-Start
+ private void OnUnbuckleDoafter(Entity entity, ref UnbuckleDoAfterEvent args)
+ {
+ if (args.Cancelled || args.Handled || args.Target == null)
+ return;
+
+ args.Handled = TryUnbuckle(args.Target.Value, args.User, popup: false);
+ }
+
+ private void UnbuckleDoafterEarly(Entity entity, UnbuckleDoAfterEvent args, CancellableEntityEventArgs ev)
+ {
+ if (args.Target == null)
+ return;
+
+ if (TryComp(args.Target, out var targetCuffableComp) && targetCuffableComp.CuffedHandCount > 0
+ || _mobState.IsIncapacitated(args.Target.Value))
+ {
+ ev.Cancel();
+ TryUnbuckle(args.Target.Value, args.User, popup: false);
+ }
+ }
+ // Sunrise-End
}
diff --git a/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs b/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs
index 29531ce72b..64996b091b 100644
--- a/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs
+++ b/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs
@@ -107,11 +107,26 @@ public abstract partial class SharedBuckleSystem
}
// Unbuckle others
- if (component.BuckledEntities.TryFirstOrNull(out var buckled) && TryUnbuckle(buckled.Value, args.User))
+ // Sunrise-Start
+ if (component.BuckledEntities.TryFirstOrNull(out var buckled))
{
- args.Handled = true;
- return;
+ if (CanUnbuckle(buckled.Value, args.User, false))
+ {
+ var doAfterArgs = new DoAfterArgs(EntityManager, args.User, buckle.UnbuckleDoafterTime, new UnbuckleDoAfterEvent(), buckled.Value, buckled.Value)
+ {
+ BreakOnMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.EveryTick
+ };
+
+ if (_doAfter.TryStartDoAfter(doAfterArgs))
+ {
+ args.Handled = true;
+ return;
+ }
+ }
}
+ // Sunrise-End
// TODO BUCKLE add out bool for whether a pop-up was generated or not.
}
@@ -122,7 +137,31 @@ public abstract partial class SharedBuckleSystem
return;
if (ent.Comp.BuckledTo != null)
- args.Handled = TryUnbuckle(ent!, args.User, popup: true);
+ {
+ // Sunrise-Start
+ if (CanUnbuckle((ent.Owner, ent.Comp), args.User, false))
+ {
+ if (ent.Owner == args.User)
+ {
+ args.Handled = TryUnbuckle(ent!, args.User, popup: true);
+ }
+ else
+ {
+ var doAfterArgs = new DoAfterArgs(EntityManager, args.User, ent.Comp.UnbuckleDoafterTime, new UnbuckleDoAfterEvent(), ent.Owner, ent.Owner)
+ {
+ BreakOnMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.EveryTick
+ };
+
+ if (_doAfter.TryStartDoAfter(doAfterArgs))
+ {
+ args.Handled = true;
+ }
+ }
+ }
+ // Sunrise-End
+ }
// TODO BUCKLE add out bool for whether a pop-up was generated or not.
}
@@ -143,9 +182,31 @@ public abstract partial class SharedBuckleSystem
if (!_interaction.InRangeUnobstructed(args.User, args.Target, range: buckledComp.Range))
continue;
+ // Sunrise-Start
+ if (!CanUnbuckle(entity, args.User, false))
+ continue;
+ // Sunrise-End
+
var verb = new InteractionVerb()
{
- Act = () => TryUnbuckle(entity, args.User, buckleComp: buckledComp),
+ // Sunrise-Start
+ Act = () => {
+ if (entity == args.User)
+ {
+ TryUnbuckle(entity, args.User, buckleComp: buckledComp);
+ }
+ else
+ {
+ var doAfterArgs = new DoAfterArgs(EntityManager, args.User, buckledComp.UnbuckleDoafterTime, new UnbuckleDoAfterEvent(), entity, entity)
+ {
+ BreakOnMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.EveryTick
+ };
+ _doAfter.TryStartDoAfter(doAfterArgs);
+ }
+ },
+ // Sunrise-End
Category = VerbCategory.Unbuckle,
Text = entity == args.User
? Loc.GetString("verb-self-target-pronoun")
@@ -212,7 +273,24 @@ public abstract partial class SharedBuckleSystem
InteractionVerb verb = new()
{
- Act = () => TryUnbuckle(uid, args.User, buckleComp: component),
+ // Sunrise-Start
+ Act = () => {
+ if (uid == args.User)
+ {
+ TryUnbuckle(uid, args.User, buckleComp: component);
+ }
+ else
+ {
+ var doAfterArgs = new DoAfterArgs(EntityManager, args.User, component.UnbuckleDoafterTime, new UnbuckleDoAfterEvent(), uid, uid)
+ {
+ BreakOnMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.EveryTick
+ };
+ _doAfter.TryStartDoAfter(doAfterArgs);
+ }
+ },
+ // Sunrise-End
Text = Loc.GetString("verb-categories-unbuckle"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/unbuckle.svg.192dpi.png"))
};
diff --git a/Content.Shared/CCVar/CCVars.Shuttle.cs b/Content.Shared/CCVar/CCVars.Shuttle.cs
index 6ca7f521b1..18f8ed9cb7 100644
--- a/Content.Shared/CCVar/CCVars.Shuttle.cs
+++ b/Content.Shared/CCVar/CCVars.Shuttle.cs
@@ -86,13 +86,13 @@ public sealed partial class CCVars
/// How long a shuttle spends in FTL.
///
public static readonly CVarDef FTLTravelTime =
- CVarDef.Create("shuttle.travel_time", 60f, CVar.SERVERONLY);
+ CVarDef.Create("shuttle.travel_time", 30f, CVar.SERVERONLY); // Sunrise-Edit
///
/// How long the final stage of FTL before arrival should be.
///
public static readonly CVarDef FTLArrivalTime =
- CVarDef.Create("shuttle.arrival_time", 20f, CVar.SERVERONLY);
+ CVarDef.Create("shuttle.arrival_time", 2f, CVar.SERVERONLY); // Sunrise-Edit
///
/// How much time needs to pass before a shuttle can FTL again.
diff --git a/Content.Shared/Damage/Components/DamageOnHighSpeedImpactComponent.cs b/Content.Shared/Damage/Components/DamageOnHighSpeedImpactComponent.cs
index e7f4fdf703..18121e5351 100644
--- a/Content.Shared/Damage/Components/DamageOnHighSpeedImpactComponent.cs
+++ b/Content.Shared/Damage/Components/DamageOnHighSpeedImpactComponent.cs
@@ -12,7 +12,7 @@ namespace Content.Shared.Damage.Components;
public sealed partial class DamageOnHighSpeedImpactComponent : Component
{
[DataField("minimumSpeed"), ViewVariables(VVAccess.ReadWrite)]
- public float MinimumSpeed = 20f;
+ public float MinimumSpeed = 10f; // Sunrise-Edit
[DataField("speedDamageFactor"), ViewVariables(VVAccess.ReadWrite)]
public float SpeedDamageFactor = 0.5f;
diff --git a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
index 0f55c99e72..85d1bfdfa0 100644
--- a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
+++ b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
@@ -454,6 +454,13 @@ public sealed class PullingSystem : EntitySystem
return false;
}
+ // Sunrise-Start
+ if (TryComp(pullableUid, out var buckleComponent) && buckleComponent.Buckled)
+ {
+ return false;
+ }
+ // Sunrise-End
+
var getPulled = new BeingPulledAttemptEvent(puller, pullableUid);
RaiseLocalEvent(pullableUid, getPulled, true);
var startPull = new StartPullAttemptEvent(puller, pullableUid);
diff --git a/Resources/Changelog/ChangelogSunrise.yml b/Resources/Changelog/ChangelogSunrise.yml
index 62f7fc990f..785d354afd 100644
--- a/Resources/Changelog/ChangelogSunrise.yml
+++ b/Resources/Changelog/ChangelogSunrise.yml
@@ -20016,3 +20016,28 @@
type: Tweak
id: 1329
time: '2025-08-02T20:54:50.494668+00:00'
+- author: VigersRay
+ changes:
+ - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043F\u0440\u0438 \u0437\u0430\
+ \u043F\u0443\u0441\u043A\u0435 \u0438 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\
+ \u0438\u0438 FTL \u043F\u043E\u043C\u0438\u043C\u043E \u043E\u0433\u043B\u0443\
+ \u0448\u0435\u043D\u0438\u044F \u0432\u0441\u0435 \u0441\u0443\u0449\u0435\u0441\
+ \u0442\u0432\u0430 \u0431\u0443\u0434\u0443\u0442 \u043E\u0442\u043F\u0440\u0430\
+ \u0432\u043B\u0435\u043D\u044B \u0432 \u043F\u043E\u043B\u0435\u0442. \u041D\
+ \u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u0437\u0430\u0432\
+ \u0438\u0441\u0438\u0442 \u043E\u0442 \u0442\u043E\u0440\u043C\u043E\u0436\u0435\
+ \u043D\u0438\u044F \u0438\u043B\u0438 \u043D\u0430\u0447\u0430\u043B\u0430 \u0434\
+ \u0432\u0438\u0436\u0435\u043D\u0438\u044F."
+ type: Tweak
+ - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043E\u0442\u0441\u0442\u0435\u0433\
+ \u0438\u0432\u0430\u043D\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\
+ \u0443\u0449\u0435\u0441\u0442\u0432 \u043F\u0440\u043E\u0438\u0441\u0445\u043E\
+ \u0434\u0438\u0442 \u0441 \u0434\u0432\u0443\u0445 \u0441\u0435\u043A\u0443\u043D\
+ \u0434\u043D\u043E\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043A\u043E\u0439\
+ . \u041D\u0438\u043A\u0430\u043A\u0438\u0445 \u0431\u043E\u043B\u044C\u0448\u0435\
+ \ \u043E\u0442\u0441\u0442\u0435\u0433\u0438\u0432\u0430\u043D\u0438\u0439 \u0440\
+ \u0430\u0434\u0438 \u0437\u0430\u0431\u0430\u0432\u044B \u043F\u0440\u0438 \u0437\
+ \u0430\u043F\u0443\u0441\u043A\u0435 \u0448\u0430\u0442\u0442\u043B\u0430."
+ type: Tweak
+ id: 1330
+ time: '2025-08-03T03:37:52.488647+00:00'