Merge remote-tracking branch 'upstream/master' into ed-05-08-2024-upstream

# Conflicts:
#	Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs
This commit is contained in:
Ed
2024-08-08 12:29:20 +03:00
155 changed files with 17151 additions and 15001 deletions

View File

@@ -93,6 +93,6 @@ public sealed class ClientAlertsSystem : AlertsSystem
public void AlertClicked(ProtoId<AlertPrototype> alertType)
{
RaiseNetworkEvent(new ClickAlertEvent(alertType));
RaisePredictiveEvent(new ClickAlertEvent(alertType));
}
}

View File

@@ -0,0 +1,10 @@
using Content.Shared.Atmos.EntitySystems;
using JetBrains.Annotations;
namespace Content.Client.Atmos.EntitySystems;
[UsedImplicitly]
public sealed class GasMinerSystem : SharedGasMinerSystem
{
}

View File

@@ -16,6 +16,7 @@ namespace Content.Client.Chat.UI
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] protected readonly IConfigurationManager ConfigManager = default!;
private readonly SharedTransformSystem _transformSystem;
public enum SpeechType : byte
{
@@ -83,6 +84,7 @@ namespace Content.Client.Chat.UI
{
IoCManager.InjectDependencies(this);
_senderEntity = senderEntity;
_transformSystem = _entityManager.System<SharedTransformSystem>();
// Use text clipping so new messages don't overlap old ones being pushed up.
RectClipContent = true;
@@ -140,7 +142,7 @@ namespace Content.Client.Chat.UI
}
var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -EntityVerticalOffset;
var worldPos = xform.WorldPosition + offset;
var worldPos = _transformSystem.GetWorldPosition(xform) + offset;
var lowerCenter = _eyeManager.WorldToScreen(worldPos) / UIScale;
var screenPos = lowerCenter - new Vector2(ContentSize.X / 2, ContentSize.Y + _verticalOffsetAchieved);

View File

@@ -1,3 +1,4 @@
using Content.Client.Actions;
using Content.Client.Mapping;
using Content.Client.Markers;
using JetBrains.Annotations;
@@ -25,7 +26,7 @@ internal sealed class MappingClientSideSetupCommand : LocalizedCommands
_entitySystemManager.GetEntitySystem<MarkerSystem>().MarkersVisible = true;
_lightManager.Enabled = false;
shell.ExecuteCommand("showsubfloorforever");
_stateManager.RequestStateChange<MappingState>();
_entitySystemManager.GetEntitySystem<ActionsSystem>().LoadActionAssignments("/mapping_actions.yml", false);
}
}
}

View File

@@ -16,6 +16,7 @@ public sealed class ExplosionOverlay : Overlay
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
private readonly SharedTransformSystem _transformSystem;
private SharedAppearanceSystem _appearance;
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
@@ -26,6 +27,7 @@ public sealed class ExplosionOverlay : Overlay
{
IoCManager.InjectDependencies(this);
_shader = _proto.Index<ShaderPrototype>("unshaded").Instance();
_transformSystem = _entMan.System<SharedTransformSystem>();
_appearance = appearanceSystem;
}
@@ -68,7 +70,7 @@ public sealed class ExplosionOverlay : Overlay
continue;
var xform = xforms.GetComponent(gridId);
var (_, _, worldMatrix, invWorldMatrix) = xform.GetWorldPositionRotationMatrixWithInv(xforms);
var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(xform, xforms);
gridBounds = invWorldMatrix.TransformBox(worldBounds).Enlarged(grid.TileSize * 2);
drawHandle.SetTransform(worldMatrix);

View File

@@ -14,6 +14,7 @@ public sealed class PuddleOverlay : Overlay
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
private readonly PuddleDebugOverlaySystem _debugOverlaySystem;
private readonly SharedTransformSystem _transformSystem;
private readonly Color _heavyPuddle = new(0, 255, 255, 50);
private readonly Color _mediumPuddle = new(0, 150, 255, 50);
@@ -29,6 +30,7 @@ public sealed class PuddleOverlay : Overlay
_debugOverlaySystem = _entitySystemManager.GetEntitySystem<PuddleDebugOverlaySystem>();
var cache = IoCManager.Resolve<IResourceCache>();
_font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8);
_transformSystem = _entityManager.System<SharedTransformSystem>();
}
protected override void Draw(in OverlayDrawArgs args)
@@ -56,7 +58,7 @@ public sealed class PuddleOverlay : Overlay
continue;
var gridXform = xformQuery.GetComponent(gridId);
var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(xformQuery);
var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform, xformQuery);
gridBounds = invWorldMatrix.TransformBox(args.WorldBounds).Enlarged(mapGrid.TileSize * 2);
drawHandle.SetTransform(worldMatrix);
@@ -89,7 +91,7 @@ public sealed class PuddleOverlay : Overlay
continue;
var gridXform = xformQuery.GetComponent(gridId);
var (_, _, matrix, invMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv(xformQuery);
var (_, _, matrix, invMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform, xformQuery);
var gridBounds = invMatrix.TransformBox(args.WorldBounds).Enlarged(mapGrid.TileSize * 2);
foreach (var debugOverlayData in _debugOverlaySystem.GetData(gridId))

View File

@@ -42,6 +42,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
// how often to recheck possible targets (prevents calling expensive
// check logic each update)
@@ -89,7 +90,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
/// </summary>
private bool _isReplaying;
private float _deadzone;
public float Deadzone;
private DragState _state = DragState.NotDragging;
@@ -121,7 +122,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
private void SetDeadZone(float deadZone)
{
_deadzone = deadZone;
Deadzone = deadZone;
}
public override void Shutdown()
@@ -211,7 +212,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
_draggedEntity = entity;
_state = DragState.MouseDown;
_mouseDownScreenPos = _inputManager.MouseScreenPosition;
_mouseDownScreenPos = args.ScreenCoordinates;
_mouseDownTime = 0;
// don't want anything else to process the click,
@@ -239,8 +240,13 @@ public sealed class DragDropSystem : SharedDragDropSystem
if (TryComp<SpriteComponent>(_draggedEntity, out var draggedSprite))
{
var screenPos = _inputManager.MouseScreenPosition;
// No _draggedEntity in null window (Happens in tests)
if (!screenPos.IsValid)
return;
// pop up drag shadow under mouse
var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition);
var mousePos = _eyeManager.PixelToMap(screenPos);
_dragShadow = EntityManager.SpawnEntity("dragshadow", mousePos);
var dragSprite = Comp<SpriteComponent>(_dragShadow.Value);
dragSprite.CopyFrom(draggedSprite);
@@ -517,6 +523,9 @@ public sealed class DragDropSystem : SharedDragDropSystem
if (dropEv2.Handled)
return dropEv2.CanDrop;
if (dropEv.Handled && dropEv.CanDrop)
return true;
return null;
}
@@ -530,7 +539,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
case DragState.MouseDown:
{
var screenPos = _inputManager.MouseScreenPosition;
if ((_mouseDownScreenPos!.Value.Position - screenPos.Position).Length() > _deadzone)
if ((_mouseDownScreenPos!.Value.Position - screenPos.Position).Length() > Deadzone)
{
StartDrag();
}
@@ -551,7 +560,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
if (Exists(_dragShadow))
{
var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition);
Transform(_dragShadow.Value).WorldPosition = mousePos.Position;
_transformSystem.SetWorldPosition(_dragShadow.Value, mousePos.Position);
}
}
}

View File

@@ -18,6 +18,7 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly InputSystem _inputSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
public bool Enabled { get; set; }
@@ -62,11 +63,11 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem
if (_dragging == null) return;
if (_lastMousePosition != null && TryComp(_dragging.Value, out TransformComponent? xform) &&
TryComp<PhysicsComponent>(_dragging.Value, out var body) &&
TryComp<PhysicsComponent>(_dragging.Value, out _) &&
xform.MapID == _lastMousePosition.Value.MapId)
{
var tickTime = _gameTiming.TickPeriod;
var distance = _lastMousePosition.Value.Position - xform.WorldPosition;
var distance = _lastMousePosition.Value.Position - _transformSystem.GetWorldPosition(xform);
RaiseNetworkEvent(new GridDragVelocityRequest()
{
Grid = GetNetEntity(_dragging.Value),

View File

@@ -9,6 +9,7 @@ public sealed class HTNOverlay : Overlay
{
private readonly IEntityManager _entManager = default!;
private readonly Font _font = default!;
private readonly SharedTransformSystem _transformSystem;
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
@@ -16,6 +17,7 @@ public sealed class HTNOverlay : Overlay
{
_entManager = entManager;
_font = new VectorFont(resourceCache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
_transformSystem = _entManager.System<SharedTransformSystem>();
}
protected override void Draw(in OverlayDrawArgs args)
@@ -30,7 +32,7 @@ public sealed class HTNOverlay : Overlay
if (string.IsNullOrEmpty(comp.DebugText) || xform.MapID != args.MapId)
continue;
var worldPos = xform.WorldPosition;
var worldPos = _transformSystem.GetWorldPosition(xform);
if (!args.WorldAABB.Contains(worldPos))
continue;

View File

@@ -81,10 +81,12 @@ public sealed class NPCSteeringOverlay : Overlay
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly IEntityManager _entManager;
private readonly SharedTransformSystem _transformSystem;
public NPCSteeringOverlay(IEntityManager entManager)
{
_entManager = entManager;
_transformSystem = _entManager.System<SharedTransformSystem>();
}
protected override void Draw(in OverlayDrawArgs args)
@@ -96,7 +98,7 @@ public sealed class NPCSteeringOverlay : Overlay
continue;
}
var (worldPos, worldRot) = xform.GetWorldPositionRotation();
var (worldPos, worldRot) = _transformSystem.GetWorldPositionRotation(xform);
if (!args.WorldAABB.Contains(worldPos))
continue;

View File

@@ -12,6 +12,7 @@ public sealed class NetworkConfiguratorLinkOverlay : Overlay
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private readonly DeviceListSystem _deviceListSystem;
private readonly SharedTransformSystem _transformSystem;
public Dictionary<EntityUid, Color> Colors = new();
public EntityUid? Action;
@@ -23,6 +24,7 @@ public sealed class NetworkConfiguratorLinkOverlay : Overlay
IoCManager.InjectDependencies(this);
_deviceListSystem = _entityManager.System<DeviceListSystem>();
_transformSystem = _entityManager.System<SharedTransformSystem>();
}
protected override void Draw(in OverlayDrawArgs args)
@@ -66,7 +68,7 @@ public sealed class NetworkConfiguratorLinkOverlay : Overlay
continue;
}
args.WorldHandle.DrawLine(sourceTransform.WorldPosition, linkTransform.WorldPosition, Colors[uid]);
args.WorldHandle.DrawLine(_transformSystem.GetWorldPosition(sourceTransform), _transformSystem.GetWorldPosition(linkTransform), Colors[uid]);
}
}
}

