Merge remote-tracking branch 'upstream/master' into 20-10-30-admins
This commit is contained in:
@@ -13,6 +13,7 @@ using Content.Client.UserInterface.AdminMenu;
|
|||||||
using Content.Client.UserInterface.Stylesheets;
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
using Content.Client.Utility;
|
using Content.Client.Utility;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Client
|
namespace Content.Client
|
||||||
@@ -37,6 +38,7 @@ namespace Content.Client
|
|||||||
IoCManager.Register<IClickMapManager, ClickMapManager>();
|
IoCManager.Register<IClickMapManager, ClickMapManager>();
|
||||||
IoCManager.Register<IStationEventManager, StationEventManager>();
|
IoCManager.Register<IStationEventManager, StationEventManager>();
|
||||||
IoCManager.Register<IAdminMenuManager, AdminMenuManager>();
|
IoCManager.Register<IAdminMenuManager, AdminMenuManager>();
|
||||||
|
IoCManager.Register<AlertManager, AlertManager>();
|
||||||
IoCManager.Register<IClientAdminManager, ClientAdminManager>();
|
IoCManager.Register<IClientAdminManager, ClientAdminManager>();
|
||||||
IoCManager.Register<EuiManager, EuiManager>();
|
IoCManager.Register<EuiManager, EuiManager>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared;
|
||||||
using Robust.Client.Interfaces.Console;
|
using Robust.Client.Interfaces.Console;
|
||||||
using Robust.Shared.Interfaces.Configuration;
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -14,10 +15,13 @@ namespace Content.Client.Commands
|
|||||||
|
|
||||||
public bool Execute(IDebugConsole console, params string[] args)
|
public bool Execute(IDebugConsole console, params string[] args)
|
||||||
{
|
{
|
||||||
var _configurationManager = IoCManager.Resolve<IConfigurationManager>();
|
var configurationManager = IoCManager.Resolve<IConfigurationManager>();
|
||||||
var old = _configurationManager.GetCVar<bool>("outline.enabled");
|
var cvar = CCVars.OutlineEnabled;
|
||||||
_configurationManager.SetCVar("outline.enabled", !old);
|
var old = configurationManager.GetCVar(cvar);
|
||||||
console.AddLine($"Draw outlines set to: {_configurationManager.GetCVar<bool>("outline.enabled")}");
|
|
||||||
|
configurationManager.SetCVar(cvar, !old);
|
||||||
|
console.AddLine($"Draw outlines set to: {configurationManager.GetCVar(cvar)}");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ using Content.Shared.GameObjects.Components.Power.AME;
|
|||||||
using Content.Shared.GameObjects.Components.Research;
|
using Content.Shared.GameObjects.Components.Research;
|
||||||
using Content.Shared.GameObjects.Components.VendingMachines;
|
using Content.Shared.GameObjects.Components.VendingMachines;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Robust.Client;
|
using Robust.Client;
|
||||||
using Robust.Client.Interfaces;
|
using Robust.Client.Interfaces;
|
||||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||||
@@ -104,8 +105,6 @@ namespace Content.Client
|
|||||||
{
|
{
|
||||||
IoCManager.Resolve<IMapManager>().CreateNewMapEntity(MapId.Nullspace);
|
IoCManager.Resolve<IMapManager>().CreateNewMapEntity(MapId.Nullspace);
|
||||||
};
|
};
|
||||||
|
|
||||||
_configurationManager.RegisterCVar("outline.enabled", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -156,6 +155,7 @@ namespace Content.Client
|
|||||||
IoCManager.Resolve<IStationEventManager>().Initialize();
|
IoCManager.Resolve<IStationEventManager>().Initialize();
|
||||||
IoCManager.Resolve<IAdminMenuManager>().Initialize();
|
IoCManager.Resolve<IAdminMenuManager>().Initialize();
|
||||||
IoCManager.Resolve<EuiManager>().Initialize();
|
IoCManager.Resolve<EuiManager>().Initialize();
|
||||||
|
IoCManager.Resolve<AlertManager>().Initialize();
|
||||||
|
|
||||||
_baseClient.RunLevelChanged += (sender, args) =>
|
_baseClient.RunLevelChanged += (sender, args) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Body.Mechanism
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedHeartBehaviorComponent))]
|
|
||||||
public class HeartBehaviorComponent : SharedHeartBehaviorComponent
|
|
||||||
{
|
|
||||||
public override void Update(float frameTime) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -49,6 +49,7 @@ namespace Content.Client.GameObjects.Components.Wires
|
|||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
||||||
|
_menu.OnClose -= Close;
|
||||||
_menu.Close();
|
_menu.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Namotion.Reflection;
|
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
@@ -142,7 +141,7 @@ namespace Content.Client.GameObjects.Components.Wires
|
|||||||
|
|
||||||
private void OnConfirm(ButtonEventArgs args)
|
private void OnConfirm(ButtonEventArgs args)
|
||||||
{
|
{
|
||||||
var config = GenerateDictionary<string, LineEdit>(_inputs, "Text");
|
var config = GenerateDictionary(_inputs, "Text");
|
||||||
|
|
||||||
Owner.SendConfiguration(config);
|
Owner.SendConfiguration(config);
|
||||||
Close();
|
Close();
|
||||||
@@ -153,13 +152,13 @@ namespace Content.Client.GameObjects.Components.Wires
|
|||||||
return Owner.Validation == null || Owner.Validation.IsMatch(value);
|
return Owner.Validation == null || Owner.Validation.IsMatch(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, TConfig> GenerateDictionary<TConfig, TInput>(List<(string name, TInput input)> inputs, string propertyName) where TInput : Control
|
private Dictionary<string, string> GenerateDictionary(IEnumerable<(string name, LineEdit input)> inputs, string propertyName)
|
||||||
{
|
{
|
||||||
var dictionary = new Dictionary<string, TConfig>();
|
var dictionary = new Dictionary<string, string>();
|
||||||
|
|
||||||
foreach (var input in inputs)
|
foreach (var input in inputs)
|
||||||
{
|
{
|
||||||
var value = input.input.TryGetPropertyValue<TConfig>(propertyName);
|
dictionary.Add(input.name, input.input.Text);
|
||||||
dictionary.Add(input.name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dictionary;
|
return dictionary;
|
||||||
|
|||||||
93
Content.Client/GameObjects/Components/Mobs/AlertControl.cs
Normal file
93
Content.Client/GameObjects/Components/Mobs/AlertControl.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.Alert;
|
||||||
|
using OpenToolkit.Mathematics;
|
||||||
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
public class AlertControl : BaseButton
|
||||||
|
{
|
||||||
|
public AlertPrototype Alert { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total duration of the cooldown in seconds. Null if no duration / cooldown.
|
||||||
|
/// </summary>
|
||||||
|
public int? TotalDuration { get; set; }
|
||||||
|
|
||||||
|
private short? _severity;
|
||||||
|
private readonly TextureRect _icon;
|
||||||
|
private CooldownGraphic _cooldownGraphic;
|
||||||
|
|
||||||
|
private readonly IResourceCache _resourceCache;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an alert control reflecting the indicated alert + state
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alert">alert to display</param>
|
||||||
|
/// <param name="severity">severity of alert, null if alert doesn't have severity levels</param>
|
||||||
|
/// <param name="resourceCache">resourceCache to use to load alert icon textures</param>
|
||||||
|
public AlertControl(AlertPrototype alert, short? severity, IResourceCache resourceCache)
|
||||||
|
{
|
||||||
|
_resourceCache = resourceCache;
|
||||||
|
Alert = alert;
|
||||||
|
_severity = severity;
|
||||||
|
var texture = _resourceCache.GetTexture(alert.GetIconPath(_severity));
|
||||||
|
_icon = new TextureRect
|
||||||
|
{
|
||||||
|
TextureScale = (2, 2),
|
||||||
|
Texture = texture
|
||||||
|
};
|
||||||
|
|
||||||
|
Children.Add(_icon);
|
||||||
|
_cooldownGraphic = new CooldownGraphic();
|
||||||
|
Children.Add(_cooldownGraphic);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Change the alert severity, changing the displayed icon
|
||||||
|
/// </summary>
|
||||||
|
public void SetSeverity(short? severity)
|
||||||
|
{
|
||||||
|
if (_severity != severity)
|
||||||
|
{
|
||||||
|
_severity = severity;
|
||||||
|
_icon.Texture = _resourceCache.GetTexture(Alert.GetIconPath(_severity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the displayed cooldown amount, doing nothing if alertCooldown is null
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alertCooldown">cooldown start and end</param>
|
||||||
|
/// <param name="curTime">current game time</param>
|
||||||
|
public void UpdateCooldown((TimeSpan Start, TimeSpan End)? alertCooldown, in TimeSpan curTime)
|
||||||
|
{
|
||||||
|
if (!alertCooldown.HasValue)
|
||||||
|
{
|
||||||
|
_cooldownGraphic.Progress = 0;
|
||||||
|
_cooldownGraphic.Visible = false;
|
||||||
|
TotalDuration = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var start = alertCooldown.Value.Start;
|
||||||
|
var end = alertCooldown.Value.End;
|
||||||
|
|
||||||
|
var length = (end - start).TotalSeconds;
|
||||||
|
var progress = (curTime - start).TotalSeconds / length;
|
||||||
|
var ratio = (progress <= 1 ? (1 - progress) : (curTime - end).TotalSeconds * -5);
|
||||||
|
|
||||||
|
TotalDuration = (int?) Math.Round(length);
|
||||||
|
_cooldownGraphic.Progress = MathHelper.Clamp((float)ratio, -1, 1);
|
||||||
|
_cooldownGraphic.Visible = ratio > -1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,345 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.Alert;
|
||||||
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Interfaces.Graphics;
|
||||||
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
|
using Robust.Client.Interfaces.UserInterface;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Input;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Timing;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(SharedAlertsComponent))]
|
||||||
|
public sealed class ClientAlertsComponent : SharedAlertsComponent
|
||||||
|
{
|
||||||
|
private static readonly float TooltipTextMaxWidth = 265;
|
||||||
|
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
|
private AlertsUI _ui;
|
||||||
|
private PanelContainer _tooltip;
|
||||||
|
private RichTextLabel _stateName;
|
||||||
|
private RichTextLabel _stateDescription;
|
||||||
|
private RichTextLabel _stateCooldown;
|
||||||
|
private AlertOrderPrototype _alertOrder;
|
||||||
|
private bool _tooltipReady;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private Dictionary<AlertKey, AlertControl> _alertControls
|
||||||
|
= new Dictionary<AlertKey, AlertControl>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows calculating if we need to act due to this component being controlled by the current mob
|
||||||
|
/// TODO: should be revisited after space-wizards/RobustToolbox#1255
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
private bool CurrentlyControlled => _playerManager.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity == Owner;
|
||||||
|
|
||||||
|
protected override void Shutdown()
|
||||||
|
{
|
||||||
|
base.Shutdown();
|
||||||
|
PlayerDetached();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandleMessage(ComponentMessage message, IComponent component)
|
||||||
|
{
|
||||||
|
base.HandleMessage(message, component);
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case PlayerAttachedMsg _:
|
||||||
|
PlayerAttached();
|
||||||
|
break;
|
||||||
|
case PlayerDetachedMsg _:
|
||||||
|
PlayerDetached();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||||
|
{
|
||||||
|
base.HandleComponentState(curState, nextState);
|
||||||
|
|
||||||
|
if (!(curState is AlertsComponentState state))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the dict of states based on the array we got in the message
|
||||||
|
SetAlerts(state.Alerts);
|
||||||
|
|
||||||
|
UpdateAlertsControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlayerAttached()
|
||||||
|
{
|
||||||
|
if (!CurrentlyControlled || _ui != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_alertOrder = IoCManager.Resolve<IPrototypeManager>().EnumeratePrototypes<AlertOrderPrototype>().FirstOrDefault();
|
||||||
|
if (_alertOrder == null)
|
||||||
|
{
|
||||||
|
Logger.ErrorS("alert", "no alertOrder prototype found, alerts will be in random order");
|
||||||
|
}
|
||||||
|
|
||||||
|
_ui = new AlertsUI(IoCManager.Resolve<IClyde>());
|
||||||
|
var uiManager = IoCManager.Resolve<IUserInterfaceManager>();
|
||||||
|
uiManager.StateRoot.AddChild(_ui);
|
||||||
|
|
||||||
|
_tooltip = new PanelContainer
|
||||||
|
{
|
||||||
|
Visible = false,
|
||||||
|
StyleClasses = { StyleNano.StyleClassTooltipPanel }
|
||||||
|
};
|
||||||
|
var tooltipVBox = new VBoxContainer
|
||||||
|
{
|
||||||
|
RectClipContent = true
|
||||||
|
};
|
||||||
|
_tooltip.AddChild(tooltipVBox);
|
||||||
|
_stateName = new RichTextLabel
|
||||||
|
{
|
||||||
|
MaxWidth = TooltipTextMaxWidth,
|
||||||
|
StyleClasses = { StyleNano.StyleClassTooltipAlertTitle }
|
||||||
|
};
|
||||||
|
tooltipVBox.AddChild(_stateName);
|
||||||
|
_stateDescription = new RichTextLabel
|
||||||
|
{
|
||||||
|
MaxWidth = TooltipTextMaxWidth,
|
||||||
|
StyleClasses = { StyleNano.StyleClassTooltipAlertDescription }
|
||||||
|
};
|
||||||
|
tooltipVBox.AddChild(_stateDescription);
|
||||||
|
_stateCooldown = new RichTextLabel
|
||||||
|
{
|
||||||
|
MaxWidth = TooltipTextMaxWidth,
|
||||||
|
StyleClasses = { StyleNano.StyleClassTooltipAlertCooldown }
|
||||||
|
};
|
||||||
|
tooltipVBox.AddChild(_stateCooldown);
|
||||||
|
|
||||||
|
uiManager.PopupRoot.AddChild(_tooltip);
|
||||||
|
|
||||||
|
UpdateAlertsControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlayerDetached()
|
||||||
|
{
|
||||||
|
_ui?.Dispose();
|
||||||
|
_ui = null;
|
||||||
|
_alertControls.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the displayed alerts based on current state of Alerts, performing
|
||||||
|
/// a diff to ensure we only change what's changed (this avoids active tooltips disappearing any
|
||||||
|
/// time state changes)
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateAlertsControls()
|
||||||
|
{
|
||||||
|
if (!CurrentlyControlled || _ui == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove any controls with keys no longer present
|
||||||
|
var toRemove = new List<AlertKey>();
|
||||||
|
foreach (var existingKey in _alertControls.Keys)
|
||||||
|
{
|
||||||
|
if (!IsShowingAlert(existingKey))
|
||||||
|
{
|
||||||
|
toRemove.Add(existingKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var alertKeyToRemove in toRemove)
|
||||||
|
{
|
||||||
|
// remove and dispose the control
|
||||||
|
_alertControls.Remove(alertKeyToRemove, out var control);
|
||||||
|
control?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we know that alertControls contains alerts that should still exist but
|
||||||
|
// may need to updated,
|
||||||
|
// also there may be some new alerts we need to show.
|
||||||
|
// further, we need to ensure they are ordered w.r.t their configured order
|
||||||
|
foreach (var alertStatus in EnumerateAlertStates())
|
||||||
|
{
|
||||||
|
if (!AlertManager.TryDecode(alertStatus.AlertEncoded, out var newAlert))
|
||||||
|
{
|
||||||
|
Logger.ErrorS("alert", "Unable to decode alert {0}", alertStatus.AlertEncoded);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_alertControls.TryGetValue(newAlert.AlertKey, out var existingAlertControl) &&
|
||||||
|
existingAlertControl.Alert.AlertType == newAlert.AlertType)
|
||||||
|
{
|
||||||
|
// id is the same, simply update the existing control severity
|
||||||
|
existingAlertControl.SetSeverity(alertStatus.Severity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existingAlertControl?.Dispose();
|
||||||
|
|
||||||
|
// this is a new alert + alert key or just a different alert with the same
|
||||||
|
// key, create the control and add it in the appropriate order
|
||||||
|
var newAlertControl = CreateAlertControl(newAlert, alertStatus);
|
||||||
|
if (_alertOrder != null)
|
||||||
|
{
|
||||||
|
var added = false;
|
||||||
|
foreach (var alertControl in _ui.Grid.Children)
|
||||||
|
{
|
||||||
|
if (_alertOrder.Compare(newAlert, ((AlertControl) alertControl).Alert) < 0)
|
||||||
|
{
|
||||||
|
var idx = alertControl.GetPositionInParent();
|
||||||
|
_ui.Grid.Children.Add(newAlertControl);
|
||||||
|
newAlertControl.SetPositionInParent(idx);
|
||||||
|
added = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!added)
|
||||||
|
{
|
||||||
|
_ui.Grid.Children.Add(newAlertControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ui.Grid.Children.Add(newAlertControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
_alertControls[newAlert.AlertKey] = newAlertControl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlertControl CreateAlertControl(AlertPrototype alert, AlertState alertState)
|
||||||
|
{
|
||||||
|
|
||||||
|
var alertControl = new AlertControl(alert, alertState.Severity, _resourceCache);
|
||||||
|
// show custom tooltip for the status control
|
||||||
|
alertControl.OnShowTooltip += AlertOnOnShowTooltip;
|
||||||
|
alertControl.OnHideTooltip += AlertOnOnHideTooltip;
|
||||||
|
|
||||||
|
alertControl.OnPressed += AlertControlOnPressed;
|
||||||
|
|
||||||
|
return alertControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AlertControlOnPressed(BaseButton.ButtonEventArgs args)
|
||||||
|
{
|
||||||
|
AlertPressed(args, args.Button as AlertControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AlertOnOnHideTooltip(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_tooltipReady = false;
|
||||||
|
_tooltip.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AlertOnOnShowTooltip(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var alertControl = (AlertControl) sender;
|
||||||
|
_stateName.SetMessage(alertControl.Alert.Name);
|
||||||
|
_stateDescription.SetMessage(alertControl.Alert.Description);
|
||||||
|
// check for a cooldown
|
||||||
|
if (alertControl.TotalDuration != null && alertControl.TotalDuration > 0)
|
||||||
|
{
|
||||||
|
_stateCooldown.SetMessage(FormattedMessage.FromMarkup("[color=#776a6a]" +
|
||||||
|
alertControl.TotalDuration +
|
||||||
|
" sec cooldown[/color]"));
|
||||||
|
_stateCooldown.Visible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_stateCooldown.Visible = false;
|
||||||
|
}
|
||||||
|
// TODO: Text display of cooldown
|
||||||
|
Tooltips.PositionTooltip(_tooltip);
|
||||||
|
// if we set it visible here the size of the previous tooltip will flicker for a frame,
|
||||||
|
// so instead we wait until FrameUpdate to make it visible
|
||||||
|
_tooltipReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AlertPressed(BaseButton.ButtonEventArgs args, AlertControl alert)
|
||||||
|
{
|
||||||
|
if (args.Event.Function != EngineKeyFunctions.UIClick)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AlertManager.TryEncode(alert.Alert, out var encoded))
|
||||||
|
{
|
||||||
|
SendNetworkMessage(new ClickAlertMessage(encoded));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.ErrorS("alert", "unable to encode alert {0}", alert.Alert.AlertType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FrameUpdate(float frameTime)
|
||||||
|
{
|
||||||
|
if (_tooltipReady)
|
||||||
|
{
|
||||||
|
_tooltipReady = false;
|
||||||
|
_tooltip.Visible = true;
|
||||||
|
}
|
||||||
|
foreach (var (alertKey, alertControl) in _alertControls)
|
||||||
|
{
|
||||||
|
// reconcile all alert controls with their current cooldowns
|
||||||
|
if (TryGetAlertState(alertKey, out var alertState))
|
||||||
|
{
|
||||||
|
alertControl.UpdateCooldown(alertState.Cooldown, _gameTiming.CurTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.WarningS("alert", "coding error - no alert state for alert {0} " +
|
||||||
|
"even though we had an AlertControl for it, this" +
|
||||||
|
" should never happen", alertControl.Alert.AlertType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AfterClearAlert()
|
||||||
|
{
|
||||||
|
UpdateAlertsControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRemove()
|
||||||
|
{
|
||||||
|
base.OnRemove();
|
||||||
|
|
||||||
|
foreach (var alertControl in _alertControls.Values)
|
||||||
|
{
|
||||||
|
alertControl.OnShowTooltip -= AlertOnOnShowTooltip;
|
||||||
|
alertControl.OnHideTooltip -= AlertOnOnHideTooltip;
|
||||||
|
alertControl.OnPressed -= AlertControlOnPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Content.Client.UserInterface;
|
|
||||||
using Content.Client.Utility;
|
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Client.Interfaces.ResourceManagement;
|
|
||||||
using Robust.Client.Interfaces.UserInterface;
|
|
||||||
using Robust.Client.Player;
|
|
||||||
using Robust.Client.UserInterface.Controls;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Input;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
|
||||||
using Robust.Shared.Interfaces.Timing;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.ViewVariables;
|
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Mobs
|
|
||||||
{
|
|
||||||
/// <inheritdoc/>
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedStatusEffectsComponent))]
|
|
||||||
public sealed class ClientStatusEffectsComponent : SharedStatusEffectsComponent
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
||||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
|
||||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
||||||
|
|
||||||
private StatusEffectsUI _ui;
|
|
||||||
[ViewVariables]
|
|
||||||
private Dictionary<StatusEffect, StatusEffectStatus> _status = new Dictionary<StatusEffect, StatusEffectStatus>();
|
|
||||||
[ViewVariables]
|
|
||||||
private Dictionary<StatusEffect, CooldownGraphic> _cooldown = new Dictionary<StatusEffect, CooldownGraphic>();
|
|
||||||
|
|
||||||
public override IReadOnlyDictionary<StatusEffect, StatusEffectStatus> Statuses => _status;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allows calculating if we need to act due to this component being controlled by the current mob
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
private bool CurrentlyControlled => _playerManager.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity == Owner;
|
|
||||||
|
|
||||||
protected override void Shutdown()
|
|
||||||
{
|
|
||||||
base.Shutdown();
|
|
||||||
PlayerDetached();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandleMessage(ComponentMessage message, IComponent component)
|
|
||||||
{
|
|
||||||
base.HandleMessage(message, component);
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case PlayerAttachedMsg _:
|
|
||||||
PlayerAttached();
|
|
||||||
break;
|
|
||||||
case PlayerDetachedMsg _:
|
|
||||||
PlayerDetached();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
|
||||||
{
|
|
||||||
base.HandleComponentState(curState, nextState);
|
|
||||||
|
|
||||||
if (!(curState is StatusEffectComponentState state) || _status == state.StatusEffects)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_status = state.StatusEffects;
|
|
||||||
UpdateStatusEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PlayerAttached()
|
|
||||||
{
|
|
||||||
if (!CurrentlyControlled || _ui != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ui = new StatusEffectsUI();
|
|
||||||
_userInterfaceManager.StateRoot.AddChild(_ui);
|
|
||||||
UpdateStatusEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PlayerDetached()
|
|
||||||
{
|
|
||||||
_ui?.Dispose();
|
|
||||||
_ui = null;
|
|
||||||
_cooldown.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ChangeStatusEffectIcon(StatusEffect effect, string icon)
|
|
||||||
{
|
|
||||||
if (_status.TryGetValue(effect, out var value) &&
|
|
||||||
value.Icon == icon)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_status[effect] = new StatusEffectStatus
|
|
||||||
{
|
|
||||||
Icon = icon,
|
|
||||||
Cooldown = value.Cooldown
|
|
||||||
};
|
|
||||||
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateStatusEffects()
|
|
||||||
{
|
|
||||||
if (!CurrentlyControlled || _ui == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_cooldown.Clear();
|
|
||||||
_ui.VBox.DisposeAllChildren();
|
|
||||||
|
|
||||||
foreach (var (key, effect) in _status.OrderBy(x => (int) x.Key))
|
|
||||||
{
|
|
||||||
var texture = _resourceCache.GetTexture(effect.Icon);
|
|
||||||
var status = new StatusControl(key, texture)
|
|
||||||
{
|
|
||||||
ToolTip = key.ToString()
|
|
||||||
};
|
|
||||||
|
|
||||||
if (effect.Cooldown.HasValue)
|
|
||||||
{
|
|
||||||
var cooldown = new CooldownGraphic();
|
|
||||||
status.Children.Add(cooldown);
|
|
||||||
_cooldown[key] = cooldown;
|
|
||||||
}
|
|
||||||
|
|
||||||
status.OnPressed += args => StatusPressed(args, status);
|
|
||||||
|
|
||||||
_ui.VBox.AddChild(status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StatusPressed(BaseButton.ButtonEventArgs args, StatusControl status)
|
|
||||||
{
|
|
||||||
if (args.Event.Function != EngineKeyFunctions.UIClick)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendNetworkMessage(new ClickStatusMessage(status.Effect));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void RemoveStatusEffect(StatusEffect effect)
|
|
||||||
{
|
|
||||||
if (!_status.Remove(effect))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateStatusEffects();
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FrameUpdate(float frameTime)
|
|
||||||
{
|
|
||||||
foreach (var (effect, cooldownGraphic) in _cooldown)
|
|
||||||
{
|
|
||||||
var status = _status[effect];
|
|
||||||
if (!status.Cooldown.HasValue)
|
|
||||||
{
|
|
||||||
cooldownGraphic.Progress = 0;
|
|
||||||
cooldownGraphic.Visible = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var start = status.Cooldown.Value.Item1;
|
|
||||||
var end = status.Cooldown.Value.Item2;
|
|
||||||
|
|
||||||
var length = (end - start).TotalSeconds;
|
|
||||||
var progress = (_gameTiming.CurTime - start).TotalSeconds / length;
|
|
||||||
var ratio = (progress <= 1 ? (1 - progress) : (_gameTiming.CurTime - end).TotalSeconds * -5);
|
|
||||||
|
|
||||||
cooldownGraphic.Progress = MathHelper.Clamp((float)ratio, -1, 1);
|
|
||||||
cooldownGraphic.Visible = ratio > -1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ChangeStatusEffect(StatusEffect effect, string icon, (TimeSpan, TimeSpan)? cooldown)
|
|
||||||
{
|
|
||||||
_status[effect] = new StatusEffectStatus()
|
|
||||||
{
|
|
||||||
Icon = icon,
|
|
||||||
Cooldown = cooldown
|
|
||||||
};
|
|
||||||
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Interfaces.GameObjects.Components;
|
using Robust.Client.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
@@ -39,15 +39,6 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
offset *= (ResetTime - _time) / ResetTime;
|
offset *= (ResetTime - _time) / ResetTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out CameraRecoilComponent recoilComponent))
|
|
||||||
{
|
|
||||||
recoilComponent.BaseOffset = offset;
|
|
||||||
}
|
|
||||||
else if (Owner.TryGetComponent(out EyeComponent eyeComponent))
|
|
||||||
{
|
|
||||||
eyeComponent.Offset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out ISpriteComponent spriteComponent))
|
if (Owner.TryGetComponent(out ISpriteComponent spriteComponent))
|
||||||
{
|
{
|
||||||
// We have to account for rotation so the offset still checks out.
|
// We have to account for rotation so the offset still checks out.
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
|
||||||
using Robust.Client.Graphics;
|
|
||||||
using Robust.Client.UserInterface.Controls;
|
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Mobs
|
|
||||||
{
|
|
||||||
public class StatusControl : BaseButton
|
|
||||||
{
|
|
||||||
public readonly StatusEffect Effect;
|
|
||||||
|
|
||||||
public StatusControl(StatusEffect effect, Texture? texture)
|
|
||||||
{
|
|
||||||
Effect = effect;
|
|
||||||
|
|
||||||
var item = new TextureRect
|
|
||||||
{
|
|
||||||
TextureScale = (2, 2),
|
|
||||||
Texture = texture
|
|
||||||
};
|
|
||||||
|
|
||||||
Children.Add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,12 +44,14 @@ namespace Content.Client.GameObjects.Components.Storage
|
|||||||
|
|
||||||
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
|
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
|
||||||
|
|
||||||
sprite.LayerSetState(
|
if (component.TryGetData(MorgueVisuals.Open, out bool open))
|
||||||
CrematoriumVisualLayers.Base,
|
{
|
||||||
component.GetData<bool>(MorgueVisuals.Open)
|
sprite.LayerSetState(CrematoriumVisualLayers.Base, open ? _stateOpen : _stateClosed);
|
||||||
? _stateOpen
|
}
|
||||||
: _stateClosed
|
else
|
||||||
);
|
{
|
||||||
|
sprite.LayerSetState(CrematoriumVisualLayers.Base, _stateClosed);
|
||||||
|
}
|
||||||
|
|
||||||
var lightState = "";
|
var lightState = "";
|
||||||
if (component.TryGetData(MorgueVisuals.HasContents, out bool hasContents) && hasContents) lightState = _lightContents;
|
if (component.TryGetData(MorgueVisuals.HasContents, out bool hasContents) && hasContents) lightState = _lightContents;
|
||||||
|
|||||||
@@ -49,12 +49,14 @@ namespace Content.Client.GameObjects.Components.Storage
|
|||||||
|
|
||||||
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
|
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
|
||||||
|
|
||||||
sprite.LayerSetState(
|
if (component.TryGetData(MorgueVisuals.Open, out bool open))
|
||||||
MorgueVisualLayers.Base,
|
{
|
||||||
component.GetData<bool>(MorgueVisuals.Open)
|
sprite.LayerSetState(MorgueVisualLayers.Base, open ? _stateOpen : _stateClosed);
|
||||||
? _stateOpen
|
}
|
||||||
: _stateClosed
|
else
|
||||||
);
|
{
|
||||||
|
sprite.LayerSetState(MorgueVisualLayers.Base, _stateClosed);
|
||||||
|
}
|
||||||
|
|
||||||
var lightState = "";
|
var lightState = "";
|
||||||
if (component.TryGetData(MorgueVisuals.HasContents, out bool hasContents) && hasContents) lightState = _lightContents;
|
if (component.TryGetData(MorgueVisuals.HasContents, out bool hasContents) && hasContents) lightState = _lightContents;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Content.Client.GameObjects.Components.PDA
|
|||||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||||
|
|
||||||
private PDAMenu _menu;
|
private PDAMenu _menu;
|
||||||
private PDAMenuPopup failPopup;
|
private PDAMenuPopup _failPopup;
|
||||||
|
|
||||||
public PDABoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
public PDABoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||||
{
|
{
|
||||||
@@ -47,6 +47,11 @@ namespace Content.Client.GameObjects.Components.PDA
|
|||||||
SendMessage(new PDAEjectIDMessage());
|
SendMessage(new PDAEjectIDMessage());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_menu.EjectPenButton.OnPressed += args =>
|
||||||
|
{
|
||||||
|
SendMessage(new PDAEjectPenMessage());
|
||||||
|
};
|
||||||
|
|
||||||
_menu.MasterTabContainer.OnTabChanged += i =>
|
_menu.MasterTabContainer.OnTabChanged += i =>
|
||||||
{
|
{
|
||||||
var tab = _menu.MasterTabContainer.GetChild(i);
|
var tab = _menu.MasterTabContainer.GetChild(i);
|
||||||
@@ -60,12 +65,12 @@ namespace Content.Client.GameObjects.Components.PDA
|
|||||||
{
|
{
|
||||||
if (_menu.CurrentLoggedInAccount.DataBalance < listing.Price)
|
if (_menu.CurrentLoggedInAccount.DataBalance < listing.Price)
|
||||||
{
|
{
|
||||||
failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!"));
|
_failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!"));
|
||||||
_userInterfaceManager.ModalRoot.AddChild(failPopup);
|
_userInterfaceManager.ModalRoot.AddChild(_failPopup);
|
||||||
failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24));
|
_failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24));
|
||||||
_menu.OnClose += () =>
|
_menu.OnClose += () =>
|
||||||
{
|
{
|
||||||
failPopup.Dispose();
|
_failPopup.Dispose();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +111,7 @@ namespace Content.Client.GameObjects.Components.PDA
|
|||||||
}
|
}
|
||||||
|
|
||||||
_menu.EjectIDButton.Visible = msg.PDAOwnerInfo.IdOwner != null;
|
_menu.EjectIDButton.Visible = msg.PDAOwnerInfo.IdOwner != null;
|
||||||
|
_menu.EjectPenButton.Visible = msg.HasPen;
|
||||||
if (msg.Account != null)
|
if (msg.Account != null)
|
||||||
{
|
{
|
||||||
_menu.CurrentLoggedInAccount = msg.Account;
|
_menu.CurrentLoggedInAccount = msg.Account;
|
||||||
@@ -220,6 +226,7 @@ namespace Content.Client.GameObjects.Components.PDA
|
|||||||
|
|
||||||
public Button FlashLightToggleButton { get; }
|
public Button FlashLightToggleButton { get; }
|
||||||
public Button EjectIDButton { get; }
|
public Button EjectIDButton { get; }
|
||||||
|
public Button EjectPenButton { get; }
|
||||||
|
|
||||||
public TabContainer MasterTabContainer;
|
public TabContainer MasterTabContainer;
|
||||||
|
|
||||||
@@ -288,13 +295,20 @@ namespace Content.Client.GameObjects.Components.PDA
|
|||||||
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
||||||
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
||||||
};
|
};
|
||||||
|
EjectPenButton = new Button
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("Eject Pen"),
|
||||||
|
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
||||||
|
};
|
||||||
|
|
||||||
var innerHBoxContainer = new HBoxContainer
|
var innerHBoxContainer = new HBoxContainer
|
||||||
{
|
{
|
||||||
Children =
|
Children =
|
||||||
{
|
{
|
||||||
IDInfoLabel,
|
IDInfoLabel,
|
||||||
EjectIDButton
|
EjectIDButton,
|
||||||
|
EjectPenButton
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
using Content.Shared.AI;
|
using Content.Shared.AI;
|
||||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
using Robust.Client.Interfaces.UserInterface;
|
using Robust.Client.Interfaces.UserInterface;
|
||||||
@@ -178,7 +179,7 @@ namespace Content.Client.GameObjects.EntitySystems.AI
|
|||||||
|
|
||||||
var panel = new PanelContainer
|
var panel = new PanelContainer
|
||||||
{
|
{
|
||||||
StyleClasses = {"tooltipBox"},
|
StyleClasses = { StyleNano.StyleClassTooltipPanel },
|
||||||
Children = {vBox},
|
Children = {vBox},
|
||||||
MouseFilter = Control.MouseFilterMode.Ignore,
|
MouseFilter = Control.MouseFilterMode.Ignore,
|
||||||
ModulateSelfOverride = Color.White.WithAlpha(0.75f),
|
ModulateSelfOverride = Color.White.WithAlpha(0.75f),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Robust.Shared.IoC;
|
|||||||
|
|
||||||
namespace Content.Client.GameObjects.EntitySystems
|
namespace Content.Client.GameObjects.EntitySystems
|
||||||
{
|
{
|
||||||
public class StatusEffectsSystem : EntitySystem
|
public class AlertsSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
@@ -16,9 +16,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
if (!_gameTiming.IsFirstTimePredicted)
|
if (!_gameTiming.IsFirstTimePredicted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var clientStatusEffectsComponent in EntityManager.ComponentManager.EntityQuery<ClientStatusEffectsComponent>())
|
foreach (var clientAlertsComponent in EntityManager.ComponentManager.EntityQuery<ClientAlertsComponent>())
|
||||||
{
|
{
|
||||||
clientStatusEffectsComponent.FrameUpdate(frameTime);
|
clientAlertsComponent.FrameUpdate(frameTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,23 +56,20 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
|||||||
/// Is the cancellation bar red?
|
/// Is the cancellation bar red?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _flash = true;
|
private bool _flash = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Last time we swapped the flash.
|
/// Last time we swapped the flash.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private TimeSpan _lastFlash;
|
private TimeSpan _lastFlash;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long each cancellation bar flash lasts in seconds.
|
/// How long each cancellation bar flash lasts in seconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float FlashTime = 0.125f;
|
private const float FlashTime = 0.125f;
|
||||||
|
|
||||||
private const int XPixelDiff = 20 * DoAfterBarScale;
|
private const int XPixelDiff = 20 * DoAfterBarScale;
|
||||||
|
|
||||||
public const byte DoAfterBarScale = 2;
|
public const byte DoAfterBarScale = 2;
|
||||||
private static readonly Color StartColor = new Color(0.8f, 0.0f, 0.2f); // red
|
|
||||||
private static readonly Color EndColor = new Color(0.92f, 0.77f, 0.34f); // yellow
|
|
||||||
private static readonly Color CompletedColor = new Color(0.0f, 0.8f, 0.27f); // green
|
|
||||||
|
|
||||||
public DoAfterBar()
|
public DoAfterBar()
|
||||||
{
|
{
|
||||||
@@ -108,28 +105,25 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
|||||||
}
|
}
|
||||||
|
|
||||||
color = new Color(1.0f, 0.0f, 0.0f, _flash ? 1.0f : 0.0f);
|
color = new Color(1.0f, 0.0f, 0.0f, _flash ? 1.0f : 0.0f);
|
||||||
}
|
}
|
||||||
else if (Ratio >= 1.0f)
|
else if (Ratio >= 1.0f)
|
||||||
{
|
{
|
||||||
color = CompletedColor;
|
color = new Color(0f, 1f, 0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// lerp
|
// lerp
|
||||||
color = new Color(
|
var hue = (5f / 18f) * Ratio;
|
||||||
StartColor.R + (EndColor.R - StartColor.R) * Ratio,
|
color = Color.FromHsv((hue, 1f, 0.75f, 1f));
|
||||||
StartColor.G + (EndColor.G - StartColor.G) * Ratio,
|
|
||||||
StartColor.B + (EndColor.B - StartColor.B) * Ratio,
|
|
||||||
StartColor.A);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handle.UseShader(_shader);
|
handle.UseShader(_shader);
|
||||||
// If you want to make this less hard-coded be my guest
|
// If you want to make this less hard-coded be my guest
|
||||||
var leftOffset = 2 * DoAfterBarScale;
|
var leftOffset = 2 * DoAfterBarScale;
|
||||||
var box = new UIBox2i(
|
var box = new UIBox2i(
|
||||||
leftOffset,
|
leftOffset,
|
||||||
-2 + 2 * DoAfterBarScale,
|
-2 + 2 * DoAfterBarScale,
|
||||||
leftOffset + (int) (XPixelDiff * Ratio),
|
leftOffset + (int) (XPixelDiff * Ratio),
|
||||||
-2);
|
-2);
|
||||||
handle.DrawRect(box, color);
|
handle.DrawRect(box, color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@
|
|||||||
"Drink",
|
"Drink",
|
||||||
"Food",
|
"Food",
|
||||||
"FoodContainer",
|
"FoodContainer",
|
||||||
"Stomach",
|
|
||||||
"Rotatable",
|
"Rotatable",
|
||||||
"MagicMirror",
|
"MagicMirror",
|
||||||
"FloorTile",
|
"FloorTile",
|
||||||
@@ -180,10 +179,8 @@
|
|||||||
"BreakableConstruction",
|
"BreakableConstruction",
|
||||||
"GasCanister",
|
"GasCanister",
|
||||||
"GasCanisterPort",
|
"GasCanisterPort",
|
||||||
"Lung",
|
|
||||||
"Cleanable",
|
"Cleanable",
|
||||||
"Configuration",
|
"Configuration",
|
||||||
"Brain",
|
|
||||||
"PlantHolder",
|
"PlantHolder",
|
||||||
"SeedExtractor",
|
"SeedExtractor",
|
||||||
"Produce",
|
"Produce",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Client.Interfaces.Parallax;
|
using Content.Client.Interfaces.Parallax;
|
||||||
|
using Content.Shared;
|
||||||
using Nett;
|
using Nett;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Interfaces.ResourceManagement;
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
@@ -34,12 +35,12 @@ namespace Content.Client.Parallax
|
|||||||
|
|
||||||
public async void LoadParallax()
|
public async void LoadParallax()
|
||||||
{
|
{
|
||||||
if (!_configurationManager.GetCVar<bool>("parallax.enabled"))
|
if (!_configurationManager.GetCVar(CCVars.ParallaxEnabled))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var debugParallax = _configurationManager.GetCVar<bool>("parallax.debug");
|
var debugParallax = _configurationManager.GetCVar(CCVars.ParallaxDebug);
|
||||||
string contents;
|
string contents;
|
||||||
TomlTable table;
|
TomlTable table;
|
||||||
// Load normal config into memory
|
// Load normal config into memory
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace Content.Client.Sandbox
|
|||||||
public Button ToggleSubfloorButton;
|
public Button ToggleSubfloorButton;
|
||||||
public Button ShowMarkersButton; //Shows spawn points
|
public Button ShowMarkersButton; //Shows spawn points
|
||||||
public Button ShowBbButton; //Shows bounding boxes
|
public Button ShowBbButton; //Shows bounding boxes
|
||||||
|
public Button MachineLinkingButton; // Enables/disables machine linking mode.
|
||||||
|
|
||||||
public SandboxWindow()
|
public SandboxWindow()
|
||||||
{
|
{
|
||||||
@@ -77,6 +78,9 @@ namespace Content.Client.Sandbox
|
|||||||
|
|
||||||
ShowBbButton = new Button { Text = Loc.GetString("Show Bb"), ToggleMode = true };
|
ShowBbButton = new Button { Text = Loc.GetString("Show Bb"), ToggleMode = true };
|
||||||
vBox.AddChild(ShowBbButton);
|
vBox.AddChild(ShowBbButton);
|
||||||
|
|
||||||
|
MachineLinkingButton = new Button { Text = Loc.GetString("Link machines"), ToggleMode = true };
|
||||||
|
vBox.AddChild(MachineLinkingButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +190,7 @@ namespace Content.Client.Sandbox
|
|||||||
_window.ToggleSubfloorButton.OnPressed += OnToggleSubfloorButtonClicked;
|
_window.ToggleSubfloorButton.OnPressed += OnToggleSubfloorButtonClicked;
|
||||||
_window.ShowMarkersButton.OnPressed += OnShowMarkersButtonClicked;
|
_window.ShowMarkersButton.OnPressed += OnShowMarkersButtonClicked;
|
||||||
_window.ShowBbButton.OnPressed += OnShowBbButtonClicked;
|
_window.ShowBbButton.OnPressed += OnShowBbButtonClicked;
|
||||||
|
_window.MachineLinkingButton.OnPressed += OnMachineLinkingButtonClicked;
|
||||||
|
|
||||||
_window.OpenCentered();
|
_window.OpenCentered();
|
||||||
}
|
}
|
||||||
@@ -241,6 +246,10 @@ namespace Content.Client.Sandbox
|
|||||||
{
|
{
|
||||||
ShowBb();
|
ShowBb();
|
||||||
}
|
}
|
||||||
|
private void OnMachineLinkingButtonClicked(BaseButton.ButtonEventArgs args)
|
||||||
|
{
|
||||||
|
LinkMachines();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnGiveAdminAccessButtonClicked(BaseButton.ButtonEventArgs args)
|
private void OnGiveAdminAccessButtonClicked(BaseButton.ButtonEventArgs args)
|
||||||
{
|
{
|
||||||
@@ -318,5 +327,10 @@ namespace Content.Client.Sandbox
|
|||||||
{
|
{
|
||||||
_console.ProcessCommand("showbb");
|
_console.ProcessCommand("showbb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LinkMachines()
|
||||||
|
{
|
||||||
|
_console.ProcessCommand("signallink");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Immutable;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Client.GameObjects.Components;
|
using Content.Client.GameObjects.Components;
|
||||||
using Content.Client.Utility;
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared;
|
||||||
using Robust.Client.GameObjects.EntitySystems;
|
using Robust.Client.GameObjects.EntitySystems;
|
||||||
using Robust.Client.Interfaces.GameObjects;
|
using Robust.Client.Interfaces.GameObjects;
|
||||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
@@ -71,7 +72,7 @@ namespace Content.Client.State
|
|||||||
}
|
}
|
||||||
|
|
||||||
InteractionOutlineComponent outline;
|
InteractionOutlineComponent outline;
|
||||||
if(!ConfigurationManager.GetCVar<bool>("outline.enabled"))
|
if(!ConfigurationManager.GetCVar(CCVars.OutlineEnabled))
|
||||||
{
|
{
|
||||||
if(entityToClick != null && entityToClick.TryGetComponent(out outline))
|
if(entityToClick != null && entityToClick.TryGetComponent(out outline))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Robust.Client.Interfaces.UserInterface;
|
|||||||
using Robust.Client.ResourceManagement;
|
using Robust.Client.ResourceManagement;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared;
|
||||||
using Robust.Shared.Interfaces.Configuration;
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -111,10 +112,10 @@ namespace Content.Client.State
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var configName = _configurationManager.GetCVar<string>("player.name");
|
var configName = _configurationManager.GetCVar(CVars.PlayerName);
|
||||||
if (_mainMenuControl.UserNameBox.Text != configName)
|
if (_mainMenuControl.UserNameBox.Text != configName)
|
||||||
{
|
{
|
||||||
_configurationManager.SetCVar("player.name", inputName);
|
_configurationManager.SetCVar(CVars.PlayerName, inputName);
|
||||||
_configurationManager.SaveToFile();
|
_configurationManager.SaveToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ namespace Content.Client.State
|
|||||||
vBox.AddChild(userNameHBox);
|
vBox.AddChild(userNameHBox);
|
||||||
userNameHBox.AddChild(new Label {Text = "Username:"});
|
userNameHBox.AddChild(new Label {Text = "Username:"});
|
||||||
|
|
||||||
var currentUserName = _configurationManager.GetCVar<string>("player.name");
|
var currentUserName = _configurationManager.GetCVar(CVars.PlayerName);
|
||||||
UserNameBox = new LineEdit
|
UserNameBox = new LineEdit
|
||||||
{
|
{
|
||||||
Text = currentUserName, PlaceHolder = "Username",
|
Text = currentUserName, PlaceHolder = "Username",
|
||||||
|
|||||||
73
Content.Client/UserInterface/AlertsUI.cs
Normal file
73
Content.Client/UserInterface/AlertsUI.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
|
using Robust.Client.Graphics.Drawing;
|
||||||
|
using Robust.Client.Interfaces.Graphics;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Client.UserInterface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The status effects display on the right side of the screen.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class AlertsUI : Control
|
||||||
|
{
|
||||||
|
public GridContainer Grid { get; }
|
||||||
|
|
||||||
|
private readonly IClyde _clyde;
|
||||||
|
|
||||||
|
public AlertsUI(IClyde clyde)
|
||||||
|
{
|
||||||
|
_clyde = clyde;
|
||||||
|
var panelContainer = new PanelContainer
|
||||||
|
{
|
||||||
|
StyleClasses = {StyleNano.StyleClassTransparentBorderedWindowPanel},
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
};
|
||||||
|
AddChild(panelContainer);
|
||||||
|
|
||||||
|
Grid = new GridContainer
|
||||||
|
{
|
||||||
|
MaxHeight = CalcMaxHeight(clyde.ScreenSize),
|
||||||
|
ExpandBackwards = true
|
||||||
|
};
|
||||||
|
panelContainer.AddChild(Grid);
|
||||||
|
clyde.OnWindowResized += ClydeOnOnWindowResized;
|
||||||
|
|
||||||
|
LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin);
|
||||||
|
LayoutContainer.SetAnchorAndMarginPreset(this, LayoutContainer.LayoutPreset.TopRight, margin: 10);
|
||||||
|
LayoutContainer.SetMarginTop(this, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UIScaleChanged()
|
||||||
|
{
|
||||||
|
Grid.MaxHeight = CalcMaxHeight(_clyde.ScreenSize);
|
||||||
|
base.UIScaleChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClydeOnOnWindowResized(WindowResizedEventArgs obj)
|
||||||
|
{
|
||||||
|
// TODO: Can rework this once https://github.com/space-wizards/RobustToolbox/issues/1392 is done,
|
||||||
|
// this is here because there isn't currently a good way to allow the grid to adjust its height based
|
||||||
|
// on constraints, otherwise we would use anchors to lay it out
|
||||||
|
Grid.MaxHeight = CalcMaxHeight(obj.NewSize);;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float CalcMaxHeight(Vector2i screenSize)
|
||||||
|
{
|
||||||
|
return Math.Max(((screenSize.Y) / UIScale) - 420, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_clyde.OnWindowResized -= ClydeOnOnWindowResized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -149,7 +149,7 @@ namespace Content.Client.UserInterface
|
|||||||
PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold},
|
PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold},
|
||||||
CustomMinimumSize = (2, 0)
|
CustomMinimumSize = (2, 0)
|
||||||
});
|
});
|
||||||
_humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager);
|
_humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager, entityManager);
|
||||||
_humanoidProfileEditor.OnProfileChanged += newProfile => { UpdateUI(); };
|
_humanoidProfileEditor.OnProfileChanged += newProfile => { UpdateUI(); };
|
||||||
hBox.AddChild(_humanoidProfileEditor);
|
hBox.AddChild(_humanoidProfileEditor);
|
||||||
|
|
||||||
@@ -158,6 +158,15 @@ namespace Content.Client.UserInterface
|
|||||||
preferencesManager.OnServerDataLoaded += UpdateUI;
|
preferencesManager.OnServerDataLoaded += UpdateUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (!disposing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_preferencesManager.OnServerDataLoaded -= UpdateUI;
|
||||||
|
}
|
||||||
|
|
||||||
public void Save() => _humanoidProfileEditor.Save();
|
public void Save() => _humanoidProfileEditor.Save();
|
||||||
|
|
||||||
private void UpdateUI()
|
private void UpdateUI()
|
||||||
@@ -283,7 +292,9 @@ namespace Content.Client.UserInterface
|
|||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
if (!disposing) return;
|
if (!disposing)
|
||||||
|
return;
|
||||||
|
|
||||||
_previewDummy.Delete();
|
_previewDummy.Delete();
|
||||||
_previewDummy = null;
|
_previewDummy = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,29 +27,23 @@ namespace Content.Client.UserInterface
|
|||||||
/// Possible values range from 1 to -1, where 1 to 0 is a depleting circle animation and 0 to -1 is a blink animation.
|
/// Possible values range from 1 to -1, where 1 to 0 is a depleting circle animation and 0 to -1 is a blink animation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float Progress { get; set; }
|
public float Progress { get; set; }
|
||||||
private static readonly Color StartColor = new Color(0.8f, 0.0f, 0.2f); // red
|
|
||||||
private static readonly Color EndColor = new Color(0.92f, 0.77f, 0.34f); // yellow
|
|
||||||
private static readonly Color CompletedColor = new Color(0.0f, 0.8f, 0.27f); // green
|
|
||||||
|
|
||||||
protected override void Draw(DrawingHandleScreen handle)
|
protected override void Draw(DrawingHandleScreen handle)
|
||||||
{
|
{
|
||||||
Span<float> x = stackalloc float[10];
|
Span<float> x = new float[10];
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
var lerp = 1f - MathF.Abs(Progress); // for future bikeshedding purposes
|
var lerp = 1f - MathF.Abs(Progress); // for future bikeshedding purposes
|
||||||
|
|
||||||
if (Progress >= 0f)
|
if (Progress >= 0f)
|
||||||
{
|
{
|
||||||
color = new Color(
|
var hue = (5f / 18f) * lerp;
|
||||||
EndColor.R + (StartColor.R - EndColor.R) * Progress,
|
color = Color.FromHsv((hue, 0.75f, 0.75f, 0.50f));
|
||||||
EndColor.G + (StartColor.G - EndColor.G) * Progress,
|
|
||||||
EndColor.B + (StartColor.B - EndColor.B) * Progress,
|
|
||||||
EndColor.A);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var alpha = MathHelper.Clamp(0.5f * lerp, 0f, 0.5f);
|
var alpha = MathHelper.Clamp(0.5f * lerp, 0f, 0.5f);
|
||||||
color = CompletedColor.WithAlpha(alpha);
|
color = new Color(1f, 1f, 1f, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
_shader.SetParameter("progress", Progress);
|
_shader.SetParameter("progress", Progress);
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
using System;
|
using Content.Client.GameObjects.Components;
|
||||||
using System.Collections.Generic;
|
using Content.Client.GameObjects.Components.Mobs;
|
||||||
using System.Linq;
|
|
||||||
using Content.Client.GameObjects.Components;
|
|
||||||
using Content.Client.Interfaces;
|
using Content.Client.Interfaces;
|
||||||
using Content.Shared;
|
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Graphics.Drawing;
|
using Robust.Client.Graphics.Drawing;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.Utility;
|
using Robust.Client.Utility;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Content.Client.UserInterface
|
namespace Content.Client.UserInterface
|
||||||
{
|
{
|
||||||
@@ -43,17 +46,25 @@ namespace Content.Client.UserInterface
|
|||||||
private readonly OptionButton _preferenceUnavailableButton;
|
private readonly OptionButton _preferenceUnavailableButton;
|
||||||
private readonly List<AntagPreferenceSelector> _antagPreferences;
|
private readonly List<AntagPreferenceSelector> _antagPreferences;
|
||||||
|
|
||||||
|
private readonly IEntity _previewDummy;
|
||||||
|
private readonly SpriteView _previewSprite;
|
||||||
|
private readonly SpriteView _previewSpriteSide;
|
||||||
|
|
||||||
private bool _isDirty;
|
private bool _isDirty;
|
||||||
public int CharacterSlot;
|
public int CharacterSlot;
|
||||||
public HumanoidCharacterProfile Profile;
|
public HumanoidCharacterProfile Profile;
|
||||||
public event Action<HumanoidCharacterProfile> OnProfileChanged;
|
public event Action<HumanoidCharacterProfile> OnProfileChanged;
|
||||||
|
|
||||||
public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager)
|
public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager, IEntityManager entityManager)
|
||||||
{
|
{
|
||||||
_random = IoCManager.Resolve<IRobustRandom>();
|
_random = IoCManager.Resolve<IRobustRandom>();
|
||||||
|
|
||||||
_preferencesManager = preferencesManager;
|
_preferencesManager = preferencesManager;
|
||||||
|
|
||||||
|
var hbox = new HBoxContainer();
|
||||||
|
AddChild(hbox);
|
||||||
|
|
||||||
|
#region Left
|
||||||
var margin = new MarginContainer
|
var margin = new MarginContainer
|
||||||
{
|
{
|
||||||
MarginTopOverride = 10,
|
MarginTopOverride = 10,
|
||||||
@@ -61,7 +72,7 @@ namespace Content.Client.UserInterface
|
|||||||
MarginLeftOverride = 10,
|
MarginLeftOverride = 10,
|
||||||
MarginRightOverride = 10
|
MarginRightOverride = 10
|
||||||
};
|
};
|
||||||
AddChild(margin);
|
hbox.AddChild(margin);
|
||||||
|
|
||||||
var vBox = new VBoxContainer();
|
var vBox = new VBoxContainer();
|
||||||
margin.AddChild(vBox);
|
margin.AddChild(vBox);
|
||||||
@@ -98,7 +109,7 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
SizeFlagsVertical = SizeFlags.FillExpand
|
SizeFlagsVertical = SizeFlags.FillExpand
|
||||||
};
|
};
|
||||||
var nameLabel = new Label {Text = Loc.GetString("Name:")};
|
var nameLabel = new Label { Text = Loc.GetString("Name:") };
|
||||||
_nameEdit = new LineEdit
|
_nameEdit = new LineEdit
|
||||||
{
|
{
|
||||||
CustomMinimumSize = (270, 0),
|
CustomMinimumSize = (270, 0),
|
||||||
@@ -119,7 +130,7 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
#endregion Name
|
#endregion Name
|
||||||
|
|
||||||
var tabContainer = new TabContainer {SizeFlagsVertical = SizeFlags.FillExpand};
|
var tabContainer = new TabContainer { SizeFlagsVertical = SizeFlags.FillExpand };
|
||||||
vBox.AddChild(tabContainer);
|
vBox.AddChild(tabContainer);
|
||||||
|
|
||||||
#region Appearance
|
#region Appearance
|
||||||
@@ -141,7 +152,7 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
var panel = HighlightedContainer();
|
var panel = HighlightedContainer();
|
||||||
var hBox = new HBoxContainer();
|
var hBox = new HBoxContainer();
|
||||||
var sexLabel = new Label {Text = Loc.GetString("Sex:")};
|
var sexLabel = new Label { Text = Loc.GetString("Sex:") };
|
||||||
|
|
||||||
var sexButtonGroup = new ButtonGroup();
|
var sexButtonGroup = new ButtonGroup();
|
||||||
|
|
||||||
@@ -171,8 +182,8 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
var panel = HighlightedContainer();
|
var panel = HighlightedContainer();
|
||||||
var hBox = new HBoxContainer();
|
var hBox = new HBoxContainer();
|
||||||
var ageLabel = new Label {Text = Loc.GetString("Age:")};
|
var ageLabel = new Label { Text = Loc.GetString("Age:") };
|
||||||
_ageEdit = new LineEdit {CustomMinimumSize = (40, 0)};
|
_ageEdit = new LineEdit { CustomMinimumSize = (40, 0) };
|
||||||
_ageEdit.OnTextChanged += args =>
|
_ageEdit.OnTextChanged += args =>
|
||||||
{
|
{
|
||||||
if (!int.TryParse(args.Text, out var newAge))
|
if (!int.TryParse(args.Text, out var newAge))
|
||||||
@@ -348,7 +359,7 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
foreach (var antag in prototypeManager.EnumeratePrototypes<AntagPrototype>().OrderBy(a => a.Name))
|
foreach (var antag in prototypeManager.EnumeratePrototypes<AntagPrototype>().OrderBy(a => a.Name))
|
||||||
{
|
{
|
||||||
if(!antag.SetPreference)
|
if (!antag.SetPreference)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -410,6 +421,71 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
#endregion Save
|
#endregion Save
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Right
|
||||||
|
|
||||||
|
margin = new MarginContainer
|
||||||
|
{
|
||||||
|
MarginTopOverride = 10,
|
||||||
|
MarginBottomOverride = 10,
|
||||||
|
MarginLeftOverride = 10,
|
||||||
|
MarginRightOverride = 10
|
||||||
|
};
|
||||||
|
hbox.AddChild(margin);
|
||||||
|
|
||||||
|
vBox = new VBoxContainer()
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
};
|
||||||
|
hbox.AddChild(vBox);
|
||||||
|
|
||||||
|
#region Preview
|
||||||
|
|
||||||
|
_previewDummy = entityManager.SpawnEntity("HumanMob_Dummy", MapCoordinates.Nullspace);
|
||||||
|
var sprite = _previewDummy.GetComponent<SpriteComponent>();
|
||||||
|
|
||||||
|
// Front
|
||||||
|
var box = new Control()
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.Fill,
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsStretchRatio = 1f,
|
||||||
|
};
|
||||||
|
vBox.AddChild(box);
|
||||||
|
_previewSprite = new SpriteView
|
||||||
|
{
|
||||||
|
Sprite = sprite,
|
||||||
|
Scale = (6, 6),
|
||||||
|
OverrideDirection = Direction.South,
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
|
SizeFlagsStretchRatio = 1
|
||||||
|
};
|
||||||
|
box.AddChild(_previewSprite);
|
||||||
|
|
||||||
|
// Side
|
||||||
|
box = new Control()
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.Fill,
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsStretchRatio = 1f,
|
||||||
|
};
|
||||||
|
vBox.AddChild(box);
|
||||||
|
_previewSpriteSide = new SpriteView
|
||||||
|
{
|
||||||
|
Sprite = sprite,
|
||||||
|
Scale = (6, 6),
|
||||||
|
OverrideDirection = Direction.East,
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
|
SizeFlagsStretchRatio = 1
|
||||||
|
};
|
||||||
|
box.AddChild(_previewSpriteSide);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
if (preferencesManager.ServerDataLoaded)
|
if (preferencesManager.ServerDataLoaded)
|
||||||
{
|
{
|
||||||
LoadServerData();
|
LoadServerData();
|
||||||
@@ -420,6 +496,16 @@ namespace Content.Client.UserInterface
|
|||||||
IsDirty = false;
|
IsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (!disposing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_previewDummy.Delete();
|
||||||
|
_preferencesManager.OnServerDataLoaded -= LoadServerData;
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadServerData()
|
private void LoadServerData()
|
||||||
{
|
{
|
||||||
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences.SelectedCharacter;
|
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences.SelectedCharacter;
|
||||||
@@ -458,6 +544,7 @@ namespace Content.Client.UserInterface
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
_isDirty = value;
|
_isDirty = value;
|
||||||
|
UpdatePreview();
|
||||||
UpdateSaveButton();
|
UpdateSaveButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,6 +590,15 @@ namespace Content.Client.UserInterface
|
|||||||
_saveButton.Disabled = Profile is null || !IsDirty;
|
_saveButton.Disabled = Profile is null || !IsDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdatePreview()
|
||||||
|
{
|
||||||
|
if (Profile is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_previewDummy.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(Profile);
|
||||||
|
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, Profile);
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateControls()
|
public void UpdateControls()
|
||||||
{
|
{
|
||||||
if (Profile is null) return;
|
if (Profile is null) return;
|
||||||
@@ -514,6 +610,8 @@ namespace Content.Client.UserInterface
|
|||||||
UpdateJobPriorities();
|
UpdateJobPriorities();
|
||||||
UpdateAntagPreferences();
|
UpdateAntagPreferences();
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
|
|
||||||
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using Robust.Client.Graphics;
|
using Content.Shared;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Interfaces.ResourceManagement;
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared;
|
||||||
using Robust.Shared.Interfaces.Configuration;
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
@@ -121,7 +123,7 @@ namespace Content.Client.UserInterface
|
|||||||
});
|
});
|
||||||
ApplyButton.OnPressed += OnApplyButtonPressed;
|
ApplyButton.OnPressed += OnApplyButtonPressed;
|
||||||
|
|
||||||
VSyncCheckBox.Pressed = _cfg.GetCVar<bool>("display.vsync");
|
VSyncCheckBox.Pressed = _cfg.GetCVar(CVars.DisplayVSync);
|
||||||
FullscreenCheckBox.Pressed = ConfigIsFullscreen;
|
FullscreenCheckBox.Pressed = ConfigIsFullscreen;
|
||||||
LightingPresetOption.SelectId(GetConfigLightingQuality());
|
LightingPresetOption.SelectId(GetConfigLightingQuality());
|
||||||
_uiScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale));
|
_uiScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale));
|
||||||
@@ -137,11 +139,11 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
|
private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
|
||||||
{
|
{
|
||||||
_cfg.SetCVar("display.vsync", VSyncCheckBox.Pressed);
|
_cfg.SetCVar(CVars.DisplayVSync, VSyncCheckBox.Pressed);
|
||||||
SetConfigLightingQuality(LightingPresetOption.SelectedId);
|
SetConfigLightingQuality(LightingPresetOption.SelectedId);
|
||||||
_cfg.SetCVar("display.windowmode",
|
_cfg.SetCVar(CVars.DisplayWindowMode,
|
||||||
(int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
|
(int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
|
||||||
_cfg.SetCVar("display.uiScale", UIScaleOptions[_uiScaleOption.SelectedId]);
|
_cfg.SetCVar(CVars.DisplayUIScale, UIScaleOptions[_uiScaleOption.SelectedId]);
|
||||||
_cfg.SaveToFile();
|
_cfg.SaveToFile();
|
||||||
UpdateApplyButton();
|
UpdateApplyButton();
|
||||||
}
|
}
|
||||||
@@ -159,7 +161,7 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
private void UpdateApplyButton()
|
private void UpdateApplyButton()
|
||||||
{
|
{
|
||||||
var isVSyncSame = VSyncCheckBox.Pressed == _cfg.GetCVar<bool>("display.vsync");
|
var isVSyncSame = VSyncCheckBox.Pressed == _cfg.GetCVar(CVars.DisplayVSync);
|
||||||
var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen;
|
var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen;
|
||||||
var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
|
var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
|
||||||
var isUIScaleSame = MathHelper.CloseTo(UIScaleOptions[_uiScaleOption.SelectedId], ConfigUIScale);
|
var isUIScaleSame = MathHelper.CloseTo(UIScaleOptions[_uiScaleOption.SelectedId], ConfigUIScale);
|
||||||
@@ -167,14 +169,14 @@ namespace Content.Client.UserInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool ConfigIsFullscreen =>
|
private bool ConfigIsFullscreen =>
|
||||||
_cfg.GetCVar<int>("display.windowmode") == (int) WindowMode.Fullscreen;
|
_cfg.GetCVar(CVars.DisplayWindowMode) == (int) WindowMode.Fullscreen;
|
||||||
|
|
||||||
private float ConfigUIScale => _cfg.GetCVar<float>("display.uiScale");
|
private float ConfigUIScale => _cfg.GetCVar(CVars.DisplayUIScale);
|
||||||
|
|
||||||
private int GetConfigLightingQuality()
|
private int GetConfigLightingQuality()
|
||||||
{
|
{
|
||||||
var val = _cfg.GetCVar<int>("display.lightmapdivider");
|
var val = _cfg.GetCVar(CVars.DisplayLightMapDivider);
|
||||||
var soft = _cfg.GetCVar<bool>("display.softshadows");
|
var soft = _cfg.GetCVar(CVars.DisplaySoftShadows);
|
||||||
if (val >= 8)
|
if (val >= 8)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -198,20 +200,20 @@ namespace Content.Client.UserInterface
|
|||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
_cfg.SetCVar("display.lightmapdivider", 8);
|
_cfg.SetCVar(CVars.DisplayLightMapDivider, 8);
|
||||||
_cfg.SetCVar("display.softshadows", false);
|
_cfg.SetCVar(CVars.DisplaySoftShadows, false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
_cfg.SetCVar("display.lightmapdivider", 2);
|
_cfg.SetCVar(CVars.DisplayLightMapDivider, 2);
|
||||||
_cfg.SetCVar("display.softshadows", false);
|
_cfg.SetCVar(CVars.DisplaySoftShadows, false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_cfg.SetCVar("display.lightmapdivider", 2);
|
_cfg.SetCVar(CVars.DisplayLightMapDivider, 2);
|
||||||
_cfg.SetCVar("display.softshadows", true);
|
_cfg.SetCVar(CVars.DisplaySoftShadows, true);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_cfg.SetCVar("display.lightmapdivider", 1);
|
_cfg.SetCVar(CVars.DisplayLightMapDivider, 1);
|
||||||
_cfg.SetCVar("display.softshadows", true);
|
_cfg.SetCVar(CVars.DisplaySoftShadows, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
using Robust.Client.UserInterface;
|
|
||||||
using Robust.Client.UserInterface.Controls;
|
|
||||||
|
|
||||||
namespace Content.Client.UserInterface
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The status effects display on the right side of the screen.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class StatusEffectsUI : Control
|
|
||||||
{
|
|
||||||
public VBoxContainer VBox { get; }
|
|
||||||
|
|
||||||
public StatusEffectsUI()
|
|
||||||
{
|
|
||||||
VBox = new VBoxContainer();
|
|
||||||
AddChild(VBox);
|
|
||||||
|
|
||||||
LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin);
|
|
||||||
LayoutContainer.SetAnchorAndMarginPreset(this, LayoutContainer.LayoutPreset.TopRight, margin: 10);
|
|
||||||
LayoutContainer.SetMarginTop(this, 250);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,13 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
{
|
{
|
||||||
public sealed class StyleNano : StyleBase
|
public sealed class StyleNano : StyleBase
|
||||||
{
|
{
|
||||||
|
public const string StyleClassBorderedWindowPanel = "BorderedWindowPanel";
|
||||||
|
public const string StyleClassTransparentBorderedWindowPanel = "TransparentBorderedWindowPanel";
|
||||||
|
public const string StyleClassTooltipPanel = "tooltipBox";
|
||||||
|
public const string StyleClassTooltipAlertTitle = "tooltipAlertTitle";
|
||||||
|
public const string StyleClassTooltipAlertDescription = "tooltipAlertDesc";
|
||||||
|
public const string StyleClassTooltipAlertCooldown = "tooltipAlertCooldown";
|
||||||
|
|
||||||
public const string StyleClassSliderRed = "Red";
|
public const string StyleClassSliderRed = "Red";
|
||||||
public const string StyleClassSliderGreen = "Green";
|
public const string StyleClassSliderGreen = "Green";
|
||||||
public const string StyleClassSliderBlue = "Blue";
|
public const string StyleClassSliderBlue = "Blue";
|
||||||
@@ -55,6 +62,7 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
var notoSansDisplayBold14 = resCache.GetFont("/Fonts/NotoSansDisplay/NotoSansDisplay-Bold.ttf", 14);
|
var notoSansDisplayBold14 = resCache.GetFont("/Fonts/NotoSansDisplay/NotoSansDisplay-Bold.ttf", 14);
|
||||||
var notoSans16 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 16);
|
var notoSans16 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 16);
|
||||||
var notoSansBold16 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 16);
|
var notoSansBold16 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 16);
|
||||||
|
var notoSansBold18 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 18);
|
||||||
var notoSansBold20 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 20);
|
var notoSansBold20 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 20);
|
||||||
var textureCloseButton = resCache.GetTexture("/Textures/Interface/Nano/cross.svg.png");
|
var textureCloseButton = resCache.GetTexture("/Textures/Interface/Nano/cross.svg.png");
|
||||||
var windowHeaderTex = resCache.GetTexture("/Textures/Interface/Nano/window_header.png");
|
var windowHeaderTex = resCache.GetTexture("/Textures/Interface/Nano/window_header.png");
|
||||||
@@ -73,6 +81,20 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
windowBackground.SetPatchMargin(StyleBox.Margin.Horizontal | StyleBox.Margin.Bottom, 2);
|
windowBackground.SetPatchMargin(StyleBox.Margin.Horizontal | StyleBox.Margin.Bottom, 2);
|
||||||
windowBackground.SetExpandMargin(StyleBox.Margin.Horizontal | StyleBox.Margin.Bottom, 2);
|
windowBackground.SetExpandMargin(StyleBox.Margin.Horizontal | StyleBox.Margin.Bottom, 2);
|
||||||
|
|
||||||
|
var borderedWindowBackgroundTex = resCache.GetTexture("/Textures/Interface/Nano/window_background_bordered.png");
|
||||||
|
var borderedWindowBackground = new StyleBoxTexture
|
||||||
|
{
|
||||||
|
Texture = borderedWindowBackgroundTex,
|
||||||
|
};
|
||||||
|
borderedWindowBackground.SetPatchMargin(StyleBox.Margin.All, 2);
|
||||||
|
|
||||||
|
var borderedTransparentWindowBackgroundTex = resCache.GetTexture("/Textures/Interface/Nano/transparent_window_background_bordered.png");
|
||||||
|
var borderedTransparentWindowBackground = new StyleBoxTexture
|
||||||
|
{
|
||||||
|
Texture = borderedTransparentWindowBackgroundTex,
|
||||||
|
};
|
||||||
|
borderedTransparentWindowBackground.SetPatchMargin(StyleBox.Margin.All, 2);
|
||||||
|
|
||||||
var textureInvertedTriangle = resCache.GetTexture("/Textures/Interface/Nano/inverted_triangle.svg.png");
|
var textureInvertedTriangle = resCache.GetTexture("/Textures/Interface/Nano/inverted_triangle.svg.png");
|
||||||
|
|
||||||
var lineEditTex = resCache.GetTexture("/Textures/Interface/Nano/lineedit.png");
|
var lineEditTex = resCache.GetTexture("/Textures/Interface/Nano/lineedit.png");
|
||||||
@@ -147,7 +169,7 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
Texture = tooltipTexture,
|
Texture = tooltipTexture,
|
||||||
};
|
};
|
||||||
tooltipBox.SetPatchMargin(StyleBox.Margin.All, 2);
|
tooltipBox.SetPatchMargin(StyleBox.Margin.All, 2);
|
||||||
tooltipBox.SetContentMarginOverride(StyleBox.Margin.Horizontal, 5);
|
tooltipBox.SetContentMarginOverride(StyleBox.Margin.Horizontal, 7);
|
||||||
|
|
||||||
// Placeholder
|
// Placeholder
|
||||||
var placeholderTexture = resCache.GetTexture("/Textures/Interface/Nano/placeholder.png");
|
var placeholderTexture = resCache.GetTexture("/Textures/Interface/Nano/placeholder.png");
|
||||||
@@ -245,6 +267,19 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
{
|
{
|
||||||
new StyleProperty(PanelContainer.StylePropertyPanel, windowBackground),
|
new StyleProperty(PanelContainer.StylePropertyPanel, windowBackground),
|
||||||
}),
|
}),
|
||||||
|
// bordered window background
|
||||||
|
new StyleRule(
|
||||||
|
new SelectorElement(null, new[] {StyleClassBorderedWindowPanel}, null, null),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new StyleProperty(PanelContainer.StylePropertyPanel, borderedWindowBackground),
|
||||||
|
}),
|
||||||
|
new StyleRule(
|
||||||
|
new SelectorElement(null, new[] {StyleClassTransparentBorderedWindowPanel}, null, null),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new StyleProperty(PanelContainer.StylePropertyPanel, borderedTransparentWindowBackground),
|
||||||
|
}),
|
||||||
// Window header.
|
// Window header.
|
||||||
new StyleRule(
|
new StyleRule(
|
||||||
new SelectorElement(typeof(PanelContainer), new[] {SS14Window.StyleClassWindowHeader}, null, null),
|
new SelectorElement(typeof(PanelContainer), new[] {SS14Window.StyleClassWindowHeader}, null, null),
|
||||||
@@ -464,7 +499,7 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new StyleRule(new SelectorElement(typeof(PanelContainer), new[] {"tooltipBox"}, null, null), new[]
|
new StyleRule(new SelectorElement(typeof(PanelContainer), new [] { StyleClassTooltipPanel }, null, null), new[]
|
||||||
{
|
{
|
||||||
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
||||||
}),
|
}),
|
||||||
@@ -482,6 +517,20 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
new StyleProperty("font", notoSansItalic12),
|
new StyleProperty("font", notoSansItalic12),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// alert tooltip
|
||||||
|
new StyleRule(new SelectorElement(typeof(RichTextLabel), new[] {StyleClassTooltipAlertTitle}, null, null), new[]
|
||||||
|
{
|
||||||
|
new StyleProperty("font", notoSansBold18)
|
||||||
|
}),
|
||||||
|
new StyleRule(new SelectorElement(typeof(RichTextLabel), new[] {StyleClassTooltipAlertDescription}, null, null), new[]
|
||||||
|
{
|
||||||
|
new StyleProperty("font", notoSans16)
|
||||||
|
}),
|
||||||
|
new StyleRule(new SelectorElement(typeof(RichTextLabel), new[] {StyleClassTooltipAlertCooldown}, null, null), new[]
|
||||||
|
{
|
||||||
|
new StyleProperty("font", notoSans16)
|
||||||
|
}),
|
||||||
|
|
||||||
// Entity tooltip
|
// Entity tooltip
|
||||||
new StyleRule(
|
new StyleRule(
|
||||||
new SelectorElement(typeof(PanelContainer), new[] {ExamineSystem.StyleClassEntityTooltip}, null,
|
new SelectorElement(typeof(PanelContainer), new[] {ExamineSystem.StyleClassEntityTooltip}, null,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using Robust.Shared.Maths;
|
|||||||
namespace Content.IntegrationTests.Tests.Body
|
namespace Content.IntegrationTests.Tests.Body
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[TestOf(typeof(LungBehaviorComponent))]
|
[TestOf(typeof(LungBehavior))]
|
||||||
public class LungTest : ContentIntegrationTest
|
public class LungTest : ContentIntegrationTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
@@ -39,7 +39,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
var human = entityManager.SpawnEntity("HumanMob_Content", MapCoordinates.Nullspace);
|
var human = entityManager.SpawnEntity("HumanMob_Content", MapCoordinates.Nullspace);
|
||||||
|
|
||||||
Assert.That(human.TryGetComponent(out IBody body));
|
Assert.That(human.TryGetComponent(out IBody body));
|
||||||
Assert.That(body.TryGetMechanismBehaviors(out List<LungBehaviorComponent> lungs));
|
Assert.That(body.TryGetMechanismBehaviors(out List<LungBehavior> lungs));
|
||||||
Assert.That(lungs.Count, Is.EqualTo(1));
|
Assert.That(lungs.Count, Is.EqualTo(1));
|
||||||
Assert.That(human.TryGetComponent(out BloodstreamComponent bloodstream));
|
Assert.That(human.TryGetComponent(out BloodstreamComponent bloodstream));
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
human = entityManager.SpawnEntity("HumanMob_Content", coordinates);
|
human = entityManager.SpawnEntity("HumanMob_Content", coordinates);
|
||||||
|
|
||||||
Assert.True(human.TryGetComponent(out IBody body));
|
Assert.True(human.TryGetComponent(out IBody body));
|
||||||
Assert.True(body.HasMechanismBehavior<LungBehaviorComponent>());
|
Assert.True(body.HasMechanismBehavior<LungBehavior>());
|
||||||
Assert.True(human.TryGetComponent(out metabolism));
|
Assert.True(human.TryGetComponent(out metabolism));
|
||||||
Assert.False(metabolism.Suffocating);
|
Assert.False(metabolism.Suffocating);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Content.Server.GameObjects.Components.Body.Behavior;
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
using Content.Shared.GameObjects.Components.Body.Behavior;
|
||||||
using Content.Shared.GameObjects.Components.Body.Mechanism;
|
using Content.Shared.GameObjects.Components.Body.Mechanism;
|
||||||
using Content.Shared.GameObjects.Components.Body.Part;
|
using Content.Shared.GameObjects.Components.Body.Part;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -18,14 +18,11 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
[TestOf(typeof(SharedBodyComponent))]
|
[TestOf(typeof(SharedBodyComponent))]
|
||||||
[TestOf(typeof(SharedBodyPartComponent))]
|
[TestOf(typeof(SharedBodyPartComponent))]
|
||||||
[TestOf(typeof(SharedMechanismComponent))]
|
[TestOf(typeof(SharedMechanismComponent))]
|
||||||
[TestOf(typeof(MechanismBehaviorComponent))]
|
[TestOf(typeof(MechanismBehavior))]
|
||||||
public class MechanismBehaviorEventsTest : ContentIntegrationTest
|
public class MechanismBehaviorEventsTest : ContentIntegrationTest
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
private class TestMechanismBehavior : MechanismBehavior
|
||||||
private class TestBehaviorComponent : MechanismBehaviorComponent
|
|
||||||
{
|
{
|
||||||
public override string Name => nameof(MechanismBehaviorEventsTest) + "TestBehavior";
|
|
||||||
|
|
||||||
public bool WasAddedToBody;
|
public bool WasAddedToBody;
|
||||||
public bool WasAddedToPart;
|
public bool WasAddedToPart;
|
||||||
public bool WasAddedToPartInBody;
|
public bool WasAddedToPartInBody;
|
||||||
@@ -33,8 +30,6 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
public bool WasRemovedFromPart;
|
public bool WasRemovedFromPart;
|
||||||
public bool WasRemovedFromPartInBody;
|
public bool WasRemovedFromPartInBody;
|
||||||
|
|
||||||
public override void Update(float frameTime) { }
|
|
||||||
|
|
||||||
public bool NoAdded()
|
public bool NoAdded()
|
||||||
{
|
{
|
||||||
return !WasAddedToBody && !WasAddedToPart && !WasAddedToPartInBody;
|
return !WasAddedToBody && !WasAddedToPart && !WasAddedToPartInBody;
|
||||||
@@ -111,13 +106,7 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task EventsTest()
|
public async Task EventsTest()
|
||||||
{
|
{
|
||||||
var server = StartServerDummyTicker(new ServerContentIntegrationOption
|
var server = StartServerDummyTicker();
|
||||||
{
|
|
||||||
ContentBeforeIoC = () =>
|
|
||||||
{
|
|
||||||
IoCManager.Resolve<IComponentFactory>().Register<TestBehaviorComponent>();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
@@ -141,68 +130,68 @@ namespace Content.IntegrationTests.Tests.Body
|
|||||||
var mechanism = centerPart!.Mechanisms.First();
|
var mechanism = centerPart!.Mechanisms.First();
|
||||||
Assert.NotNull(mechanism);
|
Assert.NotNull(mechanism);
|
||||||
|
|
||||||
var component = mechanism.Owner.AddComponent<TestBehaviorComponent>();
|
mechanism.EnsureBehavior<TestMechanismBehavior>(out var behavior);
|
||||||
Assert.False(component.WasAddedToBody);
|
Assert.False(behavior.WasAddedToBody);
|
||||||
Assert.False(component.WasAddedToPart);
|
Assert.False(behavior.WasAddedToPart);
|
||||||
Assert.That(component.WasAddedToPartInBody);
|
Assert.That(behavior.WasAddedToPartInBody);
|
||||||
Assert.That(component.NoRemoved);
|
Assert.That(behavior.NoRemoved);
|
||||||
|
|
||||||
component.ResetAll();
|
behavior.ResetAll();
|
||||||
|
|
||||||
Assert.That(component.NoAdded);
|
Assert.That(behavior.NoAdded);
|
||||||
Assert.That(component.NoRemoved);
|
Assert.That(behavior.NoRemoved);
|
||||||
|
|
||||||
centerPart.RemoveMechanism(mechanism);
|
centerPart.RemoveMechanism(mechanism);
|
||||||
|
|
||||||
Assert.That(component.NoAdded);
|
Assert.That(behavior.NoAdded);
|
||||||
Assert.False(component.WasRemovedFromBody);
|
Assert.False(behavior.WasRemovedFromBody);
|
||||||
Assert.False(component.WasRemovedFromPart);
|
Assert.False(behavior.WasRemovedFromPart);
|
||||||
Assert.That(component.WasRemovedFromPartInBody);
|
Assert.That(behavior.WasRemovedFromPartInBody);
|
||||||
|
|
||||||
component.ResetAll();
|
behavior.ResetAll();
|
||||||
|
|
||||||
centerPart.TryAddMechanism(mechanism, true);
|
centerPart.TryAddMechanism(mechanism, true);
|
||||||
|
|
||||||
Assert.False(component.WasAddedToBody);
|
Assert.False(behavior.WasAddedToBody);
|
||||||
Assert.False(component.WasAddedToPart);
|
Assert.False(behavior.WasAddedToPart);
|
||||||
Assert.That(component.WasAddedToPartInBody);
|
Assert.That(behavior.WasAddedToPartInBody);
|
||||||
Assert.That(component.NoRemoved());
|
Assert.That(behavior.NoRemoved());
|
||||||
|
|
||||||
component.ResetAll();
|
behavior.ResetAll();
|
||||||
|
|
||||||
body.RemovePart(centerPart);
|
body.RemovePart(centerPart);
|
||||||
|
|
||||||
Assert.That(component.NoAdded);
|
Assert.That(behavior.NoAdded);
|
||||||
Assert.That(component.WasRemovedFromBody);
|
Assert.That(behavior.WasRemovedFromBody);
|
||||||
Assert.False(component.WasRemovedFromPart);
|
Assert.False(behavior.WasRemovedFromPart);
|
||||||
Assert.False(component.WasRemovedFromPartInBody);
|
Assert.False(behavior.WasRemovedFromPartInBody);
|
||||||
|
|
||||||
component.ResetAll();
|
behavior.ResetAll();
|
||||||
|
|
||||||
centerPart.RemoveMechanism(mechanism);
|
centerPart.RemoveMechanism(mechanism);
|
||||||
|
|
||||||
Assert.That(component.NoAdded);
|
Assert.That(behavior.NoAdded);
|
||||||
Assert.False(component.WasRemovedFromBody);
|
Assert.False(behavior.WasRemovedFromBody);
|
||||||
Assert.That(component.WasRemovedFromPart);
|
Assert.That(behavior.WasRemovedFromPart);
|
||||||
Assert.False(component.WasRemovedFromPartInBody);
|
Assert.False(behavior.WasRemovedFromPartInBody);
|
||||||
|
|
||||||
component.ResetAll();
|
behavior.ResetAll();
|
||||||
|
|
||||||
centerPart.TryAddMechanism(mechanism, true);
|
centerPart.TryAddMechanism(mechanism, true);
|
||||||
|
|
||||||
Assert.False(component.WasAddedToBody);
|
Assert.False(behavior.WasAddedToBody);
|
||||||
Assert.That(component.WasAddedToPart);
|
Assert.That(behavior.WasAddedToPart);
|
||||||
Assert.False(component.WasAddedToPartInBody);
|
Assert.False(behavior.WasAddedToPartInBody);
|
||||||
Assert.That(component.NoRemoved);
|
Assert.That(behavior.NoRemoved);
|
||||||
|
|
||||||
component.ResetAll();
|
behavior.ResetAll();
|
||||||
|
|
||||||
body.TryAddPart(centerSlot!, centerPart, true);
|
body.TryAddPart(centerSlot!, centerPart, true);
|
||||||
|
|
||||||
Assert.That(component.WasAddedToBody);
|
Assert.That(behavior.WasAddedToBody);
|
||||||
Assert.False(component.WasAddedToPart);
|
Assert.False(behavior.WasAddedToPart);
|
||||||
Assert.False(component.WasAddedToPartInBody);
|
Assert.False(behavior.WasAddedToPartInBody);
|
||||||
Assert.That(component.NoRemoved);
|
Assert.That(behavior.NoRemoved);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ namespace Content.IntegrationTests.Tests.Buckle
|
|||||||
human.Transform.LocalPosition += (100, 0);
|
human.Transform.LocalPosition += (100, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
await WaitUntil(server, () => !buckle.Buckled, maxTicks: 10);
|
await WaitUntil(server, () => !buckle.Buckled, 10);
|
||||||
|
|
||||||
Assert.False(buckle.Buckled);
|
Assert.False(buckle.Buckled);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
|
using Content.Shared;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Robust.Shared.Interfaces.Configuration;
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -31,7 +32,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
|||||||
|
|
||||||
server.Assert(() =>
|
server.Assert(() =>
|
||||||
{
|
{
|
||||||
configManager.SetCVar("game.lobbyenabled", lobbyEnabled);
|
configManager.SetCVar(CCVars.GameLobbyEnabled, lobbyEnabled);
|
||||||
|
|
||||||
Assert.That(gameTicker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
|
Assert.That(gameTicker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Client.GameObjects.Components.Mobs;
|
||||||
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Alert;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Robust.Client.Interfaces.UserInterface;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(ClientAlertsComponent))]
|
||||||
|
[TestOf(typeof(ServerAlertsComponent))]
|
||||||
|
public class AlertsComponentTests : ContentIntegrationTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task AlertsTest()
|
||||||
|
{
|
||||||
|
var (client, server) = await StartConnectedServerClientPair();
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
await client.WaitIdleAsync();
|
||||||
|
|
||||||
|
var serverPlayerManager = server.ResolveDependency<Robust.Server.Interfaces.Player.IPlayerManager>();
|
||||||
|
|
||||||
|
await server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
var player = serverPlayerManager.GetAllPlayers().Single();
|
||||||
|
var playerEnt = player.AttachedEntity;
|
||||||
|
Assert.NotNull(playerEnt);
|
||||||
|
var alertsComponent = playerEnt.GetComponent<ServerAlertsComponent>();
|
||||||
|
Assert.NotNull(alertsComponent);
|
||||||
|
|
||||||
|
// show 2 alerts
|
||||||
|
alertsComponent.ShowAlert(AlertType.Debug1);
|
||||||
|
alertsComponent.ShowAlert(AlertType.Debug2);
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitRunTicks(5);
|
||||||
|
await client.WaitRunTicks(5);
|
||||||
|
|
||||||
|
var clientPlayerMgr = client.ResolveDependency<IPlayerManager>();
|
||||||
|
var clientUIMgr = client.ResolveDependency<IUserInterfaceManager>();
|
||||||
|
await client.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
|
||||||
|
var local = clientPlayerMgr.LocalPlayer;
|
||||||
|
Assert.NotNull(local);
|
||||||
|
var controlled = local.ControlledEntity;
|
||||||
|
Assert.NotNull(controlled);
|
||||||
|
var alertsComponent = controlled.GetComponent<ClientAlertsComponent>();
|
||||||
|
Assert.NotNull(alertsComponent);
|
||||||
|
|
||||||
|
// find the alertsui
|
||||||
|
var alertsUI =
|
||||||
|
clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is AlertsUI) as AlertsUI;
|
||||||
|
Assert.NotNull(alertsUI);
|
||||||
|
|
||||||
|
// we should be seeing 3 alerts - our health, and the 2 debug alerts, in a specific order.
|
||||||
|
Assert.That(alertsUI.Grid.ChildCount, Is.EqualTo(3));
|
||||||
|
var alertControls = alertsUI.Grid.Children.Select(c => c as AlertControl);
|
||||||
|
var alertIDs = alertControls.Select(ac => ac.Alert.AlertType).ToArray();
|
||||||
|
var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug1, AlertType.Debug2};
|
||||||
|
Assert.That(alertIDs, Is.EqualTo(expectedIDs));
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
var player = serverPlayerManager.GetAllPlayers().Single();
|
||||||
|
var playerEnt = player.AttachedEntity;
|
||||||
|
Assert.NotNull(playerEnt);
|
||||||
|
var alertsComponent = playerEnt.GetComponent<ServerAlertsComponent>();
|
||||||
|
Assert.NotNull(alertsComponent);
|
||||||
|
|
||||||
|
alertsComponent.ClearAlert(AlertType.Debug1);
|
||||||
|
});
|
||||||
|
await server.WaitRunTicks(5);
|
||||||
|
await client.WaitRunTicks(5);
|
||||||
|
|
||||||
|
await client.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
|
||||||
|
var local = clientPlayerMgr.LocalPlayer;
|
||||||
|
Assert.NotNull(local);
|
||||||
|
var controlled = local.ControlledEntity;
|
||||||
|
Assert.NotNull(controlled);
|
||||||
|
var alertsComponent = controlled.GetComponent<ClientAlertsComponent>();
|
||||||
|
Assert.NotNull(alertsComponent);
|
||||||
|
|
||||||
|
// find the alertsui
|
||||||
|
var alertsUI =
|
||||||
|
clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is AlertsUI) as AlertsUI;
|
||||||
|
Assert.NotNull(alertsUI);
|
||||||
|
|
||||||
|
// we should be seeing only 2 alerts now because one was cleared
|
||||||
|
Assert.That(alertsUI.Grid.ChildCount, Is.EqualTo(2));
|
||||||
|
var alertControls = alertsUI.Grid.Children.Select(c => c as AlertControl);
|
||||||
|
var alertIDs = alertControls.Select(ac => ac.Alert.AlertType).ToArray();
|
||||||
|
var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug2};
|
||||||
|
Assert.That(alertIDs, Is.EqualTo(expectedIDs));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.GameObjects.Components.Gravity;
|
using Content.Server.GameObjects.Components.Gravity;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Gravity;
|
using Content.Shared.GameObjects.Components.Gravity;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
@@ -32,7 +33,7 @@ namespace Content.IntegrationTests.Tests.Gravity
|
|||||||
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
|
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
|
||||||
|
|
||||||
IEntity human = null;
|
IEntity human = null;
|
||||||
SharedStatusEffectsComponent statusEffects = null;
|
SharedAlertsComponent alerts = null;
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
@@ -57,7 +58,7 @@ namespace Content.IntegrationTests.Tests.Gravity
|
|||||||
|
|
||||||
human = entityManager.SpawnEntity("HumanMob_Content", coordinates);
|
human = entityManager.SpawnEntity("HumanMob_Content", coordinates);
|
||||||
|
|
||||||
Assert.True(human.TryGetComponent(out statusEffects));
|
Assert.True(human.TryGetComponent(out alerts));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Let WeightlessSystem and GravitySystem tick
|
// Let WeightlessSystem and GravitySystem tick
|
||||||
@@ -68,7 +69,7 @@ namespace Content.IntegrationTests.Tests.Gravity
|
|||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
// No gravity without a gravity generator
|
// No gravity without a gravity generator
|
||||||
Assert.True(statusEffects.Statuses.ContainsKey(StatusEffect.Weightless));
|
Assert.True(alerts.IsShowingAlert(AlertType.Weightless));
|
||||||
|
|
||||||
gravityGenerator = human.EnsureComponent<GravityGeneratorComponent>();
|
gravityGenerator = human.EnsureComponent<GravityGeneratorComponent>();
|
||||||
});
|
});
|
||||||
@@ -78,7 +79,7 @@ namespace Content.IntegrationTests.Tests.Gravity
|
|||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
Assert.False(statusEffects.Statuses.ContainsKey(StatusEffect.Weightless));
|
Assert.False(alerts.IsShowingAlert(AlertType.Weightless));
|
||||||
|
|
||||||
// Disable the gravity generator
|
// Disable the gravity generator
|
||||||
var args = new BreakageEventArgs {Owner = human};
|
var args = new BreakageEventArgs {Owner = human};
|
||||||
@@ -89,7 +90,7 @@ namespace Content.IntegrationTests.Tests.Gravity
|
|||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
Assert.False(statusEffects.Statuses.ContainsKey(StatusEffect.Weightless));
|
Assert.False(alerts.IsShowingAlert(AlertType.Weightless));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,7 @@ namespace Content.IntegrationTests.Tests.Lobby
|
|||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var lobbyCvar = CCVars.GameLobbyEnabled;
|
serverConfig.SetCVar(CCVars.GameLobbyEnabled, true);
|
||||||
serverConfig.SetCVar(lobbyCvar.Name, true);
|
|
||||||
|
|
||||||
serverTicker.RestartRound();
|
serverTicker.RestartRound();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
66
Content.Server/Commands/CommandUtils.cs
Normal file
66
Content.Server/Commands/CommandUtils.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Server.Interfaces.Console;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
|
||||||
|
namespace Content.Server.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utilities for writing commands
|
||||||
|
/// </summary>
|
||||||
|
public static class CommandUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the player session for the player with the indicated id,
|
||||||
|
/// sending a failure to the performer if unable to.
|
||||||
|
/// </summary>
|
||||||
|
public static bool TryGetSessionByUsernameOrId(IConsoleShell shell,
|
||||||
|
string usernameOrId, IPlayerSession performer, out IPlayerSession session)
|
||||||
|
{
|
||||||
|
var plyMgr = IoCManager.Resolve<IPlayerManager>();
|
||||||
|
if (plyMgr.TryGetSessionByUsername(usernameOrId, out session)) return true;
|
||||||
|
if (Guid.TryParse(usernameOrId, out var targetGuid))
|
||||||
|
{
|
||||||
|
if (plyMgr.TryGetSessionById(new NetUserId(targetGuid), out session)) return true;
|
||||||
|
shell.SendText(performer, "Unable to find user with that name/id.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shell.SendText(performer, "Unable to find user with that name/id.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the attached entity for the player session with the indicated id,
|
||||||
|
/// sending a failure to the performer if unable to.
|
||||||
|
/// </summary>
|
||||||
|
public static bool TryGetAttachedEntityByUsernameOrId(IConsoleShell shell,
|
||||||
|
string usernameOrId, IPlayerSession performer, out IEntity attachedEntity)
|
||||||
|
{
|
||||||
|
attachedEntity = null;
|
||||||
|
if (!TryGetSessionByUsernameOrId(shell, usernameOrId, performer, out var session)) return false;
|
||||||
|
if (session.AttachedEntity == null)
|
||||||
|
{
|
||||||
|
shell.SendText(performer, "User has no attached entity.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attachedEntity = session.AttachedEntity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if attached entity is null, returning false and sending a message
|
||||||
|
/// to performer if not.
|
||||||
|
/// </summary>
|
||||||
|
public static bool ValidateAttachedEntity(IConsoleShell shell, IPlayerSession performer, IEntity attachedEntity)
|
||||||
|
{
|
||||||
|
if (attachedEntity != null) return true;
|
||||||
|
shell.SendText(performer, "User has no attached entity.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Content.Server/Commands/Hungry.cs
Normal file
39
Content.Server/Commands/Hungry.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#nullable enable
|
||||||
|
using Content.Server.GameObjects.Components.Nutrition;
|
||||||
|
using Content.Shared.GameObjects.Components.Nutrition;
|
||||||
|
using Robust.Server.Interfaces.Console;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
|
||||||
|
namespace Content.Server.Commands
|
||||||
|
{
|
||||||
|
public class Hungry : IClientCommand
|
||||||
|
{
|
||||||
|
public string Command => "hungry";
|
||||||
|
public string Description => "Makes you hungry.";
|
||||||
|
public string Help => $"{Command}";
|
||||||
|
|
||||||
|
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||||
|
{
|
||||||
|
if (player == null)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "You cannot use this command unless you are a player.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.AttachedEntity == null)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "You cannot use this command without an entity.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.AttachedEntity.TryGetComponent(out HungerComponent? hunger))
|
||||||
|
{
|
||||||
|
shell.SendText(player, $"Your entity does not have a {nameof(HungerComponent)} component.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hungryThreshold = hunger.HungerThresholds[HungerThreshold.Starving];
|
||||||
|
hunger.CurrentHunger = hungryThreshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Interfaces;
|
using System;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -11,7 +12,8 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
|||||||
{
|
{
|
||||||
private const int PACKAGES_PER_TICK = 30;
|
private const int PACKAGES_PER_TICK = 30;
|
||||||
|
|
||||||
private readonly IRobustRandom _random = IoCManager.Resolve<IRobustRandom>();
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
private readonly Dictionary<int, List<NetworkDevice>> _devices = new Dictionary<int, List<NetworkDevice>>();
|
private readonly Dictionary<int, List<NetworkDevice>> _devices = new Dictionary<int, List<NetworkDevice>>();
|
||||||
private readonly Queue<NetworkPackage> _packages = new Queue<NetworkPackage>();
|
private readonly Queue<NetworkPackage> _packages = new Queue<NetworkPackage>();
|
||||||
|
|
||||||
@@ -40,11 +42,9 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
var i = PACKAGES_PER_TICK;
|
var count = Math.Min(PACKAGES_PER_TICK, _packages.Count);
|
||||||
while (_packages.Count > 0 && i > 0)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
i--;
|
|
||||||
|
|
||||||
var package = _packages.Dequeue();
|
var package = _packages.Dequeue();
|
||||||
|
|
||||||
if (package.Broadcast)
|
if (package.Broadcast)
|
||||||
@@ -72,7 +72,7 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
|||||||
Sender = sender,
|
Sender = sender,
|
||||||
Metadata = metadata
|
Metadata = metadata
|
||||||
};
|
};
|
||||||
|
|
||||||
_packages.Enqueue(package);
|
_packages.Enqueue(package);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
|||||||
{
|
{
|
||||||
var devices = DevicesForFrequency(netId, frequency);
|
var devices = DevicesForFrequency(netId, frequency);
|
||||||
|
|
||||||
var device = devices.Find(device => device.Address == address);
|
var device = devices.Find(dvc => dvc.Address == address);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,6 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
|||||||
public IReadOnlyDictionary<string, string> Data { get; set; }
|
public IReadOnlyDictionary<string, string> Data { get; set; }
|
||||||
public Metadata Metadata;
|
public Metadata Metadata;
|
||||||
public string Sender;
|
public string Sender;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
|||||||
private readonly int _netId;
|
private readonly int _netId;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool Open { get; internal set; }
|
public bool Open { get; private set; }
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public string Address { get; internal set; }
|
public string Address { get; private set; }
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public int Frequency { get; internal set; }
|
public int Frequency { get; private set; }
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool RecieveAll
|
public bool ReceiveAll
|
||||||
{
|
{
|
||||||
get => _network.GetDeviceReceiveAll(_netId, Frequency, Address);
|
get => _network.GetDeviceReceiveAll(_netId, Frequency, Address);
|
||||||
set => _network.SetDeviceReceiveAll(_netId, Frequency, Address, value);
|
set => _network.SetDeviceReceiveAll(_netId, Frequency, Address, value);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Server.Interfaces.GameTicking;
|
|||||||
using Content.Server.Interfaces.PDA;
|
using Content.Server.Interfaces.PDA;
|
||||||
using Content.Server.Sandbox;
|
using Content.Server.Sandbox;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.ContentPack;
|
using Robust.Shared.ContentPack;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -78,6 +79,7 @@ namespace Content.Server
|
|||||||
|
|
||||||
_gameTicker.Initialize();
|
_gameTicker.Initialize();
|
||||||
IoCManager.Resolve<RecipeManager>().Initialize();
|
IoCManager.Resolve<RecipeManager>().Initialize();
|
||||||
|
IoCManager.Resolve<AlertManager>().Initialize();
|
||||||
IoCManager.Resolve<BlackboardManager>().Initialize();
|
IoCManager.Resolve<BlackboardManager>().Initialize();
|
||||||
IoCManager.Resolve<ConsiderationsManager>().Initialize();
|
IoCManager.Resolve<ConsiderationsManager>().Initialize();
|
||||||
IoCManager.Resolve<IPDAUplinkManager>().Initialize();
|
IoCManager.Resolve<IPDAUplinkManager>().Initialize();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Items.Storage;
|
|||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
||||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.ActionBlocking;
|
using Content.Shared.GameObjects.Components.ActionBlocking;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
@@ -115,7 +116,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
CanStillInteract = _hands.Hands.Count() > CuffedHandCount;
|
CanStillInteract = _hands.Hands.Count() > CuffedHandCount;
|
||||||
|
|
||||||
OnCuffedStateChanged.Invoke();
|
OnCuffedStateChanged.Invoke();
|
||||||
UpdateStatusEffect();
|
UpdateAlert();
|
||||||
UpdateHeldItems();
|
UpdateHeldItems();
|
||||||
Dirty();
|
Dirty();
|
||||||
}
|
}
|
||||||
@@ -181,17 +182,17 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the status effect indicator on the HUD.
|
/// Updates the status effect indicator on the HUD.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateStatusEffect()
|
private void UpdateAlert()
|
||||||
{
|
{
|
||||||
if (Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (Owner.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
if (CanStillInteract)
|
if (CanStillInteract)
|
||||||
{
|
{
|
||||||
status.RemoveStatusEffect(StatusEffect.Cuffed);
|
status.ClearAlert(AlertType.Handcuffed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Cuffed, "/Textures/Interface/StatusEffects/Handcuffed/Handcuffed.png");
|
status.ShowAlert(AlertType.Handcuffed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +283,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
|
|
||||||
CanStillInteract = _hands.Hands.Count() > CuffedHandCount;
|
CanStillInteract = _hands.Hands.Count() > CuffedHandCount;
|
||||||
OnCuffedStateChanged.Invoke();
|
OnCuffedStateChanged.Invoke();
|
||||||
UpdateStatusEffect();
|
UpdateAlert();
|
||||||
Dirty();
|
Dirty();
|
||||||
|
|
||||||
if (CuffedHandCount == 0)
|
if (CuffedHandCount == 0)
|
||||||
|
|||||||
@@ -299,6 +299,7 @@ namespace Content.Server.GameObjects.Components.Arcade
|
|||||||
_component = component;
|
_component = component;
|
||||||
_allBlockGamePieces = (BlockGamePieceType[]) Enum.GetValues(typeof(BlockGamePieceType));
|
_allBlockGamePieces = (BlockGamePieceType[]) Enum.GetValues(typeof(BlockGamePieceType));
|
||||||
_internalNextPiece = GetRandomBlockGamePiece(_component._random);
|
_internalNextPiece = GetRandomBlockGamePiece(_component._random);
|
||||||
|
InitializeNewBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendHighscoreUpdate()
|
private void SendHighscoreUpdate()
|
||||||
@@ -315,8 +316,6 @@ namespace Content.Server.GameObjects.Components.Arcade
|
|||||||
|
|
||||||
public void StartGame()
|
public void StartGame()
|
||||||
{
|
{
|
||||||
InitializeNewBlock();
|
|
||||||
|
|
||||||
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Game));
|
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Game));
|
||||||
|
|
||||||
FullUpdate();
|
FullUpdate();
|
||||||
@@ -569,10 +568,10 @@ namespace Content.Server.GameObjects.Components.Arcade
|
|||||||
break;
|
break;
|
||||||
case BlockGamePlayerAction.Pause:
|
case BlockGamePlayerAction.Pause:
|
||||||
_running = false;
|
_running = false;
|
||||||
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Pause));
|
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Pause, _started));
|
||||||
break;
|
break;
|
||||||
case BlockGamePlayerAction.Unpause:
|
case BlockGamePlayerAction.Unpause:
|
||||||
if (!_gameOver)
|
if (!_gameOver && _started)
|
||||||
{
|
{
|
||||||
_running = true;
|
_running = true;
|
||||||
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Game));
|
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Game));
|
||||||
@@ -583,7 +582,7 @@ namespace Content.Server.GameObjects.Components.Arcade
|
|||||||
break;
|
break;
|
||||||
case BlockGamePlayerAction.ShowHighscores:
|
case BlockGamePlayerAction.ShowHighscores:
|
||||||
_running = false;
|
_running = false;
|
||||||
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Highscores));
|
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Highscores, _started));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -654,6 +653,7 @@ namespace Content.Server.GameObjects.Components.Arcade
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool IsGameOver => _field.Any(block => block.Position.Y == 0);
|
private bool IsGameOver => _field.Any(block => block.Position.Y == 0);
|
||||||
|
|
||||||
private void InvokeGameover()
|
private void InvokeGameover()
|
||||||
{
|
{
|
||||||
_running = false;
|
_running = false;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
@@ -22,7 +23,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
public void Update(float airPressure)
|
public void Update(float airPressure)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out IDamageableComponent damageable)) return;
|
if (!Owner.TryGetComponent(out IDamageableComponent damageable)) return;
|
||||||
Owner.TryGetComponent(out ServerStatusEffectsComponent status);
|
Owner.TryGetComponent(out ServerAlertsComponent status);
|
||||||
|
|
||||||
var highPressureMultiplier = 1f;
|
var highPressureMultiplier = 1f;
|
||||||
var lowPressureMultiplier = 1f;
|
var lowPressureMultiplier = 1f;
|
||||||
@@ -50,11 +51,11 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
|
|
||||||
if (pressure <= Atmospherics.HazardLowPressure)
|
if (pressure <= Atmospherics.HazardLowPressure)
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/lowpressure2.png", null);
|
status.ShowAlert(AlertType.LowPressure, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/lowpressure1.png", null);
|
status.ShowAlert(AlertType.LowPressure, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// High pressure.
|
// High pressure.
|
||||||
@@ -72,16 +73,16 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
|
|
||||||
if (pressure >= Atmospherics.HazardHighPressure)
|
if (pressure >= Atmospherics.HazardHighPressure)
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/highpressure2.png", null);
|
status.ShowAlert(AlertType.HighPressure, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/highpressure1.png", null);
|
status.ShowAlert(AlertType.HighPressure, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Normal pressure.
|
// Normal pressure.
|
||||||
default:
|
default:
|
||||||
status?.RemoveStatusEffect(StatusEffect.Pressure);
|
status?.ClearAlertCategory(AlertCategory.Pressure);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
AutoClose = false;
|
AutoClose = false;
|
||||||
Safety = false;
|
Safety = false;
|
||||||
|
|
||||||
if (Occludes && Owner.TryGetComponent(out OccluderComponent occluder))
|
|
||||||
{
|
|
||||||
occluder.Enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
State = DoorState.Open;
|
State = DoorState.Open;
|
||||||
SetAppearance(DoorVisualState.Open);
|
SetAppearance(DoorVisualState.Open);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Atmos;
|
|||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.GameObjects.Components.Temperature;
|
using Content.Server.GameObjects.Components.Temperature;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
@@ -93,15 +94,15 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
FireStacks = MathF.Min(0, FireStacks + 1);
|
FireStacks = MathF.Min(0, FireStacks + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Owner.TryGetComponent(out ServerStatusEffectsComponent status);
|
Owner.TryGetComponent(out ServerAlertsComponent status);
|
||||||
|
|
||||||
if (!OnFire)
|
if (!OnFire)
|
||||||
{
|
{
|
||||||
status?.RemoveStatusEffect(StatusEffect.Fire);
|
status?.ClearAlert(AlertType.Fire);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
status?.ChangeStatusEffect(StatusEffect.Fire, "/Textures/Interface/StatusEffects/Fire/fire.png", null);
|
status.ShowAlert(AlertType.Fire, onClickAlert: OnClickAlert);
|
||||||
|
|
||||||
if (FireStacks > 0)
|
if (FireStacks > 0)
|
||||||
{
|
{
|
||||||
@@ -153,6 +154,14 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnClickAlert(ClickAlertEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Player.TryGetComponent(out FlammableComponent flammable))
|
||||||
|
{
|
||||||
|
flammable.Resist();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CollideWith(IEntity collidedWith)
|
public void CollideWith(IEntity collidedWith)
|
||||||
{
|
{
|
||||||
if (!collidedWith.TryGetComponent(out FlammableComponent otherFlammable))
|
if (!collidedWith.TryGetComponent(out FlammableComponent otherFlammable))
|
||||||
|
|||||||
@@ -1,22 +1,14 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.Mobs;
|
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
|
||||||
using Content.Shared.GameObjects.Components.Body.Part;
|
using Content.Shared.GameObjects.Components.Body.Part;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.ComponentDependencies;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Log;
|
|
||||||
using Robust.Shared.ViewVariables;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Body.Behavior
|
namespace Content.Server.GameObjects.Components.Body.Behavior
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
public class BrainBehavior : MechanismBehavior
|
||||||
public class BrainBehaviorComponent : MechanismBehaviorComponent
|
|
||||||
{
|
{
|
||||||
public override string Name => "Brain";
|
|
||||||
|
|
||||||
protected override void OnAddedToBody(IBody body)
|
protected override void OnAddedToBody(IBody body)
|
||||||
{
|
{
|
||||||
base.OnAddedToBody(body);
|
base.OnAddedToBody(body);
|
||||||
@@ -66,9 +58,5 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
|
|
||||||
oldMind.Mind?.TransferTo(newEntity);
|
oldMind.Mind?.TransferTo(newEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,17 @@
|
|||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
using Content.Shared.GameObjects.Components.Body.Behavior;
|
||||||
using Content.Shared.GameObjects.Components.Body.Networks;
|
using Content.Shared.GameObjects.Components.Body.Networks;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Body.Behavior
|
namespace Content.Server.GameObjects.Components.Body.Behavior
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
public class HeartBehavior : MechanismBehavior
|
||||||
[ComponentReference(typeof(SharedHeartBehaviorComponent))]
|
|
||||||
public class HeartBehaviorComponent : SharedHeartBehaviorComponent
|
|
||||||
{
|
{
|
||||||
private float _accumulatedFrameTime;
|
private float _accumulatedFrameTime;
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
// TODO BODY do between pre and metabolism
|
// TODO BODY do between pre and metabolism
|
||||||
if (Mechanism?.Body == null ||
|
if (Parent.Body == null ||
|
||||||
!Mechanism.Body.Owner.HasComponent<SharedBloodstreamComponent>())
|
!Parent.Body.Owner.HasComponent<SharedBloodstreamComponent>())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -8,19 +8,15 @@ using Content.Server.GameObjects.Components.Body.Respiratory;
|
|||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
using Content.Shared.GameObjects.Components.Body.Behavior;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Interfaces.Timing;
|
using Robust.Shared.Interfaces.Timing;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Body.Behavior
|
namespace Content.Server.GameObjects.Components.Body.Behavior
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
public class LungBehavior : MechanismBehavior
|
||||||
[ComponentReference(typeof(SharedLungBehaviorComponent))]
|
|
||||||
public class LungBehaviorComponent : SharedLungBehaviorComponent
|
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
@@ -30,18 +26,24 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
|
|
||||||
[ViewVariables] public GasMixture Air { get; set; } = default!;
|
[ViewVariables] public GasMixture Air { get; set; } = default!;
|
||||||
|
|
||||||
[ViewVariables] public override float Temperature => Air.Temperature;
|
[ViewVariables] public float Temperature => Air.Temperature;
|
||||||
|
|
||||||
[ViewVariables] public override float Volume => Air.Volume;
|
[ViewVariables] public float Volume => Air.Volume;
|
||||||
|
|
||||||
[ViewVariables] public TimeSpan GaspPopupCooldown { get; private set; }
|
[ViewVariables] public TimeSpan GaspPopupCooldown { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables] public LungStatus Status { get; set; }
|
||||||
|
|
||||||
|
[ViewVariables] public float CycleDelay { get; set; }
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
Air = new GasMixture {Temperature = Atmospherics.NormalBodyTemperature};
|
Air = new GasMixture {Temperature = Atmospherics.NormalBodyTemperature};
|
||||||
|
|
||||||
|
serializer.DataField(this, l => l.CycleDelay, "cycleDelay", 2);
|
||||||
|
|
||||||
serializer.DataReadWriteFunction(
|
serializer.DataReadWriteFunction(
|
||||||
"volume",
|
"volume",
|
||||||
6,
|
6,
|
||||||
@@ -61,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
() => GaspPopupCooldown.TotalSeconds);
|
() => GaspPopupCooldown.TotalSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Gasp()
|
public void Gasp()
|
||||||
{
|
{
|
||||||
if (_gameTiming.CurTime >= _lastGaspPopupTime + GaspPopupCooldown)
|
if (_gameTiming.CurTime >= _lastGaspPopupTime + GaspPopupCooldown)
|
||||||
{
|
{
|
||||||
@@ -148,7 +150,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
_accumulatedFrameTime = absoluteTime - delay;
|
_accumulatedFrameTime = absoluteTime - delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Inhale(float frameTime)
|
public void Inhale(float frameTime)
|
||||||
{
|
{
|
||||||
if (Body != null && Body.Owner.TryGetComponent(out InternalsComponent? internals)
|
if (Body != null && Body.Owner.TryGetComponent(out InternalsComponent? internals)
|
||||||
&& internals.BreathToolEntity != null && internals.GasTankEntity != null
|
&& internals.BreathToolEntity != null && internals.GasTankEntity != null
|
||||||
@@ -176,7 +178,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
ToBloodstream(Air);
|
ToBloodstream(Air);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Exhale(float frameTime)
|
public void Exhale(float frameTime)
|
||||||
{
|
{
|
||||||
if (!Owner.Transform.Coordinates.TryGetTileAir(out var tileAir))
|
if (!Owner.Transform.Coordinates.TryGetTileAir(out var tileAir))
|
||||||
{
|
{
|
||||||
@@ -218,4 +220,11 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
Air.Merge(lungRemoved);
|
Air.Merge(lungRemoved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum LungStatus
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Inhaling,
|
||||||
|
Exhaling
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,33 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
|
using Content.Shared.GameObjects.Components.Body.Behavior;
|
||||||
using Content.Shared.GameObjects.Components.Body.Mechanism;
|
using Content.Shared.GameObjects.Components.Body.Mechanism;
|
||||||
using Content.Shared.GameObjects.Components.Body.Part;
|
using Content.Shared.GameObjects.Components.Body.Part;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Body.Behavior
|
namespace Content.Server.GameObjects.Components.Body.Behavior
|
||||||
{
|
{
|
||||||
public abstract class MechanismBehaviorComponent : Component, IMechanismBehavior
|
public abstract class MechanismBehavior : IMechanismBehavior
|
||||||
{
|
{
|
||||||
public IBody? Body => Part?.Body;
|
public IBody? Body => Part?.Body;
|
||||||
|
|
||||||
public IBodyPart? Part => Mechanism?.Part;
|
public IBodyPart? Part => Parent.Part;
|
||||||
|
|
||||||
public IMechanism? Mechanism => Owner.GetComponentOrNull<IMechanism>();
|
public IMechanism Parent { get; private set; } = default!;
|
||||||
|
|
||||||
protected override void Startup()
|
public IEntity Owner => Parent.Owner;
|
||||||
|
|
||||||
|
public virtual void ExposeData(ObjectSerializer serializer) { }
|
||||||
|
|
||||||
|
public virtual void Initialize(IMechanism parent)
|
||||||
{
|
{
|
||||||
base.Startup();
|
Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Startup()
|
||||||
|
{
|
||||||
if (Part == null)
|
if (Part == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -33,8 +43,6 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Update(float frameTime);
|
|
||||||
|
|
||||||
public void AddedToBody(IBody body)
|
public void AddedToBody(IBody body)
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(Body);
|
DebugTools.AssertNotNull(Body);
|
||||||
@@ -98,5 +106,7 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior
|
|||||||
protected virtual void OnRemovedFromPart(IBodyPart old) { }
|
protected virtual void OnRemovedFromPart(IBodyPart old) { }
|
||||||
|
|
||||||
protected virtual void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart) { }
|
protected virtual void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart) { }
|
||||||
|
|
||||||
|
public virtual void Update(float frameTime) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,33 +2,29 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
using Content.Shared.GameObjects.Components.Body.Behavior;
|
||||||
using Content.Shared.GameObjects.Components.Body.Part;
|
using Content.Shared.GameObjects.Components.Body.Part;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Body.Mechanism
|
namespace Content.Server.GameObjects.Components.Body.Behavior
|
||||||
{
|
{
|
||||||
public static class MechanismExtensions
|
public static class MechanismExtensions
|
||||||
{
|
{
|
||||||
public static bool HasMechanismBehavior<T>(this IBody body)
|
public static bool HasMechanismBehavior<T>(this IBody body) where T : IMechanismBehavior
|
||||||
{
|
{
|
||||||
return body.Parts.Values.Any(p => p.HasMechanismBehavior<T>());
|
return body.Parts.Values.Any(p => p.HasMechanismBehavior<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasMechanismBehavior<T>(this IBodyPart part)
|
public static bool HasMechanismBehavior<T>(this IBodyPart part) where T : IMechanismBehavior
|
||||||
{
|
{
|
||||||
return part.Mechanisms.Any(m => m.Owner.HasComponent<T>());
|
return part.Mechanisms.Any(m => m.HasBehavior<T>());
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasMechanismBehavior<T>(this IMechanism mechanism)
|
|
||||||
{
|
|
||||||
return mechanism.Owner.HasComponent<T>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<IMechanismBehavior> GetMechanismBehaviors(this IBody body)
|
public static IEnumerable<IMechanismBehavior> GetMechanismBehaviors(this IBody body)
|
||||||
{
|
{
|
||||||
foreach (var part in body.Parts.Values)
|
foreach (var part in body.Parts.Values)
|
||||||
foreach (var mechanism in part.Mechanisms)
|
foreach (var mechanism in part.Mechanisms)
|
||||||
foreach (var behavior in mechanism.Owner.GetAllComponents<IMechanismBehavior>())
|
foreach (var behavior in mechanism.Behaviors.Values)
|
||||||
{
|
{
|
||||||
yield return behavior;
|
yield return behavior;
|
||||||
}
|
}
|
||||||
@@ -52,10 +48,11 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism
|
|||||||
{
|
{
|
||||||
foreach (var part in body.Parts.Values)
|
foreach (var part in body.Parts.Values)
|
||||||
foreach (var mechanism in part.Mechanisms)
|
foreach (var mechanism in part.Mechanisms)
|
||||||
|
foreach (var behavior in mechanism.Behaviors.Values)
|
||||||
{
|
{
|
||||||
if (mechanism.Owner.TryGetComponent(out T? behavior))
|
if (behavior is T tBehavior)
|
||||||
{
|
{
|
||||||
yield return behavior;
|
yield return tBehavior;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.Components.Chemistry;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.GameObjects.Components.Body.Networks;
|
using Content.Shared.GameObjects.Components.Body.Networks;
|
||||||
using Content.Shared.GameObjects.Components.Chemistry;
|
using Content.Shared.GameObjects.Components.Chemistry;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Body.Behavior
|
namespace Content.Server.GameObjects.Components.Body.Behavior
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Where reagents go when ingested. Tracks ingested reagents over time, and
|
/// Where reagents go when ingested. Tracks ingested reagents over time, and
|
||||||
/// eventually transfers them to <see cref="SharedBloodstreamComponent"/> once digested.
|
/// eventually transfers them to <see cref="SharedBloodstreamComponent"/> once digested.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class SharedStomachBehaviorComponent : MechanismBehaviorComponent
|
public class StomachBehavior : MechanismBehavior
|
||||||
{
|
{
|
||||||
public override string Name => "Stomach";
|
|
||||||
|
|
||||||
private float _accumulatedFrameTime;
|
private float _accumulatedFrameTime;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,7 +45,7 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior
|
|||||||
|
|
||||||
_accumulatedFrameTime -= 1;
|
_accumulatedFrameTime -= 1;
|
||||||
|
|
||||||
if (!Body.Owner.TryGetComponent(out SharedSolutionContainerComponent? solution) ||
|
if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solution) ||
|
||||||
!Body.Owner.TryGetComponent(out SharedBloodstreamComponent? bloodstream))
|
!Body.Owner.TryGetComponent(out SharedBloodstreamComponent? bloodstream))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -58,7 +58,7 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior
|
|||||||
foreach (var delta in _reagentDeltas.ToList())
|
foreach (var delta in _reagentDeltas.ToList())
|
||||||
{
|
{
|
||||||
//Increment lifetime of reagents
|
//Increment lifetime of reagents
|
||||||
delta.Increment(frameTime);
|
delta.Increment(1);
|
||||||
if (delta.Lifetime > _digestionDelay)
|
if (delta.Lifetime > _digestionDelay)
|
||||||
{
|
{
|
||||||
solution.TryRemoveReagent(delta.ReagentId, delta.Quantity);
|
solution.TryRemoveReagent(delta.ReagentId, delta.Quantity);
|
||||||
@@ -112,6 +112,18 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior
|
|||||||
serializer.DataField(ref _digestionDelay, "digestionDelay", 20);
|
serializer.DataField(ref _digestionDelay, "digestionDelay", 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Startup()
|
||||||
|
{
|
||||||
|
base.Startup();
|
||||||
|
|
||||||
|
if (!Owner.EnsureComponent(out SolutionContainerComponent solution))
|
||||||
|
{
|
||||||
|
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
solution.MaxVolume = InitialMaxVolume;
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanTransferSolution(Solution solution)
|
public bool CanTransferSolution(Solution solution)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solutionComponent))
|
if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solutionComponent))
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using Content.Server.GameObjects.Components.Chemistry;
|
|
||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Log;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Body.Behavior
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedStomachBehaviorComponent))]
|
|
||||||
public class StomachBehaviorComponent : SharedStomachBehaviorComponent
|
|
||||||
{
|
|
||||||
protected override void Startup()
|
|
||||||
{
|
|
||||||
base.Startup();
|
|
||||||
|
|
||||||
if (!Owner.EnsureComponent(out SolutionContainerComponent solution))
|
|
||||||
{
|
|
||||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
solution.MaxVolume = InitialMaxVolume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@ using Content.Server.GameObjects.Components.Mobs.State;
|
|||||||
using Content.Server.GameObjects.Components.Pulling;
|
using Content.Server.GameObjects.Components.Pulling;
|
||||||
using Content.Server.GameObjects.Components.Strap;
|
using Content.Server.GameObjects.Components.Strap;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Buckle;
|
using Content.Shared.GameObjects.Components.Buckle;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Strap;
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
@@ -15,21 +16,16 @@ using Content.Shared.GameObjects.Verbs;
|
|||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Utility;
|
using Content.Shared.Utility;
|
||||||
using NFluidsynth;
|
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.EntitySystemMessages;
|
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.ComponentDependencies;
|
using Robust.Shared.GameObjects.ComponentDependencies;
|
||||||
using Robust.Shared.GameObjects.Components.Transform;
|
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Map;
|
|
||||||
using Robust.Shared.Interfaces.Timing;
|
using Robust.Shared.Interfaces.Timing;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
@@ -39,12 +35,10 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class BuckleComponent : SharedBuckleComponent, IInteractHand
|
public class BuckleComponent : SharedBuckleComponent, IInteractHand
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
[ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null;
|
[ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null;
|
||||||
[ComponentDependency] private readonly ServerStatusEffectsComponent? _serverStatusEffectsComponent = null;
|
[ComponentDependency] private readonly ServerAlertsComponent? _serverAlertsComponent = null;
|
||||||
[ComponentDependency] private readonly StunnableComponent? _stunnableComponent = null;
|
[ComponentDependency] private readonly StunnableComponent? _stunnableComponent = null;
|
||||||
[ComponentDependency] private readonly MobStateManagerComponent? _mobStateManagerComponent = null;
|
[ComponentDependency] private readonly MobStateManagerComponent? _mobStateManagerComponent = null;
|
||||||
|
|
||||||
@@ -69,7 +63,10 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private TimeSpan _buckleTime;
|
private TimeSpan _buckleTime;
|
||||||
|
|
||||||
public Vector2? BuckleOffset { get; private set; }
|
/// <summary>
|
||||||
|
/// The position offset that is being applied to this entity if buckled.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2 BuckleOffset { get; private set; }
|
||||||
|
|
||||||
private StrapComponent? _buckledTo;
|
private StrapComponent? _buckledTo;
|
||||||
|
|
||||||
@@ -91,20 +88,6 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public override bool Buckled => BuckledTo != null;
|
public override bool Buckled => BuckledTo != null;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if the entity was inserted or removed from a container
|
|
||||||
/// before updating, false otherwise.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
private bool ContainerChanged { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if the entity was forcefully moved while buckled and should
|
|
||||||
/// unbuckle next update, false otherwise
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
private bool Moved { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of space that this entity occupies in a
|
/// The amount of space that this entity occupies in a
|
||||||
/// <see cref="StrapComponent"/>.
|
/// <see cref="StrapComponent"/>.
|
||||||
@@ -116,26 +99,38 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
/// Shows or hides the buckled status effect depending on if the
|
/// Shows or hides the buckled status effect depending on if the
|
||||||
/// entity is buckled or not.
|
/// entity is buckled or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BuckleStatus()
|
private void UpdateBuckleStatus()
|
||||||
{
|
{
|
||||||
if (_serverStatusEffectsComponent != null)
|
if (_serverAlertsComponent == null)
|
||||||
{
|
{
|
||||||
if (Buckled)
|
return;
|
||||||
{
|
}
|
||||||
_serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon);
|
|
||||||
}
|
if (Buckled)
|
||||||
else
|
{
|
||||||
{
|
_serverAlertsComponent.ShowAlert(BuckledTo != null ? BuckledTo.BuckledAlertType : AlertType.Buckled,
|
||||||
_serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled);
|
onClickAlert: OnClickAlert);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_serverAlertsComponent.ClearAlertCategory(AlertCategory.Buckled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnClickAlert(ClickAlertEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Player.TryGetComponent(out BuckleComponent? buckle))
|
||||||
|
{
|
||||||
|
buckle.TryUnbuckle(args.Player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reattaches this entity to the strap, modifying its position and rotation.
|
/// Reattaches this entity to the strap, modifying its position and rotation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="strap">The strap to reattach to.</param>
|
/// <param name="strap">The strap to reattach to.</param>
|
||||||
private void ReAttach(StrapComponent strap)
|
public void ReAttach(StrapComponent strap)
|
||||||
{
|
{
|
||||||
var ownTransform = Owner.Transform;
|
var ownTransform = Owner.Transform;
|
||||||
var strapTransform = strap.Owner.Transform;
|
var strapTransform = strap.Owner.Transform;
|
||||||
@@ -161,7 +156,7 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
if (strapTransform.WorldRotation.GetCardinalDir() == Direction.North)
|
if (strapTransform.WorldRotation.GetCardinalDir() == Direction.North)
|
||||||
{
|
{
|
||||||
BuckleOffset = (0, 0.15f);
|
BuckleOffset = (0, 0.15f);
|
||||||
ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset!.Value;
|
ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -266,8 +261,7 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_entitySystem.GetEntitySystem<AudioSystem>()
|
EntitySystem.Get<AudioSystem>().PlayFromEntity(strap.BuckleSound, Owner);
|
||||||
.PlayFromEntity(strap.BuckleSound, Owner);
|
|
||||||
|
|
||||||
if (!strap.TryAdd(this))
|
if (!strap.TryAdd(this))
|
||||||
{
|
{
|
||||||
@@ -283,13 +277,10 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
BuckledTo = strap;
|
BuckledTo = strap;
|
||||||
|
|
||||||
ReAttach(strap);
|
ReAttach(strap);
|
||||||
BuckleStatus();
|
UpdateBuckleStatus();
|
||||||
|
|
||||||
SendMessage(new BuckleMessage(Owner, to));
|
SendMessage(new BuckleMessage(Owner, to));
|
||||||
|
|
||||||
Owner.EntityManager.EventBus.SubscribeEvent<MoveEvent>(EventSource.Local, this, MoveEvent);
|
|
||||||
|
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out PullableComponent? pullableComponent))
|
if (Owner.TryGetComponent(out PullableComponent? pullableComponent))
|
||||||
{
|
{
|
||||||
if (pullableComponent.Puller != null)
|
if (pullableComponent.Puller != null)
|
||||||
@@ -315,12 +306,12 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public bool TryUnbuckle(IEntity user, bool force = false)
|
public bool TryUnbuckle(IEntity user, bool force = false)
|
||||||
{
|
{
|
||||||
if (!Buckled)
|
if (BuckledTo == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StrapComponent oldBuckledTo = BuckledTo!;
|
var oldBuckledTo = BuckledTo;
|
||||||
|
|
||||||
if (!force)
|
if (!force)
|
||||||
{
|
{
|
||||||
@@ -360,21 +351,15 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
EntitySystem.Get<StandingStateSystem>().Standing(Owner);
|
EntitySystem.Get<StandingStateSystem>().Standing(Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mobStateManagerComponent != null)
|
_mobStateManagerComponent?.CurrentMobState.EnterState(Owner);
|
||||||
{
|
|
||||||
_mobStateManagerComponent.CurrentMobState.EnterState(Owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
BuckleStatus();
|
UpdateBuckleStatus();
|
||||||
|
|
||||||
oldBuckledTo.Remove(this);
|
oldBuckledTo.Remove(this);
|
||||||
_entitySystem.GetEntitySystem<AudioSystem>()
|
EntitySystem.Get<AudioSystem>().PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner);
|
||||||
.PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner);
|
|
||||||
|
|
||||||
SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner));
|
SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner));
|
||||||
|
|
||||||
Owner.EntityManager.EventBus.UnsubscribeEvent<MoveEvent>(EventSource.Local, this);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,90 +387,6 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
return TryBuckle(user, to);
|
return TryBuckle(user, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a buckled entity should be unbuckled from moving
|
|
||||||
/// too far from its strap.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="moveEvent">The move event of a buckled entity.</param>
|
|
||||||
private void MoveEvent(MoveEvent moveEvent)
|
|
||||||
{
|
|
||||||
if (moveEvent.Sender != Owner)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuckledTo == null || !BuckleOffset.HasValue)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var bucklePosition = BuckledTo.Owner.Transform.Coordinates.Offset(BuckleOffset.Value);
|
|
||||||
|
|
||||||
if (moveEvent.NewPosition.InRange(_entityManager, bucklePosition, 0.2f))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Moved = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the owner is inserted or removed from a container,
|
|
||||||
/// to synchronize the state of buckling.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message received</param>
|
|
||||||
private void InsertIntoContainer(ContainerModifiedMessage message)
|
|
||||||
{
|
|
||||||
if (message.Entity != Owner)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContainerChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Synchronizes the state of buckling depending on whether the entity
|
|
||||||
/// was inserted or removed from a container, and whether or not
|
|
||||||
/// its current strap (if there is one) has also been put into or removed
|
|
||||||
/// from the same container as well.
|
|
||||||
/// </summary>
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (BuckledTo == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Moved)
|
|
||||||
{
|
|
||||||
TryUnbuckle(Owner, true);
|
|
||||||
Moved = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ContainerChanged)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var contained = ContainerHelpers.TryGetContainer(Owner, out var ownContainer);
|
|
||||||
var strapContained = ContainerHelpers.TryGetContainer(BuckledTo.Owner, out var strapContainer);
|
|
||||||
|
|
||||||
if (contained != strapContained || ownContainer != strapContainer)
|
|
||||||
{
|
|
||||||
TryUnbuckle(Owner, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contained && !strapContained)
|
|
||||||
{
|
|
||||||
ReAttach(BuckledTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
ContainerChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
@@ -499,32 +400,21 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
_unbuckleDelay = TimeSpan.FromSeconds(seconds);
|
_unbuckleDelay = TimeSpan.FromSeconds(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
_entityManager.EventBus.SubscribeEvent<EntInsertedIntoContainerMessage>(EventSource.Local, this, InsertIntoContainer);
|
|
||||||
_entityManager.EventBus.SubscribeEvent<EntRemovedFromContainerMessage>(EventSource.Local, this, InsertIntoContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Startup()
|
protected override void Startup()
|
||||||
{
|
{
|
||||||
base.Startup();
|
base.Startup();
|
||||||
BuckleStatus();
|
UpdateBuckleStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnRemove()
|
public override void OnRemove()
|
||||||
{
|
{
|
||||||
base.OnRemove();
|
base.OnRemove();
|
||||||
|
|
||||||
_entityManager.EventBus.UnsubscribeEvents(this);
|
|
||||||
|
|
||||||
BuckledTo?.Remove(this);
|
BuckledTo?.Remove(this);
|
||||||
|
|
||||||
TryUnbuckle(Owner, true);
|
TryUnbuckle(Owner, true);
|
||||||
|
|
||||||
_buckleTime = default;
|
_buckleTime = default;
|
||||||
BuckleStatus();
|
UpdateBuckleStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ComponentState GetComponentState()
|
public override ComponentState GetComponentState()
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
var trueTarget = target ?? user;
|
var trueTarget = target ?? user;
|
||||||
|
|
||||||
if (!trueTarget.TryGetComponent(out IBody body) ||
|
if (!trueTarget.TryGetComponent(out IBody body) ||
|
||||||
!body.TryGetMechanismBehaviors<StomachBehaviorComponent>(out var stomachs))
|
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ using Robust.Server.Interfaces.GameObjects;
|
|||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -28,18 +26,24 @@ namespace Content.Server.GameObjects.Components
|
|||||||
|
|
||||||
private Regex _validation;
|
private Regex _validation;
|
||||||
|
|
||||||
public event Action<Dictionary<string, string>> OnConfigUpdate;
|
public override void OnAdd()
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.OnAdd();
|
||||||
|
|
||||||
if (UserInterface != null)
|
if (UserInterface != null)
|
||||||
{
|
{
|
||||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnRemove()
|
||||||
|
{
|
||||||
|
base.OnRemove();
|
||||||
|
if (UserInterface != null)
|
||||||
|
{
|
||||||
|
UserInterface.OnReceiveMessage -= UserInterfaceOnReceiveMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
@@ -48,7 +52,7 @@ namespace Content.Server.GameObjects.Components
|
|||||||
(list) => FillConfiguration(list, _config, ""),
|
(list) => FillConfiguration(list, _config, ""),
|
||||||
() => _config.Keys.ToList());
|
() => _config.Keys.ToList());
|
||||||
|
|
||||||
serializer.DataReadFunction("vailidation", "^[a-zA-Z0-9 ]*$", value => _validation = new Regex("^[a-zA-Z0-9 ]*$", RegexOptions.Compiled));
|
serializer.DataReadFunction("validation", "^[a-zA-Z0-9 ]*$", value => _validation = new Regex("^[a-zA-Z0-9 ]*$", RegexOptions.Compiled));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetConfig(string name)
|
public string GetConfig(string name)
|
||||||
@@ -90,22 +94,19 @@ namespace Content.Server.GameObjects.Components
|
|||||||
{
|
{
|
||||||
var value = msg.Config.GetValueOrDefault(key);
|
var value = msg.Config.GetValueOrDefault(key);
|
||||||
|
|
||||||
if (_validation != null && !_validation.IsMatch(value) && value != "")
|
if (value == null || _validation != null && !_validation.IsMatch(value) && value != "")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_config[key] = value;
|
_config[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnConfigUpdate(_config);
|
SendMessage(new ConfigUpdatedComponentMessage(config));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserInterface()
|
private void UpdateUserInterface()
|
||||||
{
|
{
|
||||||
if (UserInterface == null)
|
UserInterface?.SetState(new ConfigurationBoundUserInterfaceState(_config));
|
||||||
return;
|
|
||||||
|
|
||||||
UserInterface.SetState(new ConfigurationBoundUserInterfaceState(_config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FillConfiguration<T>(List<string> list, Dictionary<string, T> configuration, T value){
|
private static void FillConfiguration<T>(List<string> list, Dictionary<string, T> configuration, T value){
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter;
|
|||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.GameObjects.Components;
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.Components.Disposal;
|
using Content.Shared.GameObjects.Components.Disposal;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
@@ -603,12 +604,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
var network = IoCManager.Resolve<IDeviceNetwork>();
|
|
||||||
_connection = new WiredNetworkConnection(OnReceiveNetMessage, false, Owner);
|
_connection = new WiredNetworkConnection(OnReceiveNetMessage, false, Owner);
|
||||||
|
|
||||||
if (Owner.TryGetComponent<ConfigurationComponent>(out var configuration))
|
|
||||||
configuration.OnConfigUpdate += OnConfigUpdate;
|
|
||||||
|
|
||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,6 +669,9 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
|
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
|
case SharedConfigurationComponent.ConfigUpdatedComponentMessage msg:
|
||||||
|
OnConfigUpdate(msg.Config);
|
||||||
|
break;
|
||||||
case RelayMovementEntityMessage msg:
|
case RelayMovementEntityMessage msg:
|
||||||
if (!msg.Entity.TryGetComponent(out HandsComponent? hands) ||
|
if (!msg.Entity.TryGetComponent(out HandsComponent? hands) ||
|
||||||
hands.Count == 0 ||
|
hands.Count == 0 ||
|
||||||
@@ -745,7 +744,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicated code here, not sure how else to get actor inside to make UserInterface happy.
|
// Duplicated code here, not sure how else to get actor inside to make UserInterface happy.
|
||||||
|
|
||||||
if (IsValidInteraction(eventArgs))
|
if (IsValidInteraction(eventArgs))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.GameObjects.Components.Stack;
|
using Content.Server.GameObjects.Components.Stack;
|
||||||
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Utility;
|
using Content.Shared.Utility;
|
||||||
@@ -8,6 +9,7 @@ using Robust.Shared.GameObjects.Systems;
|
|||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Items
|
namespace Content.Server.GameObjects.Components.Items
|
||||||
@@ -33,23 +35,52 @@ namespace Content.Server.GameObjects.Components.Items
|
|||||||
Owner.EnsureComponent<StackComponent>();
|
Owner.EnsureComponent<StackComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool HasBaseTurf(ContentTileDefinition tileDef, string baseTurf)
|
||||||
|
{
|
||||||
|
foreach (var tileBaseTurf in tileDef.BaseTurfs)
|
||||||
|
{
|
||||||
|
if (baseTurf == tileBaseTurf)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlaceAt(IMapGrid mapGrid, EntityCoordinates location, ushort tileId, float offset = 0)
|
||||||
|
{
|
||||||
|
mapGrid.SetTile(location.Offset(new Vector2(offset, offset)), new Tile(tileId));
|
||||||
|
EntitySystem.Get<AudioSystem>().PlayAtCoords("/Audio/Items/genhit.ogg", location, AudioHelpers.WithVariation(0.125f));
|
||||||
|
}
|
||||||
|
|
||||||
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
if (!Owner.TryGetComponent(out StackComponent stack)) return;
|
if (!Owner.TryGetComponent(out StackComponent stack)) return;
|
||||||
|
|
||||||
var attacked = eventArgs.Target;
|
var location = eventArgs.ClickLocation.AlignWithClosestGridTile();
|
||||||
var mapGrid = _mapManager.GetGrid(eventArgs.ClickLocation.GetGridId(Owner.EntityManager));
|
var locationMap = location.ToMap(Owner.EntityManager);
|
||||||
var tile = mapGrid.GetTileRef(eventArgs.ClickLocation);
|
|
||||||
var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId];
|
|
||||||
|
|
||||||
if (tileDef.IsSubFloor && attacked == null && stack.Use(1))
|
var desiredTile = (ContentTileDefinition)_tileDefinitionManager[_outputTile];
|
||||||
|
|
||||||
|
if (_mapManager.TryGetGrid(location.GetGridId(Owner.EntityManager), out var mapGrid))
|
||||||
{
|
{
|
||||||
var desiredTile = _tileDefinitionManager[_outputTile];
|
var tile = mapGrid.GetTileRef(location);
|
||||||
mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId));
|
var baseTurf = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId];
|
||||||
EntitySystem.Get<AudioSystem>().PlayAtCoords("/Audio/Items/genhit.ogg", eventArgs.ClickLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (HasBaseTurf(desiredTile, baseTurf.Name) && eventArgs.Target == null && stack.Use(1))
|
||||||
|
{
|
||||||
|
PlaceAt(mapGrid, location, desiredTile.TileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(HasBaseTurf(desiredTile, "space"))
|
||||||
|
{
|
||||||
|
mapGrid = _mapManager.CreateGrid(locationMap.MapId);
|
||||||
|
mapGrid.WorldPosition = locationMap.Position;
|
||||||
|
location = new EntityCoordinates(mapGrid.GridEntityId, Vector2.Zero);
|
||||||
|
PlaceAt(mapGrid, location, desiredTile.TileId, mapGrid.TileSize/2f);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ namespace Content.Server.GameObjects.Components.Metabolism
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lungs = _body.GetMechanismBehaviors<LungBehaviorComponent>().ToArray();
|
var lungs = _body.GetMechanismBehaviors<LungBehavior>().ToArray();
|
||||||
|
|
||||||
var needs = NeedsAndDeficit(frameTime);
|
var needs = NeedsAndDeficit(frameTime);
|
||||||
var used = 0f;
|
var used = 0f;
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Server.Commands;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Robust.Server.Interfaces.Console;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Players;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(SharedAlertsComponent))]
|
||||||
|
public sealed class ServerAlertsComponent : SharedAlertsComponent
|
||||||
|
{
|
||||||
|
|
||||||
|
protected override void Startup()
|
||||||
|
{
|
||||||
|
base.Startup();
|
||||||
|
|
||||||
|
if (EntitySystem.TryGet<WeightlessSystem>(out var weightlessSystem))
|
||||||
|
{
|
||||||
|
weightlessSystem.AddAlert(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.WarningS("alert", "weightlesssystem not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRemove()
|
||||||
|
{
|
||||||
|
if (EntitySystem.TryGet<WeightlessSystem>(out var weightlessSystem))
|
||||||
|
{
|
||||||
|
weightlessSystem.RemoveAlert(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.WarningS("alert", "weightlesssystem not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnRemove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ComponentState GetComponentState()
|
||||||
|
{
|
||||||
|
return new AlertsComponentState(CreateAlertStatesArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
||||||
|
{
|
||||||
|
base.HandleNetworkMessage(message, netChannel, session);
|
||||||
|
|
||||||
|
if (session == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(session));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case ClickAlertMessage msg:
|
||||||
|
{
|
||||||
|
var player = session.AttachedEntity;
|
||||||
|
|
||||||
|
if (player != Owner)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement clicking other status effects in the HUD
|
||||||
|
if (AlertManager.TryDecode(msg.EncodedAlert, out var alert))
|
||||||
|
{
|
||||||
|
PerformAlertClickCallback(alert, player);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.WarningS("alert", "unrecognized encoded alert {0}", msg.EncodedAlert);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ShowAlert : IClientCommand
|
||||||
|
{
|
||||||
|
public string Command => "showalert";
|
||||||
|
public string Description => "Shows an alert for a player, defaulting to current player";
|
||||||
|
public string Help => "showalert <alertType> <severity, -1 if no severity> <name or userID, omit for current player>";
|
||||||
|
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args)
|
||||||
|
{
|
||||||
|
var attachedEntity = player.AttachedEntity;
|
||||||
|
if (args.Length > 2)
|
||||||
|
{
|
||||||
|
var target = args[2];
|
||||||
|
if (!Commands.CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return;
|
||||||
|
|
||||||
|
|
||||||
|
if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "user has no alerts component");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var alertType = args[0];
|
||||||
|
var severity = args[1];
|
||||||
|
var alertMgr = IoCManager.Resolve<AlertManager>();
|
||||||
|
if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "unrecognized alertType " + alertType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!short.TryParse(severity, out var sevint))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "invalid severity " + sevint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ClearAlert : IClientCommand
|
||||||
|
{
|
||||||
|
public string Command => "clearalert";
|
||||||
|
public string Description => "Clears an alert for a player, defaulting to current player";
|
||||||
|
public string Help => "clearalert <alertType> <name or userID, omit for current player>";
|
||||||
|
|
||||||
|
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args)
|
||||||
|
{
|
||||||
|
var attachedEntity = player.AttachedEntity;
|
||||||
|
if (args.Length > 1)
|
||||||
|
{
|
||||||
|
var target = args[1];
|
||||||
|
if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return;
|
||||||
|
|
||||||
|
if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "user has no alerts component");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var alertType = args[0];
|
||||||
|
var alertMgr = IoCManager.Resolve<AlertManager>();
|
||||||
|
if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "unrecognized alertType " + alertType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
alertsComponent.ClearAlert(alert.AlertType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Content.Server.GameObjects.Components.Atmos;
|
|
||||||
using Content.Server.GameObjects.Components.Buckle;
|
|
||||||
using Content.Server.GameObjects.Components.Movement;
|
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
|
||||||
using Content.Shared.GameObjects.Components.Pulling;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.Interfaces;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
using Robust.Shared.Interfaces.Network;
|
|
||||||
using Robust.Shared.Players;
|
|
||||||
using Robust.Shared.ViewVariables;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Mobs
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedStatusEffectsComponent))]
|
|
||||||
public sealed class ServerStatusEffectsComponent : SharedStatusEffectsComponent
|
|
||||||
{
|
|
||||||
[ViewVariables]
|
|
||||||
private readonly Dictionary<StatusEffect, StatusEffectStatus> _statusEffects = new Dictionary<StatusEffect, StatusEffectStatus>();
|
|
||||||
|
|
||||||
public override IReadOnlyDictionary<StatusEffect, StatusEffectStatus> Statuses => _statusEffects;
|
|
||||||
|
|
||||||
protected override void Startup()
|
|
||||||
{
|
|
||||||
base.Startup();
|
|
||||||
|
|
||||||
EntitySystem.Get<WeightlessSystem>().AddStatus(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnRemove()
|
|
||||||
{
|
|
||||||
EntitySystem.Get<WeightlessSystem>().RemoveStatus(this);
|
|
||||||
|
|
||||||
base.OnRemove();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ComponentState GetComponentState()
|
|
||||||
{
|
|
||||||
return new StatusEffectComponentState(_statusEffects);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ChangeStatusEffectIcon(StatusEffect effect, string icon)
|
|
||||||
{
|
|
||||||
if (_statusEffects.TryGetValue(effect, out var value) && value.Icon == icon)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_statusEffects[effect] = new StatusEffectStatus()
|
|
||||||
{Icon = icon, Cooldown = value.Cooldown};
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ChangeStatusEffectCooldown(StatusEffect effect, ValueTuple<TimeSpan, TimeSpan> cooldown)
|
|
||||||
{
|
|
||||||
if (_statusEffects.TryGetValue(effect, out var value)
|
|
||||||
&& value.Cooldown == cooldown)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_statusEffects[effect] = new StatusEffectStatus()
|
|
||||||
{
|
|
||||||
Icon = value.Icon, Cooldown = cooldown
|
|
||||||
};
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ChangeStatusEffect(StatusEffect effect, string icon, ValueTuple<TimeSpan, TimeSpan>? cooldown)
|
|
||||||
{
|
|
||||||
_statusEffects[effect] = new StatusEffectStatus()
|
|
||||||
{Icon = icon, Cooldown = cooldown};
|
|
||||||
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void RemoveStatusEffect(StatusEffect effect)
|
|
||||||
{
|
|
||||||
if (!_statusEffects.Remove(effect))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
|
||||||
{
|
|
||||||
base.HandleNetworkMessage(message, netChannel, session);
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(session));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case ClickStatusMessage msg:
|
|
||||||
{
|
|
||||||
var player = session.AttachedEntity;
|
|
||||||
|
|
||||||
if (player != Owner)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement clicking other status effects in the HUD
|
|
||||||
switch (msg.Effect)
|
|
||||||
{
|
|
||||||
case StatusEffect.Buckled:
|
|
||||||
if (!player.TryGetComponent(out BuckleComponent buckle))
|
|
||||||
break;
|
|
||||||
|
|
||||||
buckle.TryUnbuckle(player);
|
|
||||||
break;
|
|
||||||
case StatusEffect.Piloting:
|
|
||||||
if (!player.TryGetComponent(out ShuttleControllerComponent controller))
|
|
||||||
break;
|
|
||||||
|
|
||||||
controller.RemoveController();
|
|
||||||
break;
|
|
||||||
case StatusEffect.Pulling:
|
|
||||||
EntitySystem
|
|
||||||
.Get<SharedPullingSystem>()
|
|
||||||
.GetPulled(player)?
|
|
||||||
.GetComponentOrNull<SharedPullableComponent>()?
|
|
||||||
.TryStopPull();
|
|
||||||
|
|
||||||
break;
|
|
||||||
case StatusEffect.Fire:
|
|
||||||
if (!player.TryGetComponent(out FlammableComponent flammable))
|
|
||||||
break;
|
|
||||||
|
|
||||||
flammable.Resist();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
player.PopupMessage(msg.Effect.ToString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||||
@@ -17,10 +18,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
|||||||
appearance.SetData(DamageStateVisuals.State, DamageState.Critical);
|
appearance.SetData(DamageStateVisuals.State, DamageState.Critical);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (entity.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
status.ShowAlert(AlertType.HumanCrit); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it
|
||||||
"/Textures/Interface/StatusEffects/Human/humancrit-0.png"); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
|
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||||
@@ -18,10 +19,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
|||||||
appearance.SetData(DamageStateVisuals.State, DamageState.Dead);
|
appearance.SetData(DamageStateVisuals.State, DamageState.Dead);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (entity.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
status.ShowAlert(AlertType.HumanDead);
|
||||||
"/Textures/Interface/StatusEffects/Human/humandead.png");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayComponent))
|
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayComponent))
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||||
@@ -51,9 +52,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
|||||||
// TODO: Might want to add an OnRemove() to IMobState since those are where these components are being used
|
// TODO: Might want to add an OnRemove() to IMobState since those are where these components are being used
|
||||||
base.OnRemove();
|
base.OnRemove();
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (Owner.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
status.RemoveStatusEffect(StatusEffect.Health);
|
status.ClearAlert(AlertType.HumanHealth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out ServerOverlayEffectsComponent overlay))
|
if (Owner.TryGetComponent(out ServerOverlayEffectsComponent overlay))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.GameObjects.Components.Damage;
|
using Content.Server.GameObjects.Components.Damage;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||||
@@ -27,15 +28,14 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
|||||||
|
|
||||||
public override void UpdateState(IEntity entity)
|
public override void UpdateState(IEntity entity)
|
||||||
{
|
{
|
||||||
if (!entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (!entity.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.TryGetComponent(out IDamageableComponent damageable))
|
if (!entity.TryGetComponent(out IDamageableComponent damageable))
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
status.ShowAlert(AlertType.HumanHealth, 0);
|
||||||
"/Textures/Interface/StatusEffects/Human/human0.png");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,10 +49,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var modifier = (int) (ruinable.TotalDamage / (threshold / 7f));
|
var modifier = (short) (ruinable.TotalDamage / (threshold / 7f));
|
||||||
|
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
status.ShowAlert(AlertType.HumanHealth, modifier);
|
||||||
"/Textures/Interface/StatusEffects/Human/human" + modifier + ".png");
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -63,10 +62,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var modifier = (int) (damageable.TotalDamage / (threshold / 7f));
|
var modifier = (short) (damageable.TotalDamage / (threshold / 7f));
|
||||||
|
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
status.ShowAlert(AlertType.HumanHealth, modifier);
|
||||||
"/Textures/Interface/StatusEffects/Human/human" + modifier + ".png");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Movement;
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
@@ -89,7 +90,7 @@ namespace Content.Server.GameObjects.Components.Mobs
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!StunStart.HasValue || !StunEnd.HasValue ||
|
if (!StunStart.HasValue || !StunEnd.HasValue ||
|
||||||
!Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
!Owner.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -102,7 +103,7 @@ namespace Content.Server.GameObjects.Components.Mobs
|
|||||||
|
|
||||||
if (progress >= length)
|
if (progress >= length)
|
||||||
{
|
{
|
||||||
Owner.SpawnTimer(250, () => status.RemoveStatusEffect(StatusEffect.Stun), StatusRemoveCancellation.Token);
|
Owner.SpawnTimer(250, () => status.ClearAlert(AlertType.Stun), StatusRemoveCancellation.Token);
|
||||||
LastStun = null;
|
LastStun = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Content.Server.GameObjects.Components.Items.Storage;
|
|||||||
using Content.Shared.GameObjects.Components.Morgue;
|
using Content.Shared.GameObjects.Components.Morgue;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -52,9 +53,20 @@ namespace Content.Server.GameObjects.Components.Morgue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanOpen(IEntity user, bool silent = false)
|
||||||
|
{
|
||||||
|
if (Cooking)
|
||||||
|
{
|
||||||
|
if (!silent) Owner.PopupMessage(user, Loc.GetString("Safety first, not while it's active!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return base.CanOpen(user, silent);
|
||||||
|
}
|
||||||
|
|
||||||
public void Cremate()
|
public void Cremate()
|
||||||
{
|
{
|
||||||
if (Cooking) return;
|
if (Cooking) return;
|
||||||
|
if (Open) return;
|
||||||
|
|
||||||
Appearance?.SetData(CrematoriumVisuals.Burning, true);
|
Appearance?.SetData(CrematoriumVisuals.Burning, true);
|
||||||
Cooking = true;
|
Cooking = true;
|
||||||
@@ -64,15 +76,18 @@ namespace Content.Server.GameObjects.Components.Morgue
|
|||||||
Appearance?.SetData(CrematoriumVisuals.Burning, false);
|
Appearance?.SetData(CrematoriumVisuals.Burning, false);
|
||||||
Cooking = false;
|
Cooking = false;
|
||||||
|
|
||||||
for (var i = Contents.ContainedEntities.Count - 1; i >= 0; i--)
|
if (Contents.ContainedEntities.Count > 0)
|
||||||
{
|
{
|
||||||
var item = Contents.ContainedEntities[i];
|
for (var i = Contents.ContainedEntities.Count - 1; i >= 0; i--)
|
||||||
Contents.Remove(item);
|
{
|
||||||
item.Delete();
|
var item = Contents.ContainedEntities[i];
|
||||||
}
|
Contents.Remove(item);
|
||||||
|
item.Delete();
|
||||||
|
}
|
||||||
|
|
||||||
var ash = Owner.EntityManager.SpawnEntity("Ash", Owner.Transform.Coordinates);
|
var ash = Owner.EntityManager.SpawnEntity("Ash", Owner.Transform.Coordinates);
|
||||||
Contents.Insert(ash);
|
Contents.Insert(ash);
|
||||||
|
}
|
||||||
|
|
||||||
TryOpenStorage(Owner);
|
TryOpenStorage(Owner);
|
||||||
|
|
||||||
@@ -85,7 +100,7 @@ namespace Content.Server.GameObjects.Components.Morgue
|
|||||||
{
|
{
|
||||||
protected override void GetData(IEntity user, CrematoriumEntityStorageComponent component, VerbData data)
|
protected override void GetData(IEntity user, CrematoriumEntityStorageComponent component, VerbData data)
|
||||||
{
|
{
|
||||||
if (!ActionBlockerSystem.CanInteract(user) || component.Cooking)
|
if (!ActionBlockerSystem.CanInteract(user) || component.Cooking || component.Open)
|
||||||
{
|
{
|
||||||
data.Visibility = VerbVisibility.Invisible;
|
data.Visibility = VerbVisibility.Invisible;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using Content.Shared.GameObjects.Components.Movement;
|
#nullable enable
|
||||||
|
using Content.Shared.GameObjects.Components.Buckle;
|
||||||
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Movement
|
namespace Content.Server.GameObjects.Components.Movement
|
||||||
@@ -8,8 +11,8 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class ClimbingComponent : SharedClimbingComponent
|
public class ClimbingComponent : SharedClimbingComponent
|
||||||
{
|
{
|
||||||
private bool _isClimbing = false;
|
private bool _isClimbing;
|
||||||
private ClimbController _climbController = default;
|
private ClimbController? _climbController;
|
||||||
|
|
||||||
public override bool IsClimbing
|
public override bool IsClimbing
|
||||||
{
|
{
|
||||||
@@ -29,6 +32,19 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
||||||
|
{
|
||||||
|
base.HandleMessage(message, component);
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case BuckleMessage msg:
|
||||||
|
if (msg.Buckled)
|
||||||
|
IsClimbing = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Make the owner climb from one point to another
|
/// Make the owner climb from one point to another
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Content.Server.GameObjects.Components.Buckle;
|
using Content.Server.GameObjects.Components.Buckle;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Movement;
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
using Content.Shared.GameObjects.Components.Strap;
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
@@ -31,9 +32,9 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
private bool _movingRight;
|
private bool _movingRight;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon to be displayed when piloting from this chair.
|
/// ID of the alert to show when piloting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string _pilotingIcon = default!;
|
private AlertType _pilotingAlertType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity that's currently controlling this component.
|
/// The entity that's currently controlling this component.
|
||||||
@@ -137,7 +138,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
if (_controller != null ||
|
if (_controller != null ||
|
||||||
!entity.TryGetComponent(out MindComponent? mind) ||
|
!entity.TryGetComponent(out MindComponent? mind) ||
|
||||||
mind.Mind == null ||
|
mind.Mind == null ||
|
||||||
!Owner.TryGetComponent(out ServerStatusEffectsComponent? status))
|
!Owner.TryGetComponent(out ServerAlertsComponent? status))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -145,7 +146,15 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
mind.Mind.Visit(Owner);
|
mind.Mind.Visit(Owner);
|
||||||
_controller = entity;
|
_controller = entity;
|
||||||
|
|
||||||
status.ChangeStatusEffectIcon(StatusEffect.Piloting, _pilotingIcon);
|
status.ShowAlert(_pilotingAlertType, onClickAlert: OnClickAlert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClickAlert(ClickAlertEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Player.TryGetComponent(out ShuttleControllerComponent? controller))
|
||||||
|
{
|
||||||
|
controller.RemoveController();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -177,9 +186,9 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
/// <param name="entity">The entity to update</param>
|
/// <param name="entity">The entity to update</param>
|
||||||
private void UpdateRemovedEntity(IEntity entity)
|
private void UpdateRemovedEntity(IEntity entity)
|
||||||
{
|
{
|
||||||
if (Owner.TryGetComponent(out ServerStatusEffectsComponent? status))
|
if (Owner.TryGetComponent(out ServerAlertsComponent? status))
|
||||||
{
|
{
|
||||||
status.RemoveStatusEffect(StatusEffect.Piloting);
|
status.ClearAlert(_pilotingAlertType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out MindComponent? mind))
|
if (entity.TryGetComponent(out MindComponent? mind))
|
||||||
@@ -211,13 +220,13 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
serializer.DataField(ref _pilotingIcon, "pilotingIcon", "/Textures/Interface/StatusEffects/Buckle/buckled.png");
|
serializer.DataField(ref _pilotingAlertType, "pilotingAlertType", AlertType.PilotingShuttle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
Owner.EnsureComponent<ServerStatusEffectsComponent>();
|
Owner.EnsureComponent<ServerAlertsComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components.Transform;
|
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
@@ -34,8 +31,6 @@ namespace Content.Server.GameObjects.Components.NodeContainer
|
|||||||
{
|
{
|
||||||
node.Initialize(Owner);
|
node.Initialize(Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
Owner.EntityManager.EventBus.SubscribeEvent<RotateEvent>(EventSource.Local, this, RotateEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Startup()
|
protected override void Startup()
|
||||||
@@ -55,16 +50,5 @@ namespace Content.Server.GameObjects.Components.NodeContainer
|
|||||||
}
|
}
|
||||||
base.OnRemove();
|
base.OnRemove();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RotateEvent(RotateEvent ev)
|
|
||||||
{
|
|
||||||
if (ev.Sender != Owner || ev.NewRotation == ev.OldRotation)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var rotatableNode in Nodes.OfType<IRotatableNode>())
|
|
||||||
{
|
|
||||||
rotatableNode.RotateEvent(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!target.TryGetComponent(out IBody body) ||
|
if (!target.TryGetComponent(out IBody body) ||
|
||||||
!body.TryGetMechanismBehaviors<StomachBehaviorComponent>(out var stomachs))
|
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.Components.Body.Behavior;
|
||||||
using Content.Server.GameObjects.Components.Chemistry;
|
using Content.Server.GameObjects.Components.Chemistry;
|
||||||
using Content.Server.GameObjects.Components.GUI;
|
using Content.Server.GameObjects.Components.GUI;
|
||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
@@ -133,7 +134,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
var trueTarget = target ?? user;
|
var trueTarget = target ?? user;
|
||||||
|
|
||||||
if (!trueTarget.TryGetComponent(out IBody? body) ||
|
if (!trueTarget.TryGetComponent(out IBody? body) ||
|
||||||
!body.TryGetMechanismBehaviors<SharedStomachBehaviorComponent>(out var stomachs))
|
!body.TryGetMechanismBehaviors<StomachBehavior>(out var stomachs))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
@@ -70,11 +71,11 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static readonly Dictionary<HungerThreshold, string> HungerThresholdImages = new Dictionary<HungerThreshold, string>
|
public static readonly Dictionary<HungerThreshold, AlertType> HungerThresholdAlertTypes = new Dictionary<HungerThreshold, AlertType>
|
||||||
{
|
{
|
||||||
{ HungerThreshold.Overfed, "/Textures/Interface/StatusEffects/Hunger/Overfed.png" },
|
{ HungerThreshold.Overfed, AlertType.Overfed },
|
||||||
{ HungerThreshold.Peckish, "/Textures/Interface/StatusEffects/Hunger/Peckish.png" },
|
{ HungerThreshold.Peckish, AlertType.Peckish },
|
||||||
{ HungerThreshold.Starving, "/Textures/Interface/StatusEffects/Hunger/Starving.png" },
|
{ HungerThreshold.Starving, AlertType.Starving },
|
||||||
};
|
};
|
||||||
|
|
||||||
public void HungerThresholdEffect(bool force = false)
|
public void HungerThresholdEffect(bool force = false)
|
||||||
@@ -89,15 +90,15 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
Owner.TryGetComponent(out ServerStatusEffectsComponent statusEffectsComponent);
|
Owner.TryGetComponent(out ServerAlertsComponent alertsComponent);
|
||||||
|
|
||||||
if (HungerThresholdImages.TryGetValue(_currentHungerThreshold, out var statusTexture))
|
if (HungerThresholdAlertTypes.TryGetValue(_currentHungerThreshold, out var alertId))
|
||||||
{
|
{
|
||||||
statusEffectsComponent?.ChangeStatusEffectIcon(StatusEffect.Hunger, statusTexture);
|
alertsComponent?.ShowAlert(alertId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
statusEffectsComponent?.RemoveStatusEffect(StatusEffect.Hunger);
|
alertsComponent?.ClearAlertCategory(AlertCategory.Hunger);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_currentHungerThreshold)
|
switch (_currentHungerThreshold)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
@@ -62,11 +63,11 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
{ThirstThreshold.Dead, 0.0f},
|
{ThirstThreshold.Dead, 0.0f},
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly Dictionary<ThirstThreshold, string> ThirstThresholdImages = new Dictionary<ThirstThreshold, string>
|
public static readonly Dictionary<ThirstThreshold, AlertType> ThirstThresholdAlertTypes = new Dictionary<ThirstThreshold, AlertType>
|
||||||
{
|
{
|
||||||
{ThirstThreshold.OverHydrated, "/Textures/Interface/StatusEffects/Thirst/OverHydrated.png"},
|
{ThirstThreshold.OverHydrated, AlertType.Overhydrated},
|
||||||
{ThirstThreshold.Thirsty, "/Textures/Interface/StatusEffects/Thirst/Thirsty.png"},
|
{ThirstThreshold.Thirsty, AlertType.Thirsty},
|
||||||
{ThirstThreshold.Parched, "/Textures/Interface/StatusEffects/Thirst/Parched.png"},
|
{ThirstThreshold.Parched, AlertType.Parched},
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
@@ -87,15 +88,15 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
Owner.TryGetComponent(out ServerStatusEffectsComponent statusEffectsComponent);
|
Owner.TryGetComponent(out ServerAlertsComponent alertsComponent);
|
||||||
|
|
||||||
if (ThirstThresholdImages.TryGetValue(_currentThirstThreshold, out var statusTexture))
|
if (ThirstThresholdAlertTypes.TryGetValue(_currentThirstThreshold, out var alertId))
|
||||||
{
|
{
|
||||||
statusEffectsComponent?.ChangeStatusEffectIcon(StatusEffect.Thirst, statusTexture);
|
alertsComponent?.ShowAlert(alertId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
statusEffectsComponent?.RemoveStatusEffect(StatusEffect.Thirst);
|
alertsComponent?.ClearAlertCategory(AlertCategory.Thirst);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_currentThirstThreshold)
|
switch (_currentThirstThreshold)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||||||
using Content.Server.GameObjects.Components.Access;
|
using Content.Server.GameObjects.Components.Access;
|
||||||
using Content.Server.GameObjects.Components.GUI;
|
using Content.Server.GameObjects.Components.GUI;
|
||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
|
using Content.Server.GameObjects.Components.Paper;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||||
using Content.Server.Interfaces.PDA;
|
using Content.Server.Interfaces.PDA;
|
||||||
@@ -39,13 +40,19 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
[Dependency] private readonly IPDAUplinkManager _uplinkManager = default!;
|
[Dependency] private readonly IPDAUplinkManager _uplinkManager = default!;
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
[ViewVariables] private Container _idSlot = default!;
|
[ViewVariables] private ContainerSlot _idSlot = default!;
|
||||||
|
[ViewVariables] private ContainerSlot _penSlot = default!;
|
||||||
|
|
||||||
[ViewVariables] private bool _lightOn;
|
[ViewVariables] private bool _lightOn;
|
||||||
[ViewVariables] private string _startingIdCard = default!;
|
|
||||||
[ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1;
|
[ViewVariables] private string? _startingIdCard = default!;
|
||||||
|
[ViewVariables] private string? _startingPen = default!;
|
||||||
|
|
||||||
[ViewVariables] public string? OwnerName { get; private set; }
|
[ViewVariables] public string? OwnerName { get; private set; }
|
||||||
|
|
||||||
[ViewVariables] public IdCardComponent? ContainedID { get; private set; }
|
[ViewVariables] public IdCardComponent? ContainedID { get; private set; }
|
||||||
|
[ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntity == null;
|
||||||
|
[ViewVariables] public bool PenSlotEmpty => _penSlot.ContainedEntity == null;
|
||||||
|
|
||||||
[ViewVariables] private UplinkAccount? _syndicateUplinkAccount;
|
[ViewVariables] private UplinkAccount? _syndicateUplinkAccount;
|
||||||
|
|
||||||
@@ -62,22 +69,34 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
serializer.DataField(ref _startingIdCard, "idCard", "AssistantIDCard");
|
serializer.DataField(ref _startingIdCard, "idCard", "AssistantIDCard");
|
||||||
|
serializer.DataField(ref _startingPen, "pen", "Pen");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
_idSlot = ContainerManagerComponent.Ensure<Container>("pda_entity_container", Owner, out var existed);
|
_idSlot = ContainerManagerComponent.Ensure<ContainerSlot>("pda_entity_container", Owner);
|
||||||
|
_penSlot = ContainerManagerComponent.Ensure<ContainerSlot>("pda_pen_slot", Owner);
|
||||||
|
|
||||||
if (UserInterface != null)
|
if (UserInterface != null)
|
||||||
{
|
{
|
||||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.Coordinates);
|
if (!string.IsNullOrEmpty(_startingIdCard))
|
||||||
var idCardComponent = idCard.GetComponent<IdCardComponent>();
|
{
|
||||||
_idSlot.Insert(idCardComponent.Owner);
|
var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.Coordinates);
|
||||||
ContainedID = idCardComponent;
|
var idCardComponent = idCard.GetComponent<IdCardComponent>();
|
||||||
|
_idSlot.Insert(idCardComponent.Owner);
|
||||||
|
ContainedID = idCardComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_startingPen))
|
||||||
|
{
|
||||||
|
var pen = _entityManager.SpawnEntity(_startingPen, Owner.Transform.Coordinates);
|
||||||
|
_penSlot.Insert(pen);
|
||||||
|
}
|
||||||
|
|
||||||
UpdatePDAAppearance();
|
UpdatePDAAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,23 +104,29 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
{
|
{
|
||||||
switch (message.Message)
|
switch (message.Message)
|
||||||
{
|
{
|
||||||
case PDARequestUpdateInterfaceMessage msg:
|
case PDARequestUpdateInterfaceMessage _:
|
||||||
{
|
{
|
||||||
UpdatePDAUserInterface();
|
UpdatePDAUserInterface();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PDAToggleFlashlightMessage msg:
|
case PDAToggleFlashlightMessage _:
|
||||||
{
|
{
|
||||||
ToggleLight();
|
ToggleLight();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PDAEjectIDMessage msg:
|
case PDAEjectIDMessage _:
|
||||||
{
|
{
|
||||||
HandleIDEjection(message.Session.AttachedEntity!);
|
HandleIDEjection(message.Session.AttachedEntity!);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PDAEjectPenMessage _:
|
||||||
|
{
|
||||||
|
HandlePenEjection(message.Session.AttachedEntity!);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PDAUplinkBuyListingMessage buyMsg:
|
case PDAUplinkBuyListingMessage buyMsg:
|
||||||
{
|
{
|
||||||
if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ItemId))
|
if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ItemId))
|
||||||
@@ -131,11 +156,11 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder,
|
var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder,
|
||||||
_syndicateUplinkAccount.Balance);
|
_syndicateUplinkAccount.Balance);
|
||||||
var listings = _uplinkManager.FetchListings.Values.ToArray();
|
var listings = _uplinkManager.FetchListings.Values.ToArray();
|
||||||
UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo, accData, listings));
|
UserInterface?.SetState(new PDAUpdateState(_lightOn, !PenSlotEmpty, ownerInfo, accData, listings));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo));
|
UserInterface?.SetState(new PDAUpdateState(_lightOn, !PenSlotEmpty, ownerInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatePDAAppearance();
|
UpdatePDAAppearance();
|
||||||
@@ -150,14 +175,11 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
private bool TryInsertIdCard(InteractUsingEventArgs eventArgs, IdCardComponent idCardComponent)
|
||||||
{
|
{
|
||||||
var item = eventArgs.Using;
|
var item = eventArgs.Using;
|
||||||
|
if (_idSlot.Contains(item))
|
||||||
if (!item.TryGetComponent<IdCardComponent>(out var idCardComponent) || _idSlot.Contains(item))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands))
|
if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands))
|
||||||
{
|
{
|
||||||
@@ -177,17 +199,70 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertIdCard(idCardComponent);
|
|
||||||
|
|
||||||
if (swap != null)
|
if (swap != null)
|
||||||
{
|
{
|
||||||
eventArgs.User.GetComponent<HandsComponent>().PutInHand(swap.GetComponent<ItemComponent>());
|
hands.PutInHand(swap.GetComponent<ItemComponent>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InsertIdCard(idCardComponent);
|
||||||
|
|
||||||
UpdatePDAUserInterface();
|
UpdatePDAUserInterface();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryInsertPen(InteractUsingEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
var item = eventArgs.Using;
|
||||||
|
if (_penSlot.Contains(item))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands))
|
||||||
|
{
|
||||||
|
Owner.PopupMessage(eventArgs.User, Loc.GetString("You have no hands!"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEntity? swap = null;
|
||||||
|
if (!PenSlotEmpty)
|
||||||
|
{
|
||||||
|
// Swap
|
||||||
|
swap = _penSlot.ContainedEntities[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hands.Drop(item))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swap != null)
|
||||||
|
{
|
||||||
|
hands.PutInHand(swap.GetComponent<ItemComponent>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert Pen
|
||||||
|
_penSlot.Insert(item);
|
||||||
|
|
||||||
|
UpdatePDAUserInterface();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
var item = eventArgs.Using;
|
||||||
|
|
||||||
|
if (item.TryGetComponent<IdCardComponent>(out var idCardComponent))
|
||||||
|
{
|
||||||
|
return TryInsertIdCard(eventArgs, idCardComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.HasComponent<WriteComponent>())
|
||||||
|
{
|
||||||
|
return TryInsertPen(eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
|
||||||
@@ -273,6 +348,21 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
UpdatePDAUserInterface();
|
UpdatePDAUserInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandlePenEjection(IEntity pdaUser)
|
||||||
|
{
|
||||||
|
if (PenSlotEmpty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var pen = _penSlot.ContainedEntities[0];
|
||||||
|
_penSlot.Remove(pen);
|
||||||
|
|
||||||
|
var hands = pdaUser.GetComponent<HandsComponent>();
|
||||||
|
var itemComponent = pen.GetComponent<ItemComponent>();
|
||||||
|
hands.PutInHandOrDrop(itemComponent);
|
||||||
|
|
||||||
|
UpdatePDAUserInterface();
|
||||||
|
}
|
||||||
|
|
||||||
[Verb]
|
[Verb]
|
||||||
public sealed class EjectIDVerb : Verb<PDAComponent>
|
public sealed class EjectIDVerb : Verb<PDAComponent>
|
||||||
{
|
{
|
||||||
@@ -294,6 +384,28 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Verb]
|
||||||
|
public sealed class EjectPenVerb : Verb<PDAComponent>
|
||||||
|
{
|
||||||
|
protected override void GetData(IEntity user, PDAComponent component, VerbData data)
|
||||||
|
{
|
||||||
|
if (!ActionBlockerSystem.CanInteract(user))
|
||||||
|
{
|
||||||
|
data.Visibility = VerbVisibility.Invisible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Text = Loc.GetString("Eject Pen");
|
||||||
|
data.Visibility = component.PenSlotEmpty ? VerbVisibility.Invisible : VerbVisibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Activate(IEntity user, PDAComponent component)
|
||||||
|
{
|
||||||
|
component.HandlePenEjection(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Verb]
|
||||||
public sealed class ToggleFlashlightVerb : Verb<PDAComponent>
|
public sealed class ToggleFlashlightVerb : Verb<PDAComponent>
|
||||||
{
|
{
|
||||||
protected override void GetData(IEntity user, PDAComponent component, VerbData data)
|
protected override void GetData(IEntity user, PDAComponent component, VerbData data)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ using Robust.Shared.GameObjects.Components;
|
|||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Rotatable
|
namespace Content.Server.GameObjects.Components.Rotatable
|
||||||
{
|
{
|
||||||
@@ -14,9 +16,21 @@ namespace Content.Server.GameObjects.Components.Rotatable
|
|||||||
{
|
{
|
||||||
public override string Name => "Rotatable";
|
public override string Name => "Rotatable";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, this entity can be rotated even while anchored.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool RotateWhileAnchored { get; private set; }
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
serializer.DataField(this, x => x.RotateWhileAnchored, "rotateWhileAnchored", false);
|
||||||
|
}
|
||||||
|
|
||||||
private void TryRotate(IEntity user, Angle angle)
|
private void TryRotate(IEntity user, Angle angle)
|
||||||
{
|
{
|
||||||
if (Owner.TryGetComponent(out IPhysicsComponent physics))
|
if (!RotateWhileAnchored && Owner.TryGetComponent(out IPhysicsComponent physics))
|
||||||
{
|
{
|
||||||
if (physics.Anchored)
|
if (physics.Anchored)
|
||||||
{
|
{
|
||||||
@@ -33,7 +47,7 @@ namespace Content.Server.GameObjects.Components.Rotatable
|
|||||||
{
|
{
|
||||||
protected override void GetData(IEntity user, RotatableComponent component, VerbData data)
|
protected override void GetData(IEntity user, RotatableComponent component, VerbData data)
|
||||||
{
|
{
|
||||||
if (!ActionBlockerSystem.CanInteract(user))
|
if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysicsComponent physics) && physics.Anchored))
|
||||||
{
|
{
|
||||||
data.Visibility = VerbVisibility.Invisible;
|
data.Visibility = VerbVisibility.Invisible;
|
||||||
return;
|
return;
|
||||||
@@ -55,7 +69,7 @@ namespace Content.Server.GameObjects.Components.Rotatable
|
|||||||
{
|
{
|
||||||
protected override void GetData(IEntity user, RotatableComponent component, VerbData data)
|
protected override void GetData(IEntity user, RotatableComponent component, VerbData data)
|
||||||
{
|
{
|
||||||
if (!ActionBlockerSystem.CanInteract(user))
|
if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysicsComponent physics) && physics.Anchored))
|
||||||
{
|
{
|
||||||
data.Visibility = VerbVisibility.Invisible;
|
data.Visibility = VerbVisibility.Invisible;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Buckle;
|
using Content.Server.GameObjects.Components.Buckle;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Strap;
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
@@ -27,7 +28,7 @@ namespace Content.Server.GameObjects.Components.Strap
|
|||||||
private StrapPosition _position;
|
private StrapPosition _position;
|
||||||
private string _buckleSound = null!;
|
private string _buckleSound = null!;
|
||||||
private string _unbuckleSound = null!;
|
private string _unbuckleSound = null!;
|
||||||
private string _buckledIcon = null!;
|
private AlertType _buckledAlertType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The angle in degrees to rotate the player by when they get strapped
|
/// The angle in degrees to rotate the player by when they get strapped
|
||||||
@@ -65,10 +66,10 @@ namespace Content.Server.GameObjects.Components.Strap
|
|||||||
public string UnbuckleSound => _unbuckleSound;
|
public string UnbuckleSound => _unbuckleSound;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon to be displayed as a status when buckled
|
/// ID of the alert to show when buckled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public string BuckledIcon => _buckledIcon;
|
public AlertType BuckledAlertType => _buckledAlertType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The sum of the sizes of all the buckled entities in this strap
|
/// The sum of the sizes of all the buckled entities in this strap
|
||||||
@@ -137,7 +138,7 @@ namespace Content.Server.GameObjects.Components.Strap
|
|||||||
serializer.DataField(ref _position, "position", StrapPosition.None);
|
serializer.DataField(ref _position, "position", StrapPosition.None);
|
||||||
serializer.DataField(ref _buckleSound, "buckleSound", "/Audio/Effects/buckle.ogg");
|
serializer.DataField(ref _buckleSound, "buckleSound", "/Audio/Effects/buckle.ogg");
|
||||||
serializer.DataField(ref _unbuckleSound, "unbuckleSound", "/Audio/Effects/unbuckle.ogg");
|
serializer.DataField(ref _unbuckleSound, "unbuckleSound", "/Audio/Effects/unbuckle.ogg");
|
||||||
serializer.DataField(ref _buckledIcon, "buckledIcon", "/Textures/Interface/StatusEffects/Buckle/buckled.png");
|
serializer.DataField(ref _buckledAlertType, "buckledAlertType", AlertType.Buckled);
|
||||||
serializer.DataField(ref _rotation, "rotation", 0);
|
serializer.DataField(ref _rotation, "rotation", 0);
|
||||||
|
|
||||||
var defaultSize = 100;
|
var defaultSize = 100;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
@@ -74,43 +75,43 @@ namespace Content.Server.GameObjects.Components.Temperature
|
|||||||
damageType = DamageType.Cold;
|
damageType = DamageType.Cold;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (Owner.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
switch(CurrentTemperature)
|
switch(CurrentTemperature)
|
||||||
{
|
{
|
||||||
// Cold strong.
|
// Cold strong.
|
||||||
case var t when t <= 260:
|
case var t when t <= 260:
|
||||||
status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/cold3.png", null);
|
status.ShowAlert(AlertType.Cold, 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Cold mild.
|
// Cold mild.
|
||||||
case var t when t <= 280 && t > 260:
|
case var t when t <= 280 && t > 260:
|
||||||
status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/cold2.png", null);
|
status.ShowAlert(AlertType.Cold, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Cold weak.
|
// Cold weak.
|
||||||
case var t when t <= 292 && t > 280:
|
case var t when t <= 292 && t > 280:
|
||||||
status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/cold1.png", null);
|
status.ShowAlert(AlertType.Cold, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Safe.
|
// Safe.
|
||||||
case var t when t <= 327 && t > 292:
|
case var t when t <= 327 && t > 292:
|
||||||
status.RemoveStatusEffect(StatusEffect.Temperature);
|
status.ClearAlertCategory(AlertCategory.Temperature);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Heat weak.
|
// Heat weak.
|
||||||
case var t when t <= 335 && t > 327:
|
case var t when t <= 335 && t > 327:
|
||||||
status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/hot1.png", null);
|
status.ShowAlert(AlertType.Hot, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Heat mild.
|
// Heat mild.
|
||||||
case var t when t <= 345 && t > 335:
|
case var t when t <= 345 && t > 335:
|
||||||
status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/hot2.png", null);
|
status.ShowAlert(AlertType.Hot, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Heat strong.
|
// Heat strong.
|
||||||
case var t when t > 345:
|
case var t when t > 345:
|
||||||
status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/hot3.png", null);
|
status.ShowAlert(AlertType.Hot, 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.Components.Access;
|
||||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.GameObjects.Components.VendingMachines;
|
using Content.Shared.GameObjects.Components.VendingMachines;
|
||||||
@@ -16,6 +17,7 @@ using Robust.Shared.Audio;
|
|||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components.Timers;
|
using Robust.Shared.GameObjects.Components.Timers;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -146,7 +148,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
|||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
case VendingMachineEjectMessage msg:
|
case VendingMachineEjectMessage msg:
|
||||||
TryEject(msg.ID);
|
TryEject(msg.ID, serverMsg.Session.AttachedEntity);
|
||||||
break;
|
break;
|
||||||
case InventorySyncRequestMessage _:
|
case InventorySyncRequestMessage _:
|
||||||
UserInterface?.SendMessage(new VendingMachineInventoryMessage(Inventory));
|
UserInterface?.SendMessage(new VendingMachineInventoryMessage(Inventory));
|
||||||
@@ -195,6 +197,19 @@ namespace Content.Server.GameObjects.Components.VendingMachines
|
|||||||
EntitySystem.Get<AudioSystem>().PlayFromEntity(_soundVend, Owner, AudioParams.Default.WithVolume(-2f));
|
EntitySystem.Get<AudioSystem>().PlayFromEntity(_soundVend, Owner, AudioParams.Default.WithVolume(-2f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TryEject(string id, IEntity? sender)
|
||||||
|
{
|
||||||
|
if (Owner.TryGetComponent<AccessReader>(out var accessReader))
|
||||||
|
{
|
||||||
|
if (sender == null || !accessReader.IsAllowed(sender))
|
||||||
|
{
|
||||||
|
FlickDenyAnimation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TryEject(id);
|
||||||
|
}
|
||||||
|
|
||||||
private void FlickDenyAnimation()
|
private void FlickDenyAnimation()
|
||||||
{
|
{
|
||||||
TrySetVisualState(VendingMachineVisualState.Deny);
|
TrySetVisualState(VendingMachineVisualState.Deny);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.GameObjects.Components.Movement;
|
using Content.Server.GameObjects.Components.Movement;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.GameObjects.Components.Movement;
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -44,7 +44,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
_configurationManager.RegisterCVar("ai.maxupdates", 64);
|
|
||||||
SubscribeLocalEvent<SleepAiMessage>(HandleAiSleep);
|
SubscribeLocalEvent<SleepAiMessage>(HandleAiSleep);
|
||||||
|
|
||||||
var processors = _reflectionManager.GetAllChildren<AiLogicProcessor>();
|
var processors = _reflectionManager.GetAllChildren<AiLogicProcessor>();
|
||||||
@@ -60,7 +59,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
var cvarMaxUpdates = _configurationManager.GetCVar<int>("ai.maxupdates");
|
var cvarMaxUpdates = _configurationManager.GetCVar(CCVars.AIMaxUpdates);
|
||||||
if (cvarMaxUpdates <= 0)
|
if (cvarMaxUpdates <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -328,9 +328,16 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var newGridId = moveEvent.NewPosition.GetGridId(_entityManager);
|
||||||
|
if (newGridId == GridId.Invalid)
|
||||||
|
{
|
||||||
|
HandleEntityRemove(moveEvent.Sender);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The pathfinding graph is tile-based so first we'll check if they're on a different tile and if we need to update.
|
// The pathfinding graph is tile-based so first we'll check if they're on a different tile and if we need to update.
|
||||||
// If you get entities bigger than 1 tile wide you'll need some other system so god help you.
|
// If you get entities bigger than 1 tile wide you'll need some other system so god help you.
|
||||||
var newTile = _mapManager.GetGrid(moveEvent.NewPosition.GetGridId(_entityManager)).GetTileRef(moveEvent.NewPosition);
|
var newTile = _mapManager.GetGrid(newGridId).GetTileRef(moveEvent.NewPosition);
|
||||||
|
|
||||||
if (oldNode == null || oldNode.TileRef == newTile)
|
if (oldNode == null || oldNode.TileRef == newTile)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Content.Server.GameObjects.Components.Atmos;
|
using Content.Server.GameObjects.Components.Atmos;
|
||||||
using Content.Server.Atmos;
|
using Content.Server.Atmos;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -47,7 +48,6 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
|||||||
|
|
||||||
_atmosphereSystem = Get<AtmosphereSystem>();
|
_atmosphereSystem = Get<AtmosphereSystem>();
|
||||||
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||||
_configManager.RegisterCVar("net.atmosdbgoverlaytickrate", 3.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -89,7 +89,7 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
|||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
AccumulatedFrameTime += frameTime;
|
AccumulatedFrameTime += frameTime;
|
||||||
_updateCooldown = 1 / _configManager.GetCVar<float>("net.atmosdbgoverlaytickrate");
|
_updateCooldown = 1 / _configManager.GetCVar(CCVars.NetAtmosDebugOverlayTickRate);
|
||||||
|
|
||||||
if (AccumulatedFrameTime < _updateCooldown)
|
if (AccumulatedFrameTime < _updateCooldown)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Content.Server.GameObjects.Components.Atmos;
|
using Content.Server.GameObjects.Components.Atmos;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Interfaces.Configuration;
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -65,7 +67,6 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
|||||||
_atmosphereSystem = Get<AtmosphereSystem>();
|
_atmosphereSystem = Get<AtmosphereSystem>();
|
||||||
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||||
_mapManager.OnGridRemoved += OnGridRemoved;
|
_mapManager.OnGridRemoved += OnGridRemoved;
|
||||||
_configManager.RegisterCVar("net.gasoverlaytickrate", 3.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -228,14 +229,14 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
|||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
AccumulatedFrameTime += frameTime;
|
AccumulatedFrameTime += frameTime;
|
||||||
_updateCooldown = 1 / _configManager.GetCVar<float>("net.gasoverlaytickrate");
|
_updateCooldown = 1 / _configManager.GetCVar(CCVars.NetGasOverlayTickRate);
|
||||||
|
|
||||||
if (AccumulatedFrameTime < _updateCooldown)
|
if (AccumulatedFrameTime < _updateCooldown)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateRange = _configManager.GetCVar<float>("net.maxupdaterange") + RangeOffset;
|
_updateRange = _configManager.GetCVar(CVars.NetMaxUpdateRange) + RangeOffset;
|
||||||
|
|
||||||
// TODO: So in the worst case scenario we still have to send a LOT of tile data per tick if there's a fire.
|
// TODO: So in the worst case scenario we still have to send a LOT of tile data per tick if there's a fire.
|
||||||
// If we go with say 15 tile radius then we have up to 900 tiles to update per tick.
|
// If we go with say 15 tile radius then we have up to 900 tiles to update per tick.
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
using Content.Server.GameObjects.Components.Buckle;
|
#nullable enable
|
||||||
|
using Content.Server.GameObjects.Components.Buckle;
|
||||||
|
using Content.Server.GameObjects.Components.Strap;
|
||||||
using Content.Server.GameObjects.EntitySystems.Click;
|
using Content.Server.GameObjects.EntitySystems.Click;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects.EntitySystemMessages;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.GameObjects.Components.Transform;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.EntitySystems
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
@@ -15,13 +20,84 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
UpdatesAfter.Add(typeof(InteractionSystem));
|
UpdatesAfter.Add(typeof(InteractionSystem));
|
||||||
UpdatesAfter.Add(typeof(InputSystem));
|
UpdatesAfter.Add(typeof(InputSystem));
|
||||||
|
|
||||||
|
SubscribeLocalEvent<MoveEvent>(MoveEvent);
|
||||||
|
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(ContainerModified);
|
||||||
|
SubscribeLocalEvent<EntRemovedFromContainerMessage>(ContainerModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
foreach (var buckle in ComponentManager.EntityQuery<BuckleComponent>())
|
base.Shutdown();
|
||||||
|
|
||||||
|
UnsubscribeLocalEvent<MoveEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveEvent(MoveEvent ev)
|
||||||
|
{
|
||||||
|
if (!ev.Sender.TryGetComponent(out BuckleComponent? buckle))
|
||||||
{
|
{
|
||||||
buckle.Update();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var strap = buckle.BuckledTo;
|
||||||
|
|
||||||
|
if (strap == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var strapPosition = strap.Owner.Transform.Coordinates.Offset(buckle.BuckleOffset);
|
||||||
|
|
||||||
|
if (ev.NewPosition.InRange(EntityManager, strapPosition, 0.2f))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buckle.TryUnbuckle(buckle.Owner, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ContainerModified(ContainerModifiedMessage message)
|
||||||
|
{
|
||||||
|
// Not returning is necessary in case an entity has both a buckle and strap component
|
||||||
|
if (message.Entity.TryGetComponent(out BuckleComponent? buckle))
|
||||||
|
{
|
||||||
|
ContainerModifiedReAttach(buckle, buckle.BuckledTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.Entity.TryGetComponent(out StrapComponent? strap))
|
||||||
|
{
|
||||||
|
foreach (var buckledEntity in strap.BuckledEntities)
|
||||||
|
{
|
||||||
|
if (!buckledEntity.TryGetComponent(out BuckleComponent? buckled))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContainerModifiedReAttach(buckled, strap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ContainerModifiedReAttach(BuckleComponent buckle, StrapComponent? strap)
|
||||||
|
{
|
||||||
|
if (strap == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contained = ContainerHelpers.TryGetContainer(buckle.Owner, out var ownContainer);
|
||||||
|
var strapContained = ContainerHelpers.TryGetContainer(strap.Owner, out var strapContainer);
|
||||||
|
|
||||||
|
if (contained != strapContained || ownContainer != strapContainer)
|
||||||
|
{
|
||||||
|
buckle.TryUnbuckle(buckle.Owner, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!contained)
|
||||||
|
{
|
||||||
|
buckle.ReAttach(strap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
private bool HandleWideAttack(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
private bool HandleWideAttack(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
||||||
{
|
{
|
||||||
// client sanitization
|
// client sanitization
|
||||||
if (!_mapManager.GridExists(coords.GetGridId(_entityManager)))
|
if (!coords.IsValid(_entityManager))
|
||||||
{
|
{
|
||||||
Logger.InfoS("system.interaction", $"Invalid Coordinates: client={session}, coords={coords}");
|
Logger.InfoS("system.interaction", $"Invalid Coordinates: client={session}, coords={coords}");
|
||||||
return true;
|
return true;
|
||||||
@@ -211,7 +211,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
private bool HandleClientUseItemInHand(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
private bool HandleClientUseItemInHand(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
||||||
{
|
{
|
||||||
// client sanitization
|
// client sanitization
|
||||||
if (!_mapManager.GridExists(coords.GetGridId(_entityManager)))
|
if (!coords.IsValid(_entityManager))
|
||||||
{
|
{
|
||||||
Logger.InfoS("system.interaction", $"Invalid Coordinates: client={session}, coords={coords}");
|
Logger.InfoS("system.interaction", $"Invalid Coordinates: client={session}, coords={coords}");
|
||||||
return true;
|
return true;
|
||||||
@@ -242,7 +242,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
private bool HandleTryPullObject(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
private bool HandleTryPullObject(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
||||||
{
|
{
|
||||||
// client sanitization
|
// client sanitization
|
||||||
if (!_mapManager.GridExists(coords.GetGridId(_entityManager)))
|
if (!coords.IsValid(_entityManager))
|
||||||
{
|
{
|
||||||
Logger.InfoS("system.interaction", $"Invalid Coordinates for pulling: client={session}, coords={coords}");
|
Logger.InfoS("system.interaction", $"Invalid Coordinates for pulling: client={session}, coords={coords}");
|
||||||
return false;
|
return false;
|
||||||
@@ -303,7 +303,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify player is on the same map as the entity he clicked on
|
// Verify player is on the same map as the entity he clicked on
|
||||||
if (_mapManager.GetGrid(coordinates.GetGridId(EntityManager)).ParentMapId != playerTransform.MapID)
|
if (coordinates.GetMapId(_entityManager) != playerTransform.MapID)
|
||||||
{
|
{
|
||||||
Logger.WarningS("system.interaction",
|
Logger.WarningS("system.interaction",
|
||||||
$"Player named {player.Name} clicked on a map he isn't located on");
|
$"Player named {player.Name} clicked on a map he isn't located on");
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using Robust.Shared.Interfaces.GameObjects;
|
|||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -306,8 +307,18 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private async void HandleStartItemConstruction(TryStartItemConstructionMessage ev, EntitySessionEventArgs args)
|
private async void HandleStartItemConstruction(TryStartItemConstructionMessage ev, EntitySessionEventArgs args)
|
||||||
{
|
{
|
||||||
var constructionPrototype = _prototypeManager.Index<ConstructionPrototype>(ev.PrototypeName);
|
if (!_prototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype constructionPrototype))
|
||||||
var constructionGraph = _prototypeManager.Index<ConstructionGraphPrototype>(constructionPrototype.Graph);
|
{
|
||||||
|
Logger.Error($"Tried to start construction of invalid recipe '{ev.PrototypeName}'!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_prototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype constructionGraph))
|
||||||
|
{
|
||||||
|
Logger.Error($"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{ev.PrototypeName}'!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var startNode = constructionGraph.Nodes[constructionPrototype.StartNode];
|
var startNode = constructionGraph.Nodes[constructionPrototype.StartNode];
|
||||||
var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode];
|
var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode];
|
||||||
var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name);
|
var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name);
|
||||||
@@ -352,8 +363,20 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private async void HandleStartStructureConstruction(TryStartStructureConstructionMessage ev, EntitySessionEventArgs args)
|
private async void HandleStartStructureConstruction(TryStartStructureConstructionMessage ev, EntitySessionEventArgs args)
|
||||||
{
|
{
|
||||||
var constructionPrototype = _prototypeManager.Index<ConstructionPrototype>(ev.PrototypeName);
|
if (!_prototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype constructionPrototype))
|
||||||
var constructionGraph = _prototypeManager.Index<ConstructionGraphPrototype>(constructionPrototype.Graph);
|
{
|
||||||
|
Logger.Error($"Tried to start construction of invalid recipe '{ev.PrototypeName}'!");
|
||||||
|
RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_prototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype constructionGraph))
|
||||||
|
{
|
||||||
|
Logger.Error($"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{ev.PrototypeName}'!");
|
||||||
|
RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var startNode = constructionGraph.Nodes[constructionPrototype.StartNode];
|
var startNode = constructionGraph.Nodes[constructionPrototype.StartNode];
|
||||||
var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode];
|
var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode];
|
||||||
var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name);
|
var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name);
|
||||||
|
|||||||
@@ -1,27 +1,16 @@
|
|||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
|
||||||
{
|
{
|
||||||
public class DeviceNetworkSystem : EntitySystem
|
internal sealed class DeviceNetworkSystem : EntitySystem
|
||||||
{
|
{
|
||||||
private IDeviceNetwork _network;
|
[Dependency] private readonly IDeviceNetwork _network = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
_network = IoCManager.Resolve<IDeviceNetwork>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
if (_network == null)
|
|
||||||
return;
|
|
||||||
//(ノ°Д°)ノ︵ ┻━┻
|
|
||||||
_network.Update();
|
_network.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.EntitySystems
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
|
||||||
public class HeartSystem : EntitySystem
|
|
||||||
{
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
UpdatesBefore.Add(typeof(MetabolismSystem));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
foreach (var heart in ComponentManager.EntityQuery<SharedHeartBehaviorComponent>())
|
|
||||||
{
|
|
||||||
heart.Update(frameTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
using Content.Shared.GameObjects.Components.Body.Behavior;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.EntitySystems
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
|
||||||
public class LungSystem : EntitySystem
|
|
||||||
{
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
UpdatesBefore.Add(typeof(MetabolismSystem));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
foreach (var lung in ComponentManager.EntityQuery<SharedLungBehaviorComponent>())
|
|
||||||
{
|
|
||||||
lung.Update(frameTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.Components.NodeContainer;
|
||||||
|
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameObjects.Components.Transform;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public class NodeContainerSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<RotateEvent>(RotateEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Shutdown()
|
||||||
|
{
|
||||||
|
base.Shutdown();
|
||||||
|
|
||||||
|
UnsubscribeLocalEvent<RotateEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RotateEvent(RotateEvent ev)
|
||||||
|
{
|
||||||
|
if (!ev.Sender.TryGetComponent(out NodeContainerComponent container))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.NewRotation == ev.OldRotation)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var rotatableNode in container.Nodes.OfType<IRotatableNode>())
|
||||||
|
{
|
||||||
|
rotatableNode.RotateEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using Content.Server.Players;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects.Components;
|
using Robust.Server.GameObjects.Components;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
@@ -75,9 +76,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool InRange(EntityCoordinates from, EntityCoordinates to)
|
public bool InRange(IEntity pointer, EntityCoordinates coordinates)
|
||||||
{
|
{
|
||||||
return from.InRange(EntityManager, to, 15);
|
return pointer.InRangeUnOccluded(coordinates, 15, e => e == pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryPoint(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
public bool TryPoint(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
||||||
@@ -100,7 +101,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InRange(coords, player.Transform.Coordinates))
|
if (!InRange(player, coords))
|
||||||
{
|
{
|
||||||
player.PopupMessage(Loc.GetString("You can't reach there!"));
|
player.PopupMessage(Loc.GetString("You can't reach there!"));
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.GameObjects.Components.MachineLinking;
|
using Content.Server.GameObjects.Components.MachineLinking;
|
||||||
|
using Content.Server.GameObjects.EntitySystems.Click;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Interfaces.Console;
|
using Robust.Server.Interfaces.Console;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
@@ -27,7 +28,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
_transmitters = new Dictionary<NetUserId, SignalTransmitterComponent>();
|
_transmitters = new Dictionary<NetUserId, SignalTransmitterComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SignalLinkerKeybind(NetUserId id, bool? enable)
|
public bool SignalLinkerKeybind(NetUserId id, bool? enable)
|
||||||
{
|
{
|
||||||
if (enable == null)
|
if (enable == null)
|
||||||
{
|
{
|
||||||
@@ -38,13 +39,13 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
{
|
{
|
||||||
if (_transmitters.ContainsKey(id))
|
if (_transmitters.ContainsKey(id))
|
||||||
{
|
{
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_transmitters.Count == 0)
|
if (_transmitters.Count == 0)
|
||||||
{
|
{
|
||||||
CommandBinds.Builder
|
CommandBinds.Builder
|
||||||
.Bind(EngineKeyFunctions.Use, new PointerInputCmdHandler(HandleUse))
|
.BindBefore(EngineKeyFunctions.Use, new PointerInputCmdHandler(HandleUse), typeof(InteractionSystem))
|
||||||
.Register<SignalLinkerSystem>();
|
.Register<SignalLinkerSystem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
{
|
{
|
||||||
if (!_transmitters.ContainsKey(id))
|
if (!_transmitters.ContainsKey(id))
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_transmitters.Remove(id);
|
_transmitters.Remove(id);
|
||||||
@@ -64,6 +65,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
CommandBinds.Unregister<SignalLinkerSystem>();
|
CommandBinds.Unregister<SignalLinkerSystem>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return enable == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HandleUse(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
private bool HandleUse(ICommonSession session, EntityCoordinates coords, EntityUid uid)
|
||||||
@@ -132,7 +134,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
system.SignalLinkerKeybind(player.UserId, enable);
|
var ret = system.SignalLinkerKeybind(player.UserId, enable);
|
||||||
|
shell.SendText(player, ret ? "Enabled" : "Disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ using System.Text;
|
|||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.StationEvents;
|
using Content.Server.StationEvents;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.Console;
|
using Robust.Server.Console;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.Configuration;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.Interfaces.Reflection;
|
using Robust.Shared.Interfaces.Reflection;
|
||||||
@@ -23,6 +25,7 @@ namespace Content.Server.GameObjects.EntitySystems.StationEvents
|
|||||||
// Somewhat based off of TG's implementation of events
|
// Somewhat based off of TG's implementation of events
|
||||||
public sealed class StationEventSystem : EntitySystem, IResettingEntitySystem
|
public sealed class StationEventSystem : EntitySystem, IResettingEntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||||
@@ -164,6 +167,9 @@ namespace Content.Server.GameObjects.EntitySystems.StationEvents
|
|||||||
_stationEvents.Add(stationEvent);
|
_stationEvents.Add(stationEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Can't just check debug / release for a default given mappers need to use release mode
|
||||||
|
// As such we'll always pause it by default.
|
||||||
|
_configurationManager.OnValueChanged(CCVars.EventsEnabled, value => Enabled = value, true);
|
||||||
_netManager.RegisterNetMessage<MsgGetStationEvents>(nameof(MsgGetStationEvents), GetEventReceived);
|
_netManager.RegisterNetMessage<MsgGetStationEvents>(nameof(MsgGetStationEvents), GetEventReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.EntitySystemMessages.Gravity;
|
using Content.Shared.GameObjects.EntitySystemMessages.Gravity;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -19,7 +20,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
private readonly Dictionary<GridId, List<ServerStatusEffectsComponent>> _statuses = new Dictionary<GridId, List<ServerStatusEffectsComponent>>();
|
private readonly Dictionary<GridId, List<ServerAlertsComponent>> _alerts = new Dictionary<GridId, List<ServerAlertsComponent>>();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -31,15 +32,15 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
_statuses.Clear();
|
_alerts.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddStatus(ServerStatusEffectsComponent status)
|
public void AddAlert(ServerAlertsComponent status)
|
||||||
{
|
{
|
||||||
var gridId = status.Owner.Transform.GridID;
|
var gridId = status.Owner.Transform.GridID;
|
||||||
var statuses = _statuses.GetOrNew(gridId);
|
var alerts = _alerts.GetOrNew(gridId);
|
||||||
|
|
||||||
statuses.Add(status);
|
alerts.Add(status);
|
||||||
|
|
||||||
if (_mapManager.TryGetGrid(status.Owner.Transform.GridID, out var grid))
|
if (_mapManager.TryGetGrid(status.Owner.Transform.GridID, out var grid))
|
||||||
{
|
{
|
||||||
@@ -54,10 +55,10 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveStatus(ServerStatusEffectsComponent status)
|
public void RemoveAlert(ServerAlertsComponent status)
|
||||||
{
|
{
|
||||||
var grid = status.Owner.Transform.GridID;
|
var grid = status.Owner.Transform.GridID;
|
||||||
if (!_statuses.TryGetValue(grid, out var statuses))
|
if (!_alerts.TryGetValue(grid, out var statuses))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -67,7 +68,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private void GravityChanged(GravityChangedMessage ev)
|
private void GravityChanged(GravityChangedMessage ev)
|
||||||
{
|
{
|
||||||
if (!_statuses.TryGetValue(ev.Grid.Index, out var statuses))
|
if (!_alerts.TryGetValue(ev.Grid.Index, out var statuses))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,19 +89,19 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddWeightless(ServerStatusEffectsComponent status)
|
private void AddWeightless(ServerAlertsComponent status)
|
||||||
{
|
{
|
||||||
status.ChangeStatusEffect(StatusEffect.Weightless, "/Textures/Interface/StatusEffects/Weightless/weightless.png", null);
|
status.ShowAlert(AlertType.Weightless);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveWeightless(ServerStatusEffectsComponent status)
|
private void RemoveWeightless(ServerAlertsComponent status)
|
||||||
{
|
{
|
||||||
status.RemoveStatusEffect(StatusEffect.Weightless);
|
status.ClearAlert(AlertType.Weightless);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EntParentChanged(EntParentChangedMessage ev)
|
private void EntParentChanged(EntParentChangedMessage ev)
|
||||||
{
|
{
|
||||||
if (!ev.Entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
if (!ev.Entity.TryGetComponent(out ServerAlertsComponent status))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,14 +111,14 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
{
|
{
|
||||||
var oldGrid = mapGrid.GridIndex;
|
var oldGrid = mapGrid.GridIndex;
|
||||||
|
|
||||||
if (_statuses.TryGetValue(oldGrid, out var oldStatuses))
|
if (_alerts.TryGetValue(oldGrid, out var oldStatuses))
|
||||||
{
|
{
|
||||||
oldStatuses.Remove(status);
|
oldStatuses.Remove(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var newGrid = ev.Entity.Transform.GridID;
|
var newGrid = ev.Entity.Transform.GridID;
|
||||||
var newStatuses = _statuses.GetOrNew(newGrid);
|
var newStatuses = _alerts.GetOrNew(newGrid);
|
||||||
|
|
||||||
newStatuses.Add(status);
|
newStatuses.Add(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Server.Interfaces.Chat;
|
|||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Mobs.Roles.Suspicion;
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.GameObjects.Components.Inventory;
|
using Content.Shared.GameObjects.Components.Inventory;
|
||||||
using Content.Shared.GameObjects.Components.PDA;
|
using Content.Shared.GameObjects.Components.PDA;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
@@ -44,20 +45,12 @@ namespace Content.Server.GameTicking.GamePresets
|
|||||||
private static string TraitorID = "SuspicionTraitor";
|
private static string TraitorID = "SuspicionTraitor";
|
||||||
private static string InnocentID = "SuspicionInnocent";
|
private static string InnocentID = "SuspicionInnocent";
|
||||||
|
|
||||||
public static void RegisterCVars(IConfigurationManager cfg)
|
|
||||||
{
|
|
||||||
cfg.RegisterCVar("game.suspicion_min_players", 5);
|
|
||||||
cfg.RegisterCVar("game.suspicion_min_traitors", 2);
|
|
||||||
cfg.RegisterCVar("game.suspicion_players_per_traitor", 5);
|
|
||||||
cfg.RegisterCVar("game.suspicion_starting_balance", 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Start(IReadOnlyList<IPlayerSession> readyPlayers, bool force = false)
|
public override bool Start(IReadOnlyList<IPlayerSession> readyPlayers, bool force = false)
|
||||||
{
|
{
|
||||||
MinPlayers = _cfg.GetCVar<int>("game.suspicion_min_players");
|
MinPlayers = _cfg.GetCVar(CCVars.GameSuspicionMinPlayers);
|
||||||
MinTraitors = _cfg.GetCVar<int>("game.suspicion_min_traitors");
|
MinTraitors = _cfg.GetCVar(CCVars.GameSuspicionMinTraitors);
|
||||||
PlayersPerTraitor = _cfg.GetCVar<int>("game.suspicion_players_per_traitor");
|
PlayersPerTraitor = _cfg.GetCVar(CCVars.GameSuspicionPlayersPerTraitor);
|
||||||
TraitorStartingBalance = _cfg.GetCVar<int>("game.suspicion_starting_balance");
|
TraitorStartingBalance = _cfg.GetCVar(CCVars.GameSuspicionStartingBalance);
|
||||||
|
|
||||||
if (!force && readyPlayers.Count < MinPlayers)
|
if (!force && readyPlayers.Count < MinPlayers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
@@ -56,7 +57,7 @@ namespace Content.Server.GameTicking.GameRules
|
|||||||
{
|
{
|
||||||
_checkTimerCancel = null;
|
_checkTimerCancel = null;
|
||||||
|
|
||||||
if (!_cfg.GetCVar<bool>("game.enablewin"))
|
if (!_cfg.GetCVar(CCVars.GameLobbyEnableWin))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IPlayerSession winner = null;
|
IPlayerSession winner = null;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.Interfaces.Chat;
|
|||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Mobs.Roles.Suspicion;
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Shared;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
@@ -58,7 +59,7 @@ namespace Content.Server.GameTicking.GameRules
|
|||||||
|
|
||||||
private void _checkWinConditions()
|
private void _checkWinConditions()
|
||||||
{
|
{
|
||||||
if (!_cfg.GetCVar<bool>("game.enablewin"))
|
if (!_cfg.GetCVar(CCVars.GameLobbyEnableWin))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var traitorsAlive = 0;
|
var traitorsAlive = 0;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
[ViewVariables] private bool DisallowLateJoin { get; set; } = false;
|
[ViewVariables] private bool DisallowLateJoin { get; set; } = false;
|
||||||
|
|
||||||
[ViewVariables] private bool LobbyEnabled => _configurationManager.GetCVar<bool>("game.lobbyenabled");
|
[ViewVariables] private bool LobbyEnabled => _configurationManager.GetCVar(CCVars.GameLobbyEnabled);
|
||||||
|
|
||||||
[ViewVariables] private bool _updateOnRoundEnd;
|
[ViewVariables] private bool _updateOnRoundEnd;
|
||||||
private CancellationTokenSource _updateShutdownCts;
|
private CancellationTokenSource _updateShutdownCts;
|
||||||
@@ -120,7 +120,7 @@ namespace Content.Server.GameTicking
|
|||||||
public event Action<GameRuleAddedEventArgs> OnRuleAdded;
|
public event Action<GameRuleAddedEventArgs> OnRuleAdded;
|
||||||
|
|
||||||
private TimeSpan LobbyDuration =>
|
private TimeSpan LobbyDuration =>
|
||||||
TimeSpan.FromSeconds(_configurationManager.GetCVar<int>("game.lobbyduration"));
|
TimeSpan.FromSeconds(_configurationManager.GetCVar(CCVars.GameLobbyDuration));
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -128,8 +128,6 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
DebugTools.Assert(!_initialized);
|
DebugTools.Assert(!_initialized);
|
||||||
|
|
||||||
PresetSuspicion.RegisterCVars(_configurationManager);
|
|
||||||
|
|
||||||
_netManager.RegisterNetMessage<MsgTickerJoinLobby>(nameof(MsgTickerJoinLobby));
|
_netManager.RegisterNetMessage<MsgTickerJoinLobby>(nameof(MsgTickerJoinLobby));
|
||||||
_netManager.RegisterNetMessage<MsgTickerJoinGame>(nameof(MsgTickerJoinGame));
|
_netManager.RegisterNetMessage<MsgTickerJoinGame>(nameof(MsgTickerJoinGame));
|
||||||
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus));
|
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus));
|
||||||
@@ -287,9 +285,9 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
if (!preset.Start(assignedJobs.Keys.ToList(), force))
|
if (!preset.Start(assignedJobs.Keys.ToList(), force))
|
||||||
{
|
{
|
||||||
if (_configurationManager.GetCVar<bool>("game.fallbackenabled"))
|
if (_configurationManager.GetCVar(CCVars.GameLobbyFallbackEnabled))
|
||||||
{
|
{
|
||||||
SetStartPreset(_configurationManager.GetCVar<string>("game.fallbackpreset"));
|
SetStartPreset(_configurationManager.GetCVar(CCVars.GameLobbyFallbackPreset));
|
||||||
var newPreset = MakeGamePreset(profiles);
|
var newPreset = MakeGamePreset(profiles);
|
||||||
_chatManager.DispatchServerAnnouncement(
|
_chatManager.DispatchServerAnnouncement(
|
||||||
$"Failed to start {preset.ModeTitle} mode! Defaulting to {newPreset.ModeTitle}...");
|
$"Failed to start {preset.ModeTitle} mode! Defaulting to {newPreset.ModeTitle}...");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Content.Server.GlobalVerbs
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitySystem.Get<PointingSystem>().InRange(user.Transform.Coordinates, target.Transform.Coordinates))
|
if (!EntitySystem.Get<PointingSystem>().InRange(user, target.Transform.Coordinates))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
|
using Content.Shared;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Robust.Server.Interfaces.ServerStatus;
|
using Robust.Server.Interfaces.ServerStatus;
|
||||||
@@ -27,9 +28,6 @@ namespace Content.Server
|
|||||||
|
|
||||||
void IPostInjectInit.PostInject()
|
void IPostInjectInit.PostInject()
|
||||||
{
|
{
|
||||||
_configurationManager.RegisterCVar<string>("status.mommiurl", null);
|
|
||||||
_configurationManager.RegisterCVar<string>("status.mommipassword", null);
|
|
||||||
|
|
||||||
_statusHost.AddHandler(_handleChatPost);
|
_statusHost.AddHandler(_handleChatPost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,8 +44,8 @@ namespace Content.Server
|
|||||||
|
|
||||||
private async Task _sendMessageInternal(string type, object messageObject)
|
private async Task _sendMessageInternal(string type, object messageObject)
|
||||||
{
|
{
|
||||||
var url = _configurationManager.GetCVar<string>("status.mommiurl");
|
var url = _configurationManager.GetCVar(CCVars.StatusMoMMIUrl);
|
||||||
var password = _configurationManager.GetCVar<string>("status.mommipassword");
|
var password = _configurationManager.GetCVar(CCVars.StatusMoMMIPassword);
|
||||||
if (string.IsNullOrWhiteSpace(url))
|
if (string.IsNullOrWhiteSpace(url))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -83,7 +81,7 @@ namespace Content.Server
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var password = _configurationManager.GetCVar<string>("status.mommipassword");
|
var password = _configurationManager.GetCVar(CCVars.StatusMoMMIPassword);
|
||||||
|
|
||||||
OOCPostMessage message = null;
|
OOCPostMessage message = null;
|
||||||
try
|
try
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user