Compare commits

..

1 Commits

Author SHA1 Message Date
comasqw
544a260f4b Update SpellStorage 2024-11-26 22:21:30 +04:00
1443 changed files with 14820 additions and 329773 deletions

View File

@@ -16,7 +16,7 @@ jobs:
with:
username: ${{ github.actor }}
team: "content-maintainers,junior-maintainers"
GITHUB_TOKEN: ${{ secrets.LABELER_PAT }}
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
- if: ${{ steps.checkUserMember.outputs.isTeamMember == 'true' }}
uses: actions-ecosystem/action-add-labels@v1
with:

View File

@@ -258,13 +258,13 @@ namespace Content.Client.Actions
public void LinkAllActions(ActionsComponent? actions = null)
{
if (_playerManager.LocalEntity is not { } user ||
!Resolve(user, ref actions, false))
{
return;
}
if (_playerManager.LocalEntity is not { } user ||
!Resolve(user, ref actions, false))
{
return;
}
LinkActions?.Invoke(actions);
LinkActions?.Invoke(actions);
}
public override void Shutdown()

View File

@@ -159,7 +159,6 @@ public sealed partial class NoteEdit : FancyWindow
SecretCheckBox.Pressed = false;
SeverityOption.Disabled = false;
PermanentCheckBox.Pressed = true;
SubmitButton.Disabled = true;
UpdatePermanentCheckboxFields();
break;
case (int) NoteType.Message: // Message: these are shown to the player when they log on

View File

@@ -1,4 +1,8 @@
using Robust.Shared.GameObjects;
namespace Content.Client.Atmos.Components;
[RegisterComponent]
public sealed partial class PipeColorVisualsComponent : Component;
public sealed partial class PipeColorVisualsComponent : Component
{
}

View File

@@ -1,5 +1,6 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Orientation="Vertical" HorizontalExpand ="True" Margin="0 0 0 3">
@@ -61,7 +62,7 @@
</PanelContainer>
</BoxContainer>
<!-- If the alarm is inactive, this is label is displayed instead -->
<!-- If the alarm is inactive, this is label is diplayed instead -->
<Label Name="NoDataLabel" Text="{Loc 'atmos-alerts-window-no-data-available'}" HorizontalAlignment="Center" Margin="0 15" FontColorOverride="#a9a9a9" ReservesSpace="False" Visible="False"></Label>
<!-- Silencing progress bar -->

View File

@@ -136,9 +136,8 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
GasGridContainer.RemoveAllChildren();
var gasData = focusData.Value.GasData.Where(g => g.Key != Gas.Oxygen);
var keyValuePairs = gasData.ToList();
if (keyValuePairs.Count == 0)
if (gasData.Count() == 0)
{
// No other gases
var gasLabel = new Label()
@@ -159,11 +158,13 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
else
{
// Add an entry for each gas
foreach ((var gas, (var mol, var percent, var alert)) in keyValuePairs)
foreach ((var gas, (var mol, var percent, var alert)) in gasData)
{
FixedPoint2 gasPercent = percent * 100f;
var gasPercent = (FixedPoint2)0f;
gasPercent = percent * 100f;
var gasShorthand = _gasShorthands.GetValueOrDefault(gas, "X");
if (!_gasShorthands.TryGetValue(gas, out var gasShorthand))
gasShorthand = "X";
var gasLabel = new Label()
{

View File

@@ -14,6 +14,8 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
_menu = new AtmosAlertsComputerWindow(this, Owner);
_menu.OpenCentered();
_menu.OnClose += Close;
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -22,6 +24,9 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
var castState = (AtmosAlertsComputerBoundInterfaceState) state;
if (castState == null)
return;
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
_menu?.UpdateUI(xform?.Coordinates, castState.AirAlarms, castState.FireAlarms, castState.FocusData);
}

View File

@@ -1,6 +1,7 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.Pinpointer.UI"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Title="{Loc 'atmos-alerts-window-title'}"
Resizable="False"
SetSize="1120 750"

View File

@@ -4,6 +4,8 @@ using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
namespace Content.Client.Atmos.EntitySystems;
@@ -17,7 +19,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<PipeAppearanceComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: [typeof(SubFloorHideSystem)]);
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: new[] { typeof(SubFloorHideSystem) });
}
private void OnInit(EntityUid uid, PipeAppearanceComponent component, ComponentInit args)
@@ -82,8 +84,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
layer.Visible &= visible;
if (!visible)
continue;
if (!visible) continue;
layer.Color = color;
}

View File

@@ -1,7 +1,12 @@
using System.Collections.Generic;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Power;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.Atmos.Monitor;
@@ -22,7 +27,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var visLayer in component.HideOnDepowered)
{
if (args.Sprite.LayerMapTryGet(visLayer, out var powerVisibilityLayer))
if (args.Sprite.LayerMapTryGet(visLayer, out int powerVisibilityLayer))
args.Sprite.LayerSetVisible(powerVisibilityLayer, powered);
}
}
@@ -31,7 +36,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var (setLayer, powerState) in component.SetOnDepowered)
{
if (args.Sprite.LayerMapTryGet(setLayer, out var setStateLayer))
if (args.Sprite.LayerMapTryGet(setLayer, out int setStateLayer))
args.Sprite.LayerSetState(setStateLayer, new RSI.StateId(powerState));
}
}

View File

@@ -1,7 +1,11 @@
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
namespace Content.Client.Atmos.Monitor.UI;
@@ -74,7 +78,6 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface
{
base.Dispose(disposing);
if (disposing)
_window?.Dispose();
if (disposing) _window?.Dispose();
}
}

View File

@@ -8,6 +8,7 @@ using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Temperature;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
@@ -58,7 +59,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
AirAlarmMode.Fill => "air-alarm-ui-mode-fill",
AirAlarmMode.Panic => "air-alarm-ui-mode-panic",
AirAlarmMode.None => "air-alarm-ui-mode-none",
_ => "error",
_ => "error"
};
_modes.AddItem(Loc.GetString(text));
}
@@ -69,7 +70,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
AirAlarmModeChanged!.Invoke((AirAlarmMode) args.Id);
};
_autoMode.OnToggled += _ =>
_autoMode.OnToggled += args =>
{
AutoModeChanged!.Invoke(_autoMode.Pressed);
};
@@ -175,18 +176,22 @@ public sealed partial class AirAlarmWindow : FancyWindow
public static Color ColorForThreshold(float amount, AtmosAlarmThreshold threshold)
{
threshold.CheckThreshold(amount, out var curAlarm);
threshold.CheckThreshold(amount, out AtmosAlarmType curAlarm);
return ColorForAlarm(curAlarm);
}
public static Color ColorForAlarm(AtmosAlarmType curAlarm)
{
return curAlarm switch
if(curAlarm == AtmosAlarmType.Danger)
{
AtmosAlarmType.Danger => StyleNano.DangerousRedFore,
AtmosAlarmType.Warning => StyleNano.ConcerningOrangeFore,
_ => StyleNano.GoodGreenFore,
};
return StyleNano.DangerousRedFore;
}
else if(curAlarm == AtmosAlarmType.Warning)
{
return StyleNano.ConcerningOrangeFore;
}
return StyleNano.GoodGreenFore;
}

View File

@@ -1,8 +1,12 @@
using System;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
namespace Content.Client.Atmos.Monitor.UI.Widgets;
@@ -21,7 +25,7 @@ public sealed partial class PumpControl : BoxContainer
private OptionButton _pressureCheck => CPressureCheck;
private FloatSpinBox _externalBound => CExternalBound;
private FloatSpinBox _internalBound => CInternalBound;
private Button _copySettings => CCopySettings;
private Button _copySettings => CCopySettings;
public PumpControl(GasVentPumpData data, string address)
{
@@ -82,7 +86,7 @@ public sealed partial class PumpControl : BoxContainer
_data.PressureChecks = (VentPressureBound) args.Id;
PumpDataChanged?.Invoke(_address, _data);
};
_copySettings.OnPressed += _ =>
{
PumpDataCopied?.Invoke(_data);

View File

@@ -1,9 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
namespace Content.Client.Atmos.Monitor.UI.Widgets;
@@ -21,7 +27,7 @@ public sealed partial class ScrubberControl : BoxContainer
private OptionButton _pumpDirection => CPumpDirection;
private FloatSpinBox _volumeRate => CVolumeRate;
private CheckBox _wideNet => CWideNet;
private Button _copySettings => CCopySettings;
private Button _copySettings => CCopySettings;
private GridContainer _gases => CGasContainer;
private Dictionary<Gas, Button> _gasControls = new();
@@ -71,7 +77,7 @@ public sealed partial class ScrubberControl : BoxContainer
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
ScrubberDataChanged?.Invoke(_address, _data);
};
_copySettings.OnPressed += _ =>
{
ScrubberDataCopied?.Invoke(_data);

View File

@@ -43,8 +43,7 @@ public sealed partial class SensorInfo : BoxContainer
var label = new RichTextLabel();
var fractionGas = amount / data.TotalMoles;
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
("gas", $"{gas}"),
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator", ("gas", $"{gas}"),
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
("amount", $"{amount:0.####}"),
("percentage", $"{(100 * fractionGas):0.##}")));
@@ -54,9 +53,9 @@ public sealed partial class SensorInfo : BoxContainer
var threshold = data.GasThresholds[gas];
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title", ("gas", $"{gas}")), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
gasThresholdControl.ThresholdDataChanged += (type, threshold, arg3) =>
{
OnThresholdUpdate!(_address, type, alarmThreshold, arg3);
OnThresholdUpdate!(_address, type, threshold, arg3);
};
_gasThresholds.Add(gas, gasThresholdControl);
@@ -65,8 +64,7 @@ public sealed partial class SensorInfo : BoxContainer
_pressureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-pressure-title"), data.PressureThreshold, AtmosMonitorThresholdType.Pressure);
PressureThresholdContainer.AddChild(_pressureThreshold);
_temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"),
data.TemperatureThreshold,
_temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"), data.TemperatureThreshold,
AtmosMonitorThresholdType.Temperature);
TemperatureThresholdContainer.AddChild(_temperatureThreshold);
@@ -105,8 +103,7 @@ public sealed partial class SensorInfo : BoxContainer
}
var fractionGas = amount / data.TotalMoles;
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
("gas", $"{gas}"),
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator", ("gas", $"{gas}"),
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
("amount", $"{amount:0.####}"),
("percentage", $"{(100 * fractionGas):0.##}")));

View File

@@ -1,4 +1,7 @@
using Content.Client.Message;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Temperature;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

View File