View File

@@ -20,6 +20,7 @@ namespace Content.Client.NodeContainer
private readonly IMapManager _mapManager;
private readonly IInputManager _inputManager;
private readonly IEntityManager _entityManager;
private readonly SharedTransformSystem _transformSystem;
private readonly Dictionary<(int, int), NodeRenderData> _nodeIndex = new();
private readonly Dictionary<EntityUid, Dictionary<Vector2i, List<(GroupData, NodeDatum)>>> _gridIndex = new ();
@@ -46,6 +47,7 @@ namespace Content.Client.NodeContainer
_mapManager = mapManager;
_inputManager = inputManager;
_entityManager = entityManager;
_transformSystem = _entityManager.System<SharedTransformSystem>();
_font = cache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 12);
}
@@ -146,7 +148,7 @@ namespace Content.Client.NodeContainer
foreach (var (gridId, gridDict) in _gridIndex)
{
var grid = _entityManager.GetComponent<MapGridComponent>(gridId);
var (_, _, worldMatrix, invMatrix) = _entityManager.GetComponent<TransformComponent>(gridId).GetWorldPositionRotationMatrixWithInv();
var (_, _, worldMatrix, invMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridId);
var lCursorBox = invMatrix.TransformBox(cursorBox);
foreach (var (pos, list) in gridDict)

View File

@@ -23,6 +23,7 @@ public sealed class TargetOutlineSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
private bool _enabled = false;
@@ -165,8 +166,8 @@ public sealed class TargetOutlineSystem : EntitySystem
valid = _interactionSystem.InRangeUnobstructed(player, entity, Range);
else if (Range >= 0)
{
var origin = Transform(player).WorldPosition;
var target = Transform(entity).WorldPosition;
var origin = _transformSystem.GetWorldPosition(player);
var target = _transformSystem.GetWorldPosition(entity);
valid = (origin - target).LengthSquared() <= Range;
}

View File

@@ -11,6 +11,7 @@ namespace Content.Client.Stealth;
public sealed class StealthSystem : SharedStealthSystem
{
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
private ShaderInstance _shader = default!;
@@ -81,7 +82,7 @@ public sealed class StealthSystem : SharedStealthSystem
if (!parent.IsValid())
return; // should never happen, but lets not kill the client.
var parentXform = Transform(parent);
var reference = args.Viewport.WorldToLocal(parentXform.WorldPosition);
var reference = args.Viewport.WorldToLocal(_transformSystem.GetWorldPosition(parentXform));
reference.X = -reference.X;
var visibility = GetVisibility(uid, component);

View File

@@ -27,6 +27,7 @@ namespace Content.Client.Tabletop
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
// Time in seconds to wait until sending the location of a dragged entity to the server again
private const float Delay = 1f / 10; // 10 Hz
@@ -100,7 +101,7 @@ namespace Content.Client.Tabletop
if (clampedCoords.Equals(MapCoordinates.Nullspace)) return;
// Move the entity locally every update
EntityManager.GetComponent<TransformComponent>(_draggedEntity.Value).WorldPosition = clampedCoords.Position;
_transformSystem.SetWorldPosition(_draggedEntity.Value, clampedCoords.Position);
// Increment total time passed
_timePassed += frameTime;

View File

@@ -15,7 +15,6 @@ public sealed class ViewportUIController : UIController
[Dependency] private readonly IPlayerManager _playerMan = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
public static readonly Vector2i ViewportSize = (EyeManager.PixelsPerMeter * 21, EyeManager.PixelsPerMeter * 15);
public const int ViewportHeight = 15;
private MainViewport? Viewport => UIManager.ActiveScreen?.GetWidget<MainViewport>();

View File

@@ -236,7 +236,7 @@ public sealed partial class MeleeWeaponSystem
private void UpdateEffects()
{
var query = EntityQueryEnumerator<TrackUserComponent, TransformComponent>();
while (query.MoveNext(out var arcComponent, out var xform))
while (query.MoveNext(out var uid, out var arcComponent, out var xform))
{
if (arcComponent.User == null)
continue;
@@ -249,7 +249,7 @@ public sealed partial class MeleeWeaponSystem
targetPos += entRotation.RotateVec(arcComponent.Offset);
}
TransformSystem.SetWorldPosition(xform, targetPos);
TransformSystem.SetWorldPosition(uid, targetPos);
}
}

View File

@@ -1207,11 +1207,12 @@ public abstract partial class InteractionTest
BoundKeyFunction key,
BoundKeyState state,
NetCoordinates? coordinates = null,
NetEntity? cursorEntity = null)
NetEntity? cursorEntity = null,
ScreenCoordinates? screenCoordinates = null)
{
var coords = coordinates ?? TargetCoords;
var target = cursorEntity ?? Target ?? default;
ScreenCoordinates screen = default;
var screen = screenCoordinates ?? default;
var funcId = InputManager.NetworkBindMap.KeyFunctionID(key);
var message = new ClientFullInputCmdMessage(CTiming.CurTick, CTiming.TickFraction, funcId)

View File

@@ -0,0 +1,46 @@
using Content.Client.Interaction;
using Content.IntegrationTests.Tests.Interaction;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Map;
namespace Content.IntegrationTests.Tests.Strip;
public sealed class StrippableTest : InteractionTest
{
protected override string PlayerPrototype => "MobHuman";
[Test]
public async Task DragDropOpensStrip()
{
// Spawn one tile away
TargetCoords = SEntMan.GetNetCoordinates(new EntityCoordinates(MapData.MapUid, 1, 0));
await SpawnTarget("MobHuman");
var userInterface = Comp<UserInterfaceComponent>(Target);
Assert.That(userInterface.Actors.Count == 0);
// screenCoordinates diff needs to be larger than DragDropSystem._deadzone
var screenX = CEntMan.System<DragDropSystem>().Deadzone + 1f;
// Start drag
await SetKey(EngineKeyFunctions.Use,
BoundKeyState.Down,
TargetCoords,
Target,
screenCoordinates: new ScreenCoordinates(screenX, 0f, WindowId.Main));
await RunTicks(5);
// End drag
await SetKey(EngineKeyFunctions.Use,
BoundKeyState.Up,
PlayerCoords,
Player,
screenCoordinates: new ScreenCoordinates(0f, 0f, WindowId.Main));
await RunTicks(5);
Assert.That(userInterface.Actors.Count > 0);
}
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Popups;
using Content.Shared.Abilities.Mime;
using Content.Shared.Actions;
using Content.Shared.Actions.Events;
using Content.Shared.Alert;
@@ -29,6 +30,9 @@ namespace Content.Server.Abilities.Mime
base.Initialize();
SubscribeLocalEvent<MimePowersComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<MimePowersComponent, InvisibleWallActionEvent>(OnInvisibleWall);
SubscribeLocalEvent<MimePowersComponent, BreakVowAlertEvent>(OnBreakVowAlert);
SubscribeLocalEvent<MimePowersComponent, RetakeVowAlertEvent>(OnRetakeVowAlert);
}
public override void Update(float frameTime)
@@ -99,6 +103,22 @@ namespace Content.Server.Abilities.Mime
args.Handled = true;
}
private void OnBreakVowAlert(Entity<MimePowersComponent> ent, ref BreakVowAlertEvent args)
{
if (args.Handled)
return;
BreakVow(ent, ent);
args.Handled = true;
}
private void OnRetakeVowAlert(Entity<MimePowersComponent> ent, ref RetakeVowAlertEvent args)
{
if (args.Handled)
return;
RetakeVow(ent, ent);
args.Handled = true;
}
/// <summary>
/// Break this mime's vow to not speak.
/// </summary>

View File

@@ -16,6 +16,7 @@ public sealed partial class AdminLogManager
// TODO ADMIN LOGS make this thread safe or remove thread safety from the main partial class
private readonly Dictionary<int, List<SharedAdminLog>> _roundsLogCache = new(MaxRoundsCached);
private readonly Queue<int> _roundsLogCacheQueue = new();
private static readonly Gauge CacheRoundCount = Metrics.CreateGauge(
"admin_logs_cache_round_count",
@@ -28,19 +29,21 @@ public sealed partial class AdminLogManager
// TODO ADMIN LOGS cache previous {MaxRoundsCached} rounds on startup
public void CacheNewRound()
{
List<SharedAdminLog> list;
var oldestRound = _currentRoundId - MaxRoundsCached;
List<SharedAdminLog>? list = null;
if (_roundsLogCache.Remove(oldestRound, out var oldestList))
_roundsLogCacheQueue.Enqueue(_currentRoundId);
if (_roundsLogCacheQueue.Count > MaxRoundsCached)
{
list = oldestList;
list.Clear();
}
else
{
list = new List<SharedAdminLog>(LogListInitialSize);
var oldestRound = _roundsLogCacheQueue.Dequeue();
if (_roundsLogCache.Remove(oldestRound, out var oldestList))
{
list = oldestList;
list.Clear();
}
}
list ??= new List<SharedAdminLog>(LogListInitialSize);
_roundsLogCache.Add(_currentRoundId, list);
CacheRoundCount.Set(_roundsLogCache.Count);
}

View File

@@ -1,22 +0,0 @@
using Content.Shared.Alert;
using Content.Server.Abilities.Mime;
namespace Content.Server.Alert.Click
{
///<summary>
/// Break your mime vows
///</summary>
[DataDefinition]
public sealed partial class BreakVow : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entManager = IoCManager.Resolve<IEntityManager>();
if (entManager.TryGetComponent(player, out MimePowersComponent? mimePowers))
{
entManager.System<MimePowersSystem>().BreakVow(player, mimePowers);
}
}
}
}

View File

@@ -1,21 +0,0 @@
using Content.Server.Cuffs;
using Content.Shared.Alert;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click
{
/// <summary>
/// Try to remove handcuffs from yourself
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class RemoveCuffs : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entityManager = IoCManager.Resolve<IEntityManager>();
var cuffableSys = entityManager.System<CuffableSystem>();
cuffableSys.TryUncuff(player, player);
}
}
}

View File

@@ -1,28 +0,0 @@
using Content.Server.Ensnaring;
using Content.Shared.Alert;
using Content.Shared.Ensnaring.Components;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click;
[UsedImplicitly]
[DataDefinition]
public sealed partial class RemoveEnsnare : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entManager = IoCManager.Resolve<IEntityManager>();
if (entManager.TryGetComponent(player, out EnsnareableComponent? ensnareableComponent))
{
foreach (var ensnare in ensnareableComponent.Container.ContainedEntities)
{
if (!entManager.TryGetComponent(ensnare, out EnsnaringComponent? ensnaringComponent))
return;
entManager.EntitySysManager.GetEntitySystem<EnsnareableSystem>().TryFree(player, player, ensnare, ensnaringComponent);
// Only one snare at a time.
break;
}
}
}
}

View File

