mirror of
https://github.com/wega-team/ss14-wega.git
synced 2026-02-15 03:31:44 +01:00
Stable to master (#42238)
Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
This commit is contained in:
@@ -42,7 +42,7 @@ public sealed class GuidebookRichPrototypeLink : Control, IPrototypeLinkControl
|
||||
public void SetMessage(FormattedMessage message)
|
||||
{
|
||||
_message = message;
|
||||
_richTextLabel.SetMessage(_message);
|
||||
_richTextLabel.SetMessage(_message, tagsAllowed: null);
|
||||
}
|
||||
|
||||
public IPrototype? LinkedPrototype { get; set; }
|
||||
|
||||
@@ -82,7 +82,7 @@ public sealed partial class DocumentParsingManager
|
||||
}
|
||||
|
||||
msg.Pop();
|
||||
rt.SetMessage(msg);
|
||||
rt.SetMessage(msg, tagsAllowed: null);
|
||||
return rt;
|
||||
},
|
||||
TextParser)
|
||||
|
||||
@@ -18,7 +18,7 @@ public sealed partial class InfoSection : BoxContainer
|
||||
{
|
||||
TitleLabel.Text = title;
|
||||
if (markup)
|
||||
Content.SetMessage(FormattedMessage.FromMarkupOrThrow(text.Trim()));
|
||||
Content.SetMessage(FormattedMessage.FromMarkupOrThrow(text.Trim()), tagsAllowed: null);
|
||||
else
|
||||
Content.SetMessage(text);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Content.Client.Info
|
||||
}
|
||||
public void SetInfoBlob(string markup)
|
||||
{
|
||||
_richTextLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(markup));
|
||||
_richTextLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(markup), tagsAllowed: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Content.Shared.Research.Systems;
|
||||
using Content.Shared.Research.Systems;
|
||||
|
||||
namespace Content.Client.Research;
|
||||
|
||||
public sealed class ResearchSystem : SharedResearchSystem;
|
||||
public sealed class ResearchSystem : SharedResearchSystem
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -7,22 +7,23 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Client.Research.UI;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class ResearchConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||
public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
private ResearchConsoleMenu? _consoleMenu;
|
||||
|
||||
public ResearchConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_consoleMenu = this.CreateWindow<ResearchConsoleMenu>();
|
||||
_consoleMenu.SetEntity(Owner);
|
||||
var owner = Owner;
|
||||
|
||||
_consoleMenu.OnTechnologyRediscoverPressed += () =>
|
||||
{
|
||||
SendMessage(new ConsoleRediscoverTechnologyMessage());
|
||||
};
|
||||
_consoleMenu = this.CreateWindow<ResearchConsoleMenu>();
|
||||
_consoleMenu.SetEntity(owner);
|
||||
|
||||
_consoleMenu.OnTechnologyCardPressed += id =>
|
||||
{
|
||||
@@ -55,7 +56,6 @@ public sealed class ResearchConsoleBoundUserInterface(EntityUid owner, Enum uiKe
|
||||
|
||||
if (state is not ResearchConsoleBoundInterfaceState castState)
|
||||
return;
|
||||
|
||||
_consoleMenu?.UpdatePanels(castState);
|
||||
_consoleMenu?.UpdateInformationPanel(castState);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
@@ -22,7 +22,6 @@
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalAlignment="Right">
|
||||
<Button Name="ServerButton" Text="{Loc 'research-console-menu-server-selection-button'}" MinHeight="40"/>
|
||||
<Button Name="RediscoverButton" Margin="0 5 0 0" ToolTip="{Loc 'research-console-menu-server-rediscover-tooltip'}" MinHeight="40"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal"
|
||||
|
||||
@@ -12,7 +12,6 @@ using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Research.UI;
|
||||
@@ -21,26 +20,15 @@ namespace Content.Client.Research.UI;
|
||||
public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||
{
|
||||
public Action<string>? OnTechnologyCardPressed;
|
||||
public Action? OnTechnologyRediscoverPressed;
|
||||
public Action? OnServerButtonPressed;
|
||||
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
private readonly ResearchSystem _research;
|
||||
private readonly SpriteSystem _sprite;
|
||||
private readonly AccessReaderSystem _accessReader;
|
||||
|
||||
// if set to null - we are waiting for server info and should not let rerolls
|
||||
private TimeSpan? _nextRediscover;
|
||||
private int _rediscoverCost;
|
||||
private int _serverPoints;
|
||||
|
||||
private TimeSpan _nextUpdate;
|
||||
private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(500);
|
||||
|
||||
public EntityUid Entity;
|
||||
|
||||
public ResearchConsoleMenu()
|
||||
@@ -53,7 +41,6 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||
_accessReader = _entity.System<AccessReaderSystem>();
|
||||
|
||||
ServerButton.OnPressed += _ => OnServerButtonPressed?.Invoke();
|
||||
RediscoverButton.OnPressed += OnRediscoverPressed;
|
||||
}
|
||||
|
||||
public void SetEntity(EntityUid entity)
|
||||
@@ -77,7 +64,9 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||
MinHeight = 10
|
||||
});
|
||||
|
||||
var hasAccess = HasAccess();
|
||||
var hasAccess = _player.LocalEntity is not { } local ||
|
||||
!_entity.TryGetComponent<AccessReaderComponent>(Entity, out var access) ||
|
||||
_accessReader.IsAllowed(local, Entity, access);
|
||||
foreach (var techId in database.CurrentTechnologyCards)
|
||||
{
|
||||
var tech = _prototype.Index<TechnologyPrototype>(techId);
|
||||
@@ -90,12 +79,6 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||
SyncTechnologyList(UnlockedCardsContainer, unlockedTech);
|
||||
}
|
||||
|
||||
private void UpdateRediscoverButton()
|
||||
{
|
||||
RediscoverButton.Disabled = !HasAccess() || _serverPoints < _rediscoverCost || _timing.CurTime < _nextRediscover;
|
||||
RediscoverButton.Text = Loc.GetString("research-console-menu-server-rediscover-button", ("cost", _rediscoverCost));
|
||||
}
|
||||
|
||||
public void UpdateInformationPanel(ResearchConsoleBoundInterfaceState state)
|
||||
{
|
||||
var amountMsg = new FormattedMessage();
|
||||
@@ -154,27 +137,6 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||
};
|
||||
TierDisplayContainer.AddChild(control);
|
||||
}
|
||||
|
||||
_serverPoints = state.Points;
|
||||
_rediscoverCost = state.RediscoverCost;
|
||||
_nextRediscover = state.NextRediscover;
|
||||
|
||||
UpdateRediscoverButton();
|
||||
}
|
||||
|
||||
private void OnRediscoverPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
RediscoverButton.Disabled = true;
|
||||
_nextRediscover = null;
|
||||
|
||||
OnTechnologyRediscoverPressed?.Invoke();
|
||||
}
|
||||
|
||||
private bool HasAccess()
|
||||
{
|
||||
return _player.LocalEntity is not { } local
|
||||
|| !_entity.TryGetComponent<AccessReaderComponent>(Entity, out var access)
|
||||
|| _accessReader.IsAllowed(local, Entity, access);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -217,24 +179,5 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||
container.Children.Remove(techControl);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if(_nextUpdate > _timing.CurTime)
|
||||
return;
|
||||
|
||||
_nextUpdate = _timing.CurTime + _updateInterval;
|
||||
|
||||
if (!RediscoverButton.Disabled)
|
||||
return;
|
||||
|
||||
if (_nextRediscover == null || _nextRediscover > _timing.CurTime)
|
||||
return;
|
||||
|
||||
UpdateRediscoverButton();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ public partial class ChatBox : UIWidget
|
||||
formatted.PushColor(color);
|
||||
formatted.AddMarkupOrThrow(message);
|
||||
formatted.Pop();
|
||||
Contents.AddMessage(formatted);
|
||||
Contents.AddMessage(formatted, tagsAllowed: null);
|
||||
}
|
||||
|
||||
public void Focus(ChatSelectChannel? channel = null)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Destructible;
|
||||
using Content.Server.Effects;
|
||||
using Content.Server.Weapons.Ranged.Systems;
|
||||
using Content.Shared.Camera;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Database;
|
||||
@@ -68,45 +69,11 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
||||
LogImpact.Medium,
|
||||
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {damage:damage} damage");
|
||||
|
||||
// If penetration is to be considered, we need to do some checks to see if the projectile should stop.
|
||||
if (component.PenetrationThreshold != 0)
|
||||
{
|
||||
// If a damage type is required, stop the bullet if the hit entity doesn't have that type.
|
||||
if (component.PenetrationDamageTypeRequirement != null)
|
||||
{
|
||||
var stopPenetration = false;
|
||||
foreach (var requiredDamageType in component.PenetrationDamageTypeRequirement)
|
||||
{
|
||||
if (!damage.DamageDict.Keys.Contains(requiredDamageType))
|
||||
{
|
||||
stopPenetration = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stopPenetration)
|
||||
component.ProjectileSpent = true;
|
||||
}
|
||||
|
||||
// If the object won't be destroyed, it "tanks" the penetration hit.
|
||||
if (damage.GetTotal() < damageRequired)
|
||||
{
|
||||
component.ProjectileSpent = true;
|
||||
}
|
||||
|
||||
if (!component.ProjectileSpent)
|
||||
{
|
||||
component.PenetrationAmount += damageRequired;
|
||||
// The projectile has dealt enough damage to be spent.
|
||||
if (component.PenetrationAmount >= component.PenetrationThreshold)
|
||||
{
|
||||
component.ProjectileSpent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
component.ProjectileSpent = true;
|
||||
}
|
||||
component.ProjectileSpent = !TryPenetrate((uid, component), damage, damageRequired);
|
||||
}
|
||||
else
|
||||
{
|
||||
component.ProjectileSpent = true;
|
||||
}
|
||||
|
||||
if (!deleted)
|
||||
@@ -125,4 +92,41 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
||||
RaiseNetworkEvent(new ImpactEffectEvent(component.ImpactEffect, GetNetCoordinates(xform.Coordinates)), Filter.Pvs(xform.Coordinates, entityMan: EntityManager));
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryPenetrate(Entity<ProjectileComponent> projectile, DamageSpecifier damage, FixedPoint2 damageRequired)
|
||||
{
|
||||
// If penetration is to be considered, we need to do some checks to see if the projectile should stop.
|
||||
if (projectile.Comp.PenetrationThreshold == 0)
|
||||
return false;
|
||||
|
||||
// If a damage type is required, stop the bullet if the hit entity doesn't have that type.
|
||||
if (projectile.Comp.PenetrationDamageTypeRequirement != null)
|
||||
{
|
||||
foreach (var requiredDamageType in projectile.Comp.PenetrationDamageTypeRequirement)
|
||||
{
|
||||
if (damage.DamageDict.Keys.Contains(requiredDamageType))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the object won't be destroyed, it "tanks" the penetration hit.
|
||||
if (damage.GetTotal() < damageRequired)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!projectile.Comp.ProjectileSpent)
|
||||
{
|
||||
projectile.Comp.PenetrationAmount += damageRequired;
|
||||
// The projectile has dealt enough damage to be spent.
|
||||
if (projectile.Comp.PenetrationAmount >= projectile.Comp.PenetrationThreshold)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ public sealed partial class ResearchSystem
|
||||
private void InitializeConsole()
|
||||
{
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, ConsoleUnlockTechnologyMessage>(OnConsoleUnlock);
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, ConsoleRediscoverTechnologyMessage>(OnRediscoverTechnology);
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, BeforeActivatableUIOpenEvent>(OnConsoleBeforeUiOpened);
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, ResearchServerPointsChangedEvent>(OnPointsChanged);
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, ResearchRegistrationChangedEvent>(OnConsoleRegistrationChanged);
|
||||
@@ -26,41 +25,6 @@ public sealed partial class ResearchSystem
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, GotEmaggedEvent>(OnEmagged);
|
||||
}
|
||||
|
||||
private void OnRediscoverTechnology(
|
||||
EntityUid uid,
|
||||
ResearchConsoleComponent console,
|
||||
ConsoleRediscoverTechnologyMessage args
|
||||
)
|
||||
{
|
||||
var act = args.Actor;
|
||||
|
||||
if (!this.IsPowered(uid, EntityManager))
|
||||
return;
|
||||
|
||||
if (!HasAccess(uid, act))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("research-console-no-access-popup"), act);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetClientServer(uid, out var serverEnt, out var serverComponent))
|
||||
return;
|
||||
|
||||
if(serverComponent.NextRediscover > _timing.CurTime)
|
||||
return;
|
||||
|
||||
var rediscoverCost = serverComponent.RediscoverCost;
|
||||
if (rediscoverCost > serverComponent.Points)
|
||||
return;
|
||||
|
||||
serverComponent.NextRediscover = _timing.CurTime + serverComponent.RediscoverInterval;
|
||||
|
||||
ModifyServerPoints(serverEnt.Value, -rediscoverCost);
|
||||
UpdateTechnologyCards(serverEnt.Value);
|
||||
SyncClientWithServer(uid);
|
||||
UpdateConsoleInterface(uid);
|
||||
}
|
||||
|
||||
private void OnConsoleUnlock(EntityUid uid, ResearchConsoleComponent component, ConsoleUnlockTechnologyMessage args)
|
||||
{
|
||||
var act = args.Actor;
|
||||
@@ -71,7 +35,7 @@ public sealed partial class ResearchSystem
|
||||
if (!PrototypeManager.TryIndex<TechnologyPrototype>(args.Id, out var technologyPrototype))
|
||||
return;
|
||||
|
||||
if (!HasAccess(uid, act))
|
||||
if (TryComp<AccessReaderComponent>(uid, out var access) && !_accessReader.IsAllowed(act, uid, access))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("research-console-no-access-popup"), act);
|
||||
return;
|
||||
@@ -108,17 +72,17 @@ public sealed partial class ResearchSystem
|
||||
if (!Resolve(uid, ref component, ref clientComponent, false))
|
||||
return;
|
||||
|
||||
|
||||
var points = 0;
|
||||
var nextRediscover = TimeSpan.MaxValue;
|
||||
var rediscoverCost = 0;
|
||||
if (TryGetClientServer(uid, out _, out var serverComponent, clientComponent) && clientComponent.ConnectedToServer)
|
||||
ResearchConsoleBoundInterfaceState state;
|
||||
|
||||
if (TryGetClientServer(uid, out _, out var serverComponent, clientComponent))
|
||||
{
|
||||
points = serverComponent.Points;
|
||||
nextRediscover = serverComponent.NextRediscover;
|
||||
rediscoverCost = serverComponent.RediscoverCost;
|
||||
var points = clientComponent.ConnectedToServer ? serverComponent.Points : 0;
|
||||
state = new ResearchConsoleBoundInterfaceState(points);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = new ResearchConsoleBoundInterfaceState(default);
|
||||
}
|
||||
var state = new ResearchConsoleBoundInterfaceState(points, nextRediscover, rediscoverCost);
|
||||
|
||||
_uiSystem.SetUiState(uid, ResearchConsoleUiKey.Key, state);
|
||||
}
|
||||
@@ -157,9 +121,4 @@ public sealed partial class ResearchSystem
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private bool HasAccess(EntityUid uid, EntityUid act)
|
||||
{
|
||||
return TryComp<AccessReaderComponent>(uid, out var access) && _accessReader.IsAllowed(act, uid, access);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,10 +165,10 @@ public sealed partial class ResearchSystem
|
||||
if (args.Server != null)
|
||||
return;
|
||||
component.MainDiscipline = null;
|
||||
component.CurrentTechnologyCards = new();
|
||||
component.SupportedDisciplines = new();
|
||||
component.UnlockedTechnologies = new();
|
||||
component.UnlockedRecipes = new();
|
||||
component.CurrentTechnologyCards = new List<string>();
|
||||
component.SupportedDisciplines = new List<ProtoId<TechDisciplinePrototype>>();
|
||||
component.UnlockedTechnologies = new List<ProtoId<TechnologyPrototype>>();
|
||||
component.UnlockedRecipes = new List<ProtoId<LatheRecipePrototype>>();
|
||||
Dirty(uid, component);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,11 +218,13 @@ public abstract partial class SharedMoverController : VirtualController
|
||||
* Physics simulation, which will cause issues for Dynamic bodies (Such as Friction being applied twice).
|
||||
* Kinematic bodies have even less Physics options and as such aren't suitable for a player, especially
|
||||
* when we move to Box2D v3 where there will be more support for players updating outside of simulation.
|
||||
* However, Kinematic bodies are useful currently for mobs which explicitly ignore physics, you should use
|
||||
* this type extremely sparingly and only for mobs which *explicitly* disobey the laws of physics (A-Ghosts).
|
||||
* Lastly, static bodies can't move so they shouldn't be updated. If a static body makes it here we're
|
||||
* doing unnecessary calculations.
|
||||
* Only a Kinematic Controller should be making it to this point.
|
||||
*/
|
||||
DebugTools.Assert(physicsComponent.BodyType == BodyType.KinematicController,
|
||||
DebugTools.Assert(physicsComponent.BodyType == BodyType.KinematicController || physicsComponent.BodyType == BodyType.Kinematic,
|
||||
$"Input mover: {ToPrettyString(uid)} in HandleMobMovement is not the correct BodyType, BodyType found: {physicsComponent.BodyType}, expected: KinematicController.");
|
||||
|
||||
// If the body is in air but isn't weightless then it can't move
|
||||
|
||||
@@ -1,32 +1,26 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Research.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class ResearchServerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the server
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[DataField]
|
||||
[DataField("serverName"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string ServerName = "RDSERVER";
|
||||
|
||||
/// <summary>
|
||||
/// The amount of points on the server.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[DataField]
|
||||
[DataField("points"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Points;
|
||||
|
||||
/// <summary>
|
||||
/// Cost of technology research options reroll.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[DataField]
|
||||
public int RediscoverCost = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// A unique numeric id representing the server
|
||||
/// </summary>
|
||||
@@ -43,34 +37,27 @@ public sealed partial class ResearchServerComponent : Component
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public List<EntityUid> Clients = new();
|
||||
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
[DataField("nextUpdateTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextUpdateTime = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
[DataField("researchConsoleUpdateTime"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan ResearchConsoleUpdateTime = TimeSpan.FromSeconds(1);
|
||||
|
||||
/// <summary>
|
||||
/// Time when next reroll for tech to research will be available.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
|
||||
public TimeSpan NextRediscover;
|
||||
|
||||
/// <summary>
|
||||
/// Minimal interval between rediscover actions.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan RediscoverInterval = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised on a server's clients when the point value of the server is changed.
|
||||
/// </summary>
|
||||
/// <param name="Server"></param>
|
||||
/// <param name="Total"></param>
|
||||
/// <param name="Delta"></param>
|
||||
[ByRefEvent]
|
||||
public readonly record struct ResearchServerPointsChangedEvent(EntityUid Server, int Total, int Delta);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised every second to calculate the amount of points added to the server.
|
||||
/// </summary>
|
||||
/// <param name="Server"></param>
|
||||
/// <param name="Points"></param>
|
||||
[ByRefEvent]
|
||||
public record struct ResearchServerGetPointsPerSecondEvent(EntityUid Server, int Points);
|
||||
|
||||
|
||||
@@ -9,13 +9,15 @@ namespace Content.Shared.Research.Components
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ConsoleUnlockTechnologyMessage(string id) : BoundUserInterfaceMessage
|
||||
public sealed class ConsoleUnlockTechnologyMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public string Id = id;
|
||||
}
|
||||
public string Id;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ConsoleRediscoverTechnologyMessage : BoundUserInterfaceMessage;
|
||||
public ConsoleUnlockTechnologyMessage(string id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ConsoleServerSelectionMessage : BoundUserInterfaceMessage
|
||||
@@ -24,12 +26,12 @@ namespace Content.Shared.Research.Components
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ResearchConsoleBoundInterfaceState(int points, TimeSpan nextRediscover, int rediscoverCost) : BoundUserInterfaceState
|
||||
public sealed class ResearchConsoleBoundInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public int Points = points;
|
||||
|
||||
public TimeSpan NextRediscover = nextRediscover;
|
||||
|
||||
public int RediscoverCost = rediscoverCost;
|
||||
public int Points;
|
||||
public ResearchConsoleBoundInterfaceState(int points)
|
||||
{
|
||||
Points = points;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Shared.Research.Prototypes;
|
||||
using Content.Shared.Research.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Research.Components;
|
||||
|
||||
@@ -13,12 +14,12 @@ public sealed partial class TechnologyDatabaseComponent : Component
|
||||
/// A main discipline that locks out other discipline technology past a certain tier.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[DataField]
|
||||
public ProtoId<TechDisciplinePrototype>? MainDiscipline;
|
||||
[DataField("mainDiscipline", customTypeSerializer: typeof(PrototypeIdSerializer<TechDisciplinePrototype>))]
|
||||
public string? MainDiscipline;
|
||||
|
||||
[AutoNetworkedField]
|
||||
[DataField]
|
||||
public List<ProtoId<TechnologyPrototype>> CurrentTechnologyCards = new();
|
||||
[DataField("currentTechnologyCards")]
|
||||
public List<string> CurrentTechnologyCards = new();
|
||||
|
||||
/// <summary>
|
||||
/// Which research disciplines are able to be unlocked
|
||||
|
||||
@@ -2984,13 +2984,6 @@
|
||||
id: 9240
|
||||
time: '2025-12-01T05:47:46.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/41489
|
||||
- author: TheShuEd
|
||||
changes:
|
||||
- message: Santa anomaly & santa anomaly infections is back!
|
||||
type: Add
|
||||
id: 9241
|
||||
time: '2025-12-01T11:01:51.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/41654
|
||||
- author: Spessmann
|
||||
changes:
|
||||
- message: Added a new station, Snowball, a round and icy lowpop station.
|
||||
@@ -3588,13 +3581,6 @@
|
||||
id: 9317
|
||||
time: '2025-12-18T21:08:51.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/33157
|
||||
- author: Fildrance
|
||||
changes:
|
||||
- message: reroll feature for RnD research console
|
||||
type: Add
|
||||
id: 9318
|
||||
time: '2025-12-18T21:22:45.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/32931
|
||||
- author: Hitlinemoss
|
||||
changes:
|
||||
- message: Small cardboard boxes have been added (2x2 instead of 3x3), and can be
|
||||
@@ -3663,14 +3649,6 @@
|
||||
id: 9324
|
||||
time: '2025-12-21T20:33:07.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/41932
|
||||
- author: SlamBamActionman
|
||||
changes:
|
||||
- message: 'EXPERIMENTAL: Changed the name of the "LOOC" chat channel to "Help"
|
||||
to reflect its primary usage.'
|
||||
type: Tweak
|
||||
id: 9325
|
||||
time: '2025-12-22T00:46:26.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/41933
|
||||
- author: MilonPL
|
||||
changes:
|
||||
- message: Fixed beaker solutions duplicating whenever it's thrown.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
server-shutdown = Shutdown
|
||||
server-ooc-toggle = Toggle OOC
|
||||
server-looc-toggle = Toggle Help (LOOC)
|
||||
server-looc-toggle = Toggle LOOC
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
chat-manager-max-message-length = Your message exceeds {$maxMessageLength} character limit
|
||||
chat-manager-ooc-chat-enabled-message = OOC chat has been enabled.
|
||||
chat-manager-ooc-chat-disabled-message = OOC chat has been disabled.
|
||||
chat-manager-looc-chat-enabled-message = Help chat has been enabled.
|
||||
chat-manager-looc-chat-disabled-message = Help chat has been disabled.
|
||||
chat-manager-dead-looc-chat-enabled-message = Dead players can now use Help.
|
||||
chat-manager-dead-looc-chat-disabled-message = Dead players can no longer use Help.
|
||||
chat-manager-crit-looc-chat-enabled-message = Crit players can now use Help.
|
||||
chat-manager-crit-looc-chat-disabled-message = Crit players can no longer use Help.
|
||||
chat-manager-looc-chat-enabled-message = LOOC chat has been enabled.
|
||||
chat-manager-looc-chat-disabled-message = LOOC chat has been disabled.
|
||||
chat-manager-dead-looc-chat-enabled-message = Dead players can now use LOOC.
|
||||
chat-manager-dead-looc-chat-disabled-message = Dead players can no longer use LOOC.
|
||||
chat-manager-crit-looc-chat-enabled-message = Crit players can now use LOOC.
|
||||
chat-manager-crit-looc-chat-disabled-message = Crit players can no longer use LOOC.
|
||||
chat-manager-admin-ooc-chat-enabled-message = Admin OOC chat has been enabled.
|
||||
chat-manager-admin-ooc-chat-disabled-message = Admin OOC chat has been disabled.
|
||||
|
||||
@@ -34,7 +34,7 @@ chat-manager-entity-me-wrap-message = [italic]{ PROPER($entity) ->
|
||||
[true] {CAPITALIZE($entityName)} {$message}[/italic]
|
||||
}
|
||||
|
||||
chat-manager-entity-looc-wrap-message = Help: [bold]{$entityName}:[/bold] {$message}
|
||||
chat-manager-entity-looc-wrap-message = LOOC: [bold]{$entityName}:[/bold] {$message}
|
||||
chat-manager-send-ooc-wrap-message = OOC: [bold]{$playerName}:[/bold] {$message}
|
||||
chat-manager-send-ooc-patron-wrap-message = OOC: [bold][color={$patronColor}]{$playerName}[/color]:[/bold] {$message}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ hud-chatbox-select-channel-Dead = Dead
|
||||
hud-chatbox-select-channel-Emotes = Emotes
|
||||
hud-chatbox-select-channel-Local = Local
|
||||
hud-chatbox-select-channel-Whisper = Whisper
|
||||
hud-chatbox-select-channel-LOOC = Help
|
||||
hud-chatbox-select-channel-LOOC = LOOC
|
||||
hud-chatbox-select-channel-OOC = OOC
|
||||
hud-chatbox-select-channel-Damage = Damage
|
||||
hud-chatbox-select-channel-Visual = Actions
|
||||
@@ -23,7 +23,7 @@ hud-chatbox-channel-Dead = Dead
|
||||
hud-chatbox-channel-Emotes = Emotes
|
||||
hud-chatbox-channel-Local = Local
|
||||
hud-chatbox-channel-Whisper = Whisper
|
||||
hud-chatbox-channel-LOOC = Help
|
||||
hud-chatbox-channel-LOOC = LOOC
|
||||
hud-chatbox-channel-OOC = OOC
|
||||
hud-chatbox-channel-Radio = Radio
|
||||
hud-chatbox-channel-Notifications = Notifications
|
||||
|
||||
@@ -6,8 +6,6 @@ research-console-menu-main-discipline = Main Discipline: [color={$color}]{$name}
|
||||
research-console-menu-server-selection-button = Server list
|
||||
research-console-menu-server-sync-button = Sync
|
||||
research-console-menu-server-research-button = Research
|
||||
research-console-menu-server-rediscover-button = Rediscover ({$cost})
|
||||
research-console-menu-server-rediscover-tooltip = Reroll list of technologies to research
|
||||
research-console-available-text = Researchable Technologies
|
||||
research-console-unlocked-text = Unlocked Technologies
|
||||
research-console-tier-discipline-info = Tier {$tier}, [color={$color}]{$discipline}[/color]
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- AnomalyFlora
|
||||
- AnomalyShadow
|
||||
- AnomalyTech
|
||||
- AnomalySanta
|
||||
#- AnomalySanta
|
||||
rareChance: 0.3
|
||||
rarePrototypes:
|
||||
- RandomAnomalyInjectorSpawner
|
||||
@@ -72,5 +72,5 @@
|
||||
- AnomalyTrapGravity
|
||||
- AnomalyTrapTech
|
||||
- AnomalyTrapRock
|
||||
- AnomalyTrapSanta
|
||||
#- AnomalyTrapSanta
|
||||
chance: 1
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
needsHands: false
|
||||
- type: CombatMode
|
||||
- type: Physics
|
||||
bodyType: Kinematic # Admin ghosts should ignore the laws of physics.
|
||||
ignorePaused: true
|
||||
- type: Access
|
||||
groups:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<Document>
|
||||
# Speech and Text Channels
|
||||
Talking is a key part of Space Station 14. You can press [color=yellow][bold][keybind="FocusChatInputWindow"/][/bold][/color] to jump to the text box.
|
||||
Talking is a key part of Space Station 14. You can press [keybind="FocusChatInputWindow"/] to jump to the text box.
|
||||
|
||||
The word next to the text box is the [color=#a4885c]text channel[/color] you're about to send the message to, or rather how you're about to say what you've typed.
|
||||
|
||||
[bold]Local[/bold] is normal speech at normal volume.
|
||||
Local is normal speech at normal volume.
|
||||
|
||||
[bold]Whisper[/bold] can only be heard when nearby somebody. You automatically whisper into your radio to send messages over it.
|
||||
Whisper can only be heard when nearby somebody. You automatically whisper into your radio to send messages over it.
|
||||
|
||||
[bold]Emotes[/bold] are gestures that you make. Can be recieved by anyone who is not blinded. You will often see mimes do many emotes.
|
||||
Emotes are gestures that you make. Can be recieved by anyone who is not blinded. You will often see mimes do many emotes.
|
||||
|
||||
Whisper messages can be sent by starting your message with "[color=#a4885c][keybind="FocusWhisperChatWindow"/][/color]" and Emotes can be sent by starting your message with "[color=#a4885c]@[/color]".
|
||||
You can also cycle through all of these text channels by pressing [color=yellow][bold][keybind="CycleChatChannelForward"/][/bold][/color].
|
||||
Whisper messages can be sent by starting your message with [color=#a4885c][keybind="FocusWhisperChatWindow"/][/color] and Emotes can be sent by starting your message with ([color=#a4885c]@[/color]).
|
||||
You can also cycle through all of these text channels by pressing [keybind="CycleChatChannelForward"/].
|
||||
|
||||
People may not be able to make out all of what you're saying if you're standing too far away from them. This is especially important if you're whispering.
|
||||
|
||||
@@ -23,7 +23,7 @@ Your radio allows you to communicate across the entire station and to your speci
|
||||
<GuideEntityEmbed Entity="ClothingHeadsetGrey"/>
|
||||
</Box>
|
||||
|
||||
To send a [color=#a4885c]station-wide[/color] message over the radio preface, use the [color=#32cd32][bold]Common[/bold][/color] channel by beginning your text with [color=#32cd32]semi-colon (;)[/color].
|
||||
To send a [color=#a4885c]station-wide[/color] message over the radio preface, use the [color=#32cd32]Common[/color] channel by beginning your text with [color=#32cd32]semi-colon (;)[/color].
|
||||
People standing right next to you might catch bits of your radio message, even if they don't have the access to the relevant radio channel. Watch for eavesdroppers.
|
||||
|
||||
## Departmental Radio
|
||||
@@ -43,26 +43,22 @@ For example, if you're a Station Engineer then [color=#a4885c]:h[/color] will de
|
||||
|
||||
## Encryption Keys
|
||||
[color=#a4885c]Encryption keys[/color] give you access to their respective channel.
|
||||
|
||||
|
||||
Examining our engineering headset from earlier shows us [color=#32cd32]Common[/color] and [color=#f37746]Engineering[/color] because an engineer's headset starts with those [color=#a4885c]encryption keys[/color].
|
||||
|
||||
|
||||
<Box>
|
||||
<GuideEntityEmbed Entity="EncryptionKeyCommon"/>
|
||||
<GuideEntityEmbed Entity="EncryptionKeyEngineering"/>
|
||||
</Box>
|
||||
|
||||
|
||||
You can take out encryption keys by using a [color=#a4885c]screwdriver[/color] on a headset. New encryption keys are put into headsets by clicking on one with an encryption key in your hand.
|
||||
|
||||
All command members have extras of their relevant encryption key, but you can also request one at the HoP's office when you're getting your job changed.
|
||||
|
||||
## OOC Channels
|
||||
OOC (out-of-character) channels exist outside of the game world; in them you are not speaking as your character, but as yourself! They are the Help, Dead and OOC chat.
|
||||
OOC (out-of-character) channels exist outside of the game world. They are LOOC, OOC and Dead chat.
|
||||
|
||||
[bold]Help[/bold] chat lets you ask other players near you questions about the game. It has the same range as Local chat and can be used even if your character couldn't normally speak.
|
||||
|
||||
[bold]Dead[/bold] chat is the main chat you use when you're dead. It's global and can be heard across the game, but only by other dead players.
|
||||
|
||||
[bold]OOC[/bold] is the main global chat heard by every player, and is therefore typically off until the round ends.
|
||||
LOOC is on during the rounds, OOC is typically off until the round ends and you can only see and talk in Dead chat when you are, well, dead.
|
||||
|
||||
Do not discuss the current round in the Discord or in OOC if it's on during the round.
|
||||
</Document>
|
||||
|
||||
Reference in New Issue
Block a user