@@ -1,8 +1,12 @@
using System;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
// holy FUCK
// this technically works because some of this you can *not* do in XAML but holy FUCK
@@ -111,38 +115,29 @@ public sealed partial class ThresholdControl : BoxContainer
_enabled.Pressed = !_threshold.Ignore;
}
private string LabelForBound(string boundType) //<todo.eoin Replace this with enums
private String LabelForBound(string boundType) //<todo.eoin Replace this with enums
{
return Loc.GetString($"air-alarm-ui-thresholds-{boundType}");
}
public void UpdateThresholdData(AtmosAlarmThreshold threshold, float currentAmount)
{
threshold.CheckThreshold(currentAmount, out var alarm, out var bound);
threshold.CheckThreshold(currentAmount, out AtmosAlarmType alarm, out AtmosMonitorThresholdBound which);
var upperDangerState = AtmosAlarmType.Normal;
var lowerDangerState = AtmosAlarmType.Normal;
var upperWarningState = AtmosAlarmType.Normal;
var lowerWarningState = AtmosAlarmType.Normal;
switch (alarm)
if(alarm == AtmosAlarmType.Danger)
{
case AtmosAlarmType.Danger:
{
if (bound == AtmosMonitorThresholdBound.Upper)
upperDangerState = alarm;
else
lowerDangerState = alarm;
break;
}
case AtmosAlarmType.Warning:
{
if (bound == AtmosMonitorThresholdBound.Upper)
upperWarningState = alarm;
else
lowerWarningState = alarm;
break;
}
if(which == AtmosMonitorThresholdBound.Upper) upperDangerState = alarm;
else lowerDangerState = alarm;
}
else if(alarm == AtmosAlarmType.Warning)
{
if(which == AtmosMonitorThresholdBound.Upper) upperWarningState = alarm;
else lowerWarningState = alarm;
}
_upperBoundControl.SetValue(threshold.UpperBound.Value);

View File

@@ -1,4 +1,3 @@
using System.Globalization;
using System.Linq;
using System.Numerics;
using Content.Client.Atmos.EntitySystems;
@@ -102,9 +101,14 @@ public sealed class AtmosDebugOverlay : Overlay
else
{
// Red-Green-Blue interpolation
res = interp < 0.5f
? Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2)
: Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
if (interp < 0.5f)
{
res = Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2);
}
else
{
res = Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
}
}
res = res.WithAlpha(0.75f);
@@ -177,10 +181,7 @@ public sealed class AtmosDebugOverlay : Overlay
handle.DrawCircle(tileCentre, 0.05f, Color.Black);
}
private void CheckAndShowBlockDir(
AtmosDebugOverlayData data,
DrawingHandleWorld handle,
AtmosDirection dir,
private void CheckAndShowBlockDir(AtmosDebugOverlayData data, DrawingHandleWorld handle, AtmosDirection dir,
Vector2 tileCentre)
{
if (!data.BlockDirection.HasFlag(dir))
@@ -242,7 +243,7 @@ public sealed class AtmosDebugOverlay : Overlay
var moles = data.Moles == null
? "No Air"
: data.Moles.Sum().ToString(CultureInfo.InvariantCulture);
: data.Moles.Sum().ToString();
handle.DrawString(_font, pos, $"Moles: {moles}");
pos += offset;
@@ -262,12 +263,7 @@ public sealed class AtmosDebugOverlay : Overlay
private void GetGrids(MapId mapId, Box2Rotated box)
{
_grids.Clear();
_mapManager.FindGridsIntersecting(
mapId,
box,
ref _grids,
(EntityUid uid,
MapGridComponent grid,
_mapManager.FindGridsIntersecting(mapId, box, ref _grids, (EntityUid uid, MapGridComponent grid,
ref List<(Entity<MapGridComponent>, DebugMessage)> state) =>
{
if (_system.TileData.TryGetValue(uid, out var data))

View File

@@ -30,7 +30,7 @@ public sealed class ClientClothingSystem : ClothingSystem
/// For some context, im currently refactoring inventory. Part of that is slots not being indexed by a massive enum anymore, but by strings.
/// Problem here: Every rsi-state is using the old enum-names in their state. I already used the new inventoryslots ALOT. tldr: its this or another week of renaming files.
/// </summary>
public static readonly Dictionary<string, string> TemporarySlotMap = new() //CP14 Public
private static readonly Dictionary<string, string> TemporarySlotMap = new()
{
{"head", "HELMET"},
{"eyes", "EYES"},

View File

@@ -7,7 +7,7 @@ using Robust.Client.GameObjects;
namespace Content.Client.Clothing;
public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<FlippableClothingVisualsComponent>
public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<FlippableClothingVisualsComponent>
{
[Dependency] private readonly SharedItemSystem _itemSys = default!;

View File

@@ -1,95 +0,0 @@
using Content.Shared.Electrocution;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Player;
namespace Content.Client.Electrocution;
/// <summary>
/// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent.
/// </summary>
public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<ElectrocutionHUDVisualsComponent>
{
[Dependency] private readonly IPlayerManager _playerMan = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
}
private void OnPlayerAttached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerAttachedEvent args)
{
ShowHUD();
}
private void OnPlayerDetached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerDetachedEvent args)
{
RemoveHUD();
}
private void OnInit(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentInit args)
{
if (_playerMan.LocalEntity == ent)
{
ShowHUD();
}
}
private void OnShutdown(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentShutdown args)
{
if (_playerMan.LocalEntity == ent)
{
RemoveHUD();
}
}
// Show the HUD to the client.
// We have to look for all current entities that can be electrified and toggle the HUD layer on if they are.
private void ShowHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
{
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp))
continue;
if (electrified)
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}
// Remove the HUD from the client.
// Find all current entities that can be electrified and hide the HUD layer.
private void RemoveHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
{
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}
// Toggle the HUD layer if an entity becomes (de-)electrified
protected override void OnAppearanceChange(EntityUid uid, ElectrocutionHUDVisualsComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component))
return;
var player = _playerMan.LocalEntity;
if (electrified && HasComp<ShowElectrocutionHUDComponent>(player))
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}

View File

@@ -55,7 +55,7 @@ namespace Content.Client.Eui
/// </summary>
protected void SendMessage(EuiMessageBase msg)
{
var netMsg = new MsgEuiMessage();
var netMsg = _netManager.CreateNetMessage<MsgEuiMessage>();
netMsg.Id = Id;
netMsg.Message = msg;

View File

@@ -112,12 +112,7 @@ namespace Content.Client.Ghost
_actions.RemoveAction(uid, component.ToggleLightingActionEntity);
_actions.RemoveAction(uid, component.ToggleFoVActionEntity);
_actions.RemoveAction(uid, component.ToggleGhostsActionEntity);
//_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity); //Dont need in CP14
//CP14
_actions.RemoveAction(uid, component.CP14ZLevelUpActionEntity);
_actions.RemoveAction(uid, component.CP14ZLevelDownActionEntity);
_actions.RemoveAction(uid, component.CP14ToggleRoofActionEntity);
//CP14 end
_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity);
if (uid != _playerManager.LocalEntity)
return;

View File

@@ -191,15 +191,9 @@ namespace Content.Client.Inventory
return;
if (ev.Function == ContentKeyFunctions.ExamineEntity)
{
_examine.DoExamine(slot.Entity.Value);
ev.Handle();
}
else if (ev.Function == EngineKeyFunctions.UseSecondary)
{
_ui.GetUIController<VerbMenuUIController>().OpenVerbMenu(slot.Entity.Value);
ev.Handle();
}
}
private void AddInventoryButton(EntityUid invUid, string slotId, InventoryComponent inv)

View File

@@ -21,22 +21,6 @@ public sealed class HandheldLightSystem : SharedHandheldLightSystem
SubscribeLocalEvent<HandheldLightComponent, AppearanceChangeEvent>(OnAppearanceChange);
}
/// <remarks>
/// TODO: Not properly predicted yet. Don't call this function if you want a the actual return value!
/// </remarks>
public override bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
{
return true;
}
/// <remarks>
/// TODO: Not properly predicted yet. Don't call this function if you want a the actual return value!
/// </remarks>
public override bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
{
return true;
}
private void OnAppearanceChange(EntityUid uid, HandheldLightComponent? component, ref AppearanceChangeEvent args)
{
if (!Resolve(uid, ref component))

View File

@@ -116,7 +116,7 @@ namespace Content.Client.Lobby
return;
}
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
string text;
if (_gameTicker.Paused)
@@ -136,10 +136,6 @@ namespace Content.Client.Lobby
{
text = Loc.GetString(seconds < -5 ? "lobby-state-right-now-question" : "lobby-state-right-now-confirmation");
}
else if (difference.TotalHours >= 1)
{
text = $"{Math.Floor(difference.TotalHours)}:{difference.Minutes:D2}:{difference.Seconds:D2}";
}
else
{
text = $"{difference.Minutes}:{difference.Seconds:D2}";

View File

@@ -35,7 +35,7 @@ public sealed partial class StencilOverlay
var matty = Matrix3x2.Multiply(matrix, invMatrix);
worldHandle.SetTransform(matty);
foreach (var tile in _map.GetTilesIntersecting(grid.Owner, grid, worldAABB))
foreach (var tile in grid.Comp.GetTilesIntersecting(worldAABB))
{
// Ignored tiles for stencil
if (_weather.CanWeatherAffect(grid.Owner, grid, tile))

View File

@@ -26,7 +26,6 @@ public sealed partial class StencilOverlay : Overlay
[Dependency] private readonly IPrototypeManager _protoManager = default!;
private readonly ParallaxSystem _parallax;
private readonly SharedTransformSystem _transform;
private readonly SharedMapSystem _map;
private readonly SpriteSystem _sprite;
private readonly WeatherSystem _weather;
@@ -36,12 +35,11 @@ public sealed partial class StencilOverlay : Overlay
private readonly ShaderInstance _shader;
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SharedMapSystem map, SpriteSystem sprite, WeatherSystem weather)
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SpriteSystem sprite, WeatherSystem weather)
{
ZIndex = ParallaxSystem.ParallaxZIndex + 1;
_parallax = parallax;
_transform = transform;
_map = map;
_sprite = sprite;
_weather = weather;
IoCManager.InjectDependencies(this);

View File

@@ -10,14 +10,13 @@ public sealed class StencilOverlaySystem : EntitySystem
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly ParallaxSystem _parallax = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly WeatherSystem _weather = default!;
public override void Initialize()
{
base.Initialize();
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _map, _sprite, _weather));
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _sprite, _weather));
}
public override void Shutdown()

View File

@@ -116,7 +116,7 @@ public partial class BaseShuttleControl : MapGridControl
}
}
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 matrix, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
{
var rator = Maps.GetAllTilesEnumerator(grid.Owner, grid.Comp);
var minimapScale = MinimapScale;
@@ -264,7 +264,7 @@ public partial class BaseShuttleControl : MapGridControl
Extensions.EnsureLength(ref _allVertices, totalData);
_drawJob.MidPoint = midpoint;
_drawJob.Matrix = gridToView;
_drawJob.Matrix = matrix;
_drawJob.MinimapScale = minimapScale;
_drawJob.Vertices = gridData.Vertices;
_drawJob.ScaledVertices = _allVertices;
@@ -286,7 +286,7 @@ public partial class BaseShuttleControl : MapGridControl
private record struct GridDrawJob : IParallelRobustJob
{
public int BatchSize => 64;
public int BatchSize => 16;
public float MinimapScale;
public Vector2 MidPoint;
@@ -297,7 +297,12 @@ public partial class BaseShuttleControl : MapGridControl
public void Execute(int index)
{
ScaledVertices[index] = Vector2.Transform(Vertices[index], Matrix);
var vert = Vertices[index];
var adjustedVert = Vector2.Transform(vert, Matrix);
adjustedVert = adjustedVert with { Y = -adjustedVert.Y };
var scaledVert = ScalePosition(adjustedVert, MinimapScale, MidPoint);
ScaledVertices[index] = scaledVert;
}
}
}

View File