@@ -1,25 +0,0 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Alert;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click
{
/// <summary>
/// Resist fire
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class ResistFire : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entManager = IoCManager.Resolve<IEntityManager>();
if (entManager.TryGetComponent(player, out FlammableComponent? flammable))
{
entManager.System<FlammableSystem>().Resist(player, flammable);
}
}
}
}

View File

@@ -1,22 +0,0 @@
using Content.Shared.Alert;
using Content.Server.Abilities.Mime;
namespace Content.Server.Alert.Click
{
///<summary>
/// Retake your mime vows
///</summary>
[DataDefinition]
public sealed partial class RetakeVow : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entManager = IoCManager.Resolve<IEntityManager>();
if (entManager.TryGetComponent(player, out MimePowersComponent? mimePowers))
{
entManager.System<MimePowersSystem>().RetakeVow(player, mimePowers);
}
}
}
}

View File

@@ -1,29 +0,0 @@
using Content.Shared.ActionBlocker;
using Content.Shared.Alert;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click
{
/// <summary>
/// Stop pulling something
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class StopBeingPulled : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entityManager = IoCManager.Resolve<IEntityManager>();
if (!entityManager.System<ActionBlockerSystem>().CanInteract(player, null))
return;
if (entityManager.TryGetComponent(player, out PullableComponent? playerPullable))
{
entityManager.System<PullingSystem>().TryStopPull(player, playerPullable, user: player);
}
}
}
}

View File

@@ -1,26 +0,0 @@
using Content.Server.Shuttles.Systems;
using Content.Shared.Alert;
using Content.Shared.Shuttles.Components;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click
{
/// <summary>
/// Stop piloting shuttle
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class StopPiloting : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entManager = IoCManager.Resolve<IEntityManager>();
if (entManager.TryGetComponent(player, out PilotComponent? pilotComponent)
&& pilotComponent.Console != null)
{
entManager.System<ShuttleConsoleSystem>().RemovePilot(player, pilotComponent);
}
}
}
}

View File

@@ -1,27 +0,0 @@
using Content.Shared.Alert;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click
{
/// <summary>
/// Stop pulling something
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class StopPulling : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var entManager = IoCManager.Resolve<IEntityManager>();
var ps = entManager.System<PullingSystem>();
if (entManager.TryGetComponent(player, out PullerComponent? puller) &&
entManager.TryGetComponent(puller.Pulling, out PullableComponent? pullableComp))
{
ps.TryStopPull(puller.Pulling.Value, pullableComp, user: player);
}
}
}
}

View File

@@ -1,19 +0,0 @@
using Content.Server.Body.Systems;
using Content.Shared.Alert;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click;
/// <summary>
/// Attempts to toggle the internals for a particular entity
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class ToggleInternals : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var internalsSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<InternalsSystem>();
internalsSystem.ToggleInternals(player, player, false);
}
}

View File

@@ -1,19 +0,0 @@
using Content.Shared.Alert;
using Content.Shared.Buckle;
using JetBrains.Annotations;
namespace Content.Server.Alert.Click
{
/// <summary>
/// Unbuckles if player is currently buckled.
/// </summary>
[UsedImplicitly]
[DataDefinition]
public sealed partial class Unbuckle : IAlertClick
{
public void AlertClicked(EntityUid player)
{
IoCManager.Resolve<IEntityManager>().System<SharedBuckleSystem>().TryUnbuckle(player, player);
}
}
}

View File

@@ -13,11 +13,15 @@ using Content.Server.Roles.Jobs;
using Content.Server.Shuttles.Components;
using Content.Server.Station.Systems;
using Content.Shared.Antag;
using Content.Shared.Clothing;
using Content.Shared.GameTicking;
using Content.Shared.GameTicking.Components;
using Content.Shared.Ghost;
using Content.Shared.Humanoid;
using Content.Shared.Mind;
using Content.Shared.Players;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles;
using Content.Shared.Whitelist;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
@@ -25,6 +29,7 @@ using Robust.Server.Player;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -35,10 +40,13 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
[Dependency] private readonly IChatManager _chat = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IServerPreferencesManager _pref = default!;
[Dependency] private readonly ActorSystem _actors = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly GhostRoleSystem _ghostRole = default!;
[Dependency] private readonly JobSystem _jobs = default!;
[Dependency] private readonly LoadoutSystem _loadout = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly RoleSystem _role = default!;
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
[Dependency] private readonly TransformSystem _transform = default!;
@@ -224,7 +232,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
for (var i = 0; i < count; i++)
{
var session = (ICommonSession?) null;
var session = (ICommonSession?)null;
if (picking)
{
if (!playerPool.TryPickAndTake(RobustRandom, out session) && noSpawner)
@@ -324,17 +332,29 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
// The following is where we apply components, equipment, and other changes to our antagonist entity.
EntityManager.AddComponents(player, def.Components);
_stationSpawning.EquipStartingGear(player, def.StartingGear);
// Equip the entity's RoleLoadout and LoadoutGroup
List<ProtoId<StartingGearPrototype>>? gear = new();
if (def.StartingGear is not null)
gear.Add(def.StartingGear.Value);
_loadout.Equip(player, gear, def.RoleLoadout);
if (session != null)
{
var curMind = _mind.CreateMind(session.UserId, Name(antagEnt.Value));
_mind.SetUserId(curMind, session.UserId);
_mind.TransferTo(curMind, antagEnt, ghostCheckOverride: true);
_role.MindAddRoles(curMind, def.MindComponents, null, true);
ent.Comp.SelectedMinds.Add((curMind, Name(player)));
var curMind = session.GetMind();
if (curMind == null ||
!TryComp<MindComponent>(curMind.Value, out var mindComp) ||
mindComp.OwnedEntity != antagEnt)
{
curMind = _mind.CreateMind(session.UserId, Name(antagEnt.Value));
_mind.SetUserId(curMind.Value, session.UserId);
}
_mind.TransferTo(curMind.Value, antagEnt, ghostCheckOverride: true);
_role.MindAddRoles(curMind.Value, def.MindComponents, null, true);
ent.Comp.SelectedMinds.Add((curMind.Value, Name(player)));
SendBriefing(session, def.Briefing);
}
@@ -447,7 +467,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
private void OnObjectivesTextGetInfo(Entity<AntagSelectionComponent> ent, ref ObjectivesTextGetInfoEvent args)
{
if (ent.Comp.AgentName is not {} name)
if (ent.Comp.AgentName is not { } name)
return;
args.Minds = ent.Comp.SelectedMinds;

View File

@@ -1,6 +1,7 @@
using Content.Server.Administration.Systems;
using Content.Shared.Antag;
using Content.Shared.Destructible.Thresholds;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles;
using Content.Shared.Storage;
using Content.Shared.Whitelist;
@@ -154,6 +155,12 @@ public partial struct AntagSelectionDefinition()
[DataField]
public ProtoId<StartingGearPrototype>? StartingGear;
/// <summary>
/// A list of role loadouts, from which a randomly selected one will be equipped.
/// </summary>
[DataField]
public List<ProtoId<RoleLoadoutPrototype>>? RoleLoadout;
/// <summary>
/// A briefing shown to the player.
/// </summary>

View File

@@ -237,7 +237,7 @@ namespace Content.Server.Atmos.EntitySystems
// TODO: Technically these directions won't be correct but uhh I'm just here for optimisations buddy not to fix my old bugs.
if (throwTarget != EntityCoordinates.Invalid)
{
var pos = ((throwTarget.ToMap(EntityManager, _transformSystem).Position - xform.WorldPosition).Normalized() + dirVec).Normalized();
var pos = ((_transformSystem.ToMapCoordinates(throwTarget).Position - _transformSystem.GetWorldPosition(xform)).Normalized() + dirVec).Normalized();
_physics.ApplyLinearImpulse(uid, pos * moveForce, body: physics);
}
else

View File

@@ -73,6 +73,7 @@ namespace Content.Server.Atmos.EntitySystems
SubscribeLocalEvent<FlammableComponent, IsHotEvent>(OnIsHot);
SubscribeLocalEvent<FlammableComponent, TileFireEvent>(OnTileFire);
SubscribeLocalEvent<FlammableComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<FlammableComponent, ResistFireAlertEvent>(OnResistFireAlert);
SubscribeLocalEvent<IgniteOnCollideComponent, StartCollideEvent>(IgniteOnCollide);
SubscribeLocalEvent<IgniteOnCollideComponent, LandEvent>(OnIgniteLand);
@@ -251,6 +252,15 @@ namespace Content.Server.Atmos.EntitySystems
Extinguish(uid, component);
}
private void OnResistFireAlert(Entity<FlammableComponent> ent, ref ResistFireAlertEvent args)
{
if (args.Handled)
return;
Resist(ent, ent);
args.Handled = true;
}
public void UpdateAppearance(EntityUid uid, FlammableComponent? flammable = null, AppearanceComponent? appearance = null)
{
if (!Resolve(uid, ref flammable, ref appearance))

View File

@@ -0,0 +1,90 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Atmos.Piping.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
namespace Content.Server.Atmos.EntitySystems;
[UsedImplicitly]
public sealed class GasMinerSystem : SharedGasMinerSystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasMinerComponent, AtmosDeviceUpdateEvent>(OnMinerUpdated);
}
private void OnMinerUpdated(Entity<GasMinerComponent> ent, ref AtmosDeviceUpdateEvent args)
{
var miner = ent.Comp;
var oldState = miner.MinerState;
float toSpawn;
if (!GetValidEnvironment(ent, out var environment) || !Transform(ent).Anchored)
{
miner.MinerState = GasMinerState.Disabled;
}
// SpawnAmount is declared in mol/s so to get the amount of gas we hope to mine, we have to multiply this by
// how long we have been waiting to spawn it and further cap the number according to the miner's state.
else if ((toSpawn = CapSpawnAmount(ent, miner.SpawnAmount * args.dt, environment)) == 0)
{
miner.MinerState = GasMinerState.Idle;
}
else
{
miner.MinerState = GasMinerState.Working;
// Time to mine some gas.
var merger = new GasMixture(1) { Temperature = miner.SpawnTemperature };
merger.SetMoles(miner.SpawnGas, toSpawn);
_atmosphereSystem.Merge(environment, merger);
}
if (miner.MinerState != oldState)
{
Dirty(ent);
}
}
private bool GetValidEnvironment(Entity<GasMinerComponent> ent, [NotNullWhen(true)] out GasMixture? environment)
{
var (uid, miner) = ent;
var transform = Transform(uid);
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
// Treat space as an invalid environment
if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position))
{
environment = null;
return false;
}
environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
return environment != null;
}
private float CapSpawnAmount(Entity<GasMinerComponent> ent, float toSpawnTarget, GasMixture environment)
{
var (uid, miner) = ent;
// How many moles could we theoretically spawn. Cap by pressure and amount.
var allowableMoles = Math.Min(
(miner.MaxExternalPressure - environment.Pressure) * environment.Volume / (miner.SpawnTemperature * Atmospherics.R),
miner.MaxExternalAmount - environment.TotalMoles);
var toSpawnReal = Math.Clamp(allowableMoles, 0f, toSpawnTarget);
if (toSpawnReal < Atmospherics.GasMinMoles) {
return 0f;
}
return toSpawnReal;
}
}