@@ -15,7 +15,6 @@ public sealed partial class NavScreen : BoxContainer
[Dependency] private readonly IEntityManager _entManager = default!;
private SharedTransformSystem _xformSystem;
private EntityUid? _consoleEntity; // Entity of controlling console
private EntityUid? _shuttleEntity;
public NavScreen()
@@ -36,12 +35,6 @@ public sealed partial class NavScreen : BoxContainer
_shuttleEntity = shuttle;
}
public void SetConsole(EntityUid? console)
{
_consoleEntity = console;
NavRadar.SetConsole(console);
}
private void OnIFFTogglePressed(BaseButton.ButtonEventArgs args)
{
NavRadar.ShowIFF ^= true;

View File

@@ -138,7 +138,6 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
{
var coordinates = _entManager.GetCoordinates(cState.NavState.Coordinates);
NavContainer.SetShuttle(coordinates?.EntityId);
NavContainer.SetConsole(owner);
MapContainer.SetShuttle(coordinates?.EntityId);
MapContainer.SetConsole(owner);

View File

@@ -107,19 +107,16 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
DrawCircles(handle);
var gridNent = EntManager.GetNetEntity(GridEntity);
var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value);
var ourGridToWorld = _xformSystem.GetWorldMatrix(GridEntity.Value);
var selectedDockToOurGrid = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
var selectedDockToWorld = Matrix3x2.Multiply(selectedDockToOurGrid, ourGridToWorld);
var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value);
var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix);
Box2 viewBoundsWorld = Matrix3Helpers.TransformBox(selectedDockToWorld, new Box2(-WorldRangeVector, WorldRangeVector));
Matrix3x2.Invert(selectedDockToWorld, out var worldToSelectedDock);
var selectedDockToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
Matrix3x2.Invert(worldFromDock, out var offsetMatrix);
// Draw nearby grids
var controlBounds = PixelSizeBox;
_grids.Clear();
_mapManager.FindGridsIntersecting(gridXform.MapID, viewBoundsWorld, ref _grids);
_mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(mapPos.Position - WorldRangeVector, mapPos.Position + WorldRangeVector), ref _grids);
// offset the dotted-line position to the bounds.
Vector2? viewedDockPos = _viewedState != null ? MidPointVector : null;
@@ -139,11 +136,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
if (grid.Owner != GridEntity && !_shuttles.CanDraw(grid.Owner, iffComp: iffComp))
continue;
var curGridToWorld = _xformSystem.GetWorldMatrix(grid.Owner);
var curGridToView = curGridToWorld * worldToSelectedDock * selectedDockToView;
var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner);
var matty = Matrix3x2.Multiply(gridMatrix, offsetMatrix);
var color = _shuttles.GetIFFColor(grid.Owner, grid.Owner == GridEntity, component: iffComp);
DrawGrid(handle, curGridToView, grid, color);
DrawGrid(handle, matty, grid, color);
// Draw any docks on that grid
if (!DockState.Docks.TryGetValue(EntManager.GetNetEntity(grid), out var gridDocks))
@@ -154,24 +151,23 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
if (ViewedDock == dock.Entity)
continue;
var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle);
var position = Vector2.Transform(dock.Coordinates.Position, matty);
// This box is the AABB of all the vertices we draw below.
var dockRenderBoundsLocal = new Box2(-0.5f, -0.7f, 0.5f, 0.5f);
var currentDockToCurGrid = Matrix3Helpers.CreateTransform(dock.Coordinates.Position, dock.Angle);
var currentDockToWorld = Matrix3x2.Multiply(currentDockToCurGrid, curGridToWorld);
var dockRenderBoundsWorld = Matrix3Helpers.TransformBox(currentDockToWorld, dockRenderBoundsLocal);
if (!viewBoundsWorld.Intersects(dockRenderBoundsWorld))
var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle);
var scaledPos = ScalePosition(position with {Y = -position.Y});
if (!controlBounds.Contains(scaledPos.Floored()))
continue;
// Draw the dock's collision
var collisionBL = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), matty);
var collisionBR = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), matty);
var collisionTR = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), matty);
var collisionTL = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), curGridToView);
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), matty);
var verts = new[]
{
@@ -185,6 +181,13 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
collisionBL,
};
for (var i = 0; i < verts.Length; i++)
{
var vert = verts[i];
vert.Y = -vert.Y;
verts[i] = ScalePosition(vert);
}
var collisionCenter = verts[0] + verts[1] + verts[3] + verts[5];
var otherDockConnection = Color.ToSrgb(Color.Pink);
@@ -192,10 +195,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, verts, otherDockConnection);
// Draw the dock itself
var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), curGridToView);
var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), curGridToView);
var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), curGridToView);
var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), curGridToView);
var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), matty);
var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), matty);
var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), matty);
var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), matty);
verts = new[]
{
@@ -209,6 +212,13 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
dockBL
};
for (var i = 0; i < verts.Length; i++)
{
var vert = verts[i];
vert.Y = -vert.Y;
verts[i] = ScalePosition(vert);
}
Color otherDockColor;
if (HighlightedDock == dock.Entity)
@@ -243,11 +253,9 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
collisionCenter /= 4;
var range = viewedDockPos.Value - collisionCenter;
var maxRange = SharedDockingSystem.DockingHiglightRange * MinimapScale;
var maxRangeSq = maxRange * maxRange;
if (range.LengthSquared() < maxRangeSq)
if (range.Length() < SharedDockingSystem.DockingHiglightRange * MinimapScale)
{
if (dock.GridDockedWith == null)
if (_viewedState?.GridDockedWith == null)
{
var coordsOne = EntManager.GetCoordinates(_viewedState!.Coordinates);
var coordsTwo = EntManager.GetCoordinates(dock.Coordinates);
@@ -257,11 +265,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
var rotA = _xformSystem.GetWorldRotation(coordsOne.EntityId) + _viewedState!.Angle;
var rotB = _xformSystem.GetWorldRotation(coordsTwo.EntityId) + dock.Angle;
var distanceSq = (mapOne.Position - mapTwo.Position).LengthSquared();
var distance = (mapOne.Position - mapTwo.Position).Length();
var inAlignment = _dockSystem.InAlignment(mapOne, rotA, mapTwo, rotB);
var maxDockDistSq = SharedDockingSystem.DockRange * SharedDockingSystem.DockRange;
var canDock = distanceSq < maxDockDistSq && inAlignment;
var canDock = distance < SharedDockingSystem.DockRange && inAlignment;
if (dockButton != null)
dockButton.Disabled = !canDock || !canDockChange;
@@ -290,8 +297,7 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
{
// Because it's being layed out top-down we have to arrange for first frame.
container.Arrange(PixelRect);
var dockPositionInView = Vector2.Transform(dock.Coordinates.Position, curGridToView);
var containerPos = dockPositionInView / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
var containerPos = scaledPos / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
SetPosition(container, containerPos);
}

View File

@@ -29,11 +29,6 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
/// </summary>
private EntityCoordinates? _coordinates;
/// <summary>
/// Entity of controlling console
/// </summary>
private EntityUid? _consoleEntity;
private Angle? _rotation;
private Dictionary<NetEntity, List<DockingPortState>> _docks = new();
@@ -62,11 +57,6 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
_rotation = angle;
}
public void SetConsole(EntityUid? consoleEntity)
{
_consoleEntity = consoleEntity;
}
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.KeyBindUp(args);
@@ -149,35 +139,40 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
}
var mapPos = _transform.ToMapCoordinates(_coordinates.Value);
var posMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, _rotation.Value);
var offset = _coordinates.Value.Position;
var posMatrix = Matrix3Helpers.CreateTransform(offset, _rotation.Value);
var ourEntRot = RotateWithEntity ? _transform.GetWorldRotation(xform) : _rotation.Value;
var ourEntMatrix = Matrix3Helpers.CreateTransform(_transform.GetWorldPosition(xform), ourEntRot);
var shuttleToWorld = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
Matrix3x2.Invert(shuttleToWorld, out var worldToShuttle);
var shuttleToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
var ourWorldMatrix = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
Matrix3x2.Invert(ourWorldMatrix, out var ourWorldMatrixInvert);
// Draw our grid in detail
var ourGridId = xform.GridUid;
if (EntManager.TryGetComponent<MapGridComponent>(ourGridId, out var ourGrid) &&
fixturesQuery.HasComponent(ourGridId.Value))
{
var ourGridToWorld = _transform.GetWorldMatrix(ourGridId.Value);
var ourGridToShuttle = Matrix3x2.Multiply(ourGridToWorld, worldToShuttle);
var ourGridToView = ourGridToShuttle * shuttleToView;
var ourGridMatrix = _transform.GetWorldMatrix(ourGridId.Value);
var matrix = Matrix3x2.Multiply(ourGridMatrix, ourWorldMatrixInvert);
var color = _shuttles.GetIFFColor(ourGridId.Value, self: true);
DrawGrid(handle, ourGridToView, (ourGridId.Value, ourGrid), color);
DrawDocks(handle, ourGridId.Value, ourGridToView);
DrawGrid(handle, matrix, (ourGridId.Value, ourGrid), color);
DrawDocks(handle, ourGridId.Value, matrix);
}
var invertedPosition = _coordinates.Value.Position - offset;
invertedPosition.Y = -invertedPosition.Y;
// Don't need to transform the InvWorldMatrix again as it's already offset to its position.
// Draw radar position on the station
var radarPos = invertedPosition;
const float radarVertRadius = 2f;
var radarPosVerts = new Vector2[]
{
ScalePosition(new Vector2(0f, -radarVertRadius)),
ScalePosition(new Vector2(radarVertRadius / 2f, 0f)),
ScalePosition(new Vector2(0f, radarVertRadius)),
ScalePosition(new Vector2(radarVertRadius / -2f, 0f)),
ScalePosition(radarPos + new Vector2(0f, -radarVertRadius)),
ScalePosition(radarPos + new Vector2(radarVertRadius / 2f, 0f)),
ScalePosition(radarPos + new Vector2(0f, radarVertRadius)),
ScalePosition(radarPos + new Vector2(radarVertRadius / -2f, 0f)),
};
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, radarPosVerts, Color.Lime);
@@ -202,8 +197,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
if (!_shuttles.CanDraw(gUid, gridBody, iff))
continue;
var curGridToWorld = _transform.GetWorldMatrix(gUid);
var curGridToView = curGridToWorld * worldToShuttle * shuttleToView;
var gridMatrix = _transform.GetWorldMatrix(gUid);
var matty = Matrix3x2.Multiply(gridMatrix, ourWorldMatrixInvert);
var labelColor = _shuttles.GetIFFColor(grid, self: false, iff);
var coordColor = new Color(labelColor.R * 0.8f, labelColor.G * 0.8f, labelColor.B * 0.8f, 0.5f);
@@ -218,7 +213,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
{
var gridBounds = grid.Comp.LocalAABB;
var gridCentre = Vector2.Transform(gridBody.LocalCenter, curGridToView);
var gridCentre = Vector2.Transform(gridBody.LocalCenter, matty);
gridCentre.Y = -gridCentre.Y;
var distance = gridCentre.Length();
var labelText = Loc.GetString("shuttle-console-iff-label", ("name", labelName),
@@ -234,8 +230,9 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
// y-offset the control to always render below the grid (vertically)
var yOffset = Math.Max(gridBounds.Height, gridBounds.Width) * MinimapScale / 1.8f;
// The actual position in the UI.
var gridScaledPosition = gridCentre - new Vector2(0, -yOffset);
// The actual position in the UI. We centre the label by offsetting the matrix position
// by half the label's width, plus the y-offset
var gridScaledPosition = ScalePosition(gridCentre) - new Vector2(0, -yOffset);
// Normalize the grid position if it exceeds the viewport bounds
// normalizing it instead of clamping it preserves the direction of the vector and prevents corner-hugging
@@ -267,32 +264,18 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
}
// Detailed view
var gridAABB = curGridToWorld.TransformBox(grid.Comp.LocalAABB);
var gridAABB = gridMatrix.TransformBox(grid.Comp.LocalAABB);
// Skip drawing if it's out of range.
if (!gridAABB.Intersects(viewAABB))
continue;
DrawGrid(handle, curGridToView, grid, labelColor);
DrawDocks(handle, gUid, curGridToView);
DrawGrid(handle, matty, grid, labelColor);
DrawDocks(handle, gUid, matty);
}
// If we've set the controlling console, and it's on a different grid
// to the shuttle itself, then draw an additional marker to help the
// player determine where they are relative to the shuttle.
if (_consoleEntity != null && xformQuery.TryGetComponent(_consoleEntity, out var consoleXform))
{
if (consoleXform.ParentUid != _coordinates.Value.EntityId)
{
var consolePositionWorld = _transform.GetWorldPosition((EntityUid)_consoleEntity);
var p = Vector2.Transform(consolePositionWorld, worldToShuttle * shuttleToView);
handle.DrawCircle(p, 5, Color.ToSrgb(Color.Cyan), true);
}
}
}
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 gridToView)
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 matrix)
{
if (!ShowDocks)
return;
@@ -300,32 +283,33 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
const float DockScale = 0.6f;
var nent = EntManager.GetNetEntity(uid);
const float sqrt2 = 1.41421356f;
const float dockRadius = DockScale * sqrt2;
// Worst-case bounds used to cull a dock:
Box2 viewBounds = new Box2(-dockRadius, -dockRadius, Size.X + dockRadius, Size.Y + dockRadius);
if (_docks.TryGetValue(nent, out var docks))
{
foreach (var state in docks)
{
var position = state.Coordinates.Position;
var uiPosition = Vector2.Transform(position, matrix);
var positionInView = Vector2.Transform(position, gridToView);
if (!viewBounds.Contains(positionInView))
{
if (uiPosition.Length() > (WorldRange * 2f) - DockScale)
continue;
}
var color = Color.ToSrgb(Color.Magenta);
var verts = new[]
{
Vector2.Transform(position + new Vector2(-DockScale, -DockScale), gridToView),
Vector2.Transform(position + new Vector2(DockScale, -DockScale), gridToView),
Vector2.Transform(position + new Vector2(DockScale, DockScale), gridToView),
Vector2.Transform(position + new Vector2(-DockScale, DockScale), gridToView),
Vector2.Transform(position + new Vector2(-DockScale, -DockScale), matrix),
Vector2.Transform(position + new Vector2(DockScale, -DockScale), matrix),
Vector2.Transform(position + new Vector2(DockScale, DockScale), matrix),
Vector2.Transform(position + new Vector2(-DockScale, DockScale), matrix),
};
for (var i = 0; i < verts.Length; i++)
{
var vert = verts[i];
vert.Y = -vert.Y;
verts[i] = ScalePosition(vert);
}
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts, color.WithAlpha(0.8f));
handle.DrawPrimitives(DrawPrimitiveTopology.LineStrip, verts, color);
}

View File

@@ -9,7 +9,6 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.Silicons.Laws.Ui;
@@ -19,13 +18,8 @@ public sealed partial class LawDisplay : Control
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly EntityManager _entityManager = default!;
private static readonly TimeSpan PressCooldown = TimeSpan.FromSeconds(3);
private readonly Dictionary<Button, TimeSpan> _nextAllowedPress = new();
public LawDisplay(EntityUid uid, SiliconLaw law, HashSet<string>? radioChannels)
{
RobustXamlLoader.Load(this);
@@ -53,12 +47,9 @@ public sealed partial class LawDisplay : Control
MinWidth = 75,
};
_nextAllowedPress[localButton] = TimeSpan.Zero;
localButton.OnPressed += _ =>
{
_chatManager.SendMessage($"{lawIdentifierPlaintext}: {lawDescriptionPlaintext}", ChatSelectChannel.Local);
_nextAllowedPress[localButton] = _timing.CurTime + PressCooldown;
};
LawAnnouncementButtons.AddChild(localButton);
@@ -80,8 +71,6 @@ public sealed partial class LawDisplay : Control
MinWidth = 75,
};
_nextAllowedPress[radioChannelButton] = TimeSpan.Zero;
radioChannelButton.OnPressed += _ =>
{
switch (radioChannel)
@@ -91,21 +80,9 @@ public sealed partial class LawDisplay : Control
default:
_chatManager.SendMessage($"{SharedChatSystem.RadioChannelPrefix}{radioChannelProto.KeyCode} {lawIdentifierPlaintext}: {lawDescriptionPlaintext}", ChatSelectChannel.Radio); break;
}
_nextAllowedPress[radioChannelButton] = _timing.CurTime + PressCooldown;
};
LawAnnouncementButtons.AddChild(radioChannelButton);
}
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
var curTime = _timing.CurTime;
foreach (var (button, nextPress) in _nextAllowedPress)
{
button.Disabled = curTime < nextPress;
}
}
}

View File

@@ -1,6 +1,6 @@
<widgets:AlertsUI xmlns="https://spacestation14.io"
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Alerts.Widgets"
MinSize="96 96">
MinSize="64 64">
<PanelContainer HorizontalAlignment="Right" VerticalAlignment="Top">
<BoxContainer Name="AlertContainer" Access="Public" Orientation="Vertical" />
</PanelContainer>

View File

@@ -16,8 +16,9 @@ using static Robust.Client.UserInterface.Controls.LineEdit;
namespace Content.Client.UserInterface.Systems.Chat.Widgets;
[GenerateTypedNameReferences]
[Virtual]
#pragma warning disable RA0003
public partial class ChatBox : UIWidget
#pragma warning restore RA0003
{
private readonly ChatUIController _controller;
private readonly IEntityManager _entManager;

View File

@@ -71,7 +71,6 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
buttonHeading.AddStyleClass(ContainerButton.StyleClassButton);
buttonHeading.Label.HorizontalAlignment = HAlignment.Center;
buttonHeading.Label.HorizontalExpand = true;
buttonHeading.Margin = new Thickness(8, 0, 8, 2);
var body = new CollapsibleBody
{

View File

@@ -83,27 +83,22 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
if (args.Function == EngineKeyFunctions.UIClick)
{
_handsSystem.UIHandClick(_playerHandsComponent, hand.SlotName);
args.Handle();
}
else if (args.Function == EngineKeyFunctions.UseSecondary)
{
_handsSystem.UIHandOpenContextMenu(hand.SlotName);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ActivateItemInWorld)
{
_handsSystem.UIHandActivate(hand.SlotName);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.AltActivateItemInWorld)
{
_handsSystem.UIHandAltActivateItem(hand.SlotName);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ExamineEntity)
{
_handsSystem.UIInventoryExamine(hand.SlotName);
args.Handle();
}
}

View File

@@ -160,9 +160,8 @@ public sealed class ItemGridPiece : Control, IEntityControl
}
// typically you'd divide by two, but since the textures are half a tile, this is done implicitly
var iconPosition = new Vector2(
(boundingGrid.Width + 1) * size.X + Location.Rotation.RotateVec(itemComponent.StoredOffset).X * 2,
(boundingGrid.Height + 1) * size.Y + Location.Rotation.RotateVec(itemComponent.StoredOffset).Y * 2);
var iconPosition = new Vector2((boundingGrid.Width + 1) * size.X + itemComponent.StoredOffset.X * 2,
(boundingGrid.Height + 1) * size.Y + itemComponent.StoredOffset.Y * 2);
var iconRotation = Location.Rotation + Angle.FromDegrees(itemComponent.StoredRotation);
if (itemComponent.StoredSprite is { } storageSprite)

View File