View File

@@ -1,43 +0,0 @@
using Content.Shared.Atmos;
namespace Content.Server.Atmos.Piping.Other.Components
{
[RegisterComponent]
public sealed partial class GasMinerComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public bool Enabled { get; set; } = true;
[ViewVariables(VVAccess.ReadOnly)]
public bool Idle { get; set; } = false;
/// <summary>
/// If the number of moles in the external environment exceeds this number, no gas will be mined.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("maxExternalAmount")]
public float MaxExternalAmount { get; set; } = float.PositiveInfinity;
/// <summary>
/// If the pressure (in kPA) of the external environment exceeds this number, no gas will be mined.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("maxExternalPressure")]
public float MaxExternalPressure { get; set; } = Atmospherics.GasMinerDefaultMaxExternalPressure;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("spawnGas")]
public Gas? SpawnGas { get; set; } = null;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("spawnTemperature")]
public float SpawnTemperature { get; set; } = Atmospherics.T20C;
/// <summary>
/// Number of moles created per second when the miner is working.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("spawnAmount")]
public float SpawnAmount { get; set; } = Atmospherics.MolesCellStandard * 20f;
}
}

View File

@@ -1,84 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Other.Components;
using Content.Shared.Atmos;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
namespace Content.Server.Atmos.Piping.Other.EntitySystems
{
[UsedImplicitly]
public sealed class GasMinerSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasMinerComponent, AtmosDeviceUpdateEvent>(OnMinerUpdated);
}
private void OnMinerUpdated(Entity<GasMinerComponent> ent, ref AtmosDeviceUpdateEvent args)
{
var miner = ent.Comp;
if (!GetValidEnvironment(ent, out var environment))
{
miner.Idle = true;
return;
}
// SpawnAmount is declared in mol/s so to get the amount of gas we hope to mine, we have to multiply this by
// how long we have been waiting to spawn it and further cap the number according to the miner's state.
var toSpawn = CapSpawnAmount(ent, miner.SpawnAmount * args.dt, environment);
miner.Idle = toSpawn == 0;
if (miner.Idle || !miner.Enabled || !miner.SpawnGas.HasValue)
return;
// Time to mine some gas.
var merger = new GasMixture(1) { Temperature = miner.SpawnTemperature };
merger.SetMoles(miner.SpawnGas.Value, toSpawn);
_atmosphereSystem.Merge(environment, merger);
}
private bool GetValidEnvironment(Entity<GasMinerComponent> ent, [NotNullWhen(true)] out GasMixture? environment)
{
var (uid, miner) = ent;
var transform = Transform(uid);
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
// Treat space as an invalid environment
if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position))
{
environment = null;
return false;
}
environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
return environment != null;
}
private float CapSpawnAmount(Entity<GasMinerComponent> ent, float toSpawnTarget, GasMixture environment)
{
var (uid, miner) = ent;
// How many moles could we theoretically spawn. Cap by pressure and amount.
var allowableMoles = Math.Min(
(miner.MaxExternalPressure - environment.Pressure) * environment.Volume / (miner.SpawnTemperature * Atmospherics.R),
miner.MaxExternalAmount - environment.TotalMoles);
var toSpawnReal = Math.Clamp(allowableMoles, 0f, toSpawnTarget);
if (toSpawnReal < Atmospherics.GasMinMoles) {
return 0f;
}
return toSpawnReal;
}
}
}

View File

@@ -25,4 +25,5 @@ namespace Content.Server.Body.Components
[DataField]
public ProtoId<AlertPrototype> InternalsAlert = "Internals";
}
}

View File

@@ -38,6 +38,7 @@ public sealed class InternalsSystem : EntitySystem
SubscribeLocalEvent<InternalsComponent, ComponentShutdown>(OnInternalsShutdown);
SubscribeLocalEvent<InternalsComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
SubscribeLocalEvent<InternalsComponent, InternalsDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<InternalsComponent, ToggleInternalsAlertEvent>(OnToggleInternalsAlert);
SubscribeLocalEvent<InternalsComponent, StartingGearEquippedEvent>(OnStartingGear);
}
@@ -161,6 +162,14 @@ public sealed class InternalsSystem : EntitySystem
args.Handled = true;
}
private void OnToggleInternalsAlert(Entity<InternalsComponent> ent, ref ToggleInternalsAlertEvent args)
{
if (args.Handled)
return;
ToggleInternals(ent, ent, false, internals: ent.Comp);
args.Handled = true;
}
private void OnInternalsStartup(Entity<InternalsComponent> ent, ref ComponentStartup args)
{
_alerts.ShowAlert(ent, ent.Comp.InternalsAlert, GetSeverity(ent));

View File

@@ -28,6 +28,7 @@ namespace Content.Server.Chemistry.EntitySystems
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly ReactiveSystem _reactive = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
private const float ReactTime = 0.125f;
@@ -69,7 +70,7 @@ namespace Content.Server.Chemistry.EntitySystems
_throwing.TryThrow(vapor, dir, speed, user: user);
var distance = (target.Position - vaporXform.WorldPosition).Length();
var distance = (target.Position - _transformSystem.GetWorldPosition(vaporXform)).Length();
var time = (distance / physics.LinearVelocity.Length());
despawn.Lifetime = MathF.Min(aliveTime, time);
}

View File