@@ -206,7 +206,8 @@ namespace Content.Client.Wires.UI
(_statusContainer = new GridContainer
{
Margin = new Thickness(8, 4),
Rows = 2
// TODO: automatically change columns count.
Columns = 3
})
}
}
@@ -226,8 +227,7 @@ namespace Content.Client.Wires.UI
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#525252ff")}
});
CloseButton.OnPressed += _ => Close();
SetHeight = 200;
MinWidth = 320;
SetSize = new Vector2(320, 200);
}
@@ -503,8 +503,6 @@ namespace Content.Client.Wires.UI
public StatusLight(StatusLightData data, IResourceCache resourceCache)
{
HorizontalAlignment = HAlignment.Right;
var hsv = Color.ToHsv(data.Color);
hsv.Z /= 2;
var dimColor = Color.FromHsv(hsv);

View File

@@ -1,213 +0,0 @@
using Content.Client.Clothing;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.Clothing;
using Content.Shared.Hands;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Wieldable.Components;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
namespace Content.Client._CP14.ModularCraft;
public sealed class CP14ClientModularCraftSystem : CP14SharedModularCraftSystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IResourceCache _resCache = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, GetInhandVisualsEvent>(OnGetInhandVisuals);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals);
}
private void OnAfterHandleState(Entity<CP14ModularCraftStartPointComponent> start,
ref AfterAutoHandleStateEvent args)
{
if (!TryComp<SpriteComponent>(start, out var sprite))
return;
UpdateIcon(start, sprite);
}
private void UpdateIcon(Entity<CP14ModularCraftStartPointComponent> start, SpriteComponent? sprite = null)
{
if (!Resolve(start, ref sprite, false))
return;
//Remove old layers
foreach (var key in start.Comp.RevealedLayers)
{
sprite.RemoveLayer(key);
}
start.Comp.RevealedLayers.Clear();
//Add new layers
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
if (indexedPart.IconSprite is null)
{
//Try get default sprite
if (indexedPart.RsiPath is null)
continue;
var state = $"icon";
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var keyCode = $"cp14-modular-icon-layer-{counterPart}-default";
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(defaultLayer);
sprite.LayerMapSet(keyCode, index);
}
else
{
var counter = 0;
foreach (var layer in indexedPart.IconSprite)
{
var keyCode = $"cp14-modular-icon-layer-{counterPart}-{counter}";
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(layer);
sprite.LayerMapSet(keyCode, index);
counter++;
}
}
counterPart++;
}
}
private void OnGetInhandVisuals(Entity<CP14ModularCraftStartPointComponent> start, ref GetInhandVisualsEvent args)
{
var defaultKey = $"cp14-modular-inhand-layer-{args.Location.ToString().ToLowerInvariant()}";
if (!TryComp<ItemComponent>(start, out var item))
return;
var wielded = item.HeldPrefix == "wielded"; //SHITCOOOOOOODE
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
var targetLayers =
wielded ? indexedPart.WieldedInhandVisuals : indexedPart.InhandVisuals;
if (targetLayers is not null && targetLayers.TryGetValue(args.Location, out var layers))
{
var i = 0;
foreach (var layer in layers)
{
var key = $"{defaultKey}-{counterPart}-{i}";
args.Layers.Add((key, layer));
i++;
}
}
else
{
//Try get default visuals
if (indexedPart.RsiPath is null)
continue;
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
var state = $"inhand-{args.Location.ToString().ToLowerInvariant()}";
if (wielded)
state = $"wielded-{state}";
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var key = $"{defaultKey}-{counterPart}-default";
args.Layers.Add((key, defaultLayer));
}
counterPart++;
}
}
private void OnGetEquipmentVisuals(Entity<CP14ModularCraftStartPointComponent> start,
ref GetEquipmentVisualsEvent args)
{
if (!TryComp(args.Equipee, out InventoryComponent? inventory))
return;
var defaultKey = $"cp14-modular-clothing-layer-{args.Slot}";
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
if (indexedPart.ClothingVisuals is not null && indexedPart.ClothingVisuals.TryGetValue(args.Slot, out var layers))
{
var i = 0;
foreach (var layer in layers)
{
var key = $"{defaultKey}-{counterPart}-{i}";
args.Layers.Add((key, layer));
i++;
}
}
else
{
//Try get default sprites
if (indexedPart.RsiPath is null)
continue;
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
if (!ClientClothingSystem.TemporarySlotMap.TryGetValue(args.Slot, out var correctedSlot))
continue;
var state = $"equipped-{correctedSlot}";
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var key = $"{defaultKey}-{counterPart}-default";
args.Layers.Add((key, defaultLayer));
}
}
}
}

View File

@@ -1,127 +0,0 @@
using Content.Shared._CP14.Roof;
using Content.Shared.Ghost;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Console;
using Robust.Shared.Map.Components;
namespace Content.Client._CP14.Roof;
public sealed class CP14RoofSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
private bool _roofVisible = true;
public bool DisabledByCommand = false;
private EntityQuery<GhostComponent> _ghostQuery;
private EntityQuery<TransformComponent> _xformQuery;
public bool RoofVisibility
{
get => _roofVisible && !DisabledByCommand;
set
{
_roofVisible = value;
UpdateRoofVisibilityAll();
}
}
public override void Initialize()
{
base.Initialize();
_ghostQuery = GetEntityQuery<GhostComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<CP14RoofComponent, ComponentStartup>(RoofStartup);
SubscribeLocalEvent<GhostComponent, CP14ToggleRoofVisibilityAction>(OnToggleRoof);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var player = _playerManager.LocalEntity;
if (_ghostQuery.HasComp(player))
return;
if (_xformQuery.TryComp(player, out var playerXform))
{
var grid = playerXform.GridUid;
if (grid == null || !TryComp<MapGridComponent>(grid, out var gridComp))
return;
var roofQuery = GetEntityQuery<CP14RoofComponent>();
var anchored = _map.GetAnchoredEntities(grid.Value, gridComp, playerXform.Coordinates);
var underRoof = false;
foreach (var ent in anchored)
{
if (!roofQuery.HasComp(ent))
continue;
underRoof = true;
}
if (underRoof && _roofVisible)
{
RoofVisibility = false;
}
if (!underRoof && !_roofVisible)
{
RoofVisibility = true;
}
}
}
private void OnToggleRoof(Entity<GhostComponent> ent, ref CP14ToggleRoofVisibilityAction args)
{
if (args.Handled)
return;
DisabledByCommand = !DisabledByCommand;
UpdateRoofVisibilityAll();
args.Handled = true;
}
private void RoofStartup(Entity<CP14RoofComponent> ent, ref ComponentStartup args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
UpdateVisibility(ent, sprite);
}
private void UpdateVisibility(Entity<CP14RoofComponent> ent, SpriteComponent sprite)
{
sprite.Visible = RoofVisibility;
}
public void UpdateRoofVisibilityAll()
{
var query = EntityQueryEnumerator<CP14RoofComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out var marker, out var sprite))
{
UpdateVisibility((uid, marker), sprite);
}
}
}
internal sealed class ShowRoof : LocalizedCommands
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
public override string Command => "cp14_toggleroof";
public override string Help => "Toggle roof visibility";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var roofSystem = _entitySystemManager.GetEntitySystem<CP14RoofSystem>();
roofSystem.DisabledByCommand = !roofSystem.DisabledByCommand;
roofSystem.UpdateRoofVisibilityAll();
}
}

View File

@@ -51,7 +51,7 @@ namespace Content.IntegrationTests.Tests
//CrystallEdge maps
"Village",
"Comoss",
"Island",
//CrystallEdge Map replacement end
};
@@ -197,7 +197,6 @@ namespace Content.IntegrationTests.Tests
targetGrid = gridEnt;
}
}
// Test shuttle can dock.
// This is done inside gamemap test because loading the map takes ages and we already have it.
var station = entManager.GetComponent<StationMemberComponent>(targetGrid!.Value).Station;

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>

View File

@@ -16,7 +16,6 @@ public sealed class GasProducerAnomalySystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
public override void Initialize()
{
@@ -57,11 +56,8 @@ public sealed class GasProducerAnomalySystem : EntitySystem
return;
var localpos = xform.Coordinates.Position;
var tilerefs = _map.GetLocalTilesIntersecting(
xform.GridUid.Value,
grid,
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius)))
.ToArray();
var tilerefs = grid.GetLocalTilesIntersecting(
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray();
if (tilerefs.Length == 0)
return;

View File

@@ -448,7 +448,6 @@ namespace Content.Server.Atmos.EntitySystems
if (flammable.FireStacks > 0)
{
/* CP14 Airtight walls should burn too!
var air = _atmosphereSystem.GetContainingMixture(uid);
// If we're in an oxygenless environment, put the fire out.
@@ -457,7 +456,7 @@ namespace Content.Server.Atmos.EntitySystems
Extinguish(uid, flammable);
continue;
}
*/
var source = EnsureComp<IgnitionSourceComponent>(uid);
_ignitionSourceSystem.SetIgnited((uid, source));

View File

@@ -102,12 +102,10 @@ public sealed class LogicGateSystem : EntitySystem
if (args.Port == comp.InputPortA)
{
comp.StateA = state;
_appearance.SetData(uid, LogicGateVisuals.InputA, state == SignalState.High); //If A == High => Sets input A sprite to True
}
else if (args.Port == comp.InputPortB)
{
comp.StateB = state;
_appearance.SetData(uid, LogicGateVisuals.InputB, state == SignalState.High); //If B == High => Sets input B sprite to True
}
UpdateOutput(uid, comp);
@@ -145,8 +143,6 @@ public sealed class LogicGateSystem : EntitySystem
break;
}
_appearance.SetData(uid, LogicGateVisuals.Output, output);
// only send a payload if it actually changed
if (output != comp.LastOutput)
{

View File

@@ -18,7 +18,7 @@ using JetBrains.Annotations;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Map.Events;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -66,42 +66,6 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
SubscribeLocalEvent<NetworkConfiguratorComponent, BoundUserInterfaceCheckRangeEvent>(OnUiRangeCheck);
SubscribeLocalEvent<DeviceListComponent, ComponentRemove>(OnComponentRemoved);
SubscribeLocalEvent<BeforeSaveEvent>(OnMapSave);
}
private void OnMapSave(BeforeSaveEvent ev)
{
var enumerator = AllEntityQuery<NetworkConfiguratorComponent>();
while (enumerator.MoveNext(out var uid, out var conf))
{
if (CompOrNull<TransformComponent>(conf.ActiveDeviceList)?.MapUid != ev.Map)
continue;
// The linked device list is (probably) being saved. Make sure that the configurator is also being saved
// (i.e., not in the hands of a mapper/ghost). In the future, map saving should raise a separate event
// containing a set of all entities that are about to be saved, which would make checking this much easier.
// This is a shitty bandaid, and will force close the UI during auto-saves.
// TODO Map serialization refactor
var xform = Transform(uid);
if (xform.MapUid == ev.Map && IsSaveable(uid))
continue;
_uiSystem.CloseUi(uid, NetworkConfiguratorUiKey.Configure);
DebugTools.AssertNull(conf.ActiveDeviceList);
}
bool IsSaveable(EntityUid uid)
{
while (uid.IsValid())
{
if (Prototype(uid)?.MapSavable == false)
return false;
uid = Transform(uid).ParentUid;
}
return true;
}
}
private void OnUiRangeCheck(Entity<NetworkConfiguratorComponent> ent, ref BoundUserInterfaceCheckRangeEvent args)
@@ -521,9 +485,6 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
if (!TryComp(targetUid, out DeviceListComponent? list))
return;
if (TryComp(configurator.ActiveDeviceList, out DeviceListComponent? oldList))
oldList.Configurators.Remove(configuratorUid);
list.Configurators.Add(configuratorUid);
configurator.ActiveDeviceList = targetUid;
Dirty(configuratorUid, configurator);
@@ -797,7 +758,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
{
if (query.TryGetComponent(device, out var comp))
{
component.Devices.Add(addr, device);
component.Devices[addr] = device;
comp.Configurators.Add(uid);
}
}

View File

@@ -28,7 +28,6 @@ public sealed partial class DragonSystem : EntitySystem
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
private EntityQuery<CarpRiftsConditionComponent> _objQuery;
@@ -157,7 +156,7 @@ public sealed partial class DragonSystem : EntitySystem
}
// cant put a rift on solars
foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false))
foreach (var tile in grid.GetTilesIntersecting(new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false))
{
if (!tile.IsSpace(_tileDef))
continue;

View File

@@ -121,7 +121,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
activated.TimeLeft -= frameTime;
if (activated.TimeLeft <= 0 || !IsPowered(uid, electrified, transform))
{
_appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, false);
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, false);
RemComp<ActivatedElectrifiedComponent>(uid);
}
}
@@ -217,7 +217,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
return false;
EnsureComp<ActivatedElectrifiedComponent>(uid);
_appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, true);
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, true);
siemens *= electrified.SiemensCoefficient;
if (!DoCommonElectrocutionAttempt(targetUid, uid, ref siemens) || siemens <= 0)
@@ -488,4 +488,15 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
}
_audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume));
}
public void SetElectrifiedWireCut(Entity<ElectrifiedComponent> ent, bool value)
{
if (ent.Comp.IsWireCut == value)
{
return;
}
ent.Comp.IsWireCut = value;
Dirty(ent);
}
}

View File

@@ -134,6 +134,13 @@ public sealed class DrainSystem : SharedDrainSystem
}
drain.Accumulator -= drain.DrainFrequency;
// Disable ambient sound from emptying manually
if (!drain.AutoDrain)
{
_ambientSoundSystem.SetAmbience(uid, false);
continue;
}
if (!managerQuery.TryGetComponent(uid, out var manager))
continue;
@@ -153,44 +160,41 @@ public sealed class DrainSystem : SharedDrainSystem
// This will ensure that UnitsPerSecond is per second...
var amount = drain.UnitsPerSecond * drain.DrainFrequency;
if (drain.AutoDrain)
{
_puddles.Clear();
_lookup.GetEntitiesInRange(Transform(uid).Coordinates, drain.Range, _puddles);
_puddles.Clear();
_lookup.GetEntitiesInRange(Transform(uid).Coordinates, drain.Range, _puddles);
if (_puddles.Count == 0)
if (_puddles.Count == 0)
{
_ambientSoundSystem.SetAmbience(uid, false);
continue;
}
_ambientSoundSystem.SetAmbience(uid, true);
amount /= _puddles.Count;
foreach (var puddle in _puddles)
{
// Queue the solution deletion if it's empty. EvaporationSystem might also do this
// but queuedelete should be pretty safe.
if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, puddle.Comp.SolutionName, ref puddle.Comp.Solution, out var puddleSolution))
{
_ambientSoundSystem.SetAmbience(uid, false);
EntityManager.QueueDeleteEntity(puddle);
continue;
}
_ambientSoundSystem.SetAmbience(uid, true);
// Removes the lowest of:
// the drain component's units per second adjusted for # of puddles
// the puddle's remaining volume (making it cleanly zero)
// the drain's remaining volume in its buffer.
var transferSolution = _solutionContainerSystem.SplitSolution(puddle.Comp.Solution.Value,
FixedPoint2.Min(FixedPoint2.New(amount), puddleSolution.Volume, drainSolution.AvailableVolume));
amount /= _puddles.Count;
drainSolution.AddSolution(transferSolution, _prototypeManager);
foreach (var puddle in _puddles)
if (puddleSolution.Volume <= 0)
{
// Queue the solution deletion if it's empty. EvaporationSystem might also do this
// but queuedelete should be pretty safe.
if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, puddle.Comp.SolutionName, ref puddle.Comp.Solution, out var puddleSolution))
{
EntityManager.QueueDeleteEntity(puddle);
continue;
}
// Removes the lowest of:
// the drain component's units per second adjusted for # of puddles
// the puddle's remaining volume (making it cleanly zero)
// the drain's remaining volume in its buffer.
var transferSolution = _solutionContainerSystem.SplitSolution(puddle.Comp.Solution.Value,
FixedPoint2.Min(FixedPoint2.New(amount), puddleSolution.Volume, drainSolution.AvailableVolume));
drainSolution.AddSolution(transferSolution, _prototypeManager);
if (puddleSolution.Volume <= 0)
{
QueueDel(puddle);
}
QueueDel(puddle);
}
}

View File

@@ -25,7 +25,7 @@ public sealed partial class PuddleSystem
var tileRef = _maps.GetTileRef(xform.GridUid.Value, mapGrid, xform.Coordinates);
var tileDef = (ContentTileDefinition) _tileDefManager[tileRef.Tile.TypeId];
entity.Comp.CP14ForceEvaporation = tileDef.SuckReagents;
entity.Comp.CP14ForceEvaporation = tileDef.Weather;
}
//CP14 End force evaporation under sky
}

View File

@@ -1,9 +1,7 @@
using Content.Server.Popups;
using Content.Shared.Administration;
using Content.Shared.GameTicking;
using Content.Shared.Mind;
using Robust.Shared.Console;
using Content.Server.GameTicking;
namespace Content.Server.Ghost
{
@@ -25,14 +23,6 @@ namespace Content.Server.Ghost
return;
}
var gameTicker = _entities.System<GameTicker>();
if (!gameTicker.PlayerGameStatuses.TryGetValue(player.UserId, out var playerStatus) ||
playerStatus is not PlayerGameStatus.JoinedGame)
{
shell.WriteLine("ghost-command-error-lobby");
return;
}
if (player.AttachedEntity is { Valid: true } frozen &&
_entities.HasComponent<AdminFrozenComponent>(frozen))
{

View File

@@ -1,5 +1,3 @@
using System.Linq;
using System.Numerics;
using Content.Server.Administration.Logs;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
@@ -34,13 +32,14 @@ using Robust.Shared.Physics.Systems;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using System.Linq;
using System.Numerics;
namespace Content.Server.Ghost
{
public sealed class GhostSystem : SharedGhostSystem
{
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly SharedEyeSystem _eye = default!;
[Dependency] private readonly FollowerSystem _followerSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
@@ -222,15 +221,10 @@ namespace Content.Server.Ghost
_actions.SetCooldown(component.BooActionEntity.Value, start, end);
}
//_actions.AddAction(uid, ref component.ToggleGhostHearingActionEntity, component.ToggleGhostHearingAction); //Dont need in CP14
_actions.AddAction(uid, ref component.ToggleGhostHearingActionEntity, component.ToggleGhostHearingAction);
_actions.AddAction(uid, ref component.ToggleLightingActionEntity, component.ToggleLightingAction);
_actions.AddAction(uid, ref component.ToggleFoVActionEntity, component.ToggleFoVAction);
_actions.AddAction(uid, ref component.ToggleGhostsActionEntity, component.ToggleGhostsAction);
//CP14
_actions.AddAction(uid, ref component.CP14ZLevelUpActionEntity, component.CP14ZLevelUpAction);
_actions.AddAction(uid, ref component.CP14ZLevelDownActionEntity, component.CP14ZLevelDownAction);
_actions.AddAction(uid, ref component.CP14ToggleRoofActionEntity, component.CP14ToggleRoofAction);
//CP14 end
}
private void OnGhostExamine(EntityUid uid, GhostComponent component, ExaminedEvent args)
@@ -336,8 +330,6 @@ namespace Content.Server.Ghost
private void WarpTo(EntityUid uid, EntityUid target)
{
_adminLog.Add(LogType.GhostWarp, $"{ToPrettyString(uid)} ghost warped to {ToPrettyString(target)}");
if ((TryComp(target, out WarpPointComponent? warp) && warp.Follow) || HasComp<MobStateComponent>(target))
{
_followerSystem.StartFollowingEntity(uid, target);

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Content.Server.Administration;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Ghost.Roles.Raffles;
@@ -77,13 +77,13 @@ namespace Content.Server.Ghost.Roles
if (isProto)
{
if (!_protoManager.TryIndex<GhostRoleRaffleSettingsPrototype>(args[3], out var proto))
if (!_protoManager.TryIndex<GhostRoleRaffleSettingsPrototype>(args[4], out var proto))
{
var validProtos = string.Join(", ",
_protoManager.EnumeratePrototypes<GhostRoleRaffleSettingsPrototype>().Select(p => p.ID)
);
shell.WriteLine($"{args[3]} is not a valid raffle settings prototype. Valid options: {validProtos}");
shell.WriteLine($"{args[4]} is not a valid raffle settings prototype. Valid options: {validProtos}");
return;
}

View File

@@ -92,19 +92,11 @@ public sealed class RandomGiftSystem : EntitySystem
var mapGridCompName = _componentFactory.GetComponentName(typeof(MapGridComponent));
var physicsCompName = _componentFactory.GetComponentName(typeof(PhysicsComponent));
if (!_prototype.TryIndex<EntityCategoryPrototype>("ForkFiltered", out var indexedFilter))
return;
foreach (var proto in _prototype.EnumeratePrototypes<EntityPrototype>())
{
if (proto.Abstract || proto.HideSpawnMenu || proto.Components.ContainsKey(mapGridCompName) || !proto.Components.ContainsKey(physicsCompName))
continue;
//CP14 Only cp14 items
if (!proto.Categories.Contains(indexedFilter))
continue;
//CP14 end
_possibleGiftsUnsafe.Add(proto.ID);
if (!proto.Components.ContainsKey(itemCompName))

View File

@@ -9,6 +9,7 @@ using Content.Shared.Light;
using Content.Shared.Light.Components;
using Content.Shared.Rounding;
using Content.Shared.Toggleable;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
@@ -45,6 +46,7 @@ namespace Content.Server.Light.EntitySystems
SubscribeLocalEvent<HandheldLightComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<HandheldLightComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<HandheldLightComponent, GetVerbsEvent<ActivationVerb>>(AddToggleLightVerb);
SubscribeLocalEvent<HandheldLightComponent, ActivateInWorldEvent>(OnActivate);
@@ -177,7 +179,25 @@ namespace Content.Server.Light.EntitySystems
}
}
public override bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
private void AddToggleLightVerb(Entity<HandheldLightComponent> ent, ref GetVerbsEvent<ActivationVerb> args)
{
if (!args.CanAccess || !args.CanInteract || !ent.Comp.ToggleOnInteract)
return;
var @event = args;
ActivationVerb verb = new()
{
Text = Loc.GetString("verb-common-toggle-light"),
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/light.svg.192dpi.png")),
Act = ent.Comp.Activated
? () => TurnOff(ent)
: () => TurnOn(@event.User, ent)
};
args.Verbs.Add(verb);
}
public bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
{
if (!ent.Comp.Activated || !_lights.TryGetLight(ent, out var pointLightComponent))
{
@@ -191,7 +211,7 @@ namespace Content.Server.Light.EntitySystems
return true;
}
public override bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
public bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
{
var component = uid.Comp;
if (component.Activated || !_lights.TryGetLight(uid, out var pointLightComponent))

View File

@@ -40,7 +40,6 @@ public sealed class NukeSystem : EntitySystem
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
@@ -191,7 +190,7 @@ public sealed class NukeSystem : EntitySystem
var worldPos = _transform.GetWorldPosition(xform);
foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(worldPos, component.RequiredFloorRadius), false))
foreach (var tile in grid.GetTilesIntersecting(new Circle(worldPos, component.RequiredFloorRadius), false))
{
if (!tile.IsSpace(_tileDefManager))
continue;

View File

@@ -18,11 +18,8 @@ public sealed partial class CableComponent : Component
[DataField]
public EntProtoId CableDroppedOnCutPrototype = "CableHVStack1";
/// <summary>
/// The tool quality needed to cut the cable. Setting to null prevents cutting.
/// </summary>
[DataField]
public ProtoId<ToolQualityPrototype>? CuttingQuality = SharedToolSystem.CutQuality;
public ProtoId<ToolQualityPrototype> CuttingQuality = SharedToolSystem.CutQuality;
/// <summary>
/// Checked by <see cref="CablePlacerComponent"/> to determine if there is

View File

@@ -35,7 +35,7 @@ public sealed partial class CableSystem
var snapPos = grid.TileIndicesFor(args.ClickLocation);
var tileDef = (ContentTileDefinition) _tileManager[_map.GetTileRef(gridUid, grid,snapPos).Tile.TypeId];
if (!tileDef.IsSubFloor || !tileDef.Sturdy)
if ((!tileDef.IsSubFloor || !tileDef.Sturdy) && placer.Comp.CP14OnlySubfloor) //CP14 if only subfloor
return;
foreach (var anchored in grid.GetAnchoredEntities(snapPos))

View File

@@ -35,10 +35,7 @@ public sealed partial class CableSystem : EntitySystem
if (args.Handled)
return;
if (cable.CuttingQuality != null)
{
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent());
}
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent());
}
private void OnCableCut(EntityUid uid, CableComponent cable, DoAfterEvent args)

View File

@@ -17,7 +17,7 @@ public sealed partial class PowerWireAction : BaseWireAction
[DataField("pulseTimeout")]
private int _pulseTimeout = 30;
private ElectrocutionSystem _electrocution = default!;
private ElectrocutionSystem _electrocutionSystem = default!;
public override object StatusKey { get; } = PowerWireActionKey.Status;
@@ -105,8 +105,8 @@ public sealed partial class PowerWireAction : BaseWireAction
&& !EntityManager.TryGetComponent(used, out electrified))
return;
_electrocution.SetElectrifiedWireCut((used, electrified), setting);
_electrocution.SetElectrified((used, electrified), setting);
_electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting);
electrified.Enabled = setting;
}
/// <returns>false if failed, true otherwise, or if the entity cannot be electrified</returns>
@@ -120,7 +120,7 @@ public sealed partial class PowerWireAction : BaseWireAction
// always set this to true
SetElectrified(wire.Owner, true, electrified);
var electrifiedAttempt = _electrocution.TryDoElectrifiedAct(wire.Owner, user);
var electrifiedAttempt = _electrocutionSystem.TryDoElectrifiedAct(wire.Owner, user);
// if we were electrified, then return false
return !electrifiedAttempt;
@@ -161,7 +161,7 @@ public sealed partial class PowerWireAction : BaseWireAction
{
base.Initialize();
_electrocution = EntityManager.System<ElectrocutionSystem>();
_electrocutionSystem = EntityManager.System<ElectrocutionSystem>();
}
// This should add a wire into the entity's state, whether it be

View File

@@ -58,7 +58,7 @@ public sealed partial class DungeonJob
}
}
if (biomeSystem.TryGetEntity(node, indexedBiome.Layers, tile ?? tileRef.Value.Tile, seed, _grid, out var entityProto))
if (tile is not null && biomeSystem.TryGetEntity(node, indexedBiome.Layers, tile.Value, seed, _grid, out var entityProto))
{
var ent = _entManager.SpawnEntity(entityProto, new EntityCoordinates(_gridUid, node + _grid.TileSizeHalfVector));
var xform = xformQuery.Get(ent);

View File

@@ -20,11 +20,7 @@ public sealed partial class DungeonJob
}
var tileDef = _prototype.Index(tileProto);
if (!data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto))
{
// caves can have no walls
return;
}
data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto);
var checkedTiles = new HashSet<Vector2i>();
var allExterior = new HashSet<Vector2i>(dungeon.CorridorExteriorTiles);

View File

@@ -45,6 +45,7 @@ public sealed class ProjectileSystem : SharedProjectileSystem
RaiseLocalEvent(uid, ref ev);
var otherName = ToPrettyString(target);
var direction = args.OurBody.LinearVelocity.Normalized();
var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances, origin: component.Shooter);
var deleted = Deleted(target);
@@ -63,9 +64,7 @@ public sealed class ProjectileSystem : SharedProjectileSystem
if (!deleted)
{
_guns.PlayImpactSound(target, modifiedDamage, component.SoundHit, component.ForceSound);
if (!args.OurBody.LinearVelocity.IsLengthZero())
_sharedCameraRecoil.KickCamera(target, args.OurBody.LinearVelocity.Normalized());
_sharedCameraRecoil.KickCamera(target, direction);
}
component.DamagedEntity = true;

View File