@@ -1,4 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Robust.Server.Player;
using Robust.Shared.Console;
@@ -55,13 +55,15 @@ namespace Content.Server.Commands
{
var entMan = IoCManager.Resolve<IEntityManager>();
var transform = entMan.GetComponent<TransformComponent>(ent);
var transformSystem = entMan.System<SharedTransformSystem>();
var worldPosition = transformSystem.GetWorldPosition(transform);
// gross, is there a better way to do this?
ruleString = ruleString.Replace("$ID", ent.ToString());
ruleString = ruleString.Replace("$WX",
transform.WorldPosition.X.ToString(CultureInfo.InvariantCulture));
worldPosition.X.ToString(CultureInfo.InvariantCulture));
ruleString = ruleString.Replace("$WY",
transform.WorldPosition.Y.ToString(CultureInfo.InvariantCulture));
worldPosition.Y.ToString(CultureInfo.InvariantCulture));
ruleString = ruleString.Replace("$LX",
transform.LocalPosition.X.ToString(CultureInfo.InvariantCulture));
ruleString = ruleString.Replace("$LY",
@@ -73,12 +75,13 @@ namespace Content.Server.Commands
if (player.AttachedEntity is {Valid: true} p)
{
var pTransform = entMan.GetComponent<TransformComponent>(p);
var pWorldPosition = transformSystem.GetWorldPosition(pTransform);
ruleString = ruleString.Replace("$PID", ent.ToString());
ruleString = ruleString.Replace("$PWX",
pTransform.WorldPosition.X.ToString(CultureInfo.InvariantCulture));
pWorldPosition.X.ToString(CultureInfo.InvariantCulture));
ruleString = ruleString.Replace("$PWY",
pTransform.WorldPosition.Y.ToString(CultureInfo.InvariantCulture));
pWorldPosition.Y.ToString(CultureInfo.InvariantCulture));
ruleString = ruleString.Replace("$PLX",
pTransform.LocalPosition.X.ToString(CultureInfo.InvariantCulture));
ruleString = ruleString.Replace("$PLY",

View File

@@ -6,6 +6,8 @@ namespace Content.Server.DeviceNetwork.Systems
[UsedImplicitly]
public sealed class WirelessNetworkSystem : EntitySystem
{
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
public override void Initialize()
{
base.Initialize();
@@ -25,7 +27,7 @@ namespace Content.Server.DeviceNetwork.Systems
return;
if (xform.MapID != args.SenderTransform.MapID
|| (ownPosition - xform.WorldPosition).Length() > sendingComponent.Range)
|| (ownPosition - _transformSystem.GetWorldPosition(xform)).Length() > sendingComponent.Range)
{
args.Cancel();
}

View File

@@ -156,7 +156,7 @@ public sealed partial class DragonSystem : EntitySystem
}
// cant put a rift on solars
foreach (var tile in grid.GetTilesIntersecting(new Circle(xform.WorldPosition, RiftTileRadius), false))
foreach (var tile in grid.GetTilesIntersecting(new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false))
{
if (!tile.IsSpace(_tileDef))
continue;

View File

@@ -28,6 +28,7 @@ public sealed partial class EnsnareableSystem
SubscribeLocalEvent<EnsnaringComponent, StepTriggeredOffEvent>(OnStepTrigger);
SubscribeLocalEvent<EnsnaringComponent, ThrowDoHitEvent>(OnThrowHit);
SubscribeLocalEvent<EnsnaringComponent, AttemptPacifiedThrowEvent>(OnAttemptPacifiedThrow);
SubscribeLocalEvent<EnsnareableComponent, RemoveEnsnareAlertEvent>(OnRemoveEnsnareAlert);
}
private void OnAttemptPacifiedThrow(Entity<EnsnaringComponent> ent, ref AttemptPacifiedThrowEvent args)
@@ -35,6 +36,24 @@ public sealed partial class EnsnareableSystem
args.Cancel("pacified-cannot-throw-snare");
}
private void OnRemoveEnsnareAlert(Entity<EnsnareableComponent> ent, ref RemoveEnsnareAlertEvent args)
{
if (args.Handled)
return;
foreach (var ensnare in ent.Comp.Container.ContainedEntities)
{
if (!TryComp<EnsnaringComponent>(ensnare, out var ensnaringComponent))
return;
TryFree(ent, ent, ensnare, ensnaringComponent);
args.Handled = true;
// Only one snare at a time.
break;
}
}
private void OnComponentRemove(EntityUid uid, EnsnaringComponent component, ComponentRemove args)
{
if (!TryComp<EnsnareableComponent>(component.Ensnared, out var ensnared))

View File

@@ -105,7 +105,7 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
var xform = xforms.GetComponent(gridToTransform);
var (_, gridWorldRotation, gridWorldMatrix, invGridWorldMatrid) = xform.GetWorldPositionRotationMatrixWithInv(xforms);
var (_, gridWorldRotation, gridWorldMatrix, invGridWorldMatrid) = _transformSystem.GetWorldPositionRotationMatrixWithInv(xform, xforms);
var localEpicentre = (Vector2i) Vector2.Transform(epicentre.Position, invGridWorldMatrid);
var matrix = offsetMatrix * gridWorldMatrix * targetMatrix;

View File

@@ -406,7 +406,7 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
if (player.AttachedEntity is not EntityUid uid)
continue;
var playerPos = Transform(player.AttachedEntity!.Value).WorldPosition;
var playerPos = _transformSystem.GetWorldPosition(player.AttachedEntity!.Value);
var delta = epicenter.Position - playerPos;
if (delta.EqualsApprox(Vector2.Zero))

View File

@@ -30,13 +30,12 @@ public sealed class TwoStageTriggerSystem : EntitySystem
{
foreach (var (name, entry) in component.SecondStageComponents)
{
var comp = (Component) _factory.GetComponent(name);
var temp = (object) comp;
var comp = (Component)_factory.GetComponent(name);
var temp = (object)comp;
if (EntityManager.TryGetComponent(uid, entry.Component.GetType(), out var c))
RemComp(uid, c);
comp.Owner = uid;
_serializationManager.CopyTo(entry.Component, ref temp);
EntityManager.AddComponent(uid, comp);
}

View File

@@ -1,30 +0,0 @@
using Content.Server.GameTicking.Rules;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Server.GameTicking.Rules.Components;
/// <summary>
/// Gamerule for simple antagonists that have fixed objectives.
/// </summary>
[RegisterComponent, Access(typeof(GenericAntagRuleSystem))]
public sealed partial class GenericAntagRuleComponent : Component
{
/// <summary>
/// All antag minds that are using this rule.
/// </summary>
[DataField]
public List<EntityUid> Minds = new();
/// <summary>
/// Locale id for the name of the antag used by the roundend summary.
/// </summary>
[DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
public string AgentName = string.Empty;
/// <summary>
/// List of objective entity prototypes to add to the antag when a mind is added.
/// </summary>
[DataField(required: true)]
public List<EntProtoId> Objectives = new();
}

View File

@@ -1,56 +0,0 @@
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Objectives;
using Content.Shared.Mind;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace Content.Server.GameTicking.Rules;
/// <summary>
/// Handles round end text for simple antags.
/// Adding objectives is handled in its own system.
/// </summary>
public sealed class GenericAntagRuleSystem : GameRuleSystem<GenericAntagRuleComponent>
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GenericAntagRuleComponent, ObjectivesTextGetInfoEvent>(OnObjectivesTextGetInfo);
}
/// <summary>
/// Start a simple antag's game rule.
/// If it is invalid the rule is deleted and null is returned.
/// </summary>
public bool StartRule(string rule, EntityUid mindId, [NotNullWhen(true)] out EntityUid? ruleId, [NotNullWhen(true)] out GenericAntagRuleComponent? comp)
{
ruleId = GameTicker.AddGameRule(rule);
if (!TryComp<GenericAntagRuleComponent>(ruleId, out comp))
{
Log.Error($"Simple antag rule prototype {rule} is invalid, deleting it.");
Del(ruleId);
ruleId = null;
return false;
}
if (!GameTicker.StartGameRule(ruleId.Value))
{
Log.Error($"Simple antag rule prototype {rule} failed to start, deleting it.");
Del(ruleId);
ruleId = null;
comp = null;
return false;
}
comp.Minds.Add(mindId);
return true;
}
private void OnObjectivesTextGetInfo(EntityUid uid, GenericAntagRuleComponent comp, ref ObjectivesTextGetInfoEvent args)
{
// just temporary until this is deleted
args.Minds = comp.Minds.Select(mindId => (mindId, Comp<MindComponent>(mindId).CharacterName ?? "?")).ToList();
args.AgentName = Loc.GetString(comp.AgentName);
}
}

View File

@@ -1,30 +0,0 @@
using Content.Server.GameTicking.Rules.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.GenericAntag;
/// <summary>
/// Added to a mob to make it a generic antagonist where all its objectives are fixed.
/// This is unlike say traitor where it gets objectives picked randomly using difficulty.
/// </summary>
/// <remarks>
/// A GenericAntag is not necessarily an antagonist, that depends on the roles you do or do not add after.
/// </remarks>
[RegisterComponent, Access(typeof(GenericAntagSystem))]
public sealed partial class GenericAntagComponent : Component
{
/// <summary>
/// Gamerule to start when a mind is added.
/// This must have <see cref="GenericAntagRuleComponent"/> or it will not work.
/// </summary>
[DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
public EntProtoId Rule = string.Empty;
/// <summary>
/// The rule that's been spawned.
/// Used to prevent spawning multiple rules.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public EntityUid? RuleEntity;
}

View File

@@ -1,67 +0,0 @@
using Content.Server.GameTicking.Rules;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
namespace Content.Server.GenericAntag;
/// <summary>
/// Handles adding objectives to <see cref="GenericAntagComponent"/>s.
/// Roundend summary is handled by <see cref="GenericAntagRuleSystem"/>.
/// </summary>
public sealed class GenericAntagSystem : EntitySystem
{
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly GenericAntagRuleSystem _genericAntagRule = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GenericAntagComponent, MindAddedMessage>(OnMindAdded);
}
private void OnMindAdded(EntityUid uid, GenericAntagComponent comp, MindAddedMessage args)
{
if (!TryComp<MindContainerComponent>(uid, out var mindContainer) || mindContainer.Mind == null)
return;
var mindId = mindContainer.Mind.Value;
MakeAntag(uid, mindId, comp);
}
/// <summary>
/// Turns a player into this antagonist.
/// Does the same thing that having a mind added does, use for antag ctrl.
/// </summary>
public void MakeAntag(EntityUid uid, EntityUid mindId, GenericAntagComponent? comp = null, MindComponent? mind = null)
{
if (!Resolve(uid, ref comp) || !Resolve(mindId, ref mind))
return;
// only add the rule once
if (comp.RuleEntity != null)
return;
// start the rule
if (!_genericAntagRule.StartRule(comp.Rule, mindId, out comp.RuleEntity, out var rule))
return;
// let other systems know the antag was created so they can add briefing, roles, etc.
// its important that this is before objectives are added since they may depend on roles added here
var ev = new GenericAntagCreatedEvent(mindId, mind);
RaiseLocalEvent(uid, ref ev);
// add the objectives from the rule
foreach (var id in rule.Objectives)
{
_mind.TryAddObjective(mindId, mind, id);
}
}
}
/// <summary>
/// Event raised on a player's entity after its simple antag rule is started.
/// Use this to add a briefing, roles, etc.
/// </summary>
[ByRefEvent]
public record struct GenericAntagCreatedEvent(EntityUid MindId, MindComponent Mind);

View File

@@ -201,7 +201,7 @@ namespace Content.Server.Hands.Systems
throwEnt = splitStack.Value;
}
var direction = coordinates.ToMapPos(EntityManager, _transformSystem) - Transform(player).WorldPosition;
var direction = _transformSystem.ToMapCoordinates(coordinates).Position - _transformSystem.GetWorldPosition(player);
if (direction == Vector2.Zero)
return true;

View File

@@ -50,8 +50,7 @@ public sealed class RandomHumanoidSystem : EntitySystem
{
foreach (var entry in prototype.Components.Values)
{
var comp = (Component) _serialization.CreateCopy(entry.Component, notNullableOverride: true);
comp.Owner = humanoid; // This .owner must survive for now.
var comp = (Component)_serialization.CreateCopy(entry.Component, notNullableOverride: true);
EntityManager.RemoveComponent(humanoid, comp.GetType());
EntityManager.AddComponent(humanoid, comp);
}

View File

@@ -23,12 +23,11 @@ namespace Content.Server.Jobs
foreach (var (name, data) in Components)
{
var component = (Component) factory.GetComponent(name);
component.Owner = mob;
var temp = (object) component;
var temp = (object)component;
serializationManager.CopyTo(data.Component, ref temp);
entityManager.RemoveComponent(mob, temp!.GetType());
entityManager.AddComponent(mob, (Component) temp);
entityManager.AddComponent(mob, (Component)temp);
}
}
}

View File

@@ -12,6 +12,7 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem
{
[Dependency] private readonly IConGroupController _admin = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
private readonly HashSet<ICommonSession> _draggers = new();
@@ -76,8 +77,6 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem
return;
}
var gridXform = Transform(grid);
gridXform.WorldPosition = msg.WorldPosition;
_transformSystem.SetWorldPosition(grid, msg.WorldPosition);
}
}

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Content.Server.Interaction;
using Content.Server.Mech.Equipment.Components;
using Content.Server.Mech.Systems;
@@ -85,7 +85,7 @@ public sealed class MechGrabberSystem : EntitySystem
var (mechPos, mechRot) = _transform.GetWorldPositionRotation(mechxform);
var offset = mechPos + mechRot.RotateVec(component.DepositOffset);
_transform.SetWorldPositionRotation(xform, offset, Angle.Zero);
_transform.SetWorldPositionRotation(toRemove, offset, Angle.Zero);
_mech.UpdateUserInterface(mech);
}

View File

@@ -39,7 +39,7 @@ public sealed class StressTestMovementSystem : EntitySystem
var x = MathF.Sin(stressTest.Progress * MathHelper.TwoPi);
var y = MathF.Cos(stressTest.Progress * MathHelper.TwoPi);
_transform.SetWorldPosition(transform, stressTest.Origin + new Vector2(x, y) * 5);
_transform.SetWorldPosition((uid, transform), stressTest.Origin + new Vector2(x, y) * 5);
}
}
}

View File

@@ -12,6 +12,7 @@ namespace Content.Server.Pointing.EntitySystems
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
private EntityUid? RandomNearbyPlayer(EntityUid uid, RoguePointingArrowComponent? component = null, TransformComponent? transform = null)
{
@@ -66,27 +67,28 @@ namespace Content.Server.Pointing.EntitySystems
}
component.TurningDelay -= frameTime;
var (transformPos, transformRot) = _transformSystem.GetWorldPositionRotation(transform);
if (component.TurningDelay > 0)
{
var difference = Comp<TransformComponent>(chasing).WorldPosition - transform.WorldPosition;
var difference = _transformSystem.GetWorldPosition(chasing) - transformPos;
var angle = difference.ToAngle();
var adjusted = angle.Degrees + 90;
var newAngle = Angle.FromDegrees(adjusted);
transform.WorldRotation = newAngle;
_transformSystem.SetWorldRotation(transform, newAngle);
UpdateAppearance(uid, component, transform);
continue;
}
transform.WorldRotation += Angle.FromDegrees(20);
_transformSystem.SetWorldRotation(transform, transformRot + Angle.FromDegrees(20));
UpdateAppearance(uid, component, transform);
var toChased = Comp<TransformComponent>(chasing).WorldPosition - transform.WorldPosition;
var toChased = _transformSystem.GetWorldPosition(chasing) - transformPos;
transform.WorldPosition += toChased * frameTime * component.ChasingSpeed;
_transformSystem.SetWorldPosition((uid, transform), transformPos + (toChased * frameTime * component.ChasingSpeed));
component.ChasingTime -= frameTime;

View File

@@ -1,4 +1,4 @@
using Content.Server.Administration.Logs;
using Content.Server.Administration.Logs;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
@@ -157,7 +157,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
var tile = tileRef.GridIndices;
var found = false;
var (gridPos, _, gridMatrix) = xform.GetWorldPositionRotationMatrix();
var (gridPos, _, gridMatrix) = _transform.GetWorldPositionRotationMatrix(xform);
var gridBounds = gridMatrix.TransformBox(grid.LocalAABB);
//Obviously don't put anything ridiculous in here

View File

@@ -42,6 +42,7 @@ public sealed partial class RevenantSystem
[Dependency] private readonly GhostSystem _ghost = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
private void InitializeAbilities()
{
@@ -227,7 +228,7 @@ public sealed partial class RevenantSystem
var xform = Transform(uid);
if (!TryComp<MapGridComponent>(xform.GridUid, out var map))
return;
var tiles = map.GetTilesIntersecting(Box2.CenteredAround(xform.WorldPosition,
var tiles = map.GetTilesIntersecting(Box2.CenteredAround(_transformSystem.GetWorldPosition(xform),
new Vector2(component.DefileRadius * 2, component.DefileRadius))).ToArray();
_random.Shuffle(tiles);

View File

@@ -71,6 +71,7 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
SubscribeLocalEvent<UndockEvent>(OnUndock);
SubscribeLocalEvent<PilotComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<PilotComponent, StopPilotingAlertEvent>(OnStopPilotingAlert);
SubscribeLocalEvent<FTLDestinationComponent, ComponentStartup>(OnFtlDestStartup);
SubscribeLocalEvent<FTLDestinationComponent, ComponentShutdown>(OnFtlDestShutdown);
@@ -196,6 +197,14 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
args.State = new PilotComponentState(GetNetEntity(component.Console));
}
private void OnStopPilotingAlert(Entity<PilotComponent> ent, ref StopPilotingAlertEvent args)
{
if (ent.Comp.Console != null)
{
RemovePilot(ent, ent);
}
}
/// <summary>
/// Returns the position and angle of all dockingcomponents.
/// </summary>

View File

@@ -22,6 +22,7 @@ public sealed class ContainmentFieldGeneratorSystem : EntitySystem
[Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedPointLightSystem _light = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly TagSystem _tags = default!;
public override void Initialize()
@@ -116,7 +117,7 @@ public sealed class ContainmentFieldGeneratorSystem : EntitySystem
private void OnUnanchorAttempt(EntityUid uid, ContainmentFieldGeneratorComponent component,
UnanchorAttemptEvent args)
{
if (component.Enabled)
if (component.Enabled || component.IsConnected)
{
_popupSystem.PopupEntity(Loc.GetString("comp-containment-anchor-warning"), args.User, args.User, PopupType.LargeCaution);
args.Cancel();
@@ -234,7 +235,7 @@ public sealed class ContainmentFieldGeneratorSystem : EntitySystem
if (!gen1XForm.Anchored)
return false;
var genWorldPosRot = gen1XForm.GetWorldPositionRotation();
var genWorldPosRot = _transformSystem.GetWorldPositionRotation(gen1XForm);
var dirRad = dir.ToAngle() + genWorldPosRot.WorldRotation; //needs to be like this for the raycast to work properly
var ray = new CollisionRay(genWorldPosRot.WorldPosition, dirRad.ToVec(), component.CollisionMask);

View File

@@ -1,4 +1,4 @@
using Content.Server.Popups;
using Content.Server.Popups;
using Content.Server.Shuttles.Components;
using Content.Server.Singularity.Events;
using Content.Shared.Popups;
@@ -13,6 +13,7 @@ public sealed class ContainmentFieldSystem : EntitySystem
{
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
public override void Initialize()
{
@@ -34,8 +35,8 @@ public sealed class ContainmentFieldSystem : EntitySystem
if (TryComp<PhysicsComponent>(otherBody, out var physics) && physics.Mass <= component.MaxMass && physics.Hard)
{
var fieldDir = Transform(uid).WorldPosition;
var playerDir = Transform(otherBody).WorldPosition;
var fieldDir = _transformSystem.GetWorldPosition(uid);
var playerDir = _transformSystem.GetWorldPosition(otherBody);
_throwing.TryThrow(otherBody, playerDir-fieldDir, baseThrowSpeed: component.ThrowForce);
}

View File

@@ -137,13 +137,22 @@ public sealed class RadiationCollectorSystem : EntitySystem
private void OnExamined(EntityUid uid, RadiationCollectorComponent component, ExaminedEvent args)
{
if (!TryGetLoadedGasTank(uid, out var gasTank))
using (args.PushGroup(nameof(RadiationCollectorComponent)))
{
args.PushMarkup(Loc.GetString("power-radiation-collector-gas-tank-missing"));
return;
}
args.PushMarkup(Loc.GetString("power-radiation-collector-enabled", ("state", component.Enabled)));
args.PushMarkup(Loc.GetString("power-radiation-collector-gas-tank-present"));
if (!TryGetLoadedGasTank(uid, out var gasTank))
{
args.PushMarkup(Loc.GetString("power-radiation-collector-gas-tank-missing"));
}
else
{
_appearance.TryGetData<int>(uid, RadiationCollectorVisuals.PressureState, out var state);
args.PushMarkup(Loc.GetString("power-radiation-collector-gas-tank-present",
("fullness", state)));
}
}
}
private void OnAnalyzed(EntityUid uid, RadiationCollectorComponent component, GasAnalyzerScanEvent args)

View File

@@ -18,6 +18,7 @@ namespace Content.Server.Solar.EntitySystems
{
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
/// <summary>
/// Maximum panel angular velocity range - used to stop people rotating panels fast enough that the lag prevention becomes noticable
@@ -112,7 +113,7 @@ namespace Content.Server.Solar.EntitySystems
while (query.MoveNext(out var uid, out var panel, out var xform))
{
TotalPanelPower += panel.MaxSupply * panel.Coverage;
xform.WorldRotation = TargetPanelRotation;
_transformSystem.SetWorldRotation(xform, TargetPanelRotation);
_updateQueue.Enqueue((uid, panel));
}
}
@@ -135,7 +136,7 @@ namespace Content.Server.Solar.EntitySystems
// directly downwards (abs(theta) = pi) = coverage -1
// as TowardsSun + = CCW,
// panelRelativeToSun should - = CW
var panelRelativeToSun = xform.WorldRotation - TowardsSun;
var panelRelativeToSun = _transformSystem.GetWorldRotation(xform) - TowardsSun;
// essentially, given cos = X & sin = Y & Y is 'downwards',
// then for the first 90 degrees of rotation in either direction,
// this plots the lower-right quadrant of a circle.
@@ -153,7 +154,7 @@ namespace Content.Server.Solar.EntitySystems
if (coverage > 0)
{
// Determine if the solar panel is occluded, and zero out coverage if so.
var ray = new CollisionRay(xform.WorldPosition, TowardsSun.ToWorldVec(), (int) CollisionGroup.Opaque);
var ray = new CollisionRay(_transformSystem.GetWorldPosition(xform), TowardsSun.ToWorldVec(), (int) CollisionGroup.Opaque);
var rayCastResults = _physicsSystem.IntersectRayWithPredicate(
xform.MapID,
ray,

View File

@@ -6,7 +6,7 @@ namespace Content.Server.Speech
{
public sealed class AccentSystem : EntitySystem
{
public static readonly Regex SentenceRegex = new(@"(?<=[\.!\?])", RegexOptions.Compiled);
public static readonly Regex SentenceRegex = new(@"(?<=[\.!\?‽])(?![\.!\?‽])", RegexOptions.Compiled);
public override void Initialize()
{

View File

@@ -7,5 +7,4 @@ namespace Content.Server.Speech.Components;
/// </summary>
[RegisterComponent]
[Access(typeof(FrenchAccentSystem))]
public sealed partial class FrenchAccentComponent : Component
{ }
public sealed partial class FrenchAccentComponent : Component {}

View File

@@ -1,7 +1,4 @@
namespace Content.Server.Speech.Components
{
[RegisterComponent]
public sealed partial class SpanishAccentComponent : Component
{
}
}
namespace Content.Server.Speech.Components;
[RegisterComponent]
public sealed partial class SpanishAccentComponent : Component {}

View File

@@ -27,10 +27,10 @@ public sealed class FrenchAccentSystem : EntitySystem
msg = _replacement.ApplyReplacements(msg, "french");
// replaces th with dz
// replaces th with z
msg = RegexTh.Replace(msg, "'z");
// removes the letter h from the start of words.
// replaces h with ' at the start of words.
msg = RegexStartH.Replace(msg, "'");
// spaces out ! ? : and ;.

View File

@@ -1,3 +1,4 @@
using System.Text;
using Content.Server.Speech.Components;
namespace Content.Server.Speech.EntitySystems
@@ -14,7 +15,7 @@ namespace Content.Server.Speech.EntitySystems
// Insert E before every S
message = InsertS(message);
// If a sentence ends with ?, insert a reverse ? at the beginning of the sentence
message = ReplaceQuestionMark(message);
message = ReplacePunctuation(message);
return message;
}
@@ -36,24 +37,32 @@ namespace Content.Server.Speech.EntitySystems
return msg;
}
private string ReplaceQuestionMark(string message)
private string ReplacePunctuation(string message)
{
var sentences = AccentSystem.SentenceRegex.Split(message);
var msg = "";
var msg = new StringBuilder();
foreach (var s in sentences)
{
if (s.EndsWith("?", StringComparison.Ordinal)) // We've got a question => add ¿ to the beginning
var toInsert = new StringBuilder();
for (var i = s.Length - 1; i >= 0 && "?!‽".Contains(s[i]); i--)
{
// Because we don't split by whitespace, we may have some spaces in front of the sentence.
// So we add the symbol before the first non space char
msg += s.Insert(s.Length - s.TrimStart().Length, "¿");
toInsert.Append(s[i] switch
{
'?' => '¿',
'!' => '¡',
'‽' => '⸘',
_ => ' '
});
}
else
if (toInsert.Length == 0)
{
msg += s;
msg.Append(s);
} else
{
msg.Append(s.Insert(s.Length - s.TrimStart().Length, toInsert.ToString()));
}
}
return msg;
return msg.ToString();
}
private void OnAccent(EntityUid uid, SpanishAccentComponent component, AccentGetEvent args)

View File

@@ -54,7 +54,6 @@ public sealed partial class BiomePrototype : IPrototype, IInheritingPrototype
foreach (var data in ChunkComponents.Values)
{
var comp = (Component) serialization.CreateCopy(data.Component, notNullableOverride: true);
comp.Owner = target; // look im sorry ok this .owner has to live until engine api exists
entityManager.AddComponent(target, comp);
}
}

View File

@@ -30,7 +30,6 @@ public sealed partial class WorldgenConfigPrototype : IPrototype
foreach (var data in Components.Values)
{
var comp = (Component) serialization.CreateCopy(data.Component, notNullableOverride: true);
comp.Owner = target; // look im sorry ok this .owner has to live until engine api exists
entityManager.AddComponent(target, comp);
}
}

View File

@@ -1,4 +1,4 @@
using System.Numerics;
using System.Numerics;
using Content.Server.Worldgen.Components;
using JetBrains.Annotations;
@@ -12,6 +12,7 @@ namespace Content.Server.Worldgen.Systems;
public abstract class BaseWorldSystem : EntitySystem
{
[Dependency] private readonly WorldControllerSystem _worldController = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
/// <summary>
/// Gets a chunk's coordinates in chunk space as an integer value.
@@ -25,7 +26,7 @@ public abstract class BaseWorldSystem : EntitySystem
if (!Resolve(ent, ref xform))
throw new Exception("Failed to resolve transform, somehow.");
return WorldGen.WorldToChunkCoords(xform.WorldPosition).Floored();
return WorldGen.WorldToChunkCoords(_transformSystem.GetWorldPosition(xform)).Floored();
}
/// <summary>
@@ -40,7 +41,7 @@ public abstract class BaseWorldSystem : EntitySystem
if (!Resolve(ent, ref xform))
throw new Exception("Failed to resolve transform, somehow.");
return WorldGen.WorldToChunkCoords(xform.WorldPosition);
return WorldGen.WorldToChunkCoords(_transformSystem.GetWorldPosition(xform));
}
/// <summary>

View File

@@ -182,13 +182,12 @@ public sealed partial class ArtifactSystem
EntityManager.RemoveComponent(uid, reg.Type);
}
var comp = (Component) _componentFactory.GetComponent(reg);
comp.Owner = uid;
var comp = (Component)_componentFactory.GetComponent(reg);
var temp = (object) comp;
var temp = (object)comp;
_serialization.CopyTo(entry.Component, ref temp);
EntityManager.RemoveComponent(uid, temp!.GetType());
EntityManager.AddComponent(uid, (Component) temp!);
EntityManager.AddComponent(uid, (Component)temp!);
}
node.Discovered = true;
@@ -218,12 +217,11 @@ public sealed partial class ArtifactSystem
// if the entity prototype contained the component originally
if (entityPrototype?.Components.TryGetComponent(name, out var entry) ?? false)
{
var comp = (Component) _componentFactory.GetComponent(name);
comp.Owner = uid;
var temp = (object) comp;
var comp = (Component)_componentFactory.GetComponent(name);
var temp = (object)comp;
_serialization.CopyTo(entry, ref temp);
EntityManager.RemoveComponent(uid, temp!.GetType());
EntityManager.AddComponent(uid, (Component) temp);
EntityManager.AddComponent(uid, (Component)temp);
continue;
}

View File

@@ -1,4 +1,4 @@
using System.Numerics;
using System.Numerics;
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
using Content.Shared.Maps;
@@ -31,7 +31,7 @@ public sealed class ThrowArtifactSystem : EntitySystem
if (TryComp<MapGridComponent>(xform.GridUid, out var grid))
{
var tiles = grid.GetTilesIntersecting(
Box2.CenteredAround(xform.WorldPosition, new Vector2(component.Range * 2, component.Range)));
Box2.CenteredAround(_transform.GetWorldPosition(xform), new Vector2(component.Range * 2, component.Range)));
foreach (var tile in tiles)
{

View File

@@ -110,4 +110,9 @@ public enum LogType
/// A player did an item-use interaction of an item they were holding onto another object.
/// </summary>
InteractUsing = 92,
/// <summary>
/// Storage & entity-storage related interactions
/// </summary>
Storage = 93,
}

View File

@@ -0,0 +1,7 @@
using Content.Shared.Alert;
namespace Content.Shared.Abilities.Mime;
public sealed partial class BreakVowAlertEvent : BaseAlertEvent;
public sealed partial class RetakeVowAlertEvent : BaseAlertEvent;

View File

@@ -76,11 +76,11 @@ public sealed partial class AlertPrototype : IPrototype
public bool SupportsSeverity => MaxSeverity != -1;
/// <summary>
/// Defines what to do when the alert is clicked.
/// This will always be null on clientside.
/// Event raised on the user when they click on this alert.
/// Can be null.
/// </summary>
[DataField(serverOnly: true)]
public IAlertClick? OnClick { get; private set; }
[DataField]
public BaseAlertEvent? ClickEvent;
/// <param name="severity">severity level, if supported by this alert</param>
/// <returns>the icon path to the texture for the provided severity level</returns>
@@ -114,3 +114,17 @@ public sealed partial class AlertPrototype : IPrototype
return Icons[severity.Value - _minSeverity];
}
}
[ImplicitDataDefinitionForInheritors]
public abstract partial class BaseAlertEvent : HandledEntityEventArgs
{
public EntityUid User;
public ProtoId<AlertPrototype> AlertId;
protected BaseAlertEvent(EntityUid user, ProtoId<AlertPrototype> alertId)
{
User = user;
AlertId = alertId;
}
}

View File

@@ -195,7 +195,7 @@ public abstract class AlertsSystem : EntitySystem
SubscribeLocalEvent<AlertAutoRemoveComponent, EntityUnpausedEvent>(OnAutoRemoveUnPaused);
SubscribeNetworkEvent<ClickAlertEvent>(HandleClickAlert);
SubscribeAllEvent<ClickAlertEvent>(HandleClickAlert);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(HandlePrototypesReloaded);
LoadPrototypes();
}
@@ -328,7 +328,20 @@ public abstract class AlertsSystem : EntitySystem
return;
}
alert.OnClick?.AlertClicked(player.Value);
ActivateAlert(player.Value, alert);
}
public bool ActivateAlert(EntityUid user, AlertPrototype alert)
{
if (alert.ClickEvent is not { } clickEvent)
return false;
clickEvent.Handled = false;
clickEvent.User = user;
clickEvent.AlertId = alert.ID;
RaiseLocalEvent(user, (object) clickEvent, true);
return clickEvent.Handled;
}
private void OnPlayerAttached(EntityUid uid, AlertsComponent component, PlayerAttachedEvent args)