@@ -21,7 +21,6 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly TurfSystem _turf = default!;
[Dependency] private readonly IChatManager _chat = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
@@ -106,7 +105,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
var found = false;
foreach (var tile in _map.GetTilesIntersecting(entityGridUid.Value, grid, circle))
foreach (var tile in grid.GetTilesIntersecting(circle))
{
if (tile.IsSpace(_tileDefinitionManager)
|| _turf.IsTileBlocked(tile, CollisionGroup.MobMask)
@@ -177,7 +176,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
var mapTarget = grid.WorldToTile(mapPos);
var circle = new Circle(mapPos, 2);
foreach (var newTileRef in _map.GetTilesIntersecting(targetGrid, grid, circle))
foreach (var newTileRef in grid.GetTilesIntersecting(circle))
{
if (newTileRef.IsSpace(_tileDefinitionManager) || _turf.IsTileBlocked(newTileRef, CollisionGroup.MobMask) || !_atmosphere.IsTileMixtureProbablySafe(targetGrid, targetMap, mapTarget))
continue;

View File

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

View File

@@ -193,7 +193,7 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
List<Vector2i> reservedTiles = new();
foreach (var tile in _map.GetTilesIntersecting(mapUid, grid, new Circle(Vector2.Zero, landingPadRadius), false))
foreach (var tile in grid.GetTilesIntersecting(new Circle(Vector2.Zero, landingPadRadius), false))
{
if (!_biome.TryGetBiomeTile(mapUid, grid, tile.GridIndices, out _))
continue;

View File

@@ -253,6 +253,12 @@ public sealed partial class ShuttleSystem
if (TryComp<PhysicsComponent>(shuttleUid, out var shuttlePhysics))
{
// Static physics type is set when station anchor is enabled
if (shuttlePhysics.BodyType == BodyType.Static)
{
reason = Loc.GetString("shuttle-console-static");
return false;
}
// Too large to FTL
if (FTLMassLimit > 0 && shuttlePhysics.Mass > FTLMassLimit)
@@ -1021,7 +1027,6 @@ public sealed partial class ShuttleSystem
continue;
}
// If it has the FTLSmashImmuneComponent ignore it.
if (_immuneQuery.HasComponent(ent))
{
continue;

View File

@@ -1,37 +0,0 @@
using Content.Shared.Silicons.Laws.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
namespace Content.Server.Silicons.Laws;
/// <summary>
/// This handles running the ion storm event a on specific entity when that entity is spawned in.
/// </summary>
public sealed class StartIonStormedSystem : EntitySystem
{
[Dependency] private readonly IonStormSystem _ionStorm = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly SiliconLawSystem _siliconLaw = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<StartIonStormedComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<StartIonStormedComponent> ent, ref MapInitEvent args)
{
if (!TryComp<SiliconLawBoundComponent>(ent.Owner, out var lawBound))
return;
if (!TryComp<IonStormTargetComponent>(ent.Owner, out var target))
return;
for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++)
{
_ionStorm.IonStormTarget((ent.Owner, lawBound, target), false);
}
var laws = _siliconLaw.GetLaws(ent.Owner, lawBound);
_adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent.Owner):silicon} spawned with ion stormed laws: {laws.LoggingString()}");
}
}

View File

@@ -308,7 +308,7 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
foreach (var grid in grids)
{
// TODO: Remover grid.Owner when this iterator returns entityuids as well.
AttemptConsumeTiles(uid, _mapSystem.GetTilesIntersecting(grid.Owner, grid.Comp, circle), grid, grid, eventHorizon);
AttemptConsumeTiles(uid, grid.Comp.GetTilesIntersecting(circle), grid, grid, eventHorizon);
}
}

View File

@@ -1,38 +0,0 @@
using Content.Server.StationEvents.Events;
using Content.Shared.Access;
using Content.Shared.Destructible.Thresholds;
using Robust.Shared.Prototypes;
namespace Content.Server.StationEvents.Components;
/// <summary>
/// Greytide Virus event specific configuration
/// </summary>
[RegisterComponent, Access(typeof(GreytideVirusRule))]
public sealed partial class GreytideVirusRuleComponent : Component
{
/// <summary>
/// Range from which the severity is randomly picked from.
/// </summary>
[DataField]
public MinMax SeverityRange = new(1, 3);
/// <summary>
/// Severity corresponding to the number of access groups affected.
/// Will pick randomly from the SeverityRange if not specified.
/// </summary>
[DataField]
public int? Severity;
/// <summary>
/// Access groups to pick from.
/// </summary>
[DataField]
public List<ProtoId<AccessGroupPrototype>> AccessGroups = new();
/// <summary>
/// Entities with this access level will be ignored.
/// </summary>
[DataField]
public List<ProtoId<AccessLevelPrototype>> Blacklist = new();
}

View File

@@ -148,20 +148,20 @@ public sealed class EventManagerSystem : EntitySystem
return null;
}
var sumOfWeights = 0.0f;
var sumOfWeights = 0;
foreach (var stationEvent in availableEvents.Values)
{
sumOfWeights += stationEvent.Weight;
sumOfWeights += (int) stationEvent.Weight;
}
sumOfWeights = _random.NextFloat(sumOfWeights);
sumOfWeights = _random.Next(sumOfWeights);
foreach (var (proto, stationEvent) in availableEvents)
{
sumOfWeights -= stationEvent.Weight;
sumOfWeights -= (int) stationEvent.Weight;
if (sumOfWeights <= 0.0f)
if (sumOfWeights <= 0)
{
return proto.ID;
}

View File

@@ -1,96 +0,0 @@
using Content.Server.StationEvents.Components;
using Content.Shared.Access;
using Content.Shared.Access.Systems;
using Content.Shared.Access.Components;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Content.Shared.Lock;
using Content.Shared.GameTicking.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.StationEvents.Events;
/// <summary>
/// Greytide Virus event
/// This will open and bolt airlocks and unlock lockers from randomly selected access groups.
/// </summary>
public sealed class GreytideVirusRule : StationEventSystem<GreytideVirusRuleComponent>
{
[Dependency] private readonly AccessReaderSystem _access = default!;
[Dependency] private readonly SharedDoorSystem _door = default!;
[Dependency] private readonly LockSystem _lock = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IRobustRandom _random = default!;
protected override void Added(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleAddedEvent args)
{
if (!TryComp<StationEventComponent>(uid, out var stationEvent))
return;
// pick severity randomly from range if not specified otherwise
virusComp.Severity ??= virusComp.SeverityRange.Next(_random);
virusComp.Severity = Math.Min(virusComp.Severity.Value, virusComp.AccessGroups.Count);
stationEvent.StartAnnouncement = Loc.GetString("station-event-greytide-virus-start-announcement", ("severity", virusComp.Severity.Value));
base.Added(uid, virusComp, gameRule, args);
}
protected override void Started(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, virusComp, gameRule, args);
if (virusComp.Severity == null)
return;
// pick random access groups
var chosen = _random.GetItems(virusComp.AccessGroups, virusComp.Severity.Value, allowDuplicates: false);
// combine all the selected access groups
var accessIds = new HashSet<ProtoId<AccessLevelPrototype>>();
foreach (var group in chosen)
{
if (_prototype.TryIndex(group, out var proto))
accessIds.UnionWith(proto.Tags);
}
var firelockQuery = GetEntityQuery<FirelockComponent>();
var accessQuery = GetEntityQuery<AccessReaderComponent>();
var lockQuery = AllEntityQuery<LockComponent>();
while (lockQuery.MoveNext(out var lockUid, out var lockComp))
{
if (!accessQuery.TryComp(lockUid, out var accessComp))
continue;
// check access
// the AreAccessTagsAllowed function is a little weird because it technically has support for certain tags to be locked out of opening something
// which might have unintened side effects (see the comments in the function itself)
// but no one uses that yet, so it is fine for now
if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp))
continue;
// open lockers
_lock.Unlock(lockUid, null, lockComp);
}
var airlockQuery = AllEntityQuery<AirlockComponent, DoorComponent>();
while (airlockQuery.MoveNext(out var airlockUid, out var airlockComp, out var doorComp))
{
// don't space everything
if (firelockQuery.HasComp(airlockUid))
continue;
// use the access reader from the door electronics if they exist
if (!_access.GetMainAccessReader(airlockUid, out var accessComp))
continue;
// check access
if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp))
continue;
// open and bolt airlocks
_door.TryOpenAndBolt(airlockUid, doorComp, airlockComp);
}
}
}

View File

@@ -38,7 +38,6 @@ namespace Content.Server.VendingMachines
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SpeakOnUIClosedSystem _speakOnUIClosed = default!;
[Dependency] private readonly SharedPointLightSystem _light = default!;
private const float WallVendEjectDistanceFromWall = 1f;
@@ -335,12 +334,6 @@ namespace Content.Server.VendingMachines
finalState = VendingMachineVisualState.Off;
}
if (_light.TryGetLight(uid, out var pointlight))
{
var lightState = finalState != VendingMachineVisualState.Broken && finalState != VendingMachineVisualState.Off;
_light.SetEnabled(uid, lightState, pointlight);
}
_appearanceSystem.SetData(uid, VendingMachineVisuals.VisualState, finalState);
}

View File

@@ -22,14 +22,13 @@ public abstract partial class ComponentWireAction<TComponent> : BaseWireAction w
public override bool Cut(EntityUid user, Wire wire)
{
base.Cut(user, wire);
// if the entity doesn't exist, we need to return true otherwise the wire sprite is never updated
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Cut(user, wire, component) : true;
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Cut(user, wire, component);
}
public override bool Mend(EntityUid user, Wire wire)
{
base.Mend(user, wire);
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Mend(user, wire, component) : true;
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Mend(user, wire, component);
}
public override void Pulse(EntityUid user, Wire wire)

View File

@@ -4,6 +4,7 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Throwing;
using Robust.Server.GameObjects;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Random;
@@ -16,8 +17,7 @@ public sealed class ThrowArtifactSystem : EntitySystem
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -30,9 +30,7 @@ public sealed class ThrowArtifactSystem : EntitySystem
var xform = Transform(uid);
if (TryComp<MapGridComponent>(xform.GridUid, out var grid))
{
var tiles = _mapSystem.GetTilesIntersecting(
xform.GridUid.Value,
grid,
var tiles = grid.GetTilesIntersecting(
Box2.CenteredAround(_transform.GetWorldPosition(xform), new Vector2(component.Range * 2, component.Range)));
foreach (var tile in tiles)

View File

@@ -2,6 +2,7 @@ using System.Numerics;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
using Content.Shared._CP14.Cargo;
using Content.Shared._CP14.Cargo.Prototype;
using Robust.Shared.Map;
using Robust.Shared.Random;
@@ -9,8 +10,10 @@ namespace Content.Server._CP14.Cargo;
public sealed partial class CP14CargoSystem
{
private EntityQuery<ArrivalsBlacklistComponent> _blacklistQuery;
private void InitializeShuttle()
{
_blacklistQuery = GetEntityQuery<ArrivalsBlacklistComponent>();
SubscribeLocalEvent<CP14TravelingStoreShipComponent, FTLCompletedEvent>(OnFTLCompleted);
}
@@ -43,14 +46,11 @@ public sealed partial class CP14CargoSystem
private void SendShuttleToStation(EntityUid shuttle, float startupTime = 0f)
{
var targetPoints = new List<EntityUid>();
var targetEnumerator =
EntityQueryEnumerator<CP14TravelingStoreShipFTLTargetComponent,
TransformComponent>(); //TODO - different method position location
var targetEnumerator = EntityQueryEnumerator<CP14TravelingStoreShipFTLTargetComponent, TransformComponent>(); //TODO - different method position location
while (targetEnumerator.MoveNext(out var uid, out _, out _))
{
targetPoints.Add(uid);
}
if (targetPoints.Count == 0)
return;
@@ -59,23 +59,14 @@ public sealed partial class CP14CargoSystem
var shuttleComp = Comp<ShuttleComponent>(shuttle);
_shuttles.FTLToCoordinates(shuttle,
shuttleComp,
targetXform.Coordinates,
targetXform.LocalRotation,
hyperspaceTime: 20f,
startupTime: startupTime);
_shuttles.FTLToCoordinates(shuttle, shuttleComp, targetXform.Coordinates, targetXform.LocalRotation, hyperspaceTime: 5f, startupTime: startupTime);
}
private void SendShuttleToTradepost(EntityUid shuttle, EntityUid tradePostMap)
{
var shuttleComp = Comp<ShuttleComponent>(shuttle);
_shuttles.FTLToCoordinates(shuttle,
shuttleComp,
new EntityCoordinates(tradePostMap, Vector2.Zero),
Angle.Zero,
hyperspaceTime: 20f);
_shuttles.FTLToCoordinates(shuttle, shuttleComp, new EntityCoordinates(tradePostMap, Vector2.Zero), Angle.Zero, hyperspaceTime: 5f);
}
private void OnFTLCompleted(Entity<CP14TravelingStoreShipComponent> ent, ref FTLCompletedEvent args)
@@ -83,24 +74,24 @@ public sealed partial class CP14CargoSystem
if (!TryComp<CP14StationTravelingStoreShipTargetComponent>(ent.Comp.Station, out var station))
return;
if (station.TradePostMap is not null &&
Transform(ent).MapUid == Transform(station.TradePostMap.Value).MapUid) //Landed on tradepost
if (station.TradePostMap is not null && Transform(ent).MapUid == Transform(station.TradePostMap.Value).MapUid) //Landed on tradepost
{
station.OnStation = false;
var b = station.Balance;
SellingThings((ent.Comp.Station, station)); // +balance
TopUpBalance((ent.Comp.Station, station)); //+balance
BuyToQueue((ent.Comp.Station, station)); //-balance +buyQueue
TrySpawnBuyedThings((ent.Comp.Station, station));
UpdateStorePositions((ent.Comp.Station, station));
}
else //Landed on station
else //Landed on station
{
station.OnStation = true;
CashOut((ent.Comp.Station, station));
}
UpdateAllStores();
}
}

View File

@@ -1,5 +1,4 @@
using Content.Server._CP14.Currency;
using Content.Server._CP14.RoundRemoveShuttle;
using Content.Server.Shuttles.Systems;
using Content.Server.Station.Events;
using Content.Server.Station.Systems;
@@ -9,10 +8,8 @@ using Content.Shared._CP14.Cargo.Prototype;
using Content.Shared.Maps;
using Content.Shared.Paper;
using Content.Shared.Physics;
using Content.Shared.Station.Components;
using Content.Shared.Storage;
using Content.Shared.Storage.EntitySystems;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
@@ -72,18 +69,6 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
UpdateShuttle();
}
/// <summary>
/// Allows other systems to additionally add items to the queue that are brought to the settlement on a merchant ship.
/// </summary>
[PublicAPI]
public void AddBuyQueue(Entity<CP14StationTravelingStoreShipTargetComponent> station, List<EntProtoId> products)
{
foreach (var product in products)
{
station.Comp.BuyedQueue.Enqueue(product);
}
}
private void OnPostInit(Entity<CP14StationTravelingStoreShipTargetComponent> station, ref StationPostInitEvent args)
{
if (!Deleted(station.Comp.Shuttle))
@@ -100,51 +85,28 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
var travelingStoreShipComp = EnsureComp<CP14TravelingStoreShipComponent>(station.Comp.Shuttle.Value);
travelingStoreShipComp.Station = station;
var member = EnsureComp<StationMemberComponent>(shuttle);
member.Station = station;
var roundRemover = EnsureComp<CP14RoundRemoveShuttleComponent>(shuttle);
roundRemover.Station = station;
station.Comp.NextTravelTime = _timing.CurTime + TimeSpan.FromSeconds(10f);
AddRoundstartTradingPositions(station);
UpdateStorePositions(station);
}
private void AddRoundstartTradingPositions(Entity<CP14StationTravelingStoreShipTargetComponent> station)
{
if (_buyProto is not null)
{
foreach (var buy in _buyProto)
{
if (buy.RoundstartAvailable)
station.Comp.AvailableBuyPosition.Add(buy);
}
}
if (_sellProto is not null)
{
foreach (var sell in _sellProto)
{
if (sell.RoundstartAvailable)
station.Comp.AvailableSellPosition.Add(sell);
}
}
}
private void UpdateStorePositions(Entity<CP14StationTravelingStoreShipTargetComponent> station)
{
station.Comp.CurrentBuyPositions.Clear();
station.Comp.CurrentSellPositions.Clear();
foreach (var buyPos in station.Comp.AvailableBuyPosition)
if (_buyProto is not null)
{
station.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price.Next(_random)/10*10);
foreach (var buyPos in _buyProto)
{
station.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price.Next(_random)/10*10);
}
}
foreach (var sellPos in station.Comp.AvailableSellPosition)
if (_sellProto is not null)
{
station.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price.Next(_random)/10*10);
foreach (var sellPos in _sellProto)
{
station.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price.Next(_random)/10*10);
}
}
}
@@ -260,7 +222,7 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
foreach (var service in indexedBuyed.Services)
{
service.Buy(EntityManager, _proto, station);
service.Buy(EntityManager, station);
}
}
}
@@ -301,10 +263,44 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
{
var coord = Transform(moneyBox.Value).Coordinates;
var coins = _currency.GenerateMoney(station.Comp.Balance, coord);
foreach (var coin in coins)
if (station.Comp.Balance > 0)
{
_storage.Insert(moneyBox.Value, coin, out _);
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.PP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
if (station.Comp.Balance > 0)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.GP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
if (station.Comp.Balance > 0)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.SP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
if (station.Comp.Balance > 0)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.CP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
}
}

View File

@@ -1,6 +1,6 @@
namespace Content.Server._CP14.Cargo;
[RegisterComponent, Access(typeof(CP14CargoSystem))]
[RegisterComponent, Access(typeof(CP14CargoSystem)), AutoGenerateComponentPause]
public sealed partial class CP14TravelingStoreShipComponent : Component
{
[DataField]

View File

@@ -154,56 +154,6 @@ public sealed partial class CP14CurrencySystem
return spawns;
}
public HashSet<EntityUid> GenerateMoney(
int target,
EntityCoordinates coordinates)
{
HashSet<EntityUid> coins = new();
var balance = target;
//PP
if (balance > 0)
{
var ppCoin = GenerateMoney(PP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var pp in ppCoin)
{
coins.Add(pp);
}
}
//GP
if (balance > 0)
{
var gpCoin = GenerateMoney(GP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var gp in gpCoin)
{
coins.Add(gp);
}
}
//SP
if (balance > 0)
{
var spCoin = GenerateMoney(SP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var sp in spCoin)
{
coins.Add(sp);
}
}
//CP
if (balance > 0)
{
var cpCoin = GenerateMoney(CP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var cp in cpCoin)
{
coins.Add(cp);
}
}
return coins;
}
private bool ProcessEntity(EntityUid ent, ref int remainder, HashSet<EntityUid> spawns)
{
var singleCurrency = GetTotalCurrency(ent);

View File

@@ -1,22 +0,0 @@
using Content.Shared.Damage;
namespace Content.Server._CP14.DPSMeter;
[RegisterComponent]
public sealed partial class CP14DPSMeterComponent : Component
{
[DataField]
public DamageSpecifier TotalDamage = new DamageSpecifier();
[DataField]
public TimeSpan LastHitTime = TimeSpan.Zero;
[DataField]
public TimeSpan StartTrackTime = TimeSpan.Zero;
[DataField]
public TimeSpan EndTrackTime = TimeSpan.Zero;
[DataField]
public TimeSpan TrackTimeAfterHit = TimeSpan.FromSeconds(5f);
}

View File

@@ -1,62 +0,0 @@
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.Popups;
using Robust.Shared.Timing;
namespace Content.Server._CP14.DPSMeter;
public sealed class CP14DPSMeterSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14DPSMeterComponent, DamageChangedEvent>(OnDamageChanged);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<CP14DPSMeterComponent>();
while (query.MoveNext(out var uid, out var meter))
{
if (_timing.CurTime < meter.EndTrackTime || meter.EndTrackTime == TimeSpan.Zero)
continue;
//Clear tracking
_popup.PopupEntity($"TOTAL DPS: {GetDPS((uid, meter))}", uid, PopupType.Large);
meter.TotalDamage = new DamageSpecifier();
meter.EndTrackTime = TimeSpan.Zero;
meter.StartTrackTime = TimeSpan.Zero;
}
}
private void OnDamageChanged(Entity<CP14DPSMeterComponent> ent, ref DamageChangedEvent args)
{
if (args.DamageDelta is null)
return;
ent.Comp.TotalDamage += args.DamageDelta;
if (ent.Comp.StartTrackTime == TimeSpan.Zero)
ent.Comp.StartTrackTime = _timing.CurTime;
ent.Comp.LastHitTime = _timing.CurTime;
ent.Comp.EndTrackTime = _timing.CurTime + ent.Comp.TrackTimeAfterHit;
_popup.PopupEntity($"DPS: {GetDPS(ent)}", ent);
}
private FixedPoint2 GetDPS(Entity<CP14DPSMeterComponent> ent)
{
var totalDamage = ent.Comp.TotalDamage.GetTotal();
var totalSeconds = (ent.Comp.LastHitTime - ent.Comp.StartTrackTime).TotalSeconds;
var DPS = totalDamage / Math.Max(totalSeconds, 1f);
return DPS;
}
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Administration;
using Content.Shared._CP14.DayCycle;
using Content.Shared.Administration;
using Robust.Shared.Console;
using CP14DayCycleComponent = Content.Shared._CP14.DayCycle.Components.CP14DayCycleComponent;

View File

@@ -26,7 +26,6 @@ public sealed partial class CP14DemiplaneSystem
private const double JobMaxTime = 0.002;
[Dependency] private readonly ExamineSystemShared _examine = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
private void InitGeneration()
{
@@ -63,7 +62,7 @@ public sealed partial class CP14DemiplaneSystem
: Loc.GetString("cp14-demiplane-examine-title-unknown"));
List<LocId> modifierNames = new();
foreach (var modifier in comp.SelectedModifiers)
foreach (var modifier in comp.Modifiers)
{
if (!_proto.TryIndex(modifier, out var indexedModifier))
continue;
@@ -142,23 +141,6 @@ public sealed partial class CP14DemiplaneSystem
if (generator.Comp.Location is null)
return;
var curTime = _timing.CurTime;
if (curTime < generator.Comp.LastUseTime + generator.Comp.UseDelay)
return;
generator.Comp.LastUseTime = curTime;
if (generator.Comp.NeedDemiplaneCrystal)
{
var demiplaneCrystals = _lookup.GetEntitiesInRange<CP14DemiplaneCrystalComponent>(Transform(generator).Coordinates, generator.Comp.DemiplaneCrystalRange);
if (demiplaneCrystals.Count == 0)
{
return;
}
}
//We cant open demiplan in another demiplan or if parent is not Map
if (HasComp<CP14DemiplaneComponent>(Transform(generator).MapUid) || !HasComp<MapGridComponent>(_transform.GetParentUid(args.User)))
{
@@ -166,7 +148,7 @@ public sealed partial class CP14DemiplaneSystem
return;
}
SpawnRandomDemiplane(generator.Comp.Location.Value, generator.Comp.SelectedModifiers, out var demiplane, out var mapId);
SpawnRandomDemiplane(generator.Comp.Location.Value, generator.Comp.Modifiers, out var demiplane, out var mapId);
//Admin log needed
//TEST
@@ -196,36 +178,14 @@ public sealed partial class CP14DemiplaneSystem
suitableConfigs.Add(locationConfig);
}
CP14DemiplaneLocationPrototype? selectedConfig = null;
while (suitableConfigs.Count > 0)
if (suitableConfigs.Count == 0)
{
var randomConfig = _random.Pick(suitableConfigs);
if (!generator.Comp.TiersContent.ContainsKey(randomConfig.Tier))
{
suitableConfigs.Remove(randomConfig);
continue;
}
if (!_random.Prob(generator.Comp.TiersContent[randomConfig.Tier]))
{
suitableConfigs.Remove(randomConfig);
continue;
}
selectedConfig = randomConfig;
break;
}
if (selectedConfig is null)
{
// We dont should be here
Log.Warning("Expedition mission generation failed: No suitable location configs.");
Log.Error("Expedition mission generation failed: No suitable location configs.");
QueueDel(generator);
return;
}
var selectedConfig = _random.Pick(suitableConfigs);
generator.Comp.Location = selectedConfig;
//Modifier generation
@@ -244,100 +204,42 @@ public sealed partial class CP14DemiplaneSystem
}
//Tag required filter
if (passed)
foreach (var reqTag in modifier.RequiredTags)
{
foreach (var reqTag in modifier.RequiredTags)
{
if (!selectedConfig.Tags.Contains(reqTag))
{
passed = false;
break;
}
}
}
//Tier filter
if (passed)
{
foreach (var tier in modifier.Tiers)
{
if (!generator.Comp.TiersContent.ContainsKey(tier))
{
passed = false;
break;
}
}
}
// Tier weight filter
if (passed)
{
var maxProb = 0f;
foreach (var tier in modifier.Tiers)
{
maxProb = Math.Max(maxProb, generator.Comp.TiersContent[tier]);
}
if (!_random.Prob(maxProb))
if (!selectedConfig.Tags.Contains(reqTag))
{
passed = false;
break;
}
}
//Random prob filter
if (passed)
{
if (!_random.Prob(modifier.GenerationProb))
{
passed = false;
}
}
if (passed)
suitableModifiersWeights.Add(modifier, modifier.GenerationWeight);
}
}
//Limits calculation
Dictionary<ProtoId<CP14DemiplaneModifierCategoryPrototype>, float> limits = new();
foreach (var limit in generator.Comp.Limits)
{
limits.Add(limit.Key, limit.Value);
}
while (suitableModifiersWeights.Count > 0)
var difficulty = 0f;
var reward = 0f;
while (generator.Comp.Modifiers.Count < generator.Comp.MaxModifiers && suitableModifiersWeights.Count > 0)
{
var selectedModifier = ModifierPick(suitableModifiersWeights, _random);
//Fill demiplane under limits
var passed = true;
foreach (var category in selectedModifier.Categories)
if (difficulty + selectedModifier.Difficulty > generator.Comp.DifficultyLimit)
{
if (!limits.ContainsKey(category.Key))
{
suitableModifiersWeights.Remove(selectedModifier);
passed = false;
break;
}
if (limits[category.Key] - category.Value < 0)
{
suitableModifiersWeights.Remove(selectedModifier);
passed = false;
break;
}
}
if (!passed)
suitableModifiersWeights.Remove(selectedModifier);
continue;
generator.Comp.SelectedModifiers.Add(selectedModifier);
foreach (var category in selectedModifier.Categories)
{
limits[category.Key] -= category.Value;
}
if (reward + selectedModifier.Reward > generator.Comp.RewardLimit)
{
suitableModifiersWeights.Remove(selectedModifier);
continue;
}
generator.Comp.Modifiers.Add(selectedModifier);
reward += selectedModifier.Reward;
difficulty += selectedModifier.Difficulty;
if (selectedModifier.Unique)
suitableModifiersWeights.Remove(selectedModifier);
}
@@ -372,4 +274,5 @@ public sealed partial class CP14DemiplaneSystem
// Shouldn't happen
throw new InvalidOperationException($"Invalid weighted pick in CP14DemiplanSystem.Generation!");
}
}

View File

@@ -1,4 +1,3 @@
using Content.Server.Body.Systems;
using Content.Shared._CP14.Demiplane.Components;
using Content.Shared.Mobs.Systems;
@@ -10,7 +9,6 @@ public sealed partial class CP14DemiplaneSystem
private TimeSpan _nextCheckTime = TimeSpan.Zero;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly BodySystem _body = default!;
private void InitStabilization()
{
@@ -51,26 +49,13 @@ public sealed partial class CP14DemiplaneSystem
}
var query2 = EntityQueryEnumerator<CP14DemiplaneComponent, CP14DemiplaneDestroyWithoutStabilizationComponent>();
while (query2.MoveNext(out var uid, out var demiplane, out var stabilization))
while (query2.MoveNext(out var uid, out var demiplan, out var stabilization))
{
if (_timing.CurTime < stabilization.EndProtectionTime)
continue;
if (!stabilizedMaps.Contains(uid))
DeleteDemiplane((uid, demiplane));
QueueDel(uid);
}
}
private void DeleteDemiplane(Entity<CP14DemiplaneComponent> demiplane)
{
var query = EntityQueryEnumerator<CP14DemiplaneStabilizerComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var stabilizer, out var xform))
{
if (TryTeleportOutDemiplane(demiplane, uid))
_body.GibBody(uid);
}
QueueDel(demiplane);
}
}

View File