View File

@@ -1,14 +0,0 @@
namespace Content.Shared.Alert
{
/// <summary>
/// Defines what should happen when an alert is clicked.
/// </summary>
public interface IAlertClick
{
/// <summary>
/// Invoked on server side when user clicks an alert.
/// </summary>
/// <param name="player"></param>
void AlertClicked(EntityUid player);
}
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.Alert;
using Robust.Shared.Audio;
namespace Content.Shared.Atmos.Components;
@@ -27,3 +28,5 @@ public sealed partial class ExtinguishOnInteractComponent : Component
[DataField]
public LocId ExtinguishFailed = "candle-extinguish-failed";
}
public sealed partial class ResistFireAlertEvent : BaseAlertEvent;

View File

@@ -0,0 +1,60 @@
using Robust.Shared.Serialization;
using Robust.Shared.GameStates;
namespace Content.Shared.Atmos.Components;
[NetworkedComponent]
[AutoGenerateComponentState]
[RegisterComponent]
public sealed partial class GasMinerComponent : Component
{
/// <summary>
/// Operational state of the miner.
/// </summary>
[AutoNetworkedField]
[ViewVariables(VVAccess.ReadOnly)]
public GasMinerState MinerState = GasMinerState.Disabled;
/// <summary>
/// If the number of moles in the external environment exceeds this number, no gas will be mined.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float MaxExternalAmount = float.PositiveInfinity;
/// <summary>
/// If the pressure (in kPA) of the external environment exceeds this number, no gas will be mined.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float MaxExternalPressure = Atmospherics.GasMinerDefaultMaxExternalPressure;
/// <summary>
/// Gas to spawn.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField(required: true)]
public Gas SpawnGas;
/// <summary>
/// Temperature in Kelvin.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float SpawnTemperature = Atmospherics.T20C;
/// <summary>
/// Number of moles created per second when the miner is working.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float SpawnAmount = Atmospherics.MolesCellStandard * 20f;
}
[Serializable, NetSerializable]
public enum GasMinerState : byte
{
Disabled,
Idle,
Working,
}

View File

@@ -0,0 +1,55 @@
using Content.Shared.Atmos.Components;
using Content.Shared.Examine;
using Content.Shared.Temperature;
namespace Content.Shared.Atmos.EntitySystems;
public abstract class SharedGasMinerSystem : EntitySystem
{
[Dependency] private readonly SharedAtmosphereSystem _sharedAtmosphereSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasMinerComponent, ExaminedEvent>(OnExamine);
}
private void OnExamine(Entity<GasMinerComponent> ent, ref ExaminedEvent args)
{
var component = ent.Comp;
using (args.PushGroup(nameof(GasMinerComponent)))
{
args.PushMarkup(Loc.GetString("gas-miner-mines-text",
("gas", Loc.GetString(_sharedAtmosphereSystem.GetGas(component.SpawnGas).Name))));
args.PushText(Loc.GetString("gas-miner-amount-text",
("moles", $"{component.SpawnAmount:0.#}")));
args.PushText(Loc.GetString("gas-miner-temperature-text",
("tempK", $"{component.SpawnTemperature:0.#}"),
("tempC", $"{TemperatureHelpers.KelvinToCelsius(component.SpawnTemperature):0.#}")));
if (component.MaxExternalAmount < float.PositiveInfinity)
{
args.PushText(Loc.GetString("gas-miner-moles-cutoff-text",
("moles", $"{component.MaxExternalAmount:0.#}")));
}
if (component.MaxExternalPressure < float.PositiveInfinity)
{
args.PushText(Loc.GetString("gas-miner-pressure-cutoff-text",
("pressure", $"{component.MaxExternalPressure:0.#}")));
}
args.AddMarkup(component.MinerState switch
{
GasMinerState.Disabled => Loc.GetString("gas-miner-state-disabled-text"),
GasMinerState.Idle => Loc.GetString("gas-miner-state-idle-text"),
GasMinerState.Working => Loc.GetString("gas-miner-state-working-text"),
// C# pattern matching is not exhaustive for enums
_ => throw new IndexOutOfRangeException(nameof(component.MinerState)),
});
}
}
}

View File

@@ -0,0 +1,10 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Bed.Cryostorage;
/// <summary>
/// Serves as a whitelist that allows an entity with this component to enter cryostorage.
/// It will also require MindContainerComponent.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class CanEnterCryostorageComponent : Component { }

View File