@@ -44,7 +44,6 @@ public sealed partial class CP14DemiplaneSystem : CP14SharedDemiplaneSystem
UpdateGeneration(frameTime);
UpdateStabilization(frameTime);
}
/// <summary>
/// Teleports the entity inside the demiplane, to one of the random entry points.
/// </summary>

View File

@@ -1,6 +0,0 @@
namespace Content.Server._CP14.Demiplane.Components;
[RegisterComponent, Access(typeof(CP14DemiplaneSystem))]
public sealed partial class CP14DemiplaneCrystalComponent : Component
{
}

View File

@@ -1,3 +1,4 @@
using Content.Shared._CP14.Demiplane.Components;
using Content.Shared._CP14.Demiplane.Prototypes;
using Robust.Shared.Prototypes;
@@ -13,26 +14,14 @@ public sealed partial class CP14DemiplaneGeneratorDataComponent : Component
public ProtoId<CP14DemiplaneLocationPrototype>? Location;
[DataField]
public List<ProtoId<CP14DemiplaneModifierPrototype>> SelectedModifiers = new();
/// <summary>
/// Generator Tier. Determines which modifiers and locations will be selected for this demiplane
/// </summary>
[DataField(required: true)]
public Dictionary<int, float> TiersContent = new();
[DataField(required: true)]
public Dictionary<ProtoId<CP14DemiplaneModifierCategoryPrototype>, float> Limits;
public List<ProtoId<CP14DemiplaneModifierPrototype>> Modifiers = new();
[DataField]
public bool NeedDemiplaneCrystal = true;
public float DifficultyLimit = 1;
[DataField]
public float DemiplaneCrystalRange = 15f;
public float RewardLimit = 1;
[DataField]
public TimeSpan UseDelay = TimeSpan.FromSeconds(1.0);
[DataField]
public TimeSpan LastUseTime = TimeSpan.Zero;
public int MaxModifiers = 6;
}

View File

@@ -108,9 +108,9 @@ public sealed class CP14SpawnRandomDemiplaneJob : Job<bool>
}
//Setup gravity
var gravity = _entManager.EnsureComponent<GravityComponent>(grid);
var gravity = _entManager.EnsureComponent<GravityComponent>(DemiplaneMapUid);
gravity.Enabled = true;
_entManager.Dirty(grid, gravity, metadata);
_entManager.Dirty(DemiplaneMapUid, gravity, metadata);
// Setup default atmos
var moles = new float[Atmospherics.AdjustedNumberOfGases];

View File

@@ -1,5 +1,4 @@
using Content.Server._CP14.Demiplane;
using Content.Server.Interaction;
using Content.Server.Mind;
using Content.Server.Popups;
using Content.Shared._CP14.Demiplane;
@@ -20,8 +19,8 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly InteractionSystem _interaction = default!;
public override void Initialize()
{
@@ -44,7 +43,6 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
passWay.NextTimeTeleport = _timing.CurTime + passWay.Delay;
//Get all teleporting entities
HashSet<EntityUid> teleportedEnts = new();
var nearestEnts = _lookup.GetEntitiesInRange(uid, passWay.Radius);
foreach (var ent in nearestEnts)
@@ -55,9 +53,6 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
if (!_mind.TryGetMind(ent, out var mindId, out var mind))
continue;
if (!_interaction.InRangeUnobstructed(ent, uid))
continue;
teleportedEnts.Add(ent);
}
@@ -66,7 +61,6 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
teleportedEnts.Remove(_random.Pick(teleportedEnts));
}
//Aaaand teleport it
var map = Transform(uid).MapUid;
if (TryComp<CP14DemiplaneComponent>(map, out var demiplan))
{
@@ -107,6 +101,7 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
private void RadiusMapInit(Entity<CP14DemiplaneRadiusTimedPasswayComponent> radiusPassWay, ref MapInitEvent args)
{
radiusPassWay.Comp.NextTimeTeleport = _timing.CurTime + radiusPassWay.Comp.Delay;
//Popup caution here
}
private void OnOpenRiftInteractDoAfter(Entity<CP14DemiplaneRiftOpenedComponent> passWay, ref CP14DemiplanPasswayUseDoAfter args)

View File

@@ -0,0 +1,176 @@
using System.Numerics;
using Content.Server._CP14.Footprints.Components;
using Content.Server.Decals;
using Content.Shared._CP14.Decals;
using Content.Shared.DoAfter;
using Content.Shared.Fluids;
using Content.Shared.Fluids.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Maps;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.Footprints;
public sealed class CP14FootprintsSystem : EntitySystem
{
[Dependency] private readonly DecalSystem _decal = default!;
[Dependency] private readonly SharedMapSystem _maps = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<Components.CP14FootprintTrailerComponent, MoveEvent>(OnTrailerMove);
SubscribeLocalEvent<Components.CP14FootprintTrailerComponent, StartCollideEvent>(OnTrailerCollide);
SubscribeLocalEvent<CP14FootprintHolderComponent, GotEquippedEvent>(OnHolderEquipped);
SubscribeLocalEvent<CP14FootprintHolderComponent, GotUnequippedEvent>(OnHolderUnequipped);
SubscribeLocalEvent<CP14DecalCleanerComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<CP14DecalCleanerComponent, CP14DecalCleanerDoAfterEvent>(OnCleanDoAfter);
}
private void OnCleanDoAfter(Entity<CP14DecalCleanerComponent> ent, ref CP14DecalCleanerDoAfterEvent args)
{
if (args.Cancelled || args.Handled)
return;
var gridUid = Transform(ent).GridUid;
if (gridUid is null)
return;
if (!TryComp<MapGridComponent>(gridUid, out var map))
return;
var coord = EntityManager.GetCoordinates(args.ClickLocation);
_audio.PlayPvs(ent.Comp.Sound, coord);
SpawnAtPosition(ent.Comp.SpawnEffect, coord);
var oldDecals = _decal.GetDecalsInRange(gridUid.Value, args.ClickLocation.Position, ent.Comp.Range);
foreach (var (id, decal) in oldDecals)
{
if (decal.Cleanable)
_decal.RemoveDecal(gridUid.Value, id);
}
args.Handled = true;
}
private void OnAfterInteract(Entity<CP14DecalCleanerComponent> ent, ref AfterInteractEvent args)
{
if (!args.CanReach && !args.Handled)
return;
var doAfter = new DoAfterArgs(EntityManager,
args.User,
ent.Comp.Delay,
new CP14DecalCleanerDoAfterEvent(EntityManager.GetNetCoordinates(args.ClickLocation)),
ent)
{
BreakOnMove = true,
BreakOnDamage = true,
NeedHand = true,
};
_doAfter.TryStartDoAfter(doAfter);
args.Handled = true;
}
private void OnHolderUnequipped(Entity<CP14FootprintHolderComponent> ent, ref GotUnequippedEvent args)
{
if (!TryComp<Components.CP14FootprintTrailerComponent>(args.Equipee, out var trailer))
return;
trailer.holder = null;
if (TryComp<CP14FootprintHolderComponent>(args.Equipee, out var selfHolder))
{
trailer.holder = selfHolder;
}
}
private void OnHolderEquipped(Entity<CP14FootprintHolderComponent> ent, ref GotEquippedEvent args)
{
if (!TryComp<Components.CP14FootprintTrailerComponent>(args.Equipee, out var trailer))
return;
trailer.holder = ent.Comp;
}
private void OnTrailerCollide(Entity<Components.CP14FootprintTrailerComponent> ent, ref StartCollideEvent args)
{
if (ent.Comp.holder is null)
return;
var footprint = ent.Comp.holder;
if (!TryComp<PuddleComponent>(args.OtherEntity, out var puddle))
return;
if (puddle.Solution is null)
return;
var sol = puddle.Solution;
var splittedSol = sol.Value.Comp.Solution.SplitSolutionWithout(footprint.PickSolution, SharedPuddleSystem.EvaporationReagents);
if (splittedSol.Volume > 0)
UpdateFootprint(footprint, splittedSol.GetColor(_proto));
}
private void UpdateFootprint(CP14FootprintHolderComponent comp, Color color)
{
comp.DecalColor = color;
comp.Intensity = 1f;
}
private void OnTrailerMove(Entity<Components.CP14FootprintTrailerComponent> ent, ref MoveEvent args)
{
if (ent.Comp.holder is null)
return;
var footprint = ent.Comp.holder;
var distance = Vector2.Distance(args.OldPosition.Position, args.NewPosition.Position);
footprint.DistanceTraveled += distance;
if (footprint.DistanceTraveled < footprint.DecalDistance)
return;
footprint.DistanceTraveled = 0f;
var xform = Transform(ent);
if (!TryComp<MapGridComponent>(xform.GridUid, out var mapGrid))
return;
var tileRef = _maps.GetTileRef(xform.GridUid.Value, mapGrid, xform.Coordinates);
var tileDef = (ContentTileDefinition)_tileDefManager[tileRef.Tile.TypeId];
if (tileDef.Weather && tileDef.Color is not null)
{
UpdateFootprint(footprint, tileDef.Color.Value);
return;
}
if (footprint.Intensity <= 0)
return;
_decal.TryAddDecal(footprint.DecalProto,
xform.Coordinates.Offset(new Vector2(-0.5f, -0.5f)),
out var decal,
footprint.DecalColor.WithAlpha(footprint.Intensity),
xform.LocalRotation,
cleanable: true);
footprint.Intensity = MathF.Max(0, footprint.Intensity - footprint.DistanceIntensityCost);
}
}

View File

@@ -0,0 +1,26 @@
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.Footprints.Components;
/// <summary>
/// allows you to remove cleanable decals from tiles with a short delay.
/// </summary>
[RegisterComponent, Access(typeof(CP14FootprintsSystem))]
public sealed partial class CP14DecalCleanerComponent : Component
{
[DataField]
public SoundSpecifier Sound = new SoundCollectionSpecifier("CP14Broom")
{
Params = AudioParams.Default.WithVariation(0.2f),
};
[DataField]
public EntProtoId? SpawnEffect = "CP14DustEffect";
[DataField]
public float Range = 1.2f;
[DataField]
public TimeSpan Delay = TimeSpan.FromSeconds(0.75f);
}

View File

@@ -0,0 +1,33 @@
using Content.Shared.Decals;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.Footprints.Components;
/// <summary>
/// stores the type of footprints and their settings.
/// </summary>
[RegisterComponent, Access(typeof(CP14FootprintsSystem))]
public sealed partial class CP14FootprintHolderComponent : Component
{
[DataField]
public ProtoId<DecalPrototype> DecalProto = "CP14FootprintsBoots";
[DataField]
public float DecalDistance = 1f;
[DataField]
public float DistanceTraveled = 0f;
[DataField]
public Color DecalColor = Color.White;
[DataField]
public float Intensity = 0f;
[DataField]
public FixedPoint2 PickSolution = 1f;
[DataField]
public float DistanceIntensityCost = 0.2f;
}

View File

@@ -0,0 +1,14 @@
namespace Content.Server._CP14.Footprints.Components;
/// <summary>
/// allows an entity to leave footprints on the tiles
/// </summary>
[RegisterComponent, Access(typeof(CP14FootprintsSystem))]
public sealed partial class CP14FootprintTrailerComponent : Component
{
/// <summary>
/// Source and type of footprint
/// </summary>
[DataField]
public CP14FootprintHolderComponent? holder = null;
}

View File

@@ -1,6 +0,0 @@
namespace Content.Server._CP14.Lighthouse;
[RegisterComponent]
public sealed partial class CP14LighthouseComponent : Component
{
}

View File

@@ -1,23 +0,0 @@
using Robust.Server.GameStates;
namespace Content.Server._CP14.Lighthouse;
public sealed partial class CP14LighthouseSystem : EntitySystem
{
[Dependency] private readonly PvsOverrideSystem _pvs = default!;
public override void Initialize()
{
SubscribeLocalEvent<CP14LighthouseComponent, ComponentStartup>(OnLighthouseStartup);
SubscribeLocalEvent<CP14LighthouseComponent, ComponentShutdown>(OnLighthouseShutdown);
}
private void OnLighthouseShutdown(Entity<CP14LighthouseComponent> ent, ref ComponentShutdown args)
{
_pvs.RemoveGlobalOverride(ent);
}
private void OnLighthouseStartup(Entity<CP14LighthouseComponent> ent, ref ComponentStartup args)
{
_pvs.AddGlobalOverride(ent);
}
}

View File

@@ -1,15 +0,0 @@
using Content.Shared._CP14.LockKey;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.LockKey;
[RegisterComponent]
public sealed partial class CP14AbstractKeyComponent : Component
{
[DataField(required: true)]
public ProtoId<CP14LockGroupPrototype> Group = default;
[DataField]
public bool DeleteOnFailure = true;
}

View File

@@ -1,67 +0,0 @@
using Content.Server.Station.Events;
using Content.Shared._CP14.LockKey;
using Content.Shared._CP14.LockKey.Components;
using Content.Shared.Station.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Server._CP14.LockKey;
public sealed partial class CP14KeyDistributionSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly CP14KeyholeGenerationSystem _keyGeneration = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14AbstractKeyComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<CP14AbstractKeyComponent> ent, ref MapInitEvent args)
{
if (!TrySetShape(ent) && ent.Comp.DeleteOnFailure)
QueueDel(ent);
}
private bool TrySetShape(Entity<CP14AbstractKeyComponent> ent)
{
var grid = Transform(ent).GridUid;
if (grid is null)
return false;
if (!TryComp<CP14KeyComponent>(ent, out var key))
return false;
if (!TryComp<StationMemberComponent>(grid.Value, out var member))
return false;
if (!TryComp<CP14StationKeyDistributionComponent>(member.Station, out var distribution))
return false;
var keysList = new List<ProtoId<CP14LockTypePrototype>>(distribution.Keys);
while (keysList.Count > 0)
{
var randomIndex = _random.Next(keysList.Count);
var keyA = keysList[randomIndex];
var indexedKey = _proto.Index(keyA);
if (indexedKey.Group != ent.Comp.Group)
{
keysList.RemoveAt(randomIndex);
continue;
}
_keyGeneration.SetShape((ent, key), indexedKey);
distribution.Keys.Remove(indexedKey);
return true;
}
return false;
}
}

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