@@ -89,7 +89,7 @@ public abstract class SharedCryostorageSystem : EntitySystem
return;
}
if (!TryComp<MindContainerComponent>(args.EntityUid, out var mindContainer))
if (!HasComp<CanEnterCryostorageComponent>(args.EntityUid) || !TryComp<MindContainerComponent>(args.EntityUid, out var mindContainer))
{
args.Cancel();
return;

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Alert;
using Content.Shared.Interaction;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
@@ -79,6 +80,7 @@ public sealed class BuckleState(NetEntity? buckledTo, bool dontCollide, TimeSpan
public readonly TimeSpan? BuckleTime = buckleTime;
}
public sealed partial class UnbuckleAlertEvent : BaseAlertEvent;
/// <summary>
/// Event raised directed at a strap entity before some entity gets buckled to it.

View File

@@ -41,6 +41,7 @@ public abstract partial class SharedBuckleSystem
SubscribeLocalEvent<BuckleComponent, StartPullAttemptEvent>(OnPullAttempt);
SubscribeLocalEvent<BuckleComponent, BeingPulledAttemptEvent>(OnBeingPulledAttempt);
SubscribeLocalEvent<BuckleComponent, PullStartedMessage>(OnPullStarted);
SubscribeLocalEvent<BuckleComponent, UnbuckleAlertEvent>(OnUnbuckleAlert);
SubscribeLocalEvent<BuckleComponent, InsertIntoEntityStorageAttemptEvent>(OnBuckleInsertIntoEntityStorageAttempt);
@@ -86,6 +87,13 @@ public abstract partial class SharedBuckleSystem
Unbuckle(ent!, args.PullerUid);
}
private void OnUnbuckleAlert(Entity<BuckleComponent> ent, ref UnbuckleAlertEvent args)
{
if (args.Handled)
return;
args.Handled = TryUnbuckle(ent, ent, ent);
}
#endregion
#region Transform

View File

@@ -29,7 +29,7 @@ public sealed partial class SolutionTransferComponent : Component
/// </summary>
[DataField("maxTransferAmount")]
[ViewVariables(VVAccess.ReadWrite)]
public FixedPoint2 MaximumTransferAmount { get; set; } = FixedPoint2.New(50);
public FixedPoint2 MaximumTransferAmount { get; set; } = FixedPoint2.New(100);
/// <summary>
/// Can this entity take reagent from reagent tanks?

View File

@@ -9,10 +9,8 @@ namespace Content.Shared.Clothing.Components;
public sealed partial class LoadoutComponent : Component
{
/// <summary>
/// A list of starting gears, of which one will be given.
/// A list of starting gears, of which one will be given, before RoleLoadouts are equipped.
/// All elements are weighted the same in the list.
///
/// If not specified, <see cref="RoleLoadout"/> will be used instead.
/// </summary>
[DataField("prototypes")]
[AutoNetworkedField]
@@ -21,8 +19,6 @@ public sealed partial class LoadoutComponent : Component
/// <summary>
/// A list of role loadouts, of which one will be given.
/// All elements are weighted the same in the list.
///
/// If not specified, <see cref="StartingGear"/> will be used instead.
/// </summary>
[DataField]
[AutoNetworkedField]

View File

@@ -139,22 +139,37 @@ public sealed class LoadoutSystem : EntitySystem
private void OnMapInit(EntityUid uid, LoadoutComponent component, MapInitEvent args)
{
// Use starting gear if specified
if (component.StartingGear != null)
Equip(uid, component.StartingGear, component.RoleLoadout);
}
public void Equip(EntityUid uid, List<ProtoId<StartingGearPrototype>>? startingGear,
List<ProtoId<RoleLoadoutPrototype>>? loadoutGroups)
{
// First, randomly pick a startingGear profile from those specified, and equip it.
if (startingGear != null && startingGear.Count > 0)
_station.EquipStartingGear(uid, _random.Pick(startingGear));
if (loadoutGroups == null)
{
_station.EquipStartingGear(uid, _random.Pick(component.StartingGear));
GearEquipped(uid);
return;
}
if (component.RoleLoadout == null)
return;
// ...otherwise equip from role loadout
var id = _random.Pick(component.RoleLoadout);
// Then, randomly pick a RoleLoadout profile from those specified, and process/equip all LoadoutGroups from it.
// For non-roundstart mobs there is no SelectedLoadout data, so minValue must be set in each LoadoutGroup to force selection.
var id = _random.Pick(loadoutGroups);
var proto = _protoMan.Index(id);
var loadout = new RoleLoadout(id);
loadout.SetDefault(GetProfile(uid), _actors.GetSession(uid), _protoMan, true);
_station.EquipRoleLoadout(uid, loadout, proto);
GearEquipped(uid);
}
public void GearEquipped(EntityUid uid)
{
var ev = new StartingGearEquippedEvent(uid);
RaiseLocalEvent(uid, ref ev);
}
public HumanoidCharacterProfile GetProfile(EntityUid? uid)

View File

@@ -20,13 +20,13 @@ namespace Content.Shared.Construction.Conditions
// get blueprint and user position
var transformSystem = entManager.System<SharedTransformSystem>();
var userWorldPosition = entManager.GetComponent<TransformComponent>(user).WorldPosition;
var userWorldPosition = transformSystem.GetWorldPosition(user);
var objWorldPosition = location.ToMap(entManager, transformSystem).Position;
// find direction from user to blueprint
var userToObject = (objWorldPosition - userWorldPosition);
// get direction of the grid being placed on as an offset.
var gridRotation = entManager.GetComponent<TransformComponent>(location.EntityId).WorldRotation;
var gridRotation = transformSystem.GetWorldRotation(location.EntityId);
var directionWithOffset = gridRotation.RotateVec(direction.ToVec());
// dot product will be positive if user direction and blueprint are co-directed

View File

@@ -46,6 +46,8 @@ public sealed partial class CuffableComponent : Component
public ProtoId<AlertPrototype> CuffedAlert = "Handcuffed";
}
public sealed partial class RemoveCuffsAlertEvent : BaseAlertEvent;
[Serializable, NetSerializable]
public sealed class CuffableComponentState : ComponentState
{

View File

@@ -66,6 +66,7 @@ namespace Content.Shared.Cuffs
SubscribeLocalEvent<CuffableComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<CuffableComponent, ComponentInit>(OnStartup);
SubscribeLocalEvent<CuffableComponent, AttemptStopPullingEvent>(HandleStopPull);
SubscribeLocalEvent<CuffableComponent, RemoveCuffsAlertEvent>(OnRemoveCuffsAlert);
SubscribeLocalEvent<CuffableComponent, UpdateCanMoveEvent>(HandleMoveAttempt);
SubscribeLocalEvent<CuffableComponent, IsEquippingAttemptEvent>(OnEquipAttempt);
SubscribeLocalEvent<CuffableComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
@@ -248,6 +249,14 @@ namespace Content.Shared.Cuffs
args.Cancelled = true;
}
private void OnRemoveCuffsAlert(Entity<CuffableComponent> ent, ref RemoveCuffsAlertEvent args)
{
if (args.Handled)
return;
TryUncuff(ent, ent, cuffable: ent.Comp);
args.Handled = true;
}
private void AddUncuffVerb(EntityUid uid, CuffableComponent component, GetVerbsEvent<Verb> args)
{
// Can the user access the cuffs, and is there even anything to uncuff?

View File

@@ -47,6 +47,8 @@ public sealed partial class EnsnareableComponent : Component
public ProtoId<AlertPrototype> EnsnaredAlert = "Ensnared";
}
public sealed partial class RemoveEnsnareAlertEvent : BaseAlertEvent;
[Serializable, NetSerializable]
public sealed class EnsnareableComponentState : ComponentState
{

View File

@@ -1,3 +1,4 @@
using Content.Shared.DragDrop;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
@@ -14,6 +15,38 @@ public sealed class DeployFoldableSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<DeployFoldableComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<DeployFoldableComponent, CanDragEvent>(OnCanDrag);
SubscribeLocalEvent<DeployFoldableComponent, DragDropDraggedEvent>(OnDragDropDragged);
SubscribeLocalEvent<DeployFoldableComponent, CanDropDraggedEvent>(OnCanDropDragged);
}
private void OnCanDropDragged(Entity<DeployFoldableComponent> ent, ref CanDropDraggedEvent args)
{
if (args.User != args.Target)
return;
args.Handled = true;
args.CanDrop = true;
}
private void OnDragDropDragged(Entity<DeployFoldableComponent> ent, ref DragDropDraggedEvent args)
{
if (!TryComp<FoldableComponent>(ent, out var foldable)
|| !_foldable.TrySetFolded(ent, foldable, true))
return;
_hands.PickupOrDrop(args.User, ent.Owner);
args.Handled = true;
}
private void OnCanDrag(Entity<DeployFoldableComponent> ent, ref CanDragEvent args)
{
if (!TryComp<FoldableComponent>(ent, out var foldable)
|| foldable.IsFolded)
return;
args.Handled = true;
}
private void OnAfterInteract(Entity<DeployFoldableComponent> ent, ref AfterInteractEvent args)

View File

@@ -1,4 +1,5 @@
using Content.Shared.DoAfter;
using Content.Shared.Alert;
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;
namespace Content.Shared.Internals;
@@ -7,3 +8,5 @@ namespace Content.Shared.Internals;
public sealed partial class InternalsDoAfterEvent : SimpleDoAfterEvent
{
}
public sealed partial class ToggleInternalsAlertEvent : BaseAlertEvent;

View File

@@ -369,11 +369,10 @@ public abstract class SharedMagicSystem : EntitySystem
if (HasComp(ev.Target, data.Component.GetType()))
continue;
var component = (Component) _compFact.GetComponent(name);
component.Owner = ev.Target;
var temp = (object) component;
var component = (Component)_compFact.GetComponent(name);
var temp = (object)component;
_seriMan.CopyTo(data.Component, ref temp);
EntityManager.AddComponent(ev.Target, (Component) temp!);
EntityManager.AddComponent(ev.Target, (Component)temp!);
}
}
// End Change Component Spells

View File

@@ -80,11 +80,6 @@ public partial class MobStateSystem
case MobState.Dead:
RemComp<CollisionWakeComponent>(target);
_standing.Stand(target);
if (!_standing.IsDown(target) && TryComp<PhysicsComponent>(target, out var physics))
{
_physics.SetCanCollide(target, true, body: physics);
}
break;
case MobState.Invalid:
//unused
@@ -115,12 +110,6 @@ public partial class MobStateSystem
case MobState.Dead:
EnsureComp<CollisionWakeComponent>(target);
_standing.Down(target);
if (_standing.IsDown(target) && TryComp<PhysicsComponent>(target, out var physics))
{
_physics.SetCanCollide(target, false, body: physics);
}
_appearance.SetData(target, MobStateVisuals.State, MobState.Dead);
break;
case MobState.Invalid:

View File

@@ -42,3 +42,5 @@ public sealed partial class PullableComponent : Component
[DataField]
public ProtoId<AlertPrototype> PulledAlert = "Pulled";
}
public sealed partial class StopBeingPulledAlertEvent : BaseAlertEvent;

Some files were not shown because too many files have changed in this diff Show More