diff --git a/.editorconfig b/.editorconfig index a8ce1d6b68b..59ca35cc9a5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -338,5 +338,8 @@ dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter resharper_braces_for_ifelse = required_for_multiline resharper_keep_existing_attribute_arrangement = true -[*.{csproj,xml,yml,dll.config,msbuildproj,targets}] +[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets}] indent_size = 2 + +[{*.yaml,*.yml}] +ij_yaml_indent_sequence_value = false diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index 83d927c94bb..a487e5d8d8a 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Shared.Actions; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Shared.ContentPack; using Robust.Shared.GameStates; @@ -41,8 +40,8 @@ public sealed class ActionsSystem : SharedActionsSystem public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(HandleComponentState); SubscribeLocalEvent(OnInstantHandleState); @@ -196,12 +195,12 @@ protected override void ActionRemoved(EntityUid performer, EntityUid actionId, A return GetActions(user); } - private void OnPlayerAttached(EntityUid uid, ActionsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, ActionsComponent component, LocalPlayerAttachedEvent args) { LinkAllActions(component); } - private void OnPlayerDetached(EntityUid uid, ActionsComponent component, PlayerDetachedEvent? args = null) + private void OnPlayerDetached(EntityUid uid, ActionsComponent component, LocalPlayerDetachedEvent? args = null) { UnlinkAllActions(); } diff --git a/Content.Client/Administration/Managers/ClientAdminManager.cs b/Content.Client/Administration/Managers/ClientAdminManager.cs index 8978e2fd6dd..1a1366c6f2e 100644 --- a/Content.Client/Administration/Managers/ClientAdminManager.cs +++ b/Content.Client/Administration/Managers/ClientAdminManager.cs @@ -4,7 +4,7 @@ using Robust.Client.Player; using Robust.Shared.ContentPack; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Client.Administration.Managers diff --git a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs index 6142e3a8318..5fa28bf1ac7 100644 --- a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs +++ b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs @@ -22,7 +22,7 @@ public sealed partial class PlayerListControl : BoxContainer private List _playerList = new(); private readonly List _sortedPlayerList = new(); - public event Action? OnSelectionChanged; + public event Action? OnSelectionChanged; public IReadOnlyList PlayerInfo => _playerList; public Func? OverrideText; @@ -46,9 +46,9 @@ public PlayerListControl() BackgroundPanel.PanelOverride = new StyleBoxFlat {BackgroundColor = new Color(32, 32, 40)}; } - private void PlayerListItemPressed(BaseButton.ButtonEventArgs args, ListData data) + private void PlayerListItemPressed(BaseButton.ButtonEventArgs? args, ListData? data) { - if (data is not PlayerListData {Info: var selectedPlayer}) + if (args == null || data is not PlayerListData {Info: var selectedPlayer}) return; if (args.Event.Function == EngineKeyFunctions.UIClick) { diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs index c5a9bd036a4..1978b5c3c06 100644 --- a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs @@ -5,7 +5,6 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.IoC; -using Robust.Shared.Players; namespace Content.Client.Administration.UI.Tabs.AdminTab { diff --git a/Content.Client/Alerts/ClientAlertsSystem.cs b/Content.Client/Alerts/ClientAlertsSystem.cs index bb6d2d4df4e..50890224153 100644 --- a/Content.Client/Alerts/ClientAlertsSystem.cs +++ b/Content.Client/Alerts/ClientAlertsSystem.cs @@ -1,7 +1,6 @@ using System.Linq; using Content.Shared.Alert; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Shared.Prototypes; @@ -22,8 +21,8 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(ClientAlertsHandleState); } @@ -69,7 +68,7 @@ private void ClientAlertsHandleState(EntityUid uid, AlertsComponent component, r SyncAlerts?.Invoke(this, component.Alerts); } - private void OnPlayerAttached(EntityUid uid, AlertsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, AlertsComponent component, LocalPlayerAttachedEvent args) { if (_playerManager.LocalPlayer?.ControlledEntity != uid) return; @@ -87,7 +86,7 @@ protected override void HandleComponentShutdown(EntityUid uid, AlertsComponent c ClearAlerts?.Invoke(this, EventArgs.Empty); } - private void OnPlayerDetached(EntityUid uid, AlertsComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, AlertsComponent component, LocalPlayerDetachedEvent args) { ClearAlerts?.Invoke(this, EventArgs.Empty); } diff --git a/Content.Client/CharacterInfo/CharacterInfoSystem.cs b/Content.Client/CharacterInfo/CharacterInfoSystem.cs index 93bd86d140b..844a352a184 100644 --- a/Content.Client/CharacterInfo/CharacterInfoSystem.cs +++ b/Content.Client/CharacterInfo/CharacterInfoSystem.cs @@ -1,6 +1,5 @@ using Content.Shared.CharacterInfo; using Content.Shared.Objectives; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.UserInterface; @@ -11,14 +10,11 @@ public sealed class CharacterInfoSystem : EntitySystem [Dependency] private readonly IPlayerManager _players = default!; public event Action? OnCharacterUpdate; - public event Action? OnCharacterDetached; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeNetworkEvent(OnCharacterInfoEvent); } @@ -33,14 +29,6 @@ public void RequestCharacterInfo() RaiseNetworkEvent(new RequestCharacterInfoEvent(GetNetEntity(entity.Value))); } - private void OnPlayerAttached(PlayerAttachSysMessage msg) - { - if (msg.AttachedEntity == default) - { - OnCharacterDetached?.Invoke(); - } - } - private void OnCharacterInfoEvent(CharacterInfoEvent msg, EntitySessionEventArgs args) { var entity = GetEntity(msg.NetEntity); diff --git a/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs b/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs index ec582ee0944..2ee88956ff6 100644 --- a/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs +++ b/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs @@ -1,8 +1,6 @@ -using Content.Shared.Smoking; -using Robust.Shared.Spawners; +using Content.Shared.Chemistry.Components; using Robust.Client.Animations; using Robust.Client.GameObjects; -using Robust.Shared.Network; using Robust.Shared.Timing; namespace Content.Client.Chemistry.Visualizers; @@ -18,6 +16,7 @@ public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnComponentInit); + SubscribeLocalEvent(OnAnimationComplete); } public override void Update(float frameTime) @@ -27,11 +26,11 @@ public override void Update(float frameTime) if (!_timing.IsFirstTimePredicted) return; - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var comp, out var despawn)) + while (query.MoveNext(out var uid, out var comp, out var smoke)) { - if (despawn.Lifetime > 1f) + if (_timing.CurTime < comp.StartTime + TimeSpan.FromSeconds(smoke.Duration) - TimeSpan.FromSeconds(comp.AnimationTime)) continue; // Despawn animation. @@ -48,6 +47,7 @@ public override void Update(float frameTime) /// private void OnComponentInit(EntityUid uid, FoamVisualsComponent comp, ComponentInit args) { + comp.StartTime = _timing.CurTime; comp.Animation = new Animation { Length = TimeSpan.FromSeconds(comp.AnimationTime), @@ -58,12 +58,21 @@ private void OnComponentInit(EntityUid uid, FoamVisualsComponent comp, Component LayerKey = FoamVisualLayers.Base, KeyFrames = { - new AnimationTrackSpriteFlick.KeyFrame(comp.State, 0f) + new AnimationTrackSpriteFlick.KeyFrame(comp.AnimationState, 0f) } } } }; } + + private void OnAnimationComplete(EntityUid uid, FoamVisualsComponent component, AnimationCompletedEvent args) + { + if (args.Key != FoamVisualsComponent.AnimationKey) + return; + + if (TryComp(uid, out var sprite)) + sprite.Visible = false; + } } public enum FoamVisualLayers : byte diff --git a/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs b/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs index b09c74aa0fe..8199efa42ee 100644 --- a/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs +++ b/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs @@ -1,5 +1,6 @@ using Robust.Client.Animations; using Robust.Client.Graphics; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Client.Chemistry.Visualizers; @@ -15,18 +16,21 @@ public sealed partial class FoamVisualsComponent : Component /// public const string AnimationKey = "foamdissolve_animation"; + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + public TimeSpan StartTime; + /// /// How long the foam visually dissolves for. /// - [DataField("animationTime")] - public float AnimationTime = 0.6f; + [DataField] + public float AnimationTime = 0.5f; /// /// The state of the entities base sprite RSI that is displayed when the foam dissolves. /// Cannot use because it does not have and I am not making an engine PR at this time. /// - [DataField("animationState")] - public string State = "foam-dissolve"; + [DataField] + public string AnimationState = "foam-dissolve"; /// /// The animation used while the foam dissolves. diff --git a/Content.Client/Construction/ConstructionSystem.cs b/Content.Client/Construction/ConstructionSystem.cs index 98d2dfd414d..9fc638cea22 100644 --- a/Content.Client/Construction/ConstructionSystem.cs +++ b/Content.Client/Construction/ConstructionSystem.cs @@ -38,7 +38,7 @@ public override void Initialize() base.Initialize(); UpdatesOutsidePrediction = true; - SubscribeLocalEvent(HandlePlayerAttached); + SubscribeLocalEvent(HandlePlayerAttached); SubscribeNetworkEvent(HandleAckStructure); SubscribeNetworkEvent(OnConstructionGuideReceived); @@ -110,9 +110,9 @@ private void HandleAckStructure(AckStructureConstructionMessage msg) ClearGhost(msg.GhostId); } - private void HandlePlayerAttached(PlayerAttachSysMessage msg) + private void HandlePlayerAttached(LocalPlayerAttachedEvent msg) { - var available = IsCraftingAvailable(msg.AttachedEntity); + var available = IsCraftingAvailable(msg.Entity); UpdateCraftingAvailability(available); } diff --git a/Content.Client/Drugs/DrugOverlaySystem.cs b/Content.Client/Drugs/DrugOverlaySystem.cs index 7be63b4c50e..ec0d0140720 100644 --- a/Content.Client/Drugs/DrugOverlaySystem.cs +++ b/Content.Client/Drugs/DrugOverlaySystem.cs @@ -1,5 +1,4 @@ using Content.Shared.Drugs; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; @@ -24,18 +23,18 @@ public override void Initialize() SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, SeeingRainbowsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, SeeingRainbowsComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerDetachedEvent args) { _overlay.Intoxication = 0; _overlayMan.RemoveOverlay(_overlay); diff --git a/Content.Client/Drunk/DrunkSystem.cs b/Content.Client/Drunk/DrunkSystem.cs index 0573b2ff3eb..4f2ec70b56b 100644 --- a/Content.Client/Drunk/DrunkSystem.cs +++ b/Content.Client/Drunk/DrunkSystem.cs @@ -1,5 +1,4 @@ using Content.Shared.Drunk; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; @@ -19,18 +18,18 @@ public override void Initialize() SubscribeLocalEvent(OnDrunkInit); SubscribeLocalEvent(OnDrunkShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, DrunkComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, DrunkComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, DrunkComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, DrunkComponent component, LocalPlayerDetachedEvent args) { _overlay.CurrentBoozePower = 0; _overlayMan.RemoveOverlay(_overlay); diff --git a/Content.Client/Eye/Blinding/BlindingSystem.cs b/Content.Client/Eye/Blinding/BlindingSystem.cs index f0b760d838b..f255f7ef016 100644 --- a/Content.Client/Eye/Blinding/BlindingSystem.cs +++ b/Content.Client/Eye/Blinding/BlindingSystem.cs @@ -1,17 +1,7 @@ - -using Content.Shared.Eye.Blinding; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; -using System; -using System.Collections.Generic; -using System.Linq; -using Content.Shared.Administration; -using Content.Shared.Administration.Events; using Content.Shared.Eye.Blinding.Components; using Content.Shared.GameTicking; -using Robust.Shared.GameObjects; -using Robust.Shared.Network; namespace Content.Client.Eye.Blinding; @@ -31,20 +21,20 @@ public override void Initialize() SubscribeLocalEvent(OnBlindInit); SubscribeLocalEvent(OnBlindShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeNetworkEvent(RoundRestartCleanup); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, BlindableComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, BlindableComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, BlindableComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, BlindableComponent component, LocalPlayerDetachedEvent args) { _overlayMan.RemoveOverlay(_overlay); _lightManager.Enabled = true; diff --git a/Content.Client/Eye/Blinding/BlurryVisionSystem.cs b/Content.Client/Eye/Blinding/BlurryVisionSystem.cs index 1bac2a97bf4..8be5b4ed930 100644 --- a/Content.Client/Eye/Blinding/BlurryVisionSystem.cs +++ b/Content.Client/Eye/Blinding/BlurryVisionSystem.cs @@ -1,9 +1,6 @@ -using Content.Shared.Eye.Blinding; using Content.Shared.Eye.Blinding.Components; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; -using Robust.Shared.GameStates; namespace Content.Client.Eye.Blinding; @@ -20,18 +17,18 @@ public override void Initialize() SubscribeLocalEvent(OnBlurryInit); SubscribeLocalEvent(OnBlurryShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, BlurryVisionComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, BlurryVisionComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, BlurryVisionComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, BlurryVisionComponent component, LocalPlayerDetachedEvent args) { _overlayMan.RemoveOverlay(_overlay); } diff --git a/Content.Client/Eye/EyeLerpingSystem.cs b/Content.Client/Eye/EyeLerpingSystem.cs index 8e54196b81d..b46921a9b48 100644 --- a/Content.Client/Eye/EyeLerpingSystem.cs +++ b/Content.Client/Eye/EyeLerpingSystem.cs @@ -30,7 +30,7 @@ public override void Initialize() SubscribeLocalEvent(OnAttached); SubscribeLocalEvent(HandleMapChange); - SubscribeLocalEvent(OnDetached); + SubscribeLocalEvent(OnDetached); UpdatesAfter.Add(typeof(TransformSystem)); UpdatesAfter.Add(typeof(PhysicsSystem)); @@ -94,7 +94,7 @@ private void OnAttached(ref EyeAttachedEvent ev) AddEye(ev.Entity, ev.Component, true); } - private void OnDetached(EntityUid uid, LerpingEyeComponent component, PlayerDetachedEvent args) + private void OnDetached(EntityUid uid, LerpingEyeComponent component, LocalPlayerDetachedEvent args) { if (!component.ManuallyAdded) RemCompDeferred(uid, component); diff --git a/Content.Client/Fullscreen/FullscreenHook.cs b/Content.Client/Fullscreen/FullscreenHook.cs index 78a01517361..7917fddfbb0 100644 --- a/Content.Client/Fullscreen/FullscreenHook.cs +++ b/Content.Client/Fullscreen/FullscreenHook.cs @@ -4,7 +4,7 @@ using Robust.Shared.Input.Binding; using Robust.Shared; using Robust.Shared.Configuration; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Fullscreen; public sealed class FullscreenHook diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs index 788a4e5dfff..454c0632605 100644 --- a/Content.Client/Gameplay/GameplayStateBase.cs +++ b/Content.Client/Gameplay/GameplayStateBase.cs @@ -16,7 +16,7 @@ using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Client.Gameplay diff --git a/Content.Client/Ghost/GhostSystem.cs b/Content.Client/Ghost/GhostSystem.cs index 5727534109e..a89d0858d9d 100644 --- a/Content.Client/Ghost/GhostSystem.cs +++ b/Content.Client/Ghost/GhostSystem.cs @@ -58,10 +58,10 @@ public override void Initialize() SubscribeLocalEvent(OnGhostRemove); SubscribeLocalEvent(OnGhostState); - SubscribeLocalEvent(OnGhostPlayerAttach); - SubscribeLocalEvent(OnGhostPlayerDetach); + SubscribeLocalEvent(OnGhostPlayerAttach); + SubscribeLocalEvent(OnGhostPlayerDetach); - SubscribeLocalEvent(OnPlayerAttach); + SubscribeLocalEvent(OnPlayerAttach); SubscribeNetworkEvent(OnGhostWarpsResponse); SubscribeNetworkEvent(OnUpdateGhostRoleCount); @@ -130,7 +130,7 @@ private void OnGhostRemove(EntityUid uid, GhostComponent component, ComponentRem PlayerRemoved?.Invoke(component); } - private void OnGhostPlayerAttach(EntityUid uid, GhostComponent component, PlayerAttachedEvent playerAttachedEvent) + private void OnGhostPlayerAttach(EntityUid uid, GhostComponent component, LocalPlayerAttachedEvent localPlayerAttachedEvent) { if (uid != _playerManager.LocalPlayer?.ControlledEntity) return; @@ -161,13 +161,13 @@ private bool PlayerDetach(EntityUid uid) return true; } - private void OnGhostPlayerDetach(EntityUid uid, GhostComponent component, PlayerDetachedEvent args) + private void OnGhostPlayerDetach(EntityUid uid, GhostComponent component, LocalPlayerDetachedEvent args) { if (PlayerDetach(uid)) component.IsAttached = false; } - private void OnPlayerAttach(PlayerAttachedEvent ev) + private void OnPlayerAttach(LocalPlayerAttachedEvent ev) { if (!HasComp(ev.Entity)) PlayerDetach(ev.Entity); diff --git a/Content.Client/Hands/Systems/HandsSystem.cs b/Content.Client/Hands/Systems/HandsSystem.cs index ed40589f7fd..31de7ec1433 100644 --- a/Content.Client/Hands/Systems/HandsSystem.cs +++ b/Content.Client/Hands/Systems/HandsSystem.cs @@ -42,8 +42,8 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(HandlePlayerAttached); - SubscribeLocalEvent(HandlePlayerDetached); + SubscribeLocalEvent(HandlePlayerAttached); + SubscribeLocalEvent(HandlePlayerDetached); SubscribeLocalEvent(OnHandsStartup); SubscribeLocalEvent(OnHandsShutdown); SubscribeLocalEvent(HandleComponentState); @@ -361,12 +361,12 @@ private void OnVisualsChanged(EntityUid uid, HandsComponent component, VisualsCh #region Gui - private void HandlePlayerAttached(EntityUid uid, HandsComponent component, PlayerAttachedEvent args) + private void HandlePlayerAttached(EntityUid uid, HandsComponent component, LocalPlayerAttachedEvent args) { OnPlayerHandsAdded?.Invoke(component); } - private void HandlePlayerDetached(EntityUid uid, HandsComponent component, PlayerDetachedEvent args) + private void HandlePlayerDetached(EntityUid uid, HandsComponent component, LocalPlayerDetachedEvent args) { OnPlayerHandsRemoved?.Invoke(); } diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml index 1f64feec2b4..b78c3c6a567 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml @@ -1,9 +1,33 @@  - - - + SetSize="250 100"> + + + + + \ No newline at end of file diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs index 1c5a3373e15..36f7a08b961 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs @@ -1,5 +1,5 @@ +using System.Linq; using System.Numerics; -using System.Text; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; @@ -8,85 +8,182 @@ using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.UserInterface.Controls; +using Robust.Client.ResourceManagement; using Robust.Shared.Prototypes; +using Robust.Shared.Utility; namespace Content.Client.HealthAnalyzer.UI { [GenerateTypedNameReferences] public sealed partial class HealthAnalyzerWindow : DefaultWindow { + private readonly IEntityManager _entityManager; + private readonly SpriteSystem _spriteSystem; + private readonly IPrototypeManager _prototypes; + private readonly IResourceCache _cache; + + private const int AnalyzerHeight = 430; + private const int AnalyzerWidth = 300; + public HealthAnalyzerWindow() { RobustXamlLoader.Load(this); + + var dependencies = IoCManager.Instance!; + _entityManager = dependencies.Resolve(); + _spriteSystem = _entityManager.System(); + _prototypes = dependencies.Resolve(); + _cache = dependencies.Resolve(); } public void Populate(HealthAnalyzerScannedUserMessage msg) { - var text = new StringBuilder(); - var entities = IoCManager.Resolve(); - var target = entities.GetEntity(msg.TargetEntity); + GroupsContainer.RemoveAllChildren(); - if (msg.TargetEntity != null && entities.TryGetComponent(target, out var damageable)) + var target = _entityManager.GetEntity(msg.TargetEntity); + + if (target == null + || !_entityManager.TryGetComponent(target, out var damageable)) { - string entityName = "Unknown"; - if (msg.TargetEntity != null && - entities.HasComponent(target.Value)) - { - entityName = Identity.Name(target.Value, entities); - } + NoPatientDataText.Visible = true; + return; + } + + NoPatientDataText.Visible = false; + + string entityName = Loc.GetString("health-analyzer-window-entity-unknown-text"); + if (_entityManager.HasComponent(target.Value)) + { + entityName = Identity.Name(target.Value, _entityManager); + } - IReadOnlyDictionary damagePerGroup = damageable.DamagePerGroup; - IReadOnlyDictionary damagePerType = damageable.Damage.DamageDict; + PatientName.Text = Loc.GetString( + "health-analyzer-window-entity-health-text", + ("entityName", entityName) + ); - text.Append($"{Loc.GetString("health-analyzer-window-entity-health-text", ("entityName", entityName))}\n\n"); + Temperature.Text = Loc.GetString("health-analyzer-window-entity-temperature-text", + ("temperature", float.IsNaN(msg.Temperature) ? "N/A" : $"{msg.Temperature - 273f:F1} °C") + ); + BloodLevel.Text = Loc.GetString("health-analyzer-window-entity-blood-level-text", + ("bloodLevel", float.IsNaN(msg.BloodLevel) ? "N/A" : $"{msg.BloodLevel * 100:F1} %") + ); - text.Append($"{Loc.GetString("health-analyzer-window-entity-temperature-text", ("temperature", float.IsNaN(msg.Temperature) ? "N/A" : $"{msg.Temperature - 273f:F1} °C"))}\n"); + patientDamageAmount.Text = Loc.GetString( + "health-analyzer-window-entity-damage-total-text", + ("amount", damageable.TotalDamage) + ); + var damageSortedGroups = + damageable.DamagePerGroup.OrderBy(damage => damage.Value) + .ToDictionary(x => x.Key, x => x.Value); + IReadOnlyDictionary damagePerType = damageable.Damage.DamageDict; - text.Append($"{Loc.GetString("health-analyzer-window-entity-blood-level-text", ("bloodLevel", float.IsNaN(msg.BloodLevel) ? "N/A" : $"{msg.BloodLevel * 100:F1} %"))}\n\n"); + DrawDiagnosticGroups(damageSortedGroups, damagePerType); + SetHeight = AnalyzerHeight; + SetWidth = AnalyzerWidth; + } - // Damage - text.Append($"{Loc.GetString("health-analyzer-window-entity-damage-total-text", ("amount", damageable.TotalDamage))}\n"); + private void DrawDiagnosticGroups( + Dictionary groups, IReadOnlyDictionary damageDict) + { + HashSet shownTypes = new(); - HashSet shownTypes = new(); + // Show the total damage and type breakdown for each damage group. + foreach (var (damageGroupId, damageAmount) in groups.Reverse()) + { + if (damageAmount == 0) + continue; - var protos = IoCManager.Resolve(); + var groupTitleText = $"{Loc.GetString( + "health-analyzer-window-damage-group-text", + ("damageGroup", Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId)), + ("amount", damageAmount) + )}"; - // Show the total damage and type breakdown for each damage group. - foreach (var (damageGroupId, damageAmount) in damagePerGroup) + var groupContainer = new BoxContainer { - if (damageAmount == 0) - { - continue; - } - text.Append($"\n{Loc.GetString("health-analyzer-window-damage-group-text", ("damageGroup", Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId)), ("amount", damageAmount))}"); + Margin = new Thickness(0, 0, 0, 15), + Align = BoxContainer.AlignMode.Begin, + Orientation = BoxContainer.LayoutOrientation.Vertical, + }; + + groupContainer.AddChild(CreateDiagnosticGroupTitle(groupTitleText, damageGroupId, damageAmount.Int())); + + GroupsContainer.AddChild(groupContainer); - // Show the damage for each type in that group. - var group = protos.Index(damageGroupId); - foreach (var type in group.DamageTypes) + // Show the damage for each type in that group. + var group = _prototypes.Index(damageGroupId); + + foreach (var type in group.DamageTypes) + { + if (damageDict.TryGetValue(type, out var typeAmount) && typeAmount > 0) { - if (damagePerType.TryGetValue(type, out var typeAmount) ) - { - // If damage types are allowed to belong to more than one damage group, they may appear twice here. Mark them as duplicate. - if (!shownTypes.Contains(type) && typeAmount > 0) - { - shownTypes.Add(type); - text.Append($"\n- {Loc.GetString("health-analyzer-window-damage-type-text", ("damageType", Loc.GetString("health-analyzer-window-damage-type-" + type)), ("amount", typeAmount))}"); - } - } + // If damage types are allowed to belong to more than one damage group, + // they may appear twice here. Mark them as duplicate. + if (shownTypes.Contains(type)) + continue; + + shownTypes.Add(type); + + var damageString = Loc.GetString( + "health-analyzer-window-damage-type-text", + ("damageType", Loc.GetString("health-analyzer-window-damage-type-" + type)), + ("amount", typeAmount) + ); + + groupContainer.AddChild(CreateDiagnosticItemLabel(damageString.Insert(0, "- "))); } - text.AppendLine(); } - Diagnostics.Text = text.ToString(); - SetSize = new Vector2(250, 600); } - else + } + + private Texture GetTexture(string texture) + { + var rsiPath = new ResPath("/Textures/Objects/Devices/health_analyzer.rsi"); + var rsiSprite = new SpriteSpecifier.Rsi(rsiPath, texture); + + var rsi = _cache.GetResource(rsiSprite.RsiPath).RSI; + if (!rsi.TryGetState(rsiSprite.RsiState, out var state)) { - Diagnostics.Text = Loc.GetString("health-analyzer-window-no-patient-data-text"); - SetSize = new Vector2(250, 100); + rsiSprite = new SpriteSpecifier.Rsi(rsiPath, "unknown"); } + + return _spriteSystem.Frame0(rsiSprite); + } + + private static Label CreateDiagnosticItemLabel(string text) + { + return new Label + { + Margin = new Thickness(2, 2), + Text = text, + }; + } + + private BoxContainer CreateDiagnosticGroupTitle(string text, string id, int damageAmount) + { + var rootContainer = new BoxContainer + { + VerticalAlignment = VAlignment.Bottom, + Orientation = BoxContainer.LayoutOrientation.Horizontal + }; + + rootContainer.AddChild(new TextureRect + { + Margin = new Thickness(0, 3), + SetSize = new Vector2(30, 30), + Texture = GetTexture(id.ToLower()) + }); + + rootContainer.AddChild(CreateDiagnosticItemLabel(text)); + + return rootContainer; } } } diff --git a/Content.Client/HealthOverlay/HealthOverlaySystem.cs b/Content.Client/HealthOverlay/HealthOverlaySystem.cs index baeb4fe0259..29ac937199d 100644 --- a/Content.Client/HealthOverlay/HealthOverlaySystem.cs +++ b/Content.Client/HealthOverlay/HealthOverlaySystem.cs @@ -3,8 +3,8 @@ using Content.Shared.GameTicking; using Content.Shared.Mobs.Components; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Graphics; +using Robust.Client.Player; namespace Content.Client.HealthOverlay { @@ -13,9 +13,9 @@ public sealed class HealthOverlaySystem : EntitySystem { [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEntityManager _entities = default!; + [Dependency] private readonly IPlayerManager _player = default!; private readonly Dictionary _guis = new(); - private EntityUid? _attachedEntity; private bool _enabled; public bool Enabled @@ -42,7 +42,6 @@ public override void Initialize() base.Initialize(); SubscribeNetworkEvent(Reset); - SubscribeLocalEvent(HandlePlayerAttached); } public void Reset(RoundRestartCleanupEvent ev) @@ -53,12 +52,6 @@ public void Reset(RoundRestartCleanupEvent ev) } _guis.Clear(); - _attachedEntity = default; - } - - private void HandlePlayerAttached(PlayerAttachSysMessage message) - { - _attachedEntity = message.AttachedEntity; } public override void FrameUpdate(float frameTime) @@ -70,7 +63,7 @@ public override void FrameUpdate(float frameTime) return; } - if (_attachedEntity is not {} ent || Deleted(ent)) + if (_player.LocalEntity is not {} ent || Deleted(ent)) { return; } diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index ffff392aa46..f0a12b3b1f6 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -10,7 +10,6 @@ using Content.Shared.Inventory.Events; using Content.Shared.Storage; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Shared.Containers; @@ -43,8 +42,8 @@ public override void Initialize() UpdatesOutsidePrediction = true; base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnShutdown); @@ -113,12 +112,12 @@ private void OnShutdown(EntityUid uid, InventoryComponent component, ComponentSh OnUnlinkInventory?.Invoke(); } - private void OnPlayerDetached(EntityUid uid, InventorySlotsComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, InventorySlotsComponent component, LocalPlayerDetachedEvent args) { OnUnlinkInventory?.Invoke(); } - private void OnPlayerAttached(EntityUid uid, InventorySlotsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, InventorySlotsComponent component, LocalPlayerAttachedEvent args) { if (TryGetSlots(uid, out var definitions)) { diff --git a/Content.Client/Mind/MindSystem.cs b/Content.Client/Mind/MindSystem.cs index 87d9e9ddbe0..cc43c349e47 100644 --- a/Content.Client/Mind/MindSystem.cs +++ b/Content.Client/Mind/MindSystem.cs @@ -4,4 +4,24 @@ namespace Content.Client.Mind; public sealed class MindSystem : SharedMindSystem { + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnHandleState); + } + + private void OnHandleState(EntityUid uid, MindComponent component, ref AfterAutoHandleStateEvent args) + { + // Because minds are generally not networked, there might be weird situations were a client thinks multiple + // users share a mind? E.g., if an admin periodical gets sent all minds via some PVS override, but doesn't get + // sent intermediate states? Not sure if this is actually possible, but better to be safe. + foreach (var (user, mind) in UserMinds) + { + if (mind == uid) + UserMinds.Remove(user); + } + + if (component.UserId != null) + UserMinds[component.UserId.Value] = uid; + } } diff --git a/Content.Client/Overlays/EquipmentHudSystem.cs b/Content.Client/Overlays/EquipmentHudSystem.cs index 1d5ec032918..ac618691d8b 100644 --- a/Content.Client/Overlays/EquipmentHudSystem.cs +++ b/Content.Client/Overlays/EquipmentHudSystem.cs @@ -1,7 +1,6 @@ using Content.Shared.GameTicking; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; -using Robust.Client.GameObjects; using Robust.Client.Player; namespace Content.Client.Overlays; @@ -24,8 +23,8 @@ public override void Initialize() SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnRemove); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnCompEquip); SubscribeLocalEvent(OnCompUnequip); @@ -65,12 +64,12 @@ private void OnRemove(EntityUid uid, T component, ComponentRemove args) RefreshOverlay(uid); } - private void OnPlayerAttached(PlayerAttachedEvent args) + private void OnPlayerAttached(LocalPlayerAttachedEvent args) { RefreshOverlay(args.Entity); } - private void OnPlayerDetached(PlayerDetachedEvent args) + private void OnPlayerDetached(LocalPlayerDetachedEvent args) { if (_player.LocalPlayer?.ControlledEntity == null) Deactivate(); diff --git a/Content.Client/Physics/Controllers/MoverController.cs b/Content.Client/Physics/Controllers/MoverController.cs index 54c5c3de15b..52340b33918 100644 --- a/Content.Client/Physics/Controllers/MoverController.cs +++ b/Content.Client/Physics/Controllers/MoverController.cs @@ -1,7 +1,6 @@ using Content.Shared.Movement.Components; using Content.Shared.Movement.Systems; using Content.Shared.Pulling.Components; -using Robust.Client.GameObjects; using Robust.Client.Physics; using Robust.Client.Player; using Robust.Shared.Physics.Components; @@ -17,10 +16,10 @@ public sealed class MoverController : SharedMoverController public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnRelayPlayerAttached); - SubscribeLocalEvent(OnRelayPlayerDetached); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnRelayPlayerAttached); + SubscribeLocalEvent(OnRelayPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnUpdatePredicted); SubscribeLocalEvent(OnUpdateRelayTargetPredicted); @@ -54,7 +53,7 @@ private void OnUpdatePullablePredicted(EntityUid uid, SharedPullableComponent co // What if the entity is being pulled by a vehicle controlled by the player? } - private void OnRelayPlayerAttached(EntityUid uid, RelayInputMoverComponent component, PlayerAttachedEvent args) + private void OnRelayPlayerAttached(EntityUid uid, RelayInputMoverComponent component, LocalPlayerAttachedEvent args) { Physics.UpdateIsPredicted(uid); Physics.UpdateIsPredicted(component.RelayEntity); @@ -62,7 +61,7 @@ private void OnRelayPlayerAttached(EntityUid uid, RelayInputMoverComponent compo SetMoveInput(inputMover, MoveButtons.None); } - private void OnRelayPlayerDetached(EntityUid uid, RelayInputMoverComponent component, PlayerDetachedEvent args) + private void OnRelayPlayerDetached(EntityUid uid, RelayInputMoverComponent component, LocalPlayerDetachedEvent args) { Physics.UpdateIsPredicted(uid); Physics.UpdateIsPredicted(component.RelayEntity); @@ -70,12 +69,12 @@ private void OnRelayPlayerDetached(EntityUid uid, RelayInputMoverComponent compo SetMoveInput(inputMover, MoveButtons.None); } - private void OnPlayerAttached(EntityUid uid, InputMoverComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, InputMoverComponent component, LocalPlayerAttachedEvent args) { SetMoveInput(component, MoveButtons.None); } - private void OnPlayerDetached(EntityUid uid, InputMoverComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, InputMoverComponent component, LocalPlayerDetachedEvent args) { SetMoveInput(component, MoveButtons.None); } diff --git a/Content.Client/Players/PlayerSystem.cs b/Content.Client/Players/PlayerSystem.cs index d5ce4ec197f..dba95ef7a65 100644 --- a/Content.Client/Players/PlayerSystem.cs +++ b/Content.Client/Players/PlayerSystem.cs @@ -1,11 +1,11 @@ using Content.Shared.Players; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Players; public sealed class PlayerSystem : SharedPlayerSystem { - public override PlayerData? ContentData(ICommonSession? session) + public override ContentPlayerData? ContentData(ICommonSession? session) { return null; } diff --git a/Content.Client/Popups/PopupSystem.cs b/Content.Client/Popups/PopupSystem.cs index 1d4ca19ce26..d68272a107e 100644 --- a/Content.Client/Popups/PopupSystem.cs +++ b/Content.Client/Popups/PopupSystem.cs @@ -9,7 +9,6 @@ using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Replays; using Robust.Shared.Timing; diff --git a/Content.Client/Power/Generator/GeneratorWindow.xaml.cs b/Content.Client/Power/Generator/GeneratorWindow.xaml.cs index d3949807b73..0b8f94ceaeb 100644 --- a/Content.Client/Power/Generator/GeneratorWindow.xaml.cs +++ b/Content.Client/Power/Generator/GeneratorWindow.xaml.cs @@ -14,6 +14,7 @@ public sealed partial class GeneratorWindow : FancyWindow [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly ILocalizationManager _loc = default!; + private readonly SharedPowerSwitchableSystem _switchable; private readonly FuelGeneratorComponent? _component; private PortableGeneratorComponentBuiState? _lastState; @@ -24,6 +25,7 @@ public GeneratorWindow(PortableGeneratorBoundUserInterface bui, EntityUid entity IoCManager.InjectDependencies(this); _entityManager.TryGetComponent(entity, out _component); + _switchable = _entityManager.System(); EntityView.SetEntity(entity); TargetPower.IsValid += IsValid; @@ -99,17 +101,16 @@ public void Update(PortableGeneratorComponentBuiState state) StatusLabel.SetOnlyStyleClass("Danger"); } - var canSwitch = _entityManager.TryGetComponent(_entity, out PowerSwitchableGeneratorComponent? switchable); + var canSwitch = _entityManager.TryGetComponent(_entity, out PowerSwitchableComponent? switchable); OutputSwitchLabel.Visible = canSwitch; OutputSwitchButton.Visible = canSwitch; - if (canSwitch) + if (switchable != null) { - var isHV = switchable!.ActiveOutput == PowerSwitchableGeneratorOutput.HV; - OutputSwitchLabel.Text = - Loc.GetString(isHV ? "portable-generator-ui-switch-hv" : "portable-generator-ui-switch-mv"); - OutputSwitchButton.Text = - Loc.GetString(isHV ? "portable-generator-ui-switch-to-mv" : "portable-generator-ui-switch-to-hv"); + var voltage = _switchable.VoltageString(_switchable.GetVoltage(_entity, switchable)); + OutputSwitchLabel.Text = Loc.GetString("portable-generator-ui-current-output", ("voltage", voltage)); + var nextVoltage = _switchable.VoltageString(_switchable.GetNextVoltage(_entity, switchable)); + OutputSwitchButton.Text = Loc.GetString("power-switchable-switch-voltage", ("voltage", nextVoltage)); OutputSwitchButton.Disabled = state.On; } diff --git a/Content.Client/Power/Generator/PowerSwitchableSystem.cs b/Content.Client/Power/Generator/PowerSwitchableSystem.cs new file mode 100644 index 00000000000..b235dee77dd --- /dev/null +++ b/Content.Client/Power/Generator/PowerSwitchableSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Power.Generator; + +namespace Content.Client.Power.Generator; + +public sealed class PowerSwitchableSystem : SharedPowerSwitchableSystem +{ +} diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs index 3bb2afe1221..d48a1eab466 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs @@ -2,7 +2,7 @@ using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Replay.Spectator; diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs index 45a175e6884..479e2eff976 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs @@ -1,5 +1,5 @@ using Content.Shared.Movement.Components; -using Robust.Client.GameObjects; +using Robust.Client.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; @@ -79,7 +79,7 @@ private void OnAfterSetTick() public void SetSpectatorPosition(SpectatorData data) { - if (_player.LocalPlayer == null) + if (_player.LocalSession == null) return; if (data.Controller != null @@ -87,13 +87,13 @@ public void SetSpectatorPosition(SpectatorData data) && Exists(session.AttachedEntity) && Transform(session.AttachedEntity.Value).MapID != MapId.Nullspace) { - _player.LocalPlayer.AttachEntity(session.AttachedEntity.Value, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, session.AttachedEntity); return; } if (Exists(data.Entity) && Transform(data.Entity).MapID != MapId.Nullspace) { - _player.LocalPlayer.AttachEntity(data.Entity, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, data.Entity); return; } @@ -118,7 +118,7 @@ public void SetSpectatorPosition(SpectatorData data) return; } - if (data.Eye != null && TryComp(_player.LocalPlayer.ControlledEntity, out InputMoverComponent? newMover)) + if (data.Eye != null && TryComp(_player.LocalSession.AttachedEntity, out InputMoverComponent? newMover)) { newMover.RelativeEntity = data.Eye.Value.Ent; newMover.TargetRelativeRotation = newMover.RelativeRotation = data.Eye.Value.Rot; @@ -177,7 +177,7 @@ private void OnParentChanged(EntityUid uid, ReplaySpectatorComponent component, SetSpectatorPosition(default); } - private void OnDetached(EntityUid uid, ReplaySpectatorComponent component, PlayerDetachedEvent args) + private void OnDetached(EntityUid uid, ReplaySpectatorComponent component, LocalPlayerDetachedEvent args) { if (IsClientSide(uid)) QueueDel(uid); diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs index f3475c5479c..80a8429055f 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs @@ -32,10 +32,10 @@ private void OnGetAlternativeVerbs(GetVerbsEvent ev) public void SpectateEntity(EntityUid target) { - if (_player.LocalPlayer == null) + if (_player.LocalSession == null) return; - var old = _player.LocalPlayer.ControlledEntity; + var old = _player.LocalSession.AttachedEntity; if (old == target) { @@ -44,7 +44,7 @@ public void SpectateEntity(EntityUid target) return; } - _player.LocalPlayer.AttachEntity(target, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, target); EnsureComp(target); _stateMan.RequestStateChange(); @@ -59,10 +59,10 @@ public void SpectateEntity(EntityUid target) public TransformComponent SpawnSpectatorGhost(EntityCoordinates coords, bool gridAttach) { - if (_player.LocalPlayer == null) + if (_player.LocalSession == null) throw new InvalidOperationException(); - var old = _player.LocalPlayer.ControlledEntity; + var old = _player.LocalSession.AttachedEntity; var ent = Spawn("ReplayObserver", coords); _eye.SetMaxZoom(ent, Vector2.One * 5); @@ -73,7 +73,7 @@ public TransformComponent SpawnSpectatorGhost(EntityCoordinates coords, bool gri if (gridAttach) _transform.AttachToGridOrMap(ent); - _player.LocalPlayer.AttachEntity(ent, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, ent); if (old != null) { @@ -93,7 +93,7 @@ private void SpectateCommand(IConsoleShell shell, string argStr, string[] args) { if (args.Length == 0) { - if (_player.LocalPlayer?.ControlledEntity is { } current) + if (_player.LocalSession?.AttachedEntity is { } current) SpawnSpectatorGhost(new EntityCoordinates(current, default), true); else SpawnSpectatorGhost(default, true); diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs index c75529c037f..3b9662ed8c6 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs @@ -6,7 +6,6 @@ using Robust.Client.Replays.Playback; using Robust.Client.State; using Robust.Shared.Console; -using Robust.Shared.Network; using Robust.Shared.Serialization.Markdown.Mapping; namespace Content.Client.Replay.Spectator; @@ -40,7 +39,7 @@ public override void Initialize() SubscribeLocalEvent>(OnGetAlternativeVerbs); SubscribeLocalEvent(OnTerminating); - SubscribeLocalEvent(OnDetached); + SubscribeLocalEvent(OnDetached); SubscribeLocalEvent(OnParentChanged); InitializeBlockers(); diff --git a/Content.Client/Sandbox/SandboxSystem.cs b/Content.Client/Sandbox/SandboxSystem.cs index 7dcbfa0ee02..d16751e3715 100644 --- a/Content.Client/Sandbox/SandboxSystem.cs +++ b/Content.Client/Sandbox/SandboxSystem.cs @@ -5,7 +5,7 @@ using Robust.Client.Placement; using Robust.Client.Placement.Modes; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Sandbox { diff --git a/Content.Client/Shuttles/UI/DockingControl.cs b/Content.Client/Shuttles/UI/DockingControl.cs index 92d99591109..c0ddeff86c2 100644 --- a/Content.Client/Shuttles/UI/DockingControl.cs +++ b/Content.Client/Shuttles/UI/DockingControl.cs @@ -89,7 +89,7 @@ protected override void Draw(DrawingHandleScreen handle) // Draw the fixtures around the dock before drawing it if (_entManager.TryGetComponent(GridEntity, out var fixtures)) { - foreach (var (_, fixture) in fixtures.Fixtures) + foreach (var fixture in fixtures.Fixtures.Values) { var poly = (PolygonShape) fixture.Shape; @@ -151,7 +151,7 @@ protected override void Draw(DrawingHandleScreen handle) var xformQuery = _entManager.GetEntityQuery(); _grids.Clear(); - _mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(worldPos - RangeVector, worldPos + RangeVector)); + _mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(worldPos - RangeVector, worldPos + RangeVector), ref _grids); foreach (var grid in _grids) { diff --git a/Content.Client/Storage/StorageBoundUserInterface.cs b/Content.Client/Storage/StorageBoundUserInterface.cs index 1842417a6e2..9a3340e5b0e 100644 --- a/Content.Client/Storage/StorageBoundUserInterface.cs +++ b/Content.Client/Storage/StorageBoundUserInterface.cs @@ -61,9 +61,9 @@ public void BuildEntityList(EntityUid uid, StorageComponent component) _window?.BuildEntityList(uid, component); } - public void InteractWithItem(BaseButton.ButtonEventArgs args, ListData cData) + public void InteractWithItem(BaseButton.ButtonEventArgs? args, ListData? cData) { - if (cData is not EntityListData { Uid: var entity }) + if (args == null || cData is not EntityListData { Uid: var entity }) return; if (args.Event.Function == EngineKeyFunctions.UIClick) diff --git a/Content.Client/Tools/ToolSystem.cs b/Content.Client/Tools/ToolSystem.cs index f4dc480b415..966f37146e8 100644 --- a/Content.Client/Tools/ToolSystem.cs +++ b/Content.Client/Tools/ToolSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Tools.Components; using Robust.Client.GameObjects; using Robust.Shared.GameStates; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Client.Tools { diff --git a/Content.Client/Traits/ParacusiaSystem.cs b/Content.Client/Traits/ParacusiaSystem.cs index 34c7d6859e2..87abec80bb9 100644 --- a/Content.Client/Traits/ParacusiaSystem.cs +++ b/Content.Client/Traits/ParacusiaSystem.cs @@ -1,8 +1,6 @@ using System.Numerics; using Content.Shared.Traits.Assorted; -using Content.Client.Camera; using Robust.Shared.Random; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Shared.Timing; @@ -19,7 +17,7 @@ public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnComponentStartup); - SubscribeLocalEvent(OnPlayerDetach); + SubscribeLocalEvent(OnPlayerDetach); } public override void Update(float frameTime) @@ -40,7 +38,7 @@ private void OnComponentStartup(EntityUid uid, ParacusiaComponent component, Com component.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.MinTimeBetweenIncidents, component.MaxTimeBetweenIncidents)); } - private void OnPlayerDetach(EntityUid uid, ParacusiaComponent component, PlayerDetachedEvent args) + private void OnPlayerDetach(EntityUid uid, ParacusiaComponent component, LocalPlayerDetachedEvent args) { component.Stream?.Stop(); } diff --git a/Content.Client/UserInterface/Controls/ListContainer.cs b/Content.Client/UserInterface/Controls/ListContainer.cs index d1bb103926f..c66ef33d3f8 100644 --- a/Content.Client/UserInterface/Controls/ListContainer.cs +++ b/Content.Client/UserInterface/Controls/ListContainer.cs @@ -22,7 +22,7 @@ public bool Group } public bool Toggle { get; set; } public Action? GenerateItem; - public Action? ItemPressed; + public Action? ItemPressed; public IReadOnlyList Data => _data; private const int DefaultSeparation = 3; @@ -92,6 +92,12 @@ public void PopulateList(IReadOnlyList data) _data = data.ToList(); _updateChildren = true; InvalidateArrange(); + + if (_selected != null && !data.Contains(_selected)) + { + _selected = null; + ItemPressed?.Invoke(null, null); + } } public void DirtyList() diff --git a/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs b/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs index 925b2dae4fd..45bdada6e7a 100644 --- a/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs +++ b/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs @@ -8,6 +8,7 @@ using Content.Shared.Input; using JetBrains.Annotations; using Robust.Client.GameObjects; +using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controls; @@ -21,6 +22,7 @@ namespace Content.Client.UserInterface.Systems.Character; [UsedImplicitly] public sealed class CharacterUIController : UIController, IOnStateEntered, IOnStateExited, IOnSystemChanged { + [Dependency] private readonly IPlayerManager _player = default!; [UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!; [UISystemDependency] private readonly SpriteSystem _sprite = default!; @@ -56,13 +58,13 @@ public void OnStateExited(GameplayState state) public void OnSystemLoaded(CharacterInfoSystem system) { system.OnCharacterUpdate += CharacterUpdated; - system.OnCharacterDetached += CharacterDetached; + _player.LocalPlayerDetached += CharacterDetached; } public void OnSystemUnloaded(CharacterInfoSystem system) { system.OnCharacterUpdate -= CharacterUpdated; - system.OnCharacterDetached -= CharacterDetached; + _player.LocalPlayerDetached -= CharacterDetached; } public void UnloadButton() @@ -160,7 +162,7 @@ private void CharacterUpdated(CharacterData data) _window.RolePlaceholder.Visible = briefing == null && !controls.Any() && !objectives.Any(); } - private void CharacterDetached() + private void CharacterDetached(EntityUid uid) { CloseWindow(); } diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index 36b6347a223..96c0b16a5d1 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -162,7 +162,8 @@ public override void Initialize() _sawmill = Logger.GetSawmill("chat"); _sawmill.Level = LogLevel.Info; _admin.AdminStatusUpdated += UpdateChannelPermissions; - _player.LocalPlayerChanged += OnLocalPlayerChanged; + _player.LocalPlayerAttached += OnAttachedChanged; + _player.LocalPlayerDetached += OnAttachedChanged; _state.OnStateChanged += StateChanged; _net.RegisterNetMessage(OnChatMessage); _net.RegisterNetMessage(OnDeleteChatMessagesBy); @@ -170,7 +171,7 @@ public override void Initialize() _speechBubbleRoot = new LayoutContainer(); - OnLocalPlayerChanged(new LocalPlayerChangedEventArgs(null, _player.LocalPlayer)); + UpdateChannelPermissions(); _input.SetInputCommand(ContentKeyFunctions.FocusChat, InputCmdHandler.FromDelegate(_ => FocusChat())); @@ -363,29 +364,7 @@ public void SetSpeechBubbleRoot(LayoutContainer root) _speechBubbleRoot.SetPositionLast(); } - private void OnLocalPlayerChanged(LocalPlayerChangedEventArgs obj) - { - if (obj.OldPlayer != null) - { - obj.OldPlayer.EntityAttached -= OnLocalPlayerEntityAttached; - obj.OldPlayer.EntityDetached -= OnLocalPlayerEntityDetached; - } - - if (obj.NewPlayer != null) - { - obj.NewPlayer.EntityAttached += OnLocalPlayerEntityAttached; - obj.NewPlayer.EntityDetached += OnLocalPlayerEntityDetached; - } - - UpdateChannelPermissions(); - } - - private void OnLocalPlayerEntityAttached(EntityAttachedEventArgs obj) - { - UpdateChannelPermissions(); - } - - private void OnLocalPlayerEntityDetached(EntityDetachedEventArgs obj) + private void OnAttachedChanged(EntityUid uid) { UpdateChannelPermissions(); } diff --git a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs index 0836314dbc4..ba4a871199d 100644 --- a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs +++ b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs @@ -1,11 +1,9 @@ -using Content.Client.Alerts; using Content.Shared.Damage; using Content.Shared.FixedPoint; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Client.UserInterface; @@ -25,13 +23,13 @@ public sealed class DamageOverlayUiController : UIController public override void Initialize() { _overlay = new Overlays.DamageOverlay(); - SubscribeLocalEvent(OnPlayerAttach); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttach); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnMobStateChanged); SubscribeLocalEvent(OnThresholdCheck); } - private void OnPlayerAttach(PlayerAttachedEvent args) + private void OnPlayerAttach(LocalPlayerAttachedEvent args) { ClearOverlay(); if (!EntityManager.TryGetComponent(args.Entity, out var mobState)) @@ -41,7 +39,7 @@ private void OnPlayerAttach(PlayerAttachedEvent args) _overlayManager.AddOverlay(_overlay); } - private void OnPlayerDetached(PlayerDetachedEvent args) + private void OnPlayerDetached(LocalPlayerDetachedEvent args) { _overlayManager.RemoveOverlay(_overlay); ClearOverlay(); diff --git a/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs b/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs index d7ec9f3497c..778de82210a 100644 --- a/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs +++ b/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs @@ -17,7 +17,7 @@ using Robust.Client.UserInterface.Controllers.Implementations; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; using static Robust.Client.UserInterface.Controls.BaseButton; diff --git a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml index dcd6ed91a7e..abc7252e409 100644 --- a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml +++ b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml @@ -1,6 +1,6 @@  - + diff --git a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs index 60b81af6bd2..5ef66d5f74b 100644 --- a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs +++ b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs @@ -6,7 +6,6 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; -using Robust.Shared.Graphics; using Robust.Shared.Prototypes; namespace Content.Client.VendingMachines.UI @@ -33,7 +32,6 @@ public VendingMachineMenu() VendingContents.OnItemSelected += args => { - SearchBar.Text = string.Empty; OnItemSelected?.Invoke(args); }; } @@ -42,8 +40,10 @@ public VendingMachineMenu() /// Populates the list of available items on the vending machine interface /// and sets icons based on their prototypes /// - public void Populate(List inventory, string? filter = null) + public void Populate(List inventory, out List filteredInventory, string? filter = null) { + filteredInventory = new(); + if (inventory.Count == 0) { VendingContents.Clear(); @@ -94,6 +94,7 @@ public void Populate(List inventory, string? filte vendingItem.Text = $"{itemName} [{entry.Amount}]"; vendingItem.Icon = icon; + filteredInventory.Add(i); } SetSizeAfterUpdate(longestEntry.Length, inventory.Count); diff --git a/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs b/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs index ab310144d53..6f28ddb31f0 100644 --- a/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs +++ b/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Client.VendingMachines.UI; using Content.Shared.VendingMachines; -using Robust.Client.GameObjects; using Robust.Client.UserInterface.Controls; using System.Linq; @@ -14,6 +13,9 @@ public sealed class VendingMachineBoundUserInterface : BoundUserInterface [ViewVariables] private List _cachedInventory = new(); + [ViewVariables] + private List _cachedFilteredIndex = new(); + public VendingMachineBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } @@ -32,7 +34,7 @@ protected override void Open() _menu.OnItemSelected += OnItemSelected; _menu.OnSearchChanged += OnSearchChanged; - _menu.Populate(_cachedInventory); + _menu.Populate(_cachedInventory, out _cachedFilteredIndex); _menu.OpenCentered(); } @@ -46,7 +48,7 @@ protected override void UpdateState(BoundUserInterfaceState state) _cachedInventory = newState.Inventory; - _menu?.Populate(_cachedInventory); + _menu?.Populate(_cachedInventory, out _cachedFilteredIndex, _menu.SearchBar.Text); } private void OnItemSelected(ItemList.ItemListSelectedEventArgs args) @@ -54,7 +56,7 @@ private void OnItemSelected(ItemList.ItemListSelectedEventArgs args) if (_cachedInventory.Count == 0) return; - var selectedItem = _cachedInventory.ElementAtOrDefault(args.ItemIndex); + var selectedItem = _cachedInventory.ElementAtOrDefault(_cachedFilteredIndex.ElementAtOrDefault(args.ItemIndex)); if (selectedItem == null) return; @@ -78,7 +80,7 @@ protected override void Dispose(bool disposing) private void OnSearchChanged(string? filter) { - _menu?.Populate(_cachedInventory, filter); + _menu?.Populate(_cachedInventory, out _cachedFilteredIndex, filter); } } } diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 397032cd154..2d2883d8b76 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -16,7 +16,8 @@ using Robust.Shared.Input; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; namespace Content.Client.Weapons.Melee; diff --git a/Content.IntegrationTests/Pair/TestPair.cs b/Content.IntegrationTests/Pair/TestPair.cs index 2971573ff28..2672b4db56e 100644 --- a/Content.IntegrationTests/Pair/TestPair.cs +++ b/Content.IntegrationTests/Pair/TestPair.cs @@ -3,13 +3,11 @@ using System.IO; using System.Linq; using Content.Server.GameTicking; -using Content.Server.Players; -using Content.Shared.Mind; using Content.Shared.Players; -using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.UnitTesting; @@ -30,8 +28,8 @@ public sealed partial class TestPair public RobustIntegrationTest.ServerIntegrationInstance Server { get; private set; } = default!; public RobustIntegrationTest.ClientIntegrationInstance Client { get; private set; } = default!; - public IPlayerSession? Player => (IPlayerSession?) Server.PlayerMan.Sessions.FirstOrDefault(); - public PlayerData? PlayerData => Player?.Data.ContentData(); + public ICommonSession? Player => Server.PlayerMan.Sessions.FirstOrDefault(); + public ContentPlayerData? PlayerData => Player?.Data.ContentData(); public PoolTestLogHandler ServerLogHandler { get; private set; } = default!; public PoolTestLogHandler ClientLogHandler { get; private set; } = default!; diff --git a/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs b/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs index 01f8bdd9387..01daeea93c5 100644 --- a/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs +++ b/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs @@ -3,8 +3,6 @@ using Content.Shared.CombatMode; using Robust.Server.Player; using Robust.Shared.GameObjects; -using Robust.Shared.Players; -using PlayerManager = Robust.Client.Player.PlayerManager; namespace Content.IntegrationTests.Tests.Actions; @@ -26,7 +24,7 @@ public async Task TestCombatActionsAdded() var sEntMan = server.ResolveDependency(); var cEntMan = client.ResolveDependency(); var clientSession = client.ResolveDependency().LocalPlayer?.Session; - var serverSession = server.ResolveDependency().ServerSessions.Single(); + var serverSession = server.ResolveDependency().Sessions.Single(); var sActionSystem = server.System(); var cActionSystem = client.System(); diff --git a/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs index 6562a26b5e1..98c7363a6c4 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs @@ -7,8 +7,6 @@ using Content.Shared.Database; using Robust.Server.Player; using Robust.Shared.GameObjects; -using Robust.Shared.Map; -using Robust.Shared.Utility; namespace Content.IntegrationTests.Tests.Administration.Logs; @@ -177,7 +175,7 @@ public async Task AddPlayerSessionLog() await server.WaitPost(() => { - var player = sPlayers.ServerSessions.First(); + var player = sPlayers.Sessions.First(); playerGuid = player.UserId; Assert.DoesNotThrow(() => @@ -280,7 +278,7 @@ public async Task DuplicatePlayerDoesNotThrowTest() await server.WaitPost(() => { - var player = sPlayers.ServerSessions.Single(); + var player = sPlayers.Sessions.Single(); sAdminLogSystem.Add(LogType.Unknown, $"{player} {player} test log: {guid}"); }); @@ -318,7 +316,7 @@ public async Task DuplicatePlayerIdDoesNotThrowTest() await server.WaitPost(() => { - var player = sPlayers.ServerSessions.Single(); + var player = sPlayers.Sessions.Single(); sAdminLogSystem.Add(LogType.Unknown, $"{player:first} {player:second} test log: {guid}"); }); diff --git a/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs index 1155edfad2d..5a58757d531 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs @@ -5,6 +5,7 @@ using Content.Shared.Database; using Robust.Server.Player; using Robust.Shared.GameObjects; +using Robust.Shared.Player; namespace Content.IntegrationTests.Tests.Administration.Logs; @@ -27,11 +28,11 @@ public async Task QuerySingleLog() var date = DateTime.UtcNow; var guid = Guid.NewGuid(); - IPlayerSession player = default; + ICommonSession player = default; await server.WaitPost(() => { - player = sPlayers.ServerSessions.First(); + player = sPlayers.Sessions.First(); sAdminLogSystem.Add(LogType.Unknown, $"{player.AttachedEntity:Entity} test log: {guid}"); }); diff --git a/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs b/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs index 9aac4e2892a..e2bff03501a 100644 --- a/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs +++ b/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs @@ -25,7 +25,7 @@ public async Task EuiManagerRecycleWithOpenWindowTest() await server.WaitAssertion(() => { - var clientSession = sPlayerManager.ServerSessions.Single(); + var clientSession = sPlayerManager.Sessions.Single(); var ui = new AdminAnnounceEui(); eui.OpenEui(ui, clientSession); }); diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs index b4b6c2239fb..df77410e540 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs @@ -14,6 +14,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Client.Input; using Robust.Client.UserInterface; using Robust.Server.GameObjects; @@ -21,7 +22,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.Log; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.UnitTesting; @@ -67,7 +68,7 @@ public abstract partial class InteractionTest protected NetEntity Player; protected ICommonSession ClientSession = default!; - protected IPlayerSession ServerSession = default!; + protected ICommonSession ServerSession = default!; public EntityUid? ClientTarget; diff --git a/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs b/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs index 28e49645c97..22a185798e9 100644 --- a/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs +++ b/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs @@ -5,6 +5,7 @@ using Content.Server.Players; using Content.Shared.Ghost; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Shared.Console; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -43,7 +44,7 @@ public async Task TakeRoleAndReturn() var sPlayerMan = server.ResolveDependency(); var conHost = client.ResolveDependency(); var mindSystem = entMan.System(); - var session = sPlayerMan.ServerSessions.Single(); + var session = sPlayerMan.Sessions.Single(); var originalMindId = session.ContentData()!.Mind!.Value; // Spawn player entity & attach diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs b/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs index 9fc68ef93d4..a67a45ecb4c 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs @@ -2,6 +2,7 @@ using Content.Server.Players; using Content.Shared.Ghost; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Server.Console; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -35,7 +36,7 @@ public async Task TestDeleteVisiting() MindComponent mind = default!; await server.WaitAssertion(() => { - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); visitEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); @@ -81,7 +82,7 @@ public async Task TestGhostOnDeleteMap() var entMan = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var playerMan = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var mindSystem = entMan.EntitySysManager.GetEntitySystem(); @@ -128,7 +129,7 @@ public async Task TestGhostOnDelete() var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); Assert.That(!entMan.HasComponent(player.AttachedEntity), "Player was initially a ghost?"); @@ -162,7 +163,7 @@ public async Task TestOriginalDeletedWhileGhostingKeepsGhost() var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var mind = GetMind(pair); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); #pragma warning disable NUnit2045 // Interdependent assertions. Assert.That(player.AttachedEntity, Is.Not.Null); Assert.That(entMan.EntityExists(player.AttachedEntity)); @@ -218,7 +219,7 @@ public async Task TestGhostToAghost() var playerMan = server.ResolveDependency(); var serverConsole = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var ghost = await BecomeGhost(pair); @@ -263,7 +264,7 @@ public async Task TestGhostDeletedSpawnsNewGhost() var playerMan = server.ResolveDependency(); var serverConsole = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); EntityUid ghost = default!; diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs b/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs index f71a6ad5f98..d6b30d60a0f 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs @@ -1,14 +1,17 @@ using System.Linq; using Content.IntegrationTests.Pair; +using Content.Server.Mind; using Content.Server.Players; using Content.Shared.Ghost; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.IntegrationTests.Tests.Minds; @@ -36,7 +39,7 @@ public sealed partial class MindTests var playerMan = pair.Server.ResolveDependency(); var mindSys = entMan.System(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); EntityUid entity = default; EntityUid mindId = default!; @@ -71,7 +74,7 @@ private static async Task BecomeGhost(TestPair pair, bool visit = fal EntityUid mindId = default!; MindComponent mind = default!; - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); await pair.Server.WaitAssertion(() => { var oldUid = player.AttachedEntity; @@ -116,20 +119,25 @@ private static async Task VisitGhost(Pair.TestPair pair, bool _ = fal /// private static (EntityUid Id, MindComponent Comp) GetMind(Pair.TestPair pair) { - var playerMan = pair.Server.ResolveDependency(); - var entMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.SingleOrDefault(); + var playerMan = pair.Server.PlayerMan; + var entMan = pair.Server.EntMan; + var player = playerMan.Sessions.SingleOrDefault(); Assert.That(player, Is.Not.Null); var mindId = player.ContentData()!.Mind!.Value; Assert.That(mindId, Is.Not.EqualTo(default(EntityUid))); var mind = entMan.GetComponent(mindId); + ActorComponent actor = default!; Assert.Multiple(() => { + Assert.That(player, Is.EqualTo(mind.Session), "Player session does not match mind session"); + Assert.That(entMan.System().GetMind(player.UserId), Is.EqualTo(mindId)); Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity."); Assert.That(entMan.EntityExists(mind.OwnedEntity), "The mind's current entity does not exist"); Assert.That(mind.VisitingEntity == null || entMan.EntityExists(mind.VisitingEntity), "The minds visited entity does not exist."); + Assert.That(entMan.TryGetComponent(mind.CurrentEntity, out actor)); }); + Assert.That(actor.PlayerSession, Is.EqualTo(mind.Session)); return (mindId, mind); } @@ -139,7 +147,7 @@ private static async Task Disconnect(Pair.TestPair pair) var netManager = pair.Client.ResolveDependency(); var playerMan = pair.Server.ResolveDependency(); var entMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var mindId = player.ContentData()!.Mind!.Value; var mind = entMan.GetComponent(mindId); @@ -161,21 +169,21 @@ private static async Task Connect(Pair.TestPair pair, string username) { var netManager = pair.Client.ResolveDependency(); var playerMan = pair.Server.ResolveDependency(); - Assert.That(!playerMan.ServerSessions.Any()); + Assert.That(!playerMan.Sessions.Any()); await Task.WhenAll(pair.Client.WaitIdleAsync(), pair.Client.WaitIdleAsync()); pair.Client.SetConnectTarget(pair.Server); await pair.Client.WaitPost(() => netManager.ClientConnect(null!, 0, username)); await pair.RunTicksSync(5); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); Assert.That(player.Status, Is.EqualTo(SessionStatus.InGame)); } - private static async Task DisconnectReconnect(Pair.TestPair pair) + private static async Task DisconnectReconnect(Pair.TestPair pair) { var playerMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var name = player.Name; var id = player.UserId; @@ -183,7 +191,7 @@ private static async Task DisconnectReconnect(Pair.TestPair pair await Connect(pair, name); // Session has changed - var newSession = playerMan.ServerSessions.Single(); + var newSession = playerMan.Sessions.Single(); Assert.Multiple(() => { Assert.That(newSession, Is.Not.EqualTo(player)); diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs index ea2110c03a6..3cac766825d 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs @@ -1,6 +1,8 @@ using System.Linq; using Content.Shared.Ghost; using Content.Shared.Mind; +using NUnit.Framework.Interfaces; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -49,7 +51,7 @@ public async Task TestDeletedCanReconnect() var mind = GetMind(pair); var playerMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var name = player.Name; var user = player.UserId; Assert.That(mind.Comp.OwnedEntity, Is.Not.Null); @@ -72,7 +74,7 @@ public async Task TestDeletedCanReconnect() // Reconnect await Connect(pair, name); - player = playerMan.ServerSessions.Single(); + player = playerMan.Sessions.Single(); Assert.Multiple(() => { Assert.That(user, Is.EqualTo(player.UserId)); @@ -127,8 +129,10 @@ public async Task TestVisitingReconnect() var mindSys = entMan.System(); var mind = GetMind(pair); + Assert.Null(mind.Comp.VisitingEntity); + // Make player visit a new mob - var original = mind.Comp.CurrentEntity; + var original = mind.Comp.OwnedEntity; EntityUid visiting = default; await pair.Server.WaitAssertion(() => { @@ -137,6 +141,7 @@ await pair.Server.WaitAssertion(() => }); await pair.RunTicksSync(5); + Assert.That(mind.Comp.VisitingEntity, Is.EqualTo(visiting)); await DisconnectReconnect(pair); // Player is back in control of the visited mob, mind was preserved @@ -150,4 +155,32 @@ await pair.Server.WaitAssertion(() => await pair.CleanReturnAsync(); } + + // This test will do the following + // - connect as a normal player + // - disconnect + // - reconnect + // - assert that they return to the original entity. + [Test] + public async Task TestReconnect() + { + await using var pair = await SetupPair(); + var mind = GetMind(pair); + + Assert.Null(mind.Comp.VisitingEntity); + Assert.NotNull(mind.Comp.OwnedEntity); + var entity = mind.Comp.OwnedEntity; + + await pair.RunTicksSync(5); + await DisconnectReconnect(pair); + await pair.RunTicksSync(5); + + var newMind = GetMind(pair); + + Assert.Null(newMind.Comp.VisitingEntity); + Assert.That(newMind.Comp.OwnedEntity, Is.EqualTo(entity)); + Assert.That(newMind.Id, Is.EqualTo(mind.Id)); + + await pair.CleanReturnAsync(); + } } diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.cs index fb2fef43edb..c9788b80a6d 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.cs @@ -11,6 +11,7 @@ using Content.Shared.FixedPoint; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Content.Shared.Players; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; using Robust.Server.Console; @@ -67,13 +68,12 @@ await server.WaitAssertion(() => var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); - var mindId = mindSystem.CreateMind(null); - var mind = entMan.GetComponent(mindId); + var mind = mindSystem.CreateMind(null); - Assert.That(mind.UserId, Is.EqualTo(null)); + Assert.That(mind.Comp.UserId, Is.EqualTo(null)); - mindSystem.TransferTo(mindId, entity, mind: mind); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); + mindSystem.TransferTo(mind, entity, mind: mind); + Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind.Owner)); }); await pair.CleanReturnAsync(); @@ -94,11 +94,11 @@ await server.WaitAssertion(() => var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); - var mindId = mindSystem.CreateMind(null); + var mindId = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mindId, entity); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); - var mind2 = mindSystem.CreateMind(null); + var mind2 = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mind2, entity); Assert.Multiple(() => { @@ -184,7 +184,7 @@ await server.WaitAssertion(() => var mindComp = entMan.EnsureComponent(entity); entMan.EnsureComponent(targetEntity); - var mind = mindSystem.CreateMind(null); + var mind = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mind, entity); @@ -276,7 +276,7 @@ await server.WaitAssertion(() => var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); - var mindId = mindSystem.CreateMind(null); + var mindId = mindSystem.CreateMind(null).Owner; var mind = entMan.EnsureComponent(mindId); Assert.That(mind.UserId, Is.EqualTo(null)); @@ -334,7 +334,7 @@ await server.WaitAssertion(() => public async Task TestPlayerCanGhost() { // Client is needed to spawn session - await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true }); + await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false }); var server = pair.Server; var entMan = server.ResolveDependency(); @@ -346,7 +346,7 @@ public async Task TestPlayerCanGhost() EntityUid entity = default!; EntityUid mindId = default!; MindComponent mind = default!; - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); await server.WaitAssertion(() => { @@ -407,12 +407,6 @@ await server.WaitAssertion(() => await pair.CleanReturnAsync(); } - // TODO Implement - /*[Test] - public async Task TestPlayerCanReturnFromGhostWhenDead() - { - }*/ - [Test] public async Task TestGhostDoesNotInfiniteLoop() { @@ -433,7 +427,7 @@ public async Task TestGhostDoesNotInfiniteLoop() EntityUid ghost = default!; EntityUid mindId = default!; MindComponent mind = default!; - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); await server.WaitAssertion(() => { diff --git a/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs b/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs index ca7eeac199d..d6aec781a99 100644 --- a/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs +++ b/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs @@ -2,8 +2,7 @@ using System.Collections.Generic; using Content.IntegrationTests.Pair; using Content.Server.Administration.Managers; -using Robust.Server.Player; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; using Robust.Shared.Toolshed.Syntax; @@ -60,7 +59,7 @@ public virtual async Task Setup() AdminManager = Server.ResolveDependency(); } - protected bool InvokeCommand(string command, out object? result, IPlayerSession? session = null) + protected bool InvokeCommand(string command, out object? result, ICommonSession? session = null) { return Toolshed.InvokeCommand(this, command, null, out result); } @@ -95,7 +94,7 @@ public bool CheckInvokable(CommandSpec command, out IConError? error) return true; } - protected IPlayerSession? InvocationSession { get; set; } + protected ICommonSession? InvocationSession { get; set; } public ICommonSession? Session { diff --git a/Content.MapRenderer/Painters/MapPainter.cs b/Content.MapRenderer/Painters/MapPainter.cs index b799db78a5f..8f3dd59baf8 100644 --- a/Content.MapRenderer/Painters/MapPainter.cs +++ b/Content.MapRenderer/Painters/MapPainter.cs @@ -68,7 +68,7 @@ await client.WaitPost(() => await server.WaitPost(() => { - var playerEntity = sPlayerManager.ServerSessions.Single().AttachedEntity; + var playerEntity = sPlayerManager.Sessions.Single().AttachedEntity; if (playerEntity.HasValue) { diff --git a/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.Designer.cs b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.Designer.cs new file mode 100644 index 00000000000..bf3600ba39f --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.Designer.cs @@ -0,0 +1,1775 @@ +// +using System; +using System.Net; +using System.Text.Json; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20231021071411_RoundStartDate")] + partial class RoundStartDate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("smallint") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.Property("Uid") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uid"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Uid")); + + b.Property("AdminLogId") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("AdminLogRoundId") + .HasColumnType("integer") + .HasColumnName("admin_log_round_id"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Uid") + .HasName("PK_admin_log_entity"); + + b.HasIndex("AdminLogId", "AdminLogRoundId") + .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); + + b.ToTable("admin_log_entity", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_messages_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("boolean") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenHWId") + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("text") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("text") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.HasOne("Content.Server.Database.AdminLog", null) + .WithMany("Entities") + .HasForeignKey("AdminLogId", "AdminLogRoundId") + .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Entities"); + + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.cs b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.cs new file mode 100644 index 00000000000..d98b4e45a8e --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.cs @@ -0,0 +1,39 @@ +#nullable disable + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class RoundStartDate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "start_date", + table: "round", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateIndex( + name: "IX_round_start_date", + table: "round", + column: "start_date"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_round_start_date", + table: "round"); + + migrationBuilder.DropColumn( + name: "start_date", + table: "round"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.Designer.cs b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.Designer.cs new file mode 100644 index 00000000000..5c81f0468db --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.Designer.cs @@ -0,0 +1,1735 @@ +// +using System; +using System.Net; +using System.Text.Json; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20231024041204_DropAdminLogEntity")] + partial class DropAdminLogEntity + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("smallint") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_messages_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("boolean") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenHWId") + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("text") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("text") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.cs b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.cs new file mode 100644 index 00000000000..ec9c2e9a6c3 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.cs @@ -0,0 +1,47 @@ +#nullable disable + +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class DropAdminLogEntity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "admin_log_entity"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "admin_log_entity", + columns: table => new + { + uid = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + admin_log_id = table.Column(type: "integer", nullable: true), + admin_log_round_id = table.Column(type: "integer", nullable: true), + name = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_admin_log_entity", x => x.uid); + table.ForeignKey( + name: "FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id", + columns: x => new { x.admin_log_id, x.admin_log_round_id }, + principalTable: "admin_log", + principalColumns: new[] { "admin_log_id", "round_id" }); + }); + + migrationBuilder.CreateIndex( + name: "IX_admin_log_entity_admin_log_id_admin_log_round_id", + table: "admin_log_entity", + columns: new[] { "admin_log_id", "admin_log_round_id" }); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs index 0cb52bcab0d..d00c664bd2e 100644 --- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs @@ -133,36 +133,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("admin_log", (string)null); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.Property("Uid") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("uid"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Uid")); - - b.Property("AdminLogId") - .HasColumnType("integer") - .HasColumnName("admin_log_id"); - - b.Property("AdminLogRoundId") - .HasColumnType("integer") - .HasColumnName("admin_log_round_id"); - - b.Property("Name") - .HasColumnType("text") - .HasColumnName("name"); - - b.HasKey("Uid") - .HasName("PK_admin_log_entity"); - - b.HasIndex("AdminLogId", "AdminLogRoundId") - .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); - - b.ToTable("admin_log_entity", (string)null); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.Property("PlayerUserId") @@ -863,12 +833,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer") .HasColumnName("server_id"); + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + b.HasKey("Id") .HasName("PK_round"); b.HasIndex("ServerId") .HasDatabaseName("IX_round_server_id"); + b.HasIndex("StartDate"); + b.ToTable("round", (string)null); }); @@ -1311,14 +1289,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Round"); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.HasOne("Content.Server.Database.AdminLog", null) - .WithMany("Entities") - .HasForeignKey("AdminLogId", "AdminLogRoundId") - .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.HasOne("Content.Server.Database.Player", "Player") @@ -1676,8 +1646,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Content.Server.Database.AdminLog", b => { - b.Navigation("Entities"); - b.Navigation("Players"); }); diff --git a/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.Designer.cs new file mode 100644 index 00000000000..cf8294e5e80 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.Designer.cs @@ -0,0 +1,1705 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20231021071407_RoundStartDate")] + partial class RoundStartDate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("INTEGER") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("INTEGER") + .HasColumnName("type"); + + b.HasKey("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.Property("Uid") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uid"); + + b.Property("AdminLogId") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("AdminLogRoundId") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_round_id"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Uid") + .HasName("PK_admin_log_entity"); + + b.HasIndex("AdminLogId", "AdminLogRoundId") + .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); + + b.ToTable("admin_log_entity", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_messages_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_notes_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_watchlists_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("play_time_id"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenHWId") + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("INTEGER") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_hit_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("INTEGER") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("role_unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("trait_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uploaded_resource_log_id"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("INTEGER") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("INTEGER") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.HasOne("Content.Server.Database.AdminLog", null) + .WithMany("Entities") + .HasForeignKey("AdminLogId", "AdminLogRoundId") + .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Entities"); + + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.cs b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.cs new file mode 100644 index 00000000000..0948bd99f1f --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.cs @@ -0,0 +1,39 @@ +#nullable disable + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class RoundStartDate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "start_date", + table: "round", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateIndex( + name: "IX_round_start_date", + table: "round", + column: "start_date"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_round_start_date", + table: "round"); + + migrationBuilder.DropColumn( + name: "start_date", + table: "round"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.Designer.cs new file mode 100644 index 00000000000..887e157ec34 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.Designer.cs @@ -0,0 +1,1667 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20231024041159_DropAdminLogEntity")] + partial class DropAdminLogEntity + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("INTEGER") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("INTEGER") + .HasColumnName("type"); + + b.HasKey("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_messages_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_notes_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_watchlists_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("play_time_id"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenHWId") + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("INTEGER") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_hit_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("INTEGER") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("role_unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("trait_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uploaded_resource_log_id"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("INTEGER") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("INTEGER") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.cs b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.cs new file mode 100644 index 00000000000..59e9efce4ea --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.cs @@ -0,0 +1,46 @@ +#nullable disable + +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class DropAdminLogEntity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "admin_log_entity"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "admin_log_entity", + columns: table => new + { + uid = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + admin_log_id = table.Column(type: "INTEGER", nullable: true), + admin_log_round_id = table.Column(type: "INTEGER", nullable: true), + name = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_admin_log_entity", x => x.uid); + table.ForeignKey( + name: "FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id", + columns: x => new { x.admin_log_id, x.admin_log_round_id }, + principalTable: "admin_log", + principalColumns: new[] { "admin_log_id", "round_id" }); + }); + + migrationBuilder.CreateIndex( + name: "IX_admin_log_entity_admin_log_id_admin_log_round_id", + table: "admin_log_entity", + columns: new[] { "admin_log_id", "admin_log_round_id" }); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs index 6b7d0478e75..4896118ab25 100644 --- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs @@ -119,34 +119,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("admin_log", (string)null); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.Property("Uid") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER") - .HasColumnName("uid"); - - b.Property("AdminLogId") - .HasColumnType("INTEGER") - .HasColumnName("admin_log_id"); - - b.Property("AdminLogRoundId") - .HasColumnType("INTEGER") - .HasColumnName("admin_log_round_id"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasColumnName("name"); - - b.HasKey("Uid") - .HasName("PK_admin_log_entity"); - - b.HasIndex("AdminLogId", "AdminLogRoundId") - .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); - - b.ToTable("admin_log_entity", (string)null); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.Property("PlayerUserId") @@ -813,12 +785,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER") .HasColumnName("server_id"); + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + b.HasKey("Id") .HasName("PK_round"); b.HasIndex("ServerId") .HasDatabaseName("IX_round_server_id"); + b.HasIndex("StartDate"); + b.ToTable("round", (string)null); }); @@ -1241,14 +1221,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Round"); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.HasOne("Content.Server.Database.AdminLog", null) - .WithMany("Entities") - .HasForeignKey("AdminLogId", "AdminLogRoundId") - .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.HasOne("Content.Server.Database.Player", "Player") @@ -1606,8 +1578,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Content.Server.Database.AdminLog", b => { - b.Navigation("Entities"); - b.Navigation("Players"); }); diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index 15a2a2baf45..c2ffedb31d0 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -111,6 +111,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(player => player.PlayerUserId) .HasPrincipalKey(player => player.UserId); + modelBuilder.Entity() + .HasIndex(round => round.StartDate); + + modelBuilder.Entity() + .Property(round => round.StartDate) + .HasDefaultValue(default(DateTime)); + modelBuilder.Entity() .HasKey(logPlayer => new {logPlayer.PlayerUserId, logPlayer.LogId, logPlayer.RoundId}); @@ -469,6 +476,8 @@ public class Round [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } + public DateTime StartDate { get; set; } + public List Players { get; set; } = default!; public List AdminLogs { get; set; } = default!; @@ -508,8 +517,6 @@ public class AdminLog [Required, Column(TypeName = "jsonb")] public JsonDocument Json { get; set; } = default!; public List Players { get; set; } = default!; - - public List Entities { get; set; } = default!; } public class AdminLogPlayer @@ -522,12 +529,6 @@ public class AdminLogPlayer [ForeignKey("LogId,RoundId")] public AdminLog Log { get; set; } = default!; } - public class AdminLogEntity - { - [Required, Key] public int Uid { get; set; } - public string? Name { get; set; } = default!; - } - // Used by SS14.Admin public interface IBanCommon where TUnban : IUnbanCommon { diff --git a/Content.Server/Administration/AdminPermsChangedEventArgs.cs b/Content.Server/Administration/AdminPermsChangedEventArgs.cs index 24ca7aca684..07eb416be64 100644 --- a/Content.Server/Administration/AdminPermsChangedEventArgs.cs +++ b/Content.Server/Administration/AdminPermsChangedEventArgs.cs @@ -1,5 +1,5 @@ using Content.Shared.Administration; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Administration { @@ -8,7 +8,7 @@ namespace Content.Server.Administration /// public sealed class AdminPermsChangedEventArgs : EventArgs { - public AdminPermsChangedEventArgs(IPlayerSession player, AdminFlags? flags) + public AdminPermsChangedEventArgs(ICommonSession player, AdminFlags? flags) { Player = player; Flags = flags; @@ -17,7 +17,7 @@ public AdminPermsChangedEventArgs(IPlayerSession player, AdminFlags? flags) /// /// The player that had their admin permissions changed. /// - public IPlayerSession Player { get; } + public ICommonSession Player { get; } /// /// The admin flags of the player. Null if the player is no longer an admin. diff --git a/Content.Server/Administration/Commands/AGhost.cs b/Content.Server/Administration/Commands/AGhost.cs index 42a8600ff17..2d1a15a0bed 100644 --- a/Content.Server/Administration/Commands/AGhost.cs +++ b/Content.Server/Administration/Commands/AGhost.cs @@ -2,7 +2,6 @@ using Content.Shared.Administration; using Content.Shared.Ghost; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -18,7 +17,7 @@ public sealed class AGhost : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Nah"); diff --git a/Content.Server/Administration/Commands/AdminWhoCommand.cs b/Content.Server/Administration/Commands/AdminWhoCommand.cs index 639a9d54148..73c616d3b6f 100644 --- a/Content.Server/Administration/Commands/AdminWhoCommand.cs +++ b/Content.Server/Administration/Commands/AdminWhoCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Administration.Managers; using Content.Server.Afk; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Utility; @@ -35,7 +34,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (adminData.Title is { } title) sb.Append($": [{title}]"); - if (shell.Player is IPlayerSession player && adminMgr.HasAdminFlag(player, AdminFlags.Admin)) + if (shell.Player is { } player && adminMgr.HasAdminFlag(player, AdminFlags.Admin)) { if (afk.IsAfk(admin)) sb.Append(" [AFK]"); diff --git a/Content.Server/Administration/Commands/AnnounceUiCommand.cs b/Content.Server/Administration/Commands/AnnounceUiCommand.cs index c4cd7f13e41..d80db966863 100644 --- a/Content.Server/Administration/Commands/AnnounceUiCommand.cs +++ b/Content.Server/Administration/Commands/AnnounceUiCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.UI; using Content.Server.EUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -17,7 +16,7 @@ public sealed class AnnounceUiCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("This does not work from the server console."); diff --git a/Content.Server/Administration/Commands/BanCommand.cs b/Content.Server/Administration/Commands/BanCommand.cs index 58a801e4105..156fdf496a9 100644 --- a/Content.Server/Administration/Commands/BanCommand.cs +++ b/Content.Server/Administration/Commands/BanCommand.cs @@ -1,15 +1,8 @@ using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; using Content.Server.Administration.Managers; -using Content.Server.Administration.Notes; -using Content.Server.Database; -using Content.Server.GameTicking; using Content.Shared.Administration; using Content.Shared.CCVar; using Content.Shared.Database; -using Content.Shared.Players.PlayTimeTracking; using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -84,7 +77,7 @@ public override async void Execute(IConsoleShell shell, string argStr, string[] } var located = await _locator.LookupIdByNameOrIdAsync(target); - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (located == null) { @@ -102,7 +95,7 @@ public override CompletionResult GetCompletion(IConsoleShell shell, string[] arg { if (args.Length == 1) { - var options = _playerManager.ServerSessions.Select(c => c.Name).OrderBy(c => c).ToArray(); + var options = _playerManager.Sessions.Select(c => c.Name).OrderBy(c => c).ToArray(); return CompletionResult.FromHintOptions(options, LocalizationManager.GetString("cmd-ban-hint")); } diff --git a/Content.Server/Administration/Commands/BanListCommand.cs b/Content.Server/Administration/Commands/BanListCommand.cs index 1c2be523949..a5bc97dce3e 100644 --- a/Content.Server/Administration/Commands/BanListCommand.cs +++ b/Content.Server/Administration/Commands/BanListCommand.cs @@ -36,7 +36,7 @@ public override async void Execute(IConsoleShell shell, string argStr, string[] return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastHWId, false); @@ -67,7 +67,7 @@ public override CompletionResult GetCompletion(IConsoleShell shell, string[] arg return CompletionResult.Empty; var playerMgr = IoCManager.Resolve(); - var options = playerMgr.ServerSessions.Select(c => c.Name).OrderBy(c => c).ToArray(); + var options = playerMgr.Sessions.Select(c => c.Name).OrderBy(c => c).ToArray(); return CompletionResult.FromHintOptions(options, Loc.GetString("cmd-banlist-hint")); } } diff --git a/Content.Server/Administration/Commands/BanPanelCommand.cs b/Content.Server/Administration/Commands/BanPanelCommand.cs index 6036e5aa6ea..9f9ec9e89fa 100644 --- a/Content.Server/Administration/Commands/BanPanelCommand.cs +++ b/Content.Server/Administration/Commands/BanPanelCommand.cs @@ -1,12 +1,6 @@ using Content.Shared.Administration; using Robust.Shared.Console; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Content.Server.EUI; -using Robust.Server.Player; namespace Content.Server.Administration.Commands; @@ -21,7 +15,7 @@ public sealed class BanPanelCommand : LocalizedCommands public override async void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("cmd-banpanel-server")); return; diff --git a/Content.Server/Administration/Commands/ControlMob.cs b/Content.Server/Administration/Commands/ControlMob.cs index 2d205e44d3b..317461a3736 100644 --- a/Content.Server/Administration/Commands/ControlMob.cs +++ b/Content.Server/Administration/Commands/ControlMob.cs @@ -1,6 +1,5 @@ +using Content.Server.Mind; using Content.Shared.Administration; -using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -16,7 +15,7 @@ public sealed class ControlMob : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteLine("shell-server-cannot"); return; @@ -42,14 +41,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var mindSystem = _entities.System(); - if (!mindSystem.TryGetMind(target, out var mindId, out var mind)) - { - shell.WriteLine(Loc.GetString("shell-entity-is-not-mob")); - return; - } - - mindSystem.TransferTo(mindId, target, mind: mind); + _entities.System().ControlMob(player.UserId, target); } } } diff --git a/Content.Server/Administration/Commands/DSay.cs b/Content.Server/Administration/Commands/DSay.cs index 79b0e8db7d6..61b47d78567 100644 --- a/Content.Server/Administration/Commands/DSay.cs +++ b/Content.Server/Administration/Commands/DSay.cs @@ -1,7 +1,5 @@ -using Content.Server.Chat; using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -17,7 +15,7 @@ sealed class DSay : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("shell-only-players-can-run-this-command"); diff --git a/Content.Server/Administration/Commands/DeAdminCommand.cs b/Content.Server/Administration/Commands/DeAdminCommand.cs index c2bbfa7a339..cf659412008 100644 --- a/Content.Server/Administration/Commands/DeAdminCommand.cs +++ b/Content.Server/Administration/Commands/DeAdminCommand.cs @@ -1,10 +1,8 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Console; - namespace Content.Server.Administration.Commands { [UsedImplicitly] @@ -17,7 +15,7 @@ public sealed class DeAdminCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You cannot use this command from the server console."); diff --git a/Content.Server/Administration/Commands/ExplosionCommand.cs b/Content.Server/Administration/Commands/ExplosionCommand.cs index d48b69a5ad2..56ed78b2e2e 100644 --- a/Content.Server/Administration/Commands/ExplosionCommand.cs +++ b/Content.Server/Administration/Commands/ExplosionCommand.cs @@ -3,7 +3,6 @@ using Content.Server.Explosion.EntitySystems; using Content.Shared.Administration; using Content.Shared.Explosion; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Prototypes; @@ -21,7 +20,7 @@ public sealed class OpenExplosionEui : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteError("This does not work from the server console."); diff --git a/Content.Server/Administration/Commands/FaxUiCommand.cs b/Content.Server/Administration/Commands/FaxUiCommand.cs index b06d36d08b7..cf9e97e3997 100644 --- a/Content.Server/Administration/Commands/FaxUiCommand.cs +++ b/Content.Server/Administration/Commands/FaxUiCommand.cs @@ -1,7 +1,6 @@ using Content.Server.EUI; using Content.Server.Fax.AdminUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands; @@ -16,7 +15,7 @@ public sealed class FaxUiCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("shell-only-players-can-run-this-command"); diff --git a/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs b/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs index 9f28dc907c7..47ff3e1a1c8 100644 --- a/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs +++ b/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.Logs; using Content.Server.EUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands; @@ -15,7 +14,7 @@ public sealed class OpenAdminLogsCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteLine("This does not work from the server console."); return; diff --git a/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs b/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs index 147c0d6a82e..e6ae4f76167 100644 --- a/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs +++ b/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs @@ -1,7 +1,5 @@ using Content.Server.Administration.Notes; -using Content.Server.Database; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands; @@ -17,7 +15,7 @@ public sealed class OpenAdminNotesCommand : IConsoleCommand public async void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This does not work from the server console."); return; diff --git a/Content.Server/Administration/Commands/OpenPermissionsCommand.cs b/Content.Server/Administration/Commands/OpenPermissionsCommand.cs index 78d56cb4fbc..fd3227d4aaf 100644 --- a/Content.Server/Administration/Commands/OpenPermissionsCommand.cs +++ b/Content.Server/Administration/Commands/OpenPermissionsCommand.cs @@ -1,10 +1,8 @@ using Content.Server.Administration.UI; using Content.Server.EUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; - namespace Content.Server.Administration.Commands { [AdminCommand(AdminFlags.Permissions)] @@ -16,7 +14,7 @@ public sealed class OpenPermissionsCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("This does not work from the server console."); diff --git a/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs b/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs index d61114fcae8..507c7ab2799 100644 --- a/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs +++ b/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.Notes; using Content.Shared.Administration; using Content.Shared.CCVar; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -27,7 +26,7 @@ public async void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This does not work from the server console."); return; diff --git a/Content.Server/Administration/Commands/PardonCommand.cs b/Content.Server/Administration/Commands/PardonCommand.cs index 869024eb7c0..9cbaaece310 100644 --- a/Content.Server/Administration/Commands/PardonCommand.cs +++ b/Content.Server/Administration/Commands/PardonCommand.cs @@ -1,7 +1,6 @@ using System.Text; using Content.Server.Database; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -15,7 +14,7 @@ public sealed class PardonCommand : IConsoleCommand public async void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; var dbMan = IoCManager.Resolve(); if (args.Length != 1) diff --git a/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs b/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs index ec5b21dcee8..fdf067181db 100644 --- a/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs +++ b/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs @@ -6,7 +6,6 @@ using Robust.Shared.Console; using Robust.Shared.ContentPack; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; namespace Content.Server.Administration.Commands; diff --git a/Content.Server/Administration/Commands/ReAdminCommand.cs b/Content.Server/Administration/Commands/ReAdminCommand.cs index 12ff13221a0..a3f59937663 100644 --- a/Content.Server/Administration/Commands/ReAdminCommand.cs +++ b/Content.Server/Administration/Commands/ReAdminCommand.cs @@ -1,9 +1,7 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; - namespace Content.Server.Administration.Commands { [AnyCommand] @@ -15,7 +13,7 @@ public sealed class ReAdminCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You cannot use this command from the server console."); diff --git a/Content.Server/Administration/Commands/SetAdminOOC.cs b/Content.Server/Administration/Commands/SetAdminOOC.cs index bb11b938d85..27528e1940f 100644 --- a/Content.Server/Administration/Commands/SetAdminOOC.cs +++ b/Content.Server/Administration/Commands/SetAdminOOC.cs @@ -1,8 +1,6 @@ - using Content.Server.Database; using Content.Server.Preferences.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -16,7 +14,7 @@ internal sealed class SetAdminOOC : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (!(shell.Player is IPlayerSession)) + if (shell.Player == null) { shell.WriteError(Loc.GetString("shell-only-players-can-run-this-command")); return; diff --git a/Content.Server/Administration/Commands/SetMindCommand.cs b/Content.Server/Administration/Commands/SetMindCommand.cs index b9ff329ed2e..5310c2dd7f5 100644 --- a/Content.Server/Administration/Commands/SetMindCommand.cs +++ b/Content.Server/Administration/Commands/SetMindCommand.cs @@ -2,6 +2,7 @@ using Content.Shared.Administration; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Content.Shared.Players; using Robust.Server.Player; using Robust.Shared.Console; diff --git a/Content.Server/Administration/Commands/SetOutfitCommand.cs b/Content.Server/Administration/Commands/SetOutfitCommand.cs index 28172ee6c5c..b2e7f4e6cc0 100644 --- a/Content.Server/Administration/Commands/SetOutfitCommand.cs +++ b/Content.Server/Administration/Commands/SetOutfitCommand.cs @@ -10,7 +10,6 @@ using Content.Shared.Preferences; using Content.Shared.Roles; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -57,7 +56,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (args.Length == 1) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("set-outfit-command-is-not-player-error")); return; diff --git a/Content.Server/Administration/Commands/VariantizeCommand.cs b/Content.Server/Administration/Commands/VariantizeCommand.cs index 1b5cbbd4d50..7aabd76335e 100644 --- a/Content.Server/Administration/Commands/VariantizeCommand.cs +++ b/Content.Server/Administration/Commands/VariantizeCommand.cs @@ -12,6 +12,7 @@ public sealed class VariantizeCommand : IConsoleCommand { [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; public string Command => "variantize"; @@ -39,11 +40,14 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - foreach (var tile in gridComp.GetAllTiles()) + var mapsSystem = _entManager.System(); + var tileSystem = _entManager.System(); + + foreach (var tile in mapsSystem.GetAllTiles(euid.Value, gridComp)) { - var def = tile.GetContentTileDefinition(); - var newTile = new Tile(tile.Tile.TypeId, tile.Tile.Flags, def.PickVariant(_random)); - gridComp.SetTile(tile.GridIndices, newTile); + var def = tile.GetContentTileDefinition(_tileDefManager); + var newTile = new Tile(tile.Tile.TypeId, tile.Tile.Flags, tileSystem.PickVariant(def)); + mapsSystem.SetTile(euid.Value, gridComp, tile.GridIndices, newTile); } } } diff --git a/Content.Server/Administration/Commands/WarpCommand.cs b/Content.Server/Administration/Commands/WarpCommand.cs index 30a6d127aa3..0d6da0d9937 100644 --- a/Content.Server/Administration/Commands/WarpCommand.cs +++ b/Content.Server/Administration/Commands/WarpCommand.cs @@ -4,11 +4,9 @@ using Content.Shared.Administration; using Content.Shared.Follower; using Content.Shared.Ghost; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; using Robust.Shared.Map; -using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; @@ -28,7 +26,7 @@ public sealed class WarpCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Only players can use this command"); diff --git a/Content.Server/Administration/ContentNetworkResourceManager.cs b/Content.Server/Administration/ContentNetworkResourceManager.cs index 0d3f3291e6b..dd95a2d8971 100644 --- a/Content.Server/Administration/ContentNetworkResourceManager.cs +++ b/Content.Server/Administration/ContentNetworkResourceManager.cs @@ -1,8 +1,8 @@ using Content.Server.Database; using Content.Shared.CCVar; -using Robust.Server.Player; using Robust.Server.Upload; using Robust.Shared.Configuration; +using Robust.Shared.Player; using Robust.Shared.Upload; namespace Content.Server.Administration; @@ -22,7 +22,7 @@ public void Initialize() _netRes.OnResourceUploaded += OnUploadResource; } - private async void OnUploadResource(IPlayerSession session, NetworkResourceUploadMessage msg) + private async void OnUploadResource(ICommonSession session, NetworkResourceUploadMessage msg) { if (StoreUploaded) await _serverDb.AddUploadedResourceLogAsync(session.UserId, DateTime.Now, msg.RelativePath.ToString(), msg.Data); diff --git a/Content.Server/Administration/Logs/AdminLogManager.Json.cs b/Content.Server/Administration/Logs/AdminLogManager.Json.cs index 43a1e0b8b56..0a67d61cefe 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.Json.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.Json.cs @@ -2,10 +2,9 @@ using System.Text.Json; using System.Text.Json.Serialization; using Content.Server.Administration.Logs.Converters; -using Content.Server.Database; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; +using Robust.Shared.Player; namespace Content.Server.Administration.Logs; @@ -34,10 +33,9 @@ private void InitializeJson() _sawmill.Debug($"Admin log converters found: {string.Join(" ", converterNames)}"); } - private (JsonDocument Json, HashSet Players, List Entities) ToJson( + private (JsonDocument Json, HashSet Players) ToJson( Dictionary properties) { - var entities = new Dictionary(); var players = new HashSet(); var parsed = new Dictionary(); @@ -46,7 +44,7 @@ private void InitializeJson() var value = properties[key]; value = value switch { - IPlayerSession player => new SerializablePlayer(player), + ICommonSession player => new SerializablePlayer(player), EntityCoordinates entityCoordinates => new SerializableEntityCoordinates(_entityManager, entityCoordinates), _ => value }; @@ -58,29 +56,17 @@ private void InitializeJson() { EntityUid id => id, EntityStringRepresentation rep => rep.Uid, - IPlayerSession {AttachedEntity: {Valid: true}} session => session.AttachedEntity, + ICommonSession {AttachedEntity: {Valid: true}} session => session.AttachedEntity, IComponent component => component.Owner, _ => null }; - if (entityId is not { } uid) - { - continue; - } - - var entityName = _entityManager.TryGetComponent(uid, out MetaDataComponent? metadata) - ? metadata.EntityName - : null; - - // TODO set the id too whenever we feel like running a migration for 10 hours - entities.TryAdd(uid, new AdminLogEntity { Name = entityName }); - - if (_entityManager.TryGetComponent(uid, out ActorComponent? actor)) + if (_entityManager.TryGetComponent(entityId, out ActorComponent? actor)) { players.Add(actor.PlayerSession.UserId.UserId); } } - return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities.Values.ToList()); + return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players); } } diff --git a/Content.Server/Administration/Logs/AdminLogManager.cs b/Content.Server/Administration/Logs/AdminLogManager.cs index 06f58f10b20..e869d089dac 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.cs @@ -278,7 +278,7 @@ public void RunLevelChanged(GameRunLevel level) } } - private void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet players, List entities) + private void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet players) { var preRound = _runLevel == GameRunLevel.PreRoundLobby; var count = preRound ? _preRoundLogQueue.Count : _logQueue.Count; @@ -297,8 +297,7 @@ private void Add(LogType type, LogImpact impact, string message, JsonDocument js Date = DateTime.UtcNow, Message = message, Json = json, - Players = new List(players.Count), - Entities = entities + Players = new List(players.Count) }; foreach (var id in players) @@ -331,10 +330,10 @@ public override void Add(LogType type, LogImpact impact, ref LogStringHandler ha return; } - var (json, players, entities) = ToJson(handler.Values); + var (json, players) = ToJson(handler.Values); var message = handler.ToStringAndClear(); - Add(type, impact, message, json, players, entities); + Add(type, impact, message, json, players); } public override void Add(LogType type, ref LogStringHandler handler) diff --git a/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs b/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs index 0605c2db2a3..c1567448ccb 100644 --- a/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs +++ b/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs @@ -1,5 +1,5 @@ using System.Text.Json; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Administration.Logs.Converters; @@ -36,9 +36,9 @@ public override void Write(Utf8JsonWriter writer, SerializablePlayer value, Json public readonly struct SerializablePlayer { - public readonly IPlayerSession Player; + public readonly ICommonSession Player; - public SerializablePlayer(IPlayerSession player) + public SerializablePlayer(ICommonSession player) { Player = player; } diff --git a/Content.Server/Administration/Managers/AdminManager.cs b/Content.Server/Administration/Managers/AdminManager.cs index 4aa6074b109..0895183215e 100644 --- a/Content.Server/Administration/Managers/AdminManager.cs +++ b/Content.Server/Administration/Managers/AdminManager.cs @@ -7,15 +7,15 @@ using Content.Server.Players; using Content.Shared.Administration; using Content.Shared.CCVar; +using Content.Shared.Players; using Robust.Server.Console; using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; using Robust.Shared.ContentPack; using Robust.Shared.Enums; -using Robust.Shared.Map; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; using Robust.Shared.Utility; @@ -35,16 +35,16 @@ public sealed class AdminManager : IAdminManager, IPostInjectInit, IConGroupCont [Dependency] private readonly IChatManager _chat = default!; [Dependency] private readonly ToolshedManager _toolshed = default!; - private readonly Dictionary _admins = new(); + private readonly Dictionary _admins = new(); private readonly HashSet _promotedPlayers = new(); public event Action? OnPermsChanged; - public IEnumerable ActiveAdmins => _admins + public IEnumerable ActiveAdmins => _admins .Where(p => p.Value.Data.Active) .Select(p => p.Key); - public IEnumerable AllAdmins => _admins.Select(p => p.Key); + public IEnumerable AllAdmins => _admins.Select(p => p.Key); private readonly AdminCommandPermissions _commandPermissions = new(); private readonly AdminCommandPermissions _toolshedCommandPermissions = new(); @@ -56,7 +56,7 @@ public bool IsAdmin(ICommonSession session, bool includeDeAdmin = false) public AdminData? GetAdminData(ICommonSession session, bool includeDeAdmin = false) { - if (_admins.TryGetValue((IPlayerSession)session, out var reg) && (reg.Data.Active || includeDeAdmin)) + if (_admins.TryGetValue(session, out var reg) && (reg.Data.Active || includeDeAdmin)) { return reg.Data; } @@ -66,13 +66,13 @@ public bool IsAdmin(ICommonSession session, bool includeDeAdmin = false) public AdminData? GetAdminData(EntityUid uid, bool includeDeAdmin = false) { - if (_playerManager.TryGetSessionByEntity(uid, out var session) && session is IPlayerSession playerSession) - return GetAdminData(playerSession, includeDeAdmin); + if (_playerManager.TryGetSessionByEntity(uid, out var session)) + return GetAdminData(session, includeDeAdmin); return null; } - public void DeAdmin(IPlayerSession session) + public void DeAdmin(ICommonSession session) { if (!_admins.TryGetValue(session, out var reg)) { @@ -95,7 +95,7 @@ public void DeAdmin(IPlayerSession session) UpdateAdminStatus(session); } - public void ReAdmin(IPlayerSession session) + public void ReAdmin(ICommonSession session) { if (!_admins.TryGetValue(session, out var reg)) { @@ -119,7 +119,7 @@ public void ReAdmin(IPlayerSession session) UpdateAdminStatus(session); } - public async void ReloadAdmin(IPlayerSession player) + public async void ReloadAdmin(ICommonSession player) { var data = await LoadAdminData(player); var curAdmin = _admins.GetValueOrDefault(player); @@ -236,7 +236,7 @@ public void Initialize() _toolshed.ActivePermissionController = this; } - public void PromoteHost(IPlayerSession player) + public void PromoteHost(ICommonSession player) { _promotedPlayers.Add(player.UserId); @@ -250,7 +250,7 @@ void IPostInjectInit.PostInject() } // NOTE: Also sends commands list for non admins.. - private void UpdateAdminStatus(IPlayerSession session) + private void UpdateAdminStatus(ICommonSession session) { var msg = new MsgUpdateAdminStatus(); @@ -290,7 +290,7 @@ private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e) } } - private async void LoginAdminMaybe(IPlayerSession session) + private async void LoginAdminMaybe(ICommonSession session) { var adminDat = await LoadAdminData(session); if (adminDat == null) @@ -323,7 +323,7 @@ private async void LoginAdminMaybe(IPlayerSession session) UpdateAdminStatus(session); } - private async Task<(AdminData dat, int? rankId, bool specialLogin)?> LoadAdminData(IPlayerSession session) + private async Task<(AdminData dat, int? rankId, bool specialLogin)?> LoadAdminData(ICommonSession session) { var promoteHost = IsLocal(session) && _cfg.GetCVar(CCVars.ConsoleLoginLocal) || _promotedPlayers.Contains(session.UserId) @@ -387,7 +387,7 @@ private async void LoginAdminMaybe(IPlayerSession session) } } - private static bool IsLocal(IPlayerSession player) + private static bool IsLocal(ICommonSession player) { var ep = player.ConnectedClient.RemoteEndPoint; var addr = ep.Address; @@ -419,7 +419,7 @@ public bool TryGetCommandFlags(CommandSpec command, out AdminFlags[]? flags) return false; } - public bool CanCommand(IPlayerSession session, string cmdName) + public bool CanCommand(ICommonSession session, string cmdName) { if (_commandPermissions.AnyCommands.Contains(cmdName)) { @@ -474,7 +474,7 @@ public bool CheckInvokable(CommandSpec command, ICommonSession? user, out IConEr return true; } - var data = GetAdminData((IPlayerSession)user); + var data = GetAdminData(user); if (data == null) { // Player isn't an admin. @@ -520,32 +520,32 @@ private static (bool isAvail, AdminFlags[] flagsReq) GetRequiredFlag(object cmd) return (attribs.Length != 0, attribs); } - public bool CanViewVar(IPlayerSession session) + public bool CanViewVar(ICommonSession session) { return CanCommand(session, "vv"); } - public bool CanAdminPlace(IPlayerSession session) + public bool CanAdminPlace(ICommonSession session) { return GetAdminData(session)?.CanAdminPlace() ?? false; } - public bool CanScript(IPlayerSession session) + public bool CanScript(ICommonSession session) { return GetAdminData(session)?.CanScript() ?? false; } - public bool CanAdminMenu(IPlayerSession session) + public bool CanAdminMenu(ICommonSession session) { return GetAdminData(session)?.CanAdminMenu() ?? false; } - public bool CanAdminReloadPrototypes(IPlayerSession session) + public bool CanAdminReloadPrototypes(ICommonSession session) { return GetAdminData(session)?.CanAdminReloadPrototypes() ?? false; } - private void SendPermsChangedEvent(IPlayerSession session) + private void SendPermsChangedEvent(ICommonSession session) { var flags = GetAdminData(session)?.Flags; OnPermsChanged?.Invoke(new AdminPermsChangedEventArgs(session, flags)); @@ -553,7 +553,7 @@ private void SendPermsChangedEvent(IPlayerSession session) private sealed class AdminReg { - public readonly IPlayerSession Session; + public readonly ICommonSession Session; public AdminData Data; public int? RankId; @@ -561,7 +561,7 @@ private sealed class AdminReg // Such as console.loginlocal or promotehost public bool IsSpecialLogin; - public AdminReg(IPlayerSession session, AdminData data) + public AdminReg(ICommonSession session, AdminData data) { Data = data; Session = session; diff --git a/Content.Server/Administration/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index 765df17b179..4d51d35576a 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -15,6 +15,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -283,7 +284,7 @@ public void SendRoleBans(NetUserId userId) SendRoleBans(player); } - public void SendRoleBans(IPlayerSession pSession) + public void SendRoleBans(ICommonSession pSession) { var roleBans = _cachedRoleBans.GetValueOrDefault(pSession.UserId) ?? new HashSet(); var bans = new MsgRoleBans() diff --git a/Content.Server/Administration/Managers/IAdminManager.cs b/Content.Server/Administration/Managers/IAdminManager.cs index eeed5cc36e0..a52ec7b099c 100644 --- a/Content.Server/Administration/Managers/IAdminManager.cs +++ b/Content.Server/Administration/Managers/IAdminManager.cs @@ -1,9 +1,8 @@ using Content.Shared.Administration; using Content.Shared.Administration.Managers; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; - namespace Content.Server.Administration.Managers { /// @@ -22,12 +21,12 @@ public interface IAdminManager : ISharedAdminManager /// /// This does not include admins that are de-adminned. /// - IEnumerable ActiveAdmins { get; } + IEnumerable ActiveAdmins { get; } /// /// Gets all admins currently on the server, even de-adminned ones. /// - IEnumerable AllAdmins { get; } + IEnumerable AllAdmins { get; } /// /// De-admins an admin temporarily so they are effectively a normal player. @@ -35,18 +34,18 @@ public interface IAdminManager : ISharedAdminManager /// /// De-adminned admins are able to re-admin at any time if they so desire. /// - void DeAdmin(IPlayerSession session); + void DeAdmin(ICommonSession session); /// /// Re-admins a de-adminned admin. /// - void ReAdmin(IPlayerSession session); + void ReAdmin(ICommonSession session); /// /// Re-loads the permissions of an player in case their admin data changed DB-side. /// /// - void ReloadAdmin(IPlayerSession player); + void ReloadAdmin(ICommonSession player); /// /// Reloads admin permissions for all admins with a certain rank. @@ -57,7 +56,7 @@ public interface IAdminManager : ISharedAdminManager void Initialize(); - void PromoteHost(IPlayerSession player); + void PromoteHost(ICommonSession player); bool TryGetCommandFlags(CommandSpec command, out AdminFlags[]? flags); } diff --git a/Content.Server/Administration/Managers/IBanManager.cs b/Content.Server/Administration/Managers/IBanManager.cs index 8458feac8d0..dafe3d35bdd 100644 --- a/Content.Server/Administration/Managers/IBanManager.cs +++ b/Content.Server/Administration/Managers/IBanManager.cs @@ -2,8 +2,8 @@ using System.Net; using System.Threading.Tasks; using Content.Shared.Database; -using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration.Managers; @@ -55,5 +55,5 @@ public interface IBanManager /// Sends role bans to the target /// /// Player's session - public void SendRoleBans(IPlayerSession pSession); + public void SendRoleBans(ICommonSession pSession); } diff --git a/Content.Server/Administration/Notes/AdminNotesManager.cs b/Content.Server/Administration/Notes/AdminNotesManager.cs index 8a7846663f3..0c1e7f3daad 100644 --- a/Content.Server/Administration/Notes/AdminNotesManager.cs +++ b/Content.Server/Administration/Notes/AdminNotesManager.cs @@ -11,7 +11,7 @@ using Content.Shared.Players.PlayTimeTracking; using Robust.Shared.Configuration; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Administration.Notes; diff --git a/Content.Server/Administration/Notes/AdminNotesSystem.cs b/Content.Server/Administration/Notes/AdminNotesSystem.cs index fd9f3f6bfae..f2eb033dcaa 100644 --- a/Content.Server/Administration/Notes/AdminNotesSystem.cs +++ b/Content.Server/Administration/Notes/AdminNotesSystem.cs @@ -1,13 +1,13 @@ using Content.Server.Administration.Commands; using Content.Server.Chat.Managers; using Content.Server.EUI; -using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Administration.Notes; diff --git a/Content.Server/Administration/Notes/IAdminNotesManager.cs b/Content.Server/Administration/Notes/IAdminNotesManager.cs index ae7133c56d9..a726bd11c82 100644 --- a/Content.Server/Administration/Notes/IAdminNotesManager.cs +++ b/Content.Server/Administration/Notes/IAdminNotesManager.cs @@ -2,7 +2,7 @@ using Content.Server.Database; using Content.Shared.Administration.Notes; using Content.Shared.Database; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Administration.Notes; diff --git a/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs b/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs index 521bee776f0..fb013a88ad9 100644 --- a/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs +++ b/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs @@ -1,6 +1,6 @@ using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Administration; @@ -16,7 +16,7 @@ public sealed partial class QuickDialogSystem /// The action to execute upon the dialog being cancelled. /// Type of the input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt, Action okAction, + public void OpenDialog(ICommonSession session, string title, string prompt, Action okAction, Action? cancelAction = null) { OpenDialogInternal( @@ -53,7 +53,7 @@ public void OpenDialog(IPlayerSession session, string title, string prompt, /// Type of the first input. /// Type of the second input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt1, string prompt2, + public void OpenDialog(ICommonSession session, string title, string prompt1, string prompt2, Action okAction, Action? cancelAction = null) { OpenDialogInternal( @@ -96,7 +96,7 @@ public void OpenDialog(IPlayerSession session, string title, string prom /// Type of the second input. /// Type of the third input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt1, string prompt2, + public void OpenDialog(ICommonSession session, string title, string prompt1, string prompt2, string prompt3, Action okAction, Action? cancelAction = null) { OpenDialogInternal( @@ -142,7 +142,7 @@ public void OpenDialog(IPlayerSession session, string title, string /// Type of the third input. /// Type of the fourth input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt1, string prompt2, + public void OpenDialog(ICommonSession session, string title, string prompt1, string prompt2, string prompt3, string prompt4, Action okAction, Action? cancelAction = null) { OpenDialogInternal( diff --git a/Content.Server/Administration/QuickDialogSystem.cs b/Content.Server/Administration/QuickDialogSystem.cs index 51b8cf79c2a..96423e52238 100644 --- a/Content.Server/Administration/QuickDialogSystem.cs +++ b/Content.Server/Administration/QuickDialogSystem.cs @@ -1,12 +1,9 @@ -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using Content.Shared.Administration; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Serialization.TypeSerializers.Interfaces; namespace Content.Server.Administration; @@ -87,7 +84,7 @@ private void PlayerManagerOnPlayerStatusChanged(object? sender, SessionStatusEve _openDialogsByUser.Remove(user); } - private void OpenDialogInternal(IPlayerSession session, string title, List entries, QuickDialogButtonFlag buttons, Action okAction, Action cancelAction) + private void OpenDialogInternal(ICommonSession session, string title, List entries, QuickDialogButtonFlag buttons, Action okAction, Action cancelAction) { var did = GetDialogId(); RaiseNetworkEvent( diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index 66f7a8999b3..feabaa2aad6 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -109,7 +109,7 @@ private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev) } } - public void UpdatePlayerList(IPlayerSession player) + public void UpdatePlayerList(ICommonSession player) { _playerList[player.UserId] = GetPlayerInfo(player.Data, player); @@ -203,7 +203,7 @@ private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) UpdatePanicBunker(); } - private void SendFullPlayerList(IPlayerSession playerSession) + private void SendFullPlayerList(ICommonSession playerSession) { var ev = new FullPlayerListEvent(); @@ -212,7 +212,7 @@ private void SendFullPlayerList(IPlayerSession playerSession) RaiseNetworkEvent(ev, playerSession.ConnectedClient); } - private PlayerInfo GetPlayerInfo(IPlayerData data, IPlayerSession? session) + private PlayerInfo GetPlayerInfo(SessionData data, ICommonSession? session) { var name = data.UserName; var entityName = string.Empty; @@ -326,7 +326,7 @@ private void SendPanicBunkerStatusAll() /// chat messages and showing a popup to other players. /// Their items are dropped on the ground. /// - public void Erase(IPlayerSession player) + public void Erase(ICommonSession player) { var entity = player.AttachedEntity; _chat.DeleteMessagesBy(player); diff --git a/Content.Server/Administration/Systems/AdminTestArenaSystem.cs b/Content.Server/Administration/Systems/AdminTestArenaSystem.cs index e65acf571cb..e3671bcdfb3 100644 --- a/Content.Server/Administration/Systems/AdminTestArenaSystem.cs +++ b/Content.Server/Administration/Systems/AdminTestArenaSystem.cs @@ -1,8 +1,8 @@ using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration.Systems; @@ -20,7 +20,7 @@ public sealed class AdminTestArenaSystem : EntitySystem public Dictionary ArenaMap { get; private set; } = new(); public Dictionary ArenaGrid { get; private set; } = new(); - public (EntityUid Map, EntityUid? Grid) AssertArenaLoaded(IPlayerSession admin) + public (EntityUid Map, EntityUid? Grid) AssertArenaLoaded(ICommonSession admin) { if (ArenaMap.TryGetValue(admin.UserId, out var arenaMap) && !Deleted(arenaMap) && !Terminating(arenaMap)) { diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs index c7e23374a3c..bc065745f5e 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Disposal.Tube.Components; using Content.Server.EUI; using Content.Server.Ghost.Roles; +using Content.Server.Mind; using Content.Server.Mind.Commands; using Content.Server.Prayer; using Content.Server.Xenoarchaeology.XenoArtifacts; @@ -18,17 +19,15 @@ using Content.Shared.Examine; using Content.Shared.GameTicking; using Content.Shared.Inventory; -using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Popups; using Content.Shared.Verbs; using Robust.Server.Console; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Map.Components; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Toolshed; @@ -56,7 +55,7 @@ public sealed partial class AdminVerbSystem : EntitySystem [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; [Dependency] private readonly PrayerSystem _prayerSystem = default!; [Dependency] private readonly EuiManager _eui = default!; - [Dependency] private readonly SharedMindSystem _mindSystem = default!; + [Dependency] private readonly MindSystem _mindSystem = default!; [Dependency] private readonly ToolshedManager _toolshed = default!; [Dependency] private readonly RejuvenateSystem _rejuvenate = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; @@ -277,12 +276,7 @@ private void AddDebugVerbs(GetVerbsEvent args) // TODO VERB ICON control mob icon Act = () => { - MakeSentientCommand.MakeSentient(args.Target, EntityManager); - - if (!_minds.TryGetMind(player, out var mindId, out var mind)) - return; - - _mindSystem.TransferTo(mindId, args.Target, ghostCheckOverride: true, mind: mind); + _mindSystem.ControlMob(args.User, args.Target); }, Impact = LogImpact.High, ConfirmationPopup = true @@ -358,7 +352,7 @@ private void AddDebugVerbs(GetVerbsEvent args) var message = ExamineSystemShared.InRangeUnOccluded(args.User, args.Target) ? Loc.GetString("in-range-unoccluded-verb-on-activate-not-occluded") : Loc.GetString("in-range-unoccluded-verb-on-activate-occluded"); - + _popup.PopupEntity(message, args.Target, args.User); } }; @@ -432,7 +426,7 @@ private void OnSolutionChanged(EntityUid uid, SolutionContainerManagerComponent } } - public void OpenEditSolutionsEui(IPlayerSession session, EntityUid uid) + public void OpenEditSolutionsEui(ICommonSession session, EntityUid uid) { if (session.AttachedEntity == null) return; diff --git a/Content.Server/Administration/Systems/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs index 98e5af1126b..31ef285a882 100644 --- a/Content.Server/Administration/Systems/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -17,6 +17,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -119,7 +120,7 @@ private void OnClientTypingUpdated(BwoinkClientTypingUpdated msg, EntitySessionE _typingUpdateTimestamps[args.SenderSession.UserId] = (_timing.RealTime, msg.Typing); // Non-admins can only ever type on their own ahelp, guard against fake messages - var isAdmin = _adminManager.GetAdminData((IPlayerSession) args.SenderSession)?.HasFlag(AdminFlags.Adminhelp) ?? false; + var isAdmin = _adminManager.GetAdminData(args.SenderSession)?.HasFlag(AdminFlags.Adminhelp) ?? false; var channel = isAdmin ? msg.Channel : args.SenderSession.UserId; var update = new BwoinkPlayerTypingUpdated(channel, args.SenderSession.Name, msg.Typing); @@ -376,7 +377,7 @@ public override void Update(float frameTime) protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs) { base.OnBwoinkTextMessage(message, eventArgs); - var senderSession = (IPlayerSession) eventArgs.SenderSession; + var senderSession = eventArgs.SenderSession; // TODO: Sanitize text? // Confirm that this person is actually allowed to send a message here. diff --git a/Content.Server/Administration/Toolshed/AdminsCommand.cs b/Content.Server/Administration/Toolshed/AdminsCommand.cs index aa82e0f1d93..1d64f748fd2 100644 --- a/Content.Server/Administration/Toolshed/AdminsCommand.cs +++ b/Content.Server/Administration/Toolshed/AdminsCommand.cs @@ -1,6 +1,6 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; namespace Content.Server.Administration.Toolshed; @@ -11,13 +11,13 @@ public sealed class AdminsCommand : ToolshedCommand [Dependency] private readonly IAdminManager _admin = default!; [CommandImplementation("active")] - public IEnumerable Active() + public IEnumerable Active() { return _admin.ActiveAdmins; } [CommandImplementation("all")] - public IEnumerable All() + public IEnumerable All() { return _admin.AllAdmins; } diff --git a/Content.Server/Afk/AFKSystem.cs b/Content.Server/Afk/AFKSystem.cs index 0938f45f73e..f634a415dc5 100644 --- a/Content.Server/Afk/AFKSystem.cs +++ b/Content.Server/Afk/AFKSystem.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Server.Afk.Events; using Content.Server.GameTicking; using Content.Shared.CCVar; @@ -24,7 +23,7 @@ public sealed class AFKSystem : EntitySystem private float _checkDelay; private TimeSpan _checkTime; - private readonly HashSet _afkPlayers = new(); + private readonly HashSet _afkPlayers = new(); public override void Initialize() { @@ -73,11 +72,9 @@ public override void Update(float frameTime) _checkTime = _timing.CurTime + TimeSpan.FromSeconds(_checkDelay); - foreach (var session in Filter.GetAllPlayers()) + foreach (var pSession in Filter.GetAllPlayers()) { - if (session.Status != SessionStatus.InGame) continue; - - var pSession = (IPlayerSession) session; + if (pSession.Status != SessionStatus.InGame) continue; var isAfk = _afkManager.IsAfk(pSession); if (isAfk && _afkPlayers.Add(pSession)) diff --git a/Content.Server/Afk/AfkManager.cs b/Content.Server/Afk/AfkManager.cs index 24cd1e28cec..52dc7715df3 100644 --- a/Content.Server/Afk/AfkManager.cs +++ b/Content.Server/Afk/AfkManager.cs @@ -5,6 +5,7 @@ using Robust.Shared.Console; using Robust.Shared.Enums; using Robust.Shared.Input; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Afk @@ -20,13 +21,13 @@ public interface IAfkManager /// /// The player to check. /// True if the player is AFK, false otherwise. - bool IsAfk(IPlayerSession player); + bool IsAfk(ICommonSession player); /// /// Resets AFK status for the player as if they just did an action and are definitely not AFK. /// /// The player to set AFK status for. - void PlayerDidAction(IPlayerSession player); + void PlayerDidAction(ICommonSession player); void Initialize(); } @@ -40,7 +41,7 @@ public sealed class AfkManager : IAfkManager, IEntityEventSubscriber [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IConsoleHost _consoleHost = default!; - private readonly Dictionary _lastActionTimes = new(); + private readonly Dictionary _lastActionTimes = new(); public void Initialize() { @@ -55,7 +56,7 @@ public void Initialize() HandleInputCmd); } - public void PlayerDidAction(IPlayerSession player) + public void PlayerDidAction(ICommonSession player) { if (player.Status == SessionStatus.Disconnected) // Make sure we don't re-add to the dictionary if the player is disconnected now. @@ -64,7 +65,7 @@ public void PlayerDidAction(IPlayerSession player) _lastActionTimes[player] = _gameTiming.RealTime; } - public bool IsAfk(IPlayerSession player) + public bool IsAfk(ICommonSession player) { if (!_lastActionTimes.TryGetValue(player, out var time)) // Some weird edge case like disconnected clients. Just say true I guess. @@ -87,13 +88,13 @@ private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e) private void ConsoleHostOnAnyCommandExecuted(IConsoleShell shell, string commandname, string argstr, string[] args) { - if (shell.Player is IPlayerSession player) + if (shell.Player is { } player) PlayerDidAction(player); } private void HandleInputCmd(FullInputCmdMessage msg, EntitySessionEventArgs args) { - PlayerDidAction((IPlayerSession) args.SenderSession); + PlayerDidAction(args.SenderSession); } } } diff --git a/Content.Server/Afk/Events/AFKEvent.cs b/Content.Server/Afk/Events/AFKEvent.cs index 6adb950e475..ee9d548043f 100644 --- a/Content.Server/Afk/Events/AFKEvent.cs +++ b/Content.Server/Afk/Events/AFKEvent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Afk.Events; @@ -8,9 +8,9 @@ namespace Content.Server.Afk.Events; [ByRefEvent] public readonly struct AFKEvent { - public readonly IPlayerSession Session; + public readonly ICommonSession Session; - public AFKEvent(IPlayerSession playerSession) + public AFKEvent(ICommonSession playerSession) { Session = playerSession; } diff --git a/Content.Server/Afk/Events/UnAFKEvent.cs b/Content.Server/Afk/Events/UnAFKEvent.cs index 3dd034583c5..0983c256f05 100644 --- a/Content.Server/Afk/Events/UnAFKEvent.cs +++ b/Content.Server/Afk/Events/UnAFKEvent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Afk.Events; @@ -8,9 +8,9 @@ namespace Content.Server.Afk.Events; [ByRefEvent] public readonly struct UnAFKEvent { - public readonly IPlayerSession Session; + public readonly ICommonSession Session; - public UnAFKEvent(IPlayerSession playerSession) + public UnAFKEvent(ICommonSession playerSession) { Session = playerSession; } diff --git a/Content.Server/Alert/Commands/ClearAlert.cs b/Content.Server/Alert/Commands/ClearAlert.cs index e43f06413c3..1759612702f 100644 --- a/Content.Server/Alert/Commands/ClearAlert.cs +++ b/Content.Server/Alert/Commands/ClearAlert.cs @@ -2,7 +2,6 @@ using Content.Server.Commands; using Content.Shared.Administration; using Content.Shared.Alert; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Alert.Commands @@ -16,7 +15,7 @@ public sealed class ClearAlert : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine("You don't have an entity."); diff --git a/Content.Server/Alert/Commands/ShowAlert.cs b/Content.Server/Alert/Commands/ShowAlert.cs index edb634b546c..11901e9af00 100644 --- a/Content.Server/Alert/Commands/ShowAlert.cs +++ b/Content.Server/Alert/Commands/ShowAlert.cs @@ -2,7 +2,6 @@ using Content.Server.Commands; using Content.Shared.Administration; using Content.Shared.Alert; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Alert.Commands @@ -16,7 +15,7 @@ public sealed class ShowAlert : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine("You cannot run this from the server or without an attached entity."); diff --git a/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs b/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs index 009a8b5f236..2c432a24190 100644 --- a/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs +++ b/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs @@ -3,7 +3,6 @@ using Content.Server.Station.Systems; using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.AlertLevel.Commands @@ -19,7 +18,7 @@ public sealed class SetAlertLevelCommand : IConsoleCommand public CompletionResult GetCompletion(IConsoleShell shell, string[] args) { var levelNames = new string[] {}; - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity != null) { var stationUid = EntitySystem.Get().GetOwningStation(player.AttachedEntity.Value); @@ -54,7 +53,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine(Loc.GetString("shell-only-players-can-run-this-command")); diff --git a/Content.Server/Antag/AntagSelectionSystem.cs b/Content.Server/Antag/AntagSelectionSystem.cs index 5e323f5ab8e..737b723d390 100644 --- a/Content.Server/Antag/AntagSelectionSystem.cs +++ b/Content.Server/Antag/AntagSelectionSystem.cs @@ -22,6 +22,7 @@ using Content.Server.Shuttles.Systems; using Content.Shared.Mobs; using Robust.Server.Containers; +using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Server.Antag; @@ -88,9 +89,9 @@ public void EligiblePlayers(string antagPrototype, out List chosen, bool includeHeads = false) { - var allPlayers = _playerSystem.ServerSessions.ToList(); - var playerList = new List(); - var prefList = new List(); + var allPlayers = _playerSystem.Sessions.ToList(); + var playerList = new List(); + var prefList = new List(); chosen = new List(); foreach (var player in allPlayers) { @@ -116,7 +117,7 @@ public void EligiblePlayers(string antagPrototype, var antags = Math.Clamp(allPlayers.Count / antagsPerPlayer, 1, maxAntags); for (var antag = 0; antag < antags; antag++) { - IPlayerSession chosenPlayer = null!; + ICommonSession? chosenPlayer = null; if (prefList.Count == 0) { if (playerList.Count == 0) diff --git a/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs b/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs index 92a96ea2266..ef69600783b 100644 --- a/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs +++ b/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs @@ -1,6 +1,6 @@ using Content.Shared.Arcade; -using Robust.Server.Player; using System.Linq; +using Robust.Shared.Player; namespace Content.Server.Arcade.BlockGame; @@ -166,7 +166,7 @@ private void SendMessage(BoundUserInterfaceMessage message) /// /// The message to send to a specific player/spectator. /// The target recipient. - private void SendMessage(BoundUserInterfaceMessage message, IPlayerSession session) + private void SendMessage(BoundUserInterfaceMessage message, ICommonSession session) { if (_uiSystem.TryGetUi(_owner, BlockGameUiKey.Key, out var bui)) _uiSystem.TrySendUiMessage(bui, message, session); @@ -176,7 +176,7 @@ private void SendMessage(BoundUserInterfaceMessage message, IPlayerSession sessi /// Handles sending the current state of the game to a player that has just opened the UI. /// /// The target recipient. - public void UpdateNewPlayerUI(IPlayerSession session) + public void UpdateNewPlayerUI(ICommonSession session) { if (_gameOver) { @@ -209,7 +209,7 @@ private void FullUpdate() /// Handles broadcasting the full player-visible game state to a specific player/spectator. /// /// The target recipient. - private void FullUpdate(IPlayerSession session) + private void FullUpdate(ICommonSession session) { UpdateFieldUI(session); SendNextPieceUpdate(session); @@ -235,7 +235,7 @@ public void UpdateFieldUI() /// Handles broadcasting the current location of all of the blocks in the playfield + the active piece to a specific player/spectator. /// /// The target recipient. - public void UpdateFieldUI(IPlayerSession session) + public void UpdateFieldUI(ICommonSession session) { if (!Started) return; @@ -283,7 +283,7 @@ private void SendNextPieceUpdate() /// Broadcasts the state of the next queued piece to a specific viewer. /// /// The target recipient. - private void SendNextPieceUpdate(IPlayerSession session) + private void SendNextPieceUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameVisualUpdateMessage(NextPiece.BlocksForPreview(), BlockGameMessages.BlockGameVisualType.NextBlock), session); } @@ -303,7 +303,7 @@ private void SendHoldPieceUpdate() /// Broadcasts the state of the currently held piece to a specific viewer. /// /// The target recipient. - private void SendHoldPieceUpdate(IPlayerSession session) + private void SendHoldPieceUpdate(ICommonSession session) { if (HeldPiece.HasValue) SendMessage(new BlockGameMessages.BlockGameVisualUpdateMessage(HeldPiece.Value.BlocksForPreview(), BlockGameMessages.BlockGameVisualType.HoldBlock), session); @@ -323,7 +323,7 @@ private void SendLevelUpdate() /// Broadcasts the current game level to a specific viewer. /// /// The target recipient. - private void SendLevelUpdate(IPlayerSession session) + private void SendLevelUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameLevelUpdateMessage(Level), session); } @@ -340,7 +340,7 @@ private void SendPointsUpdate() /// Broadcasts the current game score to a specific viewer. /// /// The target recipient. - private void SendPointsUpdate(IPlayerSession session) + private void SendPointsUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameScoreUpdateMessage(Points), session); } @@ -357,7 +357,7 @@ private void SendHighscoreUpdate() /// Broadcasts the current game high score positions to a specific viewer. /// /// The target recipient. - private void SendHighscoreUpdate(IPlayerSession session) + private void SendHighscoreUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameHighScoreUpdateMessage(_arcadeSystem.GetLocalHighscores(), _arcadeSystem.GetGlobalHighscores()), session); } diff --git a/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs b/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs index 268d5be4d2e..5613d915444 100644 --- a/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs +++ b/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Arcade.BlockGame; @@ -13,10 +13,10 @@ public sealed partial class BlockGameArcadeComponent : Component /// /// The player currently playing the active session of NT-BG. /// - public IPlayerSession? Player = null; + public ICommonSession? Player = null; /// /// The players currently viewing (but not playing) the active session of NT-BG. /// - public readonly List Spectators = new(); + public readonly List Spectators = new(); } diff --git a/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs b/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs index dac29accc96..ecc5bfd3e2c 100644 --- a/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs +++ b/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs @@ -2,7 +2,7 @@ using Content.Server.UserInterface; using Content.Shared.Arcade; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Arcade.BlockGame; @@ -30,7 +30,7 @@ public override void Update(float frameTime) } } - private void UpdatePlayerStatus(EntityUid uid, IPlayerSession session, PlayerBoundUserInterface? bui = null, BlockGameArcadeComponent? blockGame = null) + private void UpdatePlayerStatus(EntityUid uid, ICommonSession session, PlayerBoundUserInterface? bui = null, BlockGameArcadeComponent? blockGame = null) { if (!Resolve(uid, ref blockGame)) return; @@ -67,7 +67,7 @@ private void OnAfterUIOpen(EntityUid uid, BlockGameArcadeComponent component, Af private void OnAfterUiClose(EntityUid uid, BlockGameArcadeComponent component, BoundUIClosedEvent args) { - if (args.Session is not IPlayerSession session) + if (args.Session is not { } session) return; if (component.Player != session) diff --git a/Content.Server/Atmos/Commands/DeleteGasCommand.cs b/Content.Server/Atmos/Commands/DeleteGasCommand.cs index 0f0c399b11a..9e7594c024b 100644 --- a/Content.Server/Atmos/Commands/DeleteGasCommand.cs +++ b/Content.Server/Atmos/Commands/DeleteGasCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Atmos.EntitySystems; using Content.Shared.Administration; using Content.Shared.Atmos; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; @@ -20,7 +19,7 @@ public sealed class DeleteGasCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; Gas? gas = null; diff --git a/Content.Server/Atmos/Commands/ShowAtmosCommand.cs b/Content.Server/Atmos/Commands/ShowAtmosCommand.cs index 5ad73ec9063..263ef947d0a 100644 --- a/Content.Server/Atmos/Commands/ShowAtmosCommand.cs +++ b/Content.Server/Atmos/Commands/ShowAtmosCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Server.Atmos.EntitySystems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Atmos.Commands @@ -15,7 +14,7 @@ public sealed class ShowAtmos : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You must be a player to use this command."); diff --git a/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs index 34f558a2521..90edd4caed5 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs @@ -10,6 +10,7 @@ using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; namespace Content.Server.Atmos.EntitySystems { @@ -27,7 +28,7 @@ public sealed class AtmosDebugOverlaySystem : SharedAtmosDebugOverlaySystem /// To modify it see and /// . /// - private readonly HashSet _playerObservers = new(); + private readonly HashSet _playerObservers = new(); /// /// Overlay update ticks per second. @@ -48,17 +49,17 @@ public override void Shutdown() _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged; } - public bool AddObserver(IPlayerSession observer) + public bool AddObserver(ICommonSession observer) { return _playerObservers.Add(observer); } - public bool HasObserver(IPlayerSession observer) + public bool HasObserver(ICommonSession observer) { return _playerObservers.Contains(observer); } - public bool RemoveObserver(IPlayerSession observer) + public bool RemoveObserver(ICommonSession observer) { if (!_playerObservers.Remove(observer)) { @@ -76,7 +77,7 @@ public bool RemoveObserver(IPlayerSession observer) /// /// The observer to toggle. /// true if added, false if removed. - public bool ToggleObserver(IPlayerSession observer) + public bool ToggleObserver(ICommonSession observer) { if (HasObserver(observer)) { diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs index 91634de8d7a..d8364b652b8 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs @@ -4,6 +4,7 @@ using Content.Server.Maps; using Content.Server.NodeContainer.EntitySystems; using Content.Shared.Atmos.EntitySystems; +using Content.Shared.Maps; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Containers; diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs index df867d35163..17715435b2f 100644 --- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs @@ -12,7 +12,6 @@ using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Physics.Systems; @@ -60,12 +59,6 @@ private void OnGasShutdown(Entity gasTank, ref ComponentShutdo private void OnGasTankToggleInternals(Entity ent, ref GasTankToggleInternalsMessage args) { - if (args.Session is not IPlayerSession playerSession || - playerSession.AttachedEntity == null) - { - return; - } - ToggleInternals(ent); } diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs index c229ef50c9a..b0e8cf71c79 100644 --- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -16,6 +16,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Threading; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -35,7 +36,7 @@ public sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem [Robust.Shared.IoC.Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Robust.Shared.IoC.Dependency] private readonly ChunkingSystem _chunkingSys = default!; - private readonly Dictionary>> _lastSentChunks = new(); + private readonly Dictionary>> _lastSentChunks = new(); // Oh look its more duplicated decal system code! private ObjectPool> _chunkIndexPool = @@ -286,12 +287,12 @@ public override void Update(float frameTime) // Now we'll go through each player, then through each chunk in range of that player checking if the player is still in range // If they are, check if they need the new data to send (i.e. if there's an overlay for the gas). // Afterwards we reset all the chunk data for the next time we tick. - var players = _playerManager.ServerSessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); + var players = _playerManager.Sessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount }; Parallel.ForEach(players, opts, p => UpdatePlayer(p, curTick)); } - private void UpdatePlayer(IPlayerSession playerSession, GameTick curTick) + private void UpdatePlayer(ICommonSession playerSession, GameTick curTick) { var chunksInRange = _chunkingSys.GetChunksForSession(playerSession, ChunkSize, _chunkIndexPool, _chunkViewerPool); var previouslySent = _lastSentChunks[playerSession]; diff --git a/Content.Server/Body/Commands/AddHandCommand.cs b/Content.Server/Body/Commands/AddHandCommand.cs index 308295c06cc..655d0c88f9b 100644 --- a/Content.Server/Body/Commands/AddHandCommand.cs +++ b/Content.Server/Body/Commands/AddHandCommand.cs @@ -4,7 +4,6 @@ using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -27,7 +26,7 @@ sealed class AddHandCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid entity; EntityUid hand; diff --git a/Content.Server/Body/Commands/AttachBodyPartCommand.cs b/Content.Server/Body/Commands/AttachBodyPartCommand.cs index 267b5208086..24604b88b7a 100644 --- a/Content.Server/Body/Commands/AttachBodyPartCommand.cs +++ b/Content.Server/Body/Commands/AttachBodyPartCommand.cs @@ -1,10 +1,8 @@ -using System.Linq; using Content.Server.Administration; using Content.Server.Body.Systems; using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Body.Commands @@ -20,7 +18,7 @@ public sealed class AttachBodyPartCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid bodyId; EntityUid? partUid; diff --git a/Content.Server/Body/Commands/DestroyMechanismCommand.cs b/Content.Server/Body/Commands/DestroyMechanismCommand.cs index 6ad0631150a..3aa28f40720 100644 --- a/Content.Server/Body/Commands/DestroyMechanismCommand.cs +++ b/Content.Server/Body/Commands/DestroyMechanismCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Body.Systems; using Content.Shared.Administration; using Content.Shared.Body.Components; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Random; @@ -17,7 +16,7 @@ sealed class DestroyMechanismCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Only a player can run this command."); diff --git a/Content.Server/Body/Commands/RemoveHandCommand.cs b/Content.Server/Body/Commands/RemoveHandCommand.cs index 729db4bc446..4a2956ae7ab 100644 --- a/Content.Server/Body/Commands/RemoveHandCommand.cs +++ b/Content.Server/Body/Commands/RemoveHandCommand.cs @@ -4,7 +4,6 @@ using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Random; @@ -22,7 +21,7 @@ public sealed class RemoveHandCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Only a player can run this command."); diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index f2f848c488d..242b02d78c1 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -116,7 +116,7 @@ public override HashSet GibBody(EntityUid bodyId, bool gibOrgans = fa if (!Resolve(bodyId, ref body, false)) return new HashSet(); - if (LifeStage(bodyId) >= EntityLifeStage.Terminating || EntityManager.IsQueuedForDeletion(bodyId)) + if (TerminatingOrDeleted(bodyId) || EntityManager.IsQueuedForDeletion(bodyId)) return new HashSet(); var xform = Transform(bodyId); diff --git a/Content.Server/Body/Systems/InternalsSystem.cs b/Content.Server/Body/Systems/InternalsSystem.cs index ec4faa345cd..17a6544976b 100644 --- a/Content.Server/Body/Systems/InternalsSystem.cs +++ b/Content.Server/Body/Systems/InternalsSystem.cs @@ -197,6 +197,14 @@ public bool TryConnectTank(Entity ent, EntityUid tankEntity) return true; } + public bool AreInternalsWorking(EntityUid uid, InternalsComponent? component = null) + { + if (!Resolve(uid, ref component, false)) + return false; + + return AreInternalsWorking(component); + } + public bool AreInternalsWorking(InternalsComponent component) { return TryComp(component.BreathToolEntity, out BreathToolComponent? breathTool) && diff --git a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs index d9327b51505..f659357ad38 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs @@ -8,7 +8,7 @@ using Content.Shared.Cargo.Prototypes; using Content.Shared.Database; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; diff --git a/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs b/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs index 9f7acce4fd2..02b2eee7712 100644 --- a/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs +++ b/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs @@ -6,9 +6,9 @@ using Content.Shared.Interaction; using Robust.Server.Containers; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Containers; using Robust.Shared.Map; +using Robust.Shared.Player; namespace Content.Server.CartridgeLoader; @@ -98,7 +98,7 @@ public bool HasProgram( /// and use this method to update its state so the cartridge loaders state can be added to it. /// /// - public void UpdateUiState(EntityUid loaderUid, IPlayerSession? session, CartridgeLoaderComponent? loader) + public void UpdateUiState(EntityUid loaderUid, ICommonSession? session, CartridgeLoaderComponent? loader) { if (!Resolve(loaderUid, ref loader)) return; @@ -122,7 +122,7 @@ public void UpdateUiState(EntityUid loaderUid, IPlayerSession? session, Cartridg /// This method is called "UpdateCartridgeUiState" but cartridges and a programs are the same. A cartridge is just a program as a visible item. /// /// - public void UpdateCartridgeUiState(EntityUid loaderUid, BoundUserInterfaceState state, IPlayerSession? session = default!, CartridgeLoaderComponent? loader = default!) + public void UpdateCartridgeUiState(EntityUid loaderUid, BoundUserInterfaceState state, ICommonSession? session = default!, CartridgeLoaderComponent? loader = default!) { if (!Resolve(loaderUid, ref loader)) return; diff --git a/Content.Server/Chat/Commands/AdminChatCommand.cs b/Content.Server/Chat/Commands/AdminChatCommand.cs index 8aa95ffee18..979051e9d3e 100644 --- a/Content.Server/Chat/Commands/AdminChatCommand.cs +++ b/Content.Server/Chat/Commands/AdminChatCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Server.Chat.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Chat.Commands @@ -15,7 +14,7 @@ internal sealed class AdminChatCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = (IPlayerSession?) shell.Player; + var player = shell.Player; if (player == null) { diff --git a/Content.Server/Chat/Commands/LOOCCommand.cs b/Content.Server/Chat/Commands/LOOCCommand.cs index a897a0b2bfb..9e16193fc38 100644 --- a/Content.Server/Chat/Commands/LOOCCommand.cs +++ b/Content.Server/Chat/Commands/LOOCCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ internal sealed class LOOCCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/MeCommand.cs b/Content.Server/Chat/Commands/MeCommand.cs index 36f86cf4d6b..e763d5656e1 100644 --- a/Content.Server/Chat/Commands/MeCommand.cs +++ b/Content.Server/Chat/Commands/MeCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ internal sealed class MeCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/OOCCommand.cs b/Content.Server/Chat/Commands/OOCCommand.cs index bef2024608d..36f6303fbd1 100644 --- a/Content.Server/Chat/Commands/OOCCommand.cs +++ b/Content.Server/Chat/Commands/OOCCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Chat.Commands @@ -14,7 +13,7 @@ internal sealed class OOCCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/SayCommand.cs b/Content.Server/Chat/Commands/SayCommand.cs index 7c2125d8c1c..273f908c9ab 100644 --- a/Content.Server/Chat/Commands/SayCommand.cs +++ b/Content.Server/Chat/Commands/SayCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ internal sealed class SayCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/SuicideCommand.cs b/Content.Server/Chat/Commands/SuicideCommand.cs index 389ff039bf0..c967ba78d7f 100644 --- a/Content.Server/Chat/Commands/SuicideCommand.cs +++ b/Content.Server/Chat/Commands/SuicideCommand.cs @@ -1,7 +1,6 @@ using Content.Server.GameTicking; using Content.Shared.Administration; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -18,7 +17,7 @@ internal sealed class SuicideCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteLine(Loc.GetString("shell-cannot-run-command-from-server")); return; diff --git a/Content.Server/Chat/Commands/WhisperCommand.cs b/Content.Server/Chat/Commands/WhisperCommand.cs index 41eba8b3842..c88e2519ee6 100644 --- a/Content.Server/Chat/Commands/WhisperCommand.cs +++ b/Content.Server/Chat/Commands/WhisperCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ internal sealed class WhisperCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index ea7dcd52920..c9e66ff124a 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -11,11 +11,9 @@ using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Replays; using Robust.Shared.Utility; @@ -53,8 +51,8 @@ internal sealed class ChatManager : IChatManager private bool _oocEnabled = true; private bool _adminOocEnabled = true; - public Dictionary SenderKeys { get; } = new(); - public Dictionary> SenderEntities { get; } = new(); + public Dictionary SenderKeys { get; } = new(); + public Dictionary> SenderEntities { get; } = new(); public void Initialize() { @@ -82,7 +80,7 @@ private void OnAdminOocEnabledChanged(bool val) DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message")); } - public void DeleteMessagesBy(IPlayerSession player) + public void DeleteMessagesBy(ICommonSession player) { var key = SenderKeys.GetValueOrDefault(player); var entities = SenderEntities.GetValueOrDefault(player) ?? new HashSet(); @@ -168,7 +166,7 @@ public void SendHookOOC(string sender, string message) /// The player sending the message. /// The message. /// The type of message. - public void TrySendOOCMessage(IPlayerSession player, string message, OOCChatType type) + public void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type) { // Check if message exceeds the character limit if (message.Length > MaxMessageLength) @@ -192,7 +190,7 @@ public void TrySendOOCMessage(IPlayerSession player, string message, OOCChatType #region Private API - private void SendOOC(IPlayerSession player, string message) + private void SendOOC(ICommonSession player, string message) { if (_adminManager.IsAdmin(player)) { @@ -236,7 +234,7 @@ private void SendOOC(IPlayerSession player, string message) _adminLogger.Add(LogType.Chat, LogImpact.Low, $"OOC from {player:Player}: {message}"); } - private void SendAdminChat(IPlayerSession player, string message) + private void SendAdminChat(ICommonSession player, string message) { if (!_adminManager.IsAdmin(player)) { @@ -336,7 +334,7 @@ public void ChatMessageToAll(ChatChannel channel, string message, string wrapped } } - public bool MessageCharacterLimit(IPlayerSession? player, string message) + public bool MessageCharacterLimit(ICommonSession? player, string message) { var isOverLength = false; diff --git a/Content.Server/Chat/Managers/IChatManager.cs b/Content.Server/Chat/Managers/IChatManager.cs index 10103f011df..5317b3054e4 100644 --- a/Content.Server/Chat/Managers/IChatManager.cs +++ b/Content.Server/Chat/Managers/IChatManager.cs @@ -1,8 +1,6 @@ using Content.Shared.Chat; -using Robust.Server.Player; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; namespace Content.Server.Chat.Managers { @@ -12,12 +10,12 @@ public interface IChatManager /// Keys identifying messages sent by a specific player, used when sending /// /// - Dictionary SenderKeys { get; } + Dictionary SenderKeys { get; } /// /// Tracks which entities a player was attached to while sending messages. /// - Dictionary> SenderEntities { get; } + Dictionary> SenderEntities { get; } void Initialize(); @@ -30,7 +28,7 @@ public interface IChatManager void DispatchServerMessage(ICommonSession player, string message, bool suppressLog = false); - void TrySendOOCMessage(IPlayerSession player, string message, OOCChatType type); + void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type); void SendHookOOC(string sender, string message); void SendAdminAnnouncement(string message); @@ -47,8 +45,8 @@ void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessag void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, int? senderKey = null); - bool MessageCharacterLimit(IPlayerSession player, string message); + bool MessageCharacterLimit(ICommonSession player, string message); - void DeleteMessagesBy(IPlayerSession player); + void DeleteMessagesBy(ICommonSession player); } } diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 1615de69e88..c4aafa10cc2 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -7,7 +7,6 @@ using Content.Server.Administration.Managers; using Content.Server.Chat.Managers; using Content.Server.GameTicking; -using Content.Server.Players; using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Shared.ActionBlocker; @@ -19,6 +18,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Mobs.Systems; +using Content.Shared.Players; using Content.Shared.Radio; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -27,7 +27,6 @@ using Robust.Shared.Console; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Replays; @@ -149,7 +148,7 @@ public void TrySendInGameICMessage( InGameICChatType desiredType, bool hideChat, bool hideLog = false, IConsoleShell? shell = null, - IPlayerSession? player = null, string? nameOverride = null, + ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, bool ignoreActionBlocker = false) { @@ -174,7 +173,7 @@ public void TrySendInGameICMessage( ChatTransmitRange range, bool hideLog = false, IConsoleShell? shell = null, - IPlayerSession? player = null, + ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, bool ignoreActionBlocker = false @@ -255,7 +254,7 @@ public void TrySendInGameOOCMessage( InGameOOCChatType type, bool hideChat, IConsoleShell? shell = null, - IPlayerSession? player = null + ICommonSession? player = null ) { if (!CanSendInGame(message, shell, player)) @@ -557,7 +556,7 @@ private void SendEntityEmote( } // ReSharper disable once InconsistentNaming - private void SendLOOC(EntityUid source, IPlayerSession player, string message, bool hideChat) + private void SendLOOC(EntityUid source, ICommonSession player, string message, bool hideChat) { var name = FormattedMessage.EscapeText(Identity.Name(source, EntityManager)); @@ -581,7 +580,7 @@ private void SendLOOC(EntityUid source, IPlayerSession player, string message, b _adminLogger.Add(LogType.Chat, LogImpact.Low, $"LOOC from {player:Player}: {message}"); } - private void SendDeadChat(EntityUid source, IPlayerSession player, string message, bool hideChat) + private void SendDeadChat(EntityUid source, ICommonSession player, string message, bool hideChat) { var clients = GetDeadChatClients(); var playerName = Name(source); @@ -638,13 +637,13 @@ private MessageRangeCheckResult MessageRangeCheck(ICommonSession session, ICChat initialResult = MessageRangeCheckResult.Full; break; case ChatTransmitRange.GhostRangeLimit: - initialResult = (data.Observer && data.Range < 0 && !_adminManager.IsAdmin((IPlayerSession) session)) ? MessageRangeCheckResult.HideChat : MessageRangeCheckResult.Full; + initialResult = (data.Observer && data.Range < 0 && !_adminManager.IsAdmin(session)) ? MessageRangeCheckResult.HideChat : MessageRangeCheckResult.Full; break; case ChatTransmitRange.HideChat: initialResult = MessageRangeCheckResult.HideChat; break; case ChatTransmitRange.NoGhosts: - initialResult = (data.Observer && !_adminManager.IsAdmin((IPlayerSession) session)) ? MessageRangeCheckResult.Disallowed : MessageRangeCheckResult.Full; + initialResult = (data.Observer && !_adminManager.IsAdmin(session)) ? MessageRangeCheckResult.Disallowed : MessageRangeCheckResult.Full; break; } var insistHideChat = data.HideChatOverride ?? false; @@ -676,7 +675,7 @@ private void SendInVoiceRange(ChatChannel channel, string message, string wrappe /// /// Returns true if the given player is 'allowed' to send the given message, false otherwise. /// - private bool CanSendInGame(string message, IConsoleShell? shell = null, IPlayerSession? player = null) + private bool CanSendInGame(string message, IConsoleShell? shell = null, ICommonSession? player = null) { // Non-players don't have to worry about these restrictions. if (player == null) diff --git a/Content.Server/Chemistry/Components/SmokeComponent.cs b/Content.Server/Chemistry/Components/SmokeComponent.cs deleted file mode 100644 index 133ad41f139..00000000000 --- a/Content.Server/Chemistry/Components/SmokeComponent.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Shared.Fluids.Components; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; - -namespace Content.Server.Chemistry.Components; - -/// -/// Stores solution on an anchored entity that has touch and ingestion reactions -/// to entities that collide with it. Similar to -/// -[RegisterComponent] -public sealed partial class SmokeComponent : Component -{ - public const string SolutionName = "solutionArea"; - - [DataField("nextReact", customTypeSerializer:typeof(TimeOffsetSerializer))] - public TimeSpan NextReact = TimeSpan.Zero; - - [DataField("spreadAmount")] - public int SpreadAmount = 0; - - /// - /// Have we reacted with our tile yet? - /// - [DataField("reactedTile")] - public bool ReactedTile = false; -} diff --git a/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs index 8cbdd82f079..7485c0e9016 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs @@ -2,6 +2,7 @@ using Content.Shared.Chemistry.Reagent; using Robust.Server.Player; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Server.Chemistry.EntitySystems; diff --git a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs index e6eaab8a59b..291a654422e 100644 --- a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs @@ -1,4 +1,3 @@ -using Content.Server.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Shared.Audio; using Content.Shared.Chemistry.EntitySystems; @@ -10,7 +9,6 @@ using JetBrains.Annotations; using Robust.Shared.Audio; using Robust.Shared.Map; -using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -71,18 +69,10 @@ public override void Effect(ReagentEffectArgs args) var coords = grid.MapToGrid(transform.MapPosition); var ent = args.EntityManager.SpawnEntity(_prototypeId, coords.SnapToGrid()); - if (!args.EntityManager.TryGetComponent(ent, out var smokeComponent)) - { - Logger.Error("Couldn't get AreaEffectComponent from " + _prototypeId); - args.EntityManager.QueueDeleteEntity(ent); - return; - } - var smoke = args.EntityManager.System(); - smokeComponent.SpreadAmount = spreadAmount; - smoke.Start(ent, smokeComponent, splitSolution, _duration); + smoke.StartSmoke(ent, splitSolution, _duration, spreadAmount); - SoundSystem.Play(_sound.GetSound(), Filter.Pvs(args.SolutionEntity), args.SolutionEntity, AudioHelpers.WithVariation(0.125f)); + args.EntityManager.System().PlayPvs(_sound, args.SolutionEntity, AudioHelpers.WithVariation(0.125f)); } } } diff --git a/Content.Server/Chunking/ChunkingSystem.cs b/Content.Server/Chunking/ChunkingSystem.cs index 4ef44d1678d..6f44c43be85 100644 --- a/Content.Server/Chunking/ChunkingSystem.cs +++ b/Content.Server/Chunking/ChunkingSystem.cs @@ -1,12 +1,12 @@ using System.Linq; using Content.Shared.Decals; using Microsoft.Extensions.ObjectPool; -using Robust.Server.Player; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Shared.Chunking; @@ -41,7 +41,7 @@ public override void Shutdown() private void OnPvsRangeChanged(float value) => _baseViewBounds = Box2.UnitCentered.Scale(value); public Dictionary> GetChunksForSession( - IPlayerSession session, + ICommonSession session, int chunkSize, ObjectPool> indexPool, ObjectPool>> viewerPool, @@ -52,7 +52,7 @@ public Dictionary> GetChunksForSession( return chunks; } - private HashSet GetSessionViewers(IPlayerSession session) + private HashSet GetSessionViewers(ICommonSession session) { var viewers = new HashSet(); if (session.Status != SessionStatus.InGame || session.AttachedEntity is null) diff --git a/Content.Server/Commands/CommandUtils.cs b/Content.Server/Commands/CommandUtils.cs index 11adaec9a2f..172f3324e35 100644 --- a/Content.Server/Commands/CommandUtils.cs +++ b/Content.Server/Commands/CommandUtils.cs @@ -3,6 +3,7 @@ using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Commands { @@ -16,7 +17,7 @@ public static class CommandUtils /// sending a failure to the performer if unable to. /// public static bool TryGetSessionByUsernameOrId(IConsoleShell shell, - string usernameOrId, IPlayerSession performer, [NotNullWhen(true)] out IPlayerSession? session) + string usernameOrId, ICommonSession performer, [NotNullWhen(true)] out ICommonSession? session) { var plyMgr = IoCManager.Resolve(); if (plyMgr.TryGetSessionByUsername(usernameOrId, out session)) return true; @@ -36,7 +37,7 @@ public static bool TryGetSessionByUsernameOrId(IConsoleShell shell, /// sending a failure to the performer if unable to. /// public static bool TryGetAttachedEntityByUsernameOrId(IConsoleShell shell, - string usernameOrId, IPlayerSession performer, out EntityUid attachedEntity) + string usernameOrId, ICommonSession performer, out EntityUid attachedEntity) { attachedEntity = default; if (!TryGetSessionByUsernameOrId(shell, usernameOrId, performer, out var session)) return false; @@ -67,7 +68,7 @@ public static string SubstituteEntityDetails(IConsoleShell shell, EntityUid ent, transform.LocalPosition.Y.ToString(CultureInfo.InvariantCulture)); ruleString = ruleString.Replace("$NAME", entMan.GetComponent(ent).EntityName); - if (shell.Player is IPlayerSession player) + if (shell.Player is { } player) { if (player.AttachedEntity is {Valid: true} p) { diff --git a/Content.Server/Construction/Commands/FixRotationsCommand.cs b/Content.Server/Construction/Commands/FixRotationsCommand.cs index d23fa0a31b1..bdbfaf170d4 100644 --- a/Content.Server/Construction/Commands/FixRotationsCommand.cs +++ b/Content.Server/Construction/Commands/FixRotationsCommand.cs @@ -3,7 +3,6 @@ using Content.Shared.Administration; using Content.Shared.Construction; using Content.Shared.Tag; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map.Components; @@ -21,7 +20,7 @@ public sealed class FixRotationsCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argsOther, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; var xformQuery = _entManager.GetEntityQuery(); diff --git a/Content.Server/Construction/Commands/TileReplaceCommand.cs b/Content.Server/Construction/Commands/TileReplaceCommand.cs index ed1fba2424a..f63fd4c13e0 100644 --- a/Content.Server/Construction/Commands/TileReplaceCommand.cs +++ b/Content.Server/Construction/Commands/TileReplaceCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Administration; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -20,7 +19,7 @@ sealed class TileReplaceCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; string tileIdA; string tileIdB; diff --git a/Content.Server/Construction/Commands/TileWallsCommand.cs b/Content.Server/Construction/Commands/TileWallsCommand.cs index 55389e41cc7..731d4da7f84 100644 --- a/Content.Server/Construction/Commands/TileWallsCommand.cs +++ b/Content.Server/Construction/Commands/TileWallsCommand.cs @@ -2,10 +2,9 @@ using Content.Shared.Administration; using Content.Shared.Maps; using Content.Shared.Tag; -using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; +using Robust.Server.GameObjects; using Robust.Shared.Map.Components; namespace Content.Server.Construction.Commands @@ -29,7 +28,7 @@ sealed class TileWallsCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; switch (args.Length) diff --git a/Content.Server/Construction/ConstructionSystem.Initial.cs b/Content.Server/Construction/ConstructionSystem.Initial.cs index e74edb5da24..21978f2d0cb 100644 --- a/Content.Server/Construction/ConstructionSystem.Initial.cs +++ b/Content.Server/Construction/ConstructionSystem.Initial.cs @@ -16,7 +16,7 @@ using Content.Shared.Inventory; using Content.Shared.Storage; using Robust.Shared.Containers; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Construction diff --git a/Content.Server/Construction/ConstructionSystem.cs b/Content.Server/Construction/ConstructionSystem.cs index 76d37432cb5..6e40b7b856c 100644 --- a/Content.Server/Construction/ConstructionSystem.cs +++ b/Content.Server/Construction/ConstructionSystem.cs @@ -7,6 +7,7 @@ using Robust.Server.Containers; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Construction { diff --git a/Content.Server/Construction/RefiningSystem.cs b/Content.Server/Construction/RefiningSystem.cs index 40f69c51f81..b9d80c7170a 100644 --- a/Content.Server/Construction/RefiningSystem.cs +++ b/Content.Server/Construction/RefiningSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Stacks; using Content.Shared.Tools; using Robust.Shared.Serialization; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Construction { diff --git a/Content.Server/Corvax/Objectives/Components/HijackShuttleConditionComponent.cs b/Content.Server/Corvax/Objectives/Components/HijackShuttleConditionComponent.cs deleted file mode 100644 index 31c7ce84442..00000000000 --- a/Content.Server/Corvax/Objectives/Components/HijackShuttleConditionComponent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Content.Server.Corvax.Objectives.Systems; - -namespace Content.Server.Corvax.Objectives.Components; - -[RegisterComponent, Access(typeof(HijackShuttleConditionSystem))] -public sealed partial class HijackShuttleConditionComponent : Component -{ -} diff --git a/Content.Server/CrewManifest/CrewManifestSystem.cs b/Content.Server/CrewManifest/CrewManifestSystem.cs index aed0575324f..4c4f17f61d4 100644 --- a/Content.Server/CrewManifest/CrewManifestSystem.cs +++ b/Content.Server/CrewManifest/CrewManifestSystem.cs @@ -10,10 +10,9 @@ using Content.Shared.CrewManifest; using Content.Shared.GameTicking; using Content.Shared.StationRecords; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.CrewManifest; @@ -60,7 +59,7 @@ private void OnRoundRestart(RoundRestartCleanupEvent ev) private void OnRequestCrewManifest(RequestCrewManifestMessage message, EntitySessionEventArgs args) { - if (args.SenderSession is not IPlayerSession sessionCast + if (args.SenderSession is not { } sessionCast || !_configManager.GetCVar(CCVars.CrewManifestWithoutEntity)) { return; @@ -93,12 +92,12 @@ private void OnRecordRemoved(RecordRemovedEvent ev) private void OnBoundUiClose(EntityUid uid, CrewManifestViewerComponent component, BoundUIClosedEvent ev) { var owningStation = _stationSystem.GetOwningStation(uid); - if (owningStation == null || ev.Session is not IPlayerSession sessionCast) + if (owningStation == null || ev.Session is not { } session) { return; } - CloseEui(owningStation.Value, sessionCast, uid); + CloseEui(owningStation.Value, session, uid); } /// @@ -126,7 +125,7 @@ private void UpdateEuis(EntityUid station) private void OpenEuiFromBui(EntityUid uid, CrewManifestViewerComponent component, CrewManifestOpenUiMessage msg) { var owningStation = _stationSystem.GetOwningStation(uid); - if (owningStation == null || msg.Session is not IPlayerSession sessionCast) + if (owningStation == null || msg.Session is not { } session) { return; } @@ -136,7 +135,7 @@ private void OpenEuiFromBui(EntityUid uid, CrewManifestViewerComponent component return; } - OpenEui(owningStation.Value, sessionCast, uid); + OpenEui(owningStation.Value, session, uid); } /// @@ -145,7 +144,7 @@ private void OpenEuiFromBui(EntityUid uid, CrewManifestViewerComponent component /// Station that we're displaying the crew manifest for. /// The player's session. /// If this EUI should be 'owned' by an entity. - public void OpenEui(EntityUid station, IPlayerSession session, EntityUid? owner = null) + public void OpenEui(EntityUid station, ICommonSession session, EntityUid? owner = null) { if (!HasComp(station)) { @@ -252,7 +251,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (shell.Player == null || shell.Player is not IPlayerSession session) + if (shell.Player == null || shell.Player is not { } session) { shell.WriteLine("You must run this from a client."); return; diff --git a/Content.Server/Damage/Commands/GodModeCommand.cs b/Content.Server/Damage/Commands/GodModeCommand.cs index 92a0e53f0f0..866737f17a9 100644 --- a/Content.Server/Damage/Commands/GodModeCommand.cs +++ b/Content.Server/Damage/Commands/GodModeCommand.cs @@ -1,8 +1,6 @@ using Content.Server.Administration; -using Content.Server.Damage.Systems; using Content.Shared.Administration; using Content.Shared.Damage.Systems; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Damage.Commands @@ -18,7 +16,7 @@ public sealed class GodModeCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid entity; switch (args.Length) diff --git a/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs b/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs index 3d3346403ad..457fab4bb28 100644 --- a/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs +++ b/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs @@ -6,7 +6,6 @@ using Content.Shared.Stunnable; using Robust.Server.GameObjects; using Robust.Server.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index 116bb4ccf98..2c3373ea231 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -685,6 +685,7 @@ public virtual async Task AddNewRound(Server server, params Guid[] playerId var round = new Round { + StartDate = DateTime.UtcNow, Players = players, ServerId = server.Id }; diff --git a/Content.Server/Database/UserDbDataManager.cs b/Content.Server/Database/UserDbDataManager.cs index f2c506240bf..f8b1611fd57 100644 --- a/Content.Server/Database/UserDbDataManager.cs +++ b/Content.Server/Database/UserDbDataManager.cs @@ -2,8 +2,8 @@ using System.Threading.Tasks; using Content.Server.Players.PlayTimeTracking; using Content.Server.Preferences.Managers; -using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Database; @@ -25,7 +25,7 @@ public sealed class UserDbDataManager // TODO: Ideally connected/disconnected would be subscribed to IPlayerManager directly, // but this runs into ordering issues with game ticker. - public void ClientConnected(IPlayerSession session) + public void ClientConnected(ICommonSession session) { DebugTools.Assert(!_users.ContainsKey(session.UserId), "We should not have any cached data on client connect."); @@ -36,7 +36,7 @@ public void ClientConnected(IPlayerSession session) _users.Add(session.UserId, data); } - public void ClientDisconnected(IPlayerSession session) + public void ClientDisconnected(ICommonSession session) { _users.Remove(session.UserId, out var data); if (data == null) @@ -49,24 +49,24 @@ public void ClientDisconnected(IPlayerSession session) _playTimeTracking.ClientDisconnected(session); } - private async Task Load(IPlayerSession session, CancellationToken cancel) + private async Task Load(ICommonSession session, CancellationToken cancel) { await Task.WhenAll( _prefs.LoadData(session, cancel), _playTimeTracking.LoadData(session, cancel)); } - public Task WaitLoadComplete(IPlayerSession session) + public Task WaitLoadComplete(ICommonSession session) { return _users[session.UserId].Task; } - public bool IsLoadComplete(IPlayerSession session) + public bool IsLoadComplete(ICommonSession session) { return GetLoadTask(session).IsCompleted; } - public Task GetLoadTask(IPlayerSession session) + public Task GetLoadTask(ICommonSession session) { return _users[session.UserId].Task; } diff --git a/Content.Server/Decals/DecalSystem.cs b/Content.Server/Decals/DecalSystem.cs index d5a5bf9affa..ce2e0711e74 100644 --- a/Content.Server/Decals/DecalSystem.cs +++ b/Content.Server/Decals/DecalSystem.cs @@ -16,6 +16,7 @@ using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Threading; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -36,7 +37,7 @@ public sealed class DecalSystem : SharedDecalSystem [Dependency] private readonly MapSystem _mapSystem = default!; private readonly Dictionary> _dirtyChunks = new(); - private readonly Dictionary>> _previousSentChunks = new(); + private readonly Dictionary>> _previousSentChunks = new(); private static readonly Vector2 _boundsMinExpansion = new(0.01f, 0.01f); private static readonly Vector2 _boundsMaxExpansion = new(1.01f, 1.01f); @@ -197,7 +198,7 @@ private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) private void OnDecalPlacementRequest(RequestDecalPlacementEvent ev, EntitySessionEventArgs eventArgs) { - if (eventArgs.SenderSession is not IPlayerSession session) + if (eventArgs.SenderSession is not { } session) return; // bad @@ -226,7 +227,7 @@ private void OnDecalPlacementRequest(RequestDecalPlacementEvent ev, EntitySessio private void OnDecalRemovalRequest(RequestDecalRemovalEvent ev, EntitySessionEventArgs eventArgs) { - if (eventArgs.SenderSession is not IPlayerSession session) + if (eventArgs.SenderSession is not { } session) return; // bad @@ -305,10 +306,10 @@ public bool TryAddDecal(Decal decal, EntityCoordinates coordinates, out uint dec return true; } - public bool RemoveDecal(EntityUid gridId, uint decalId, DecalGridComponent? component = null) + public override bool RemoveDecal(EntityUid gridId, uint decalId, DecalGridComponent? component = null) => RemoveDecalInternal(gridId, decalId, out _, component); - public HashSet<(uint Index, Decal Decal)> GetDecalsInRange(EntityUid gridId, Vector2 position, float distance = 0.75f, Func? validDelegate = null) + public override HashSet<(uint Index, Decal Decal)> GetDecalsInRange(EntityUid gridId, Vector2 position, float distance = 0.75f, Func? validDelegate = null) { var decalIds = new HashSet<(uint, Decal)>(); var chunkCollection = ChunkCollection(gridId); @@ -427,7 +428,7 @@ public override void Update(float frameTime) if (PvsEnabled) { - var players = _playerManager.ServerSessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); + var players = _playerManager.Sessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount }; Parallel.ForEach(players, opts, UpdatePlayer); } @@ -435,7 +436,7 @@ public override void Update(float frameTime) _dirtyChunks.Clear(); } - public void UpdatePlayer(IPlayerSession player) + public void UpdatePlayer(ICommonSession player) { var chunksInRange = _chunking.GetChunksForSession(player, ChunkSize, _chunkIndexPool, _chunkViewerPool); var staleChunks = _chunkViewerPool.Get(); @@ -530,7 +531,7 @@ private void ReturnToPool(Dictionary> chunks) } private void SendChunkUpdates( - IPlayerSession session, + ICommonSession session, Dictionary> updatedChunks, Dictionary> staleChunks) { diff --git a/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs b/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs index 360f86eebe9..5641b0b4aee 100644 --- a/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs +++ b/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Interaction; using Content.Shared.Tools; using Content.Shared.Popups; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; using SignalReceivedEvent = Content.Server.DeviceLinking.Events.SignalReceivedEvent; namespace Content.Server.DeviceLinking.Systems; diff --git a/Content.Server/Disposal/TubeConnectionsCommand.cs b/Content.Server/Disposal/TubeConnectionsCommand.cs index 7895dcbca66..55e64659379 100644 --- a/Content.Server/Disposal/TubeConnectionsCommand.cs +++ b/Content.Server/Disposal/TubeConnectionsCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Disposal.Tube; using Content.Server.Disposal.Tube.Components; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Disposal @@ -18,7 +17,7 @@ public sealed class TubeConnectionsCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine(Loc.GetString("shell-only-players-can-run-this-command")); diff --git a/Content.Server/Doors/Systems/AirlockSystem.cs b/Content.Server/Doors/Systems/AirlockSystem.cs index 1321b609783..6274f953fdb 100644 --- a/Content.Server/Doors/Systems/AirlockSystem.cs +++ b/Content.Server/Doors/Systems/AirlockSystem.cs @@ -179,11 +179,16 @@ private void OnGetPryMod(EntityUid uid, AirlockComponent component, ref GetPryTi private void OnBeforePry(EntityUid uid, AirlockComponent component, ref BeforePryEvent args) { - if (this.IsPowered(uid, EntityManager) && !args.PryPowered) - { - Popup.PopupEntity(Loc.GetString("airlock-component-cannot-pry-is-powered-message"), uid, args.User); - args.Cancelled = true; - } + if (args.Cancelled) + return; + + if (!this.IsPowered(uid, EntityManager) || args.PryPowered) + return; + + args.Message = "airlock-component-cannot-pry-is-powered-message"; + + args.Cancelled = true; + } public bool CanChangeState(EntityUid uid, AirlockComponent component) diff --git a/Content.Server/EUI/BaseEui.cs b/Content.Server/EUI/BaseEui.cs index 4a41ad40a55..70cbfc37750 100644 --- a/Content.Server/EUI/BaseEui.cs +++ b/Content.Server/EUI/BaseEui.cs @@ -1,6 +1,6 @@ using Content.Shared.Eui; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.EUI { diff --git a/Content.Server/EUI/EuiManager.cs b/Content.Server/EUI/EuiManager.cs index 4d997195252..fe8e486b680 100644 --- a/Content.Server/EUI/EuiManager.cs +++ b/Content.Server/EUI/EuiManager.cs @@ -2,7 +2,7 @@ using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.EUI diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 6c962667404..8ddc8540c04 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -192,18 +192,13 @@ private void OnElectrifiedHandInteract(EntityUid uid, ElectrifiedComponent elect private void OnLightAttacked(EntityUid uid, PoweredLightComponent component, AttackedEvent args) { - - if (!_meleeWeapon.GetDamage(args.Used, args.User).Any()) - return; - - if (args.Used != args.User) + if (!component.CurrentLit || args.Used != args.User) return; - if (component.CurrentLit == false) + if (!_meleeWeapon.GetDamage(args.Used, args.User).Any()) return; DoCommonElectrocution(args.User, uid, component.UnarmedHitShock, component.UnarmedHitStun, false, 1); - } private void OnElectrifiedInteractUsing(EntityUid uid, ElectrifiedComponent electrified, InteractUsingEvent args) @@ -498,7 +493,7 @@ private void OnRandomInsulationMapInit(EntityUid uid, RandomInsulationComponent private void PlayElectrocutionSound(EntityUid targetUid, EntityUid sourceUid, ElectrifiedComponent? electrified = null) { - if (!Resolve(sourceUid, ref electrified) || !electrified.PlaySoundOnShock) + if (!Resolve(sourceUid, ref electrified, false) || !electrified.PlaySoundOnShock) { return; } diff --git a/Content.Server/EntityList/SpawnEntityListCommand.cs b/Content.Server/EntityList/SpawnEntityListCommand.cs index 0891bbd12ac..027d25dc2c2 100644 --- a/Content.Server/EntityList/SpawnEntityListCommand.cs +++ b/Content.Server/EntityList/SpawnEntityListCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Shared.Administration; using Content.Shared.EntityList; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -22,7 +21,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("You must be a player to run this command."); return; diff --git a/Content.Server/Examine/ExamineSystem.cs b/Content.Server/Examine/ExamineSystem.cs index 98aa806885d..3447810896f 100644 --- a/Content.Server/Examine/ExamineSystem.cs +++ b/Content.Server/Examine/ExamineSystem.cs @@ -4,7 +4,6 @@ using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Utility; namespace Content.Server.Examine @@ -46,7 +45,7 @@ public override void SendExamineTooltip(EntityUid player, EntityUid target, Form private void ExamineInfoRequest(ExamineSystemMessages.RequestExamineInfoMessage request, EntitySessionEventArgs eventArgs) { - var player = (IPlayerSession) eventArgs.SenderSession; + var player = eventArgs.SenderSession; var session = eventArgs.SenderSession; var channel = player.ConnectedClient; var entity = GetEntity(request.NetEntity); diff --git a/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs b/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs index 59f0a13695e..c17eea684db 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs @@ -1,9 +1,9 @@ using System.Numerics; using Content.Shared.Fluids; using Content.Shared.Fluids.Components; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Fluids.EntitySystems; @@ -14,10 +14,10 @@ public sealed class PuddleDebugDebugOverlaySystem : SharedPuddleDebugOverlaySyst [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly PuddleSystem _puddle = default!; - private readonly HashSet _playerObservers = new(); + private readonly HashSet _playerObservers = new(); private List> _grids = new(); - public bool ToggleObserver(IPlayerSession observer) + public bool ToggleObserver(ICommonSession observer) { NextTick ??= _timing.CurTime + Cooldown; @@ -31,7 +31,7 @@ public bool ToggleObserver(IPlayerSession observer) return true; } - private void RemoveObserver(IPlayerSession observer) + private void RemoveObserver(ICommonSession observer) { if (!_playerObservers.Remove(observer)) { diff --git a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs index f7732fec62f..5459dacf0b9 100644 --- a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs @@ -1,14 +1,23 @@ using System.Linq; -using Content.Server.Chemistry.Components; +using Content.Server.Administration.Logs; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; using Content.Server.Chemistry.ReactionEffects; using Content.Server.Spreader; +using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reaction; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Database; using Content.Shared.FixedPoint; using Content.Shared.Smoking; using Robust.Server.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -22,70 +31,140 @@ namespace Content.Server.Fluids.EntitySystems; public sealed class SmokeSystem : EntitySystem { // If I could do it all again this could probably use a lot more of puddles. + [Dependency] private readonly IAdminLogManager _logger = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly AppearanceSystem _appearance = default!; - [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly BloodstreamSystem _blood = default!; + [Dependency] private readonly InternalsSystem _internals = default!; + [Dependency] private readonly ReactiveSystem _reactive = default!; + [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; - [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly TransformSystem _transform = default!; + + private EntityQuery _smokeQuery; + private EntityQuery _smokeAffectedQuery; /// public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnSmokeUnpaused); + + _smokeQuery = GetEntityQuery(); + _smokeAffectedQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); SubscribeLocalEvent(OnReactionAttempt); SubscribeLocalEvent(OnSmokeSpread); + SubscribeLocalEvent(OnAffectedUnpaused); + } + + /// + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + var curTime = _timing.CurTime; + while (query.MoveNext(out var uid, out var smoke)) + { + if (curTime < smoke.NextSecond) + continue; + + smoke.NextSecond += TimeSpan.FromSeconds(1); + SmokeReact(uid, smoke.SmokeEntity); + } + } + + private void OnStartCollide(EntityUid uid, SmokeComponent component, ref StartCollideEvent args) + { + if (_smokeAffectedQuery.HasComponent(args.OtherEntity)) + return; + + var smokeAffected = AddComp(args.OtherEntity); + smokeAffected.SmokeEntity = uid; + smokeAffected.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1); + } + + private void OnEndCollide(EntityUid uid, SmokeComponent component, ref EndCollideEvent args) + { + // if we are already in smoke, make sure the thing we are exiting is the current smoke we are in. + if (_smokeAffectedQuery.TryGetComponent(args.OtherEntity, out var smokeAffectedComponent)) + { + if (smokeAffectedComponent.SmokeEntity != uid) + return; + } + + var exists = Exists(uid); + + if (!TryComp(args.OtherEntity, out var body)) + return; + + foreach (var ent in _physics.GetContactingEntities(args.OtherEntity, body)) + { + if (exists && ent == uid) + continue; + + if (!_smokeQuery.HasComponent(ent)) + continue; + + smokeAffectedComponent ??= EnsureComp(args.OtherEntity); + smokeAffectedComponent.SmokeEntity = ent; + return; // exit the function so we don't remove the component. + } + + if (smokeAffectedComponent != null) + RemComp(args.OtherEntity, smokeAffectedComponent); + } + + private void OnAffectedUnpaused(EntityUid uid, SmokeAffectedComponent component, ref EntityUnpausedEvent args) + { + component.NextSecond += args.PausedTime; } private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args) { - if (component.SpreadAmount == 0 - || !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) + if (component.SpreadAmount == 0 || !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) { RemCompDeferred(uid); return; } - var prototype = MetaData(uid).EntityPrototype; - - if (prototype == null) + if (Prototype(uid) is not { } prototype) { RemCompDeferred(uid); return; } + if (!args.NeighborFreeTiles.Any()) + return; + TryComp(uid, out var timer); - _appearance.TryGetData(uid, SmokeVisuals.Color, out var color); // wtf is the logic behind any of this. - var smokePerSpread = 1 + component.SpreadAmount / Math.Max(1, args.NeighborFreeTiles.Count); + var smokePerSpread = component.SpreadAmount / Math.Max(1, args.NeighborFreeTiles.Count); foreach (var neighbor in args.NeighborFreeTiles) { var coords = neighbor.Grid.GridTileToLocal(neighbor.Tile); var ent = Spawn(prototype.ID, coords); - var neighborSmoke = EnsureComp(ent); - neighborSmoke.SpreadAmount = Math.Max(0, smokePerSpread - 2); // why - 2? who the fuck knows. - component.SpreadAmount--; - args.Updates--; - - // Listen this is the old behaviour iunno - Start(ent, neighborSmoke, solution.Clone(), timer?.Lifetime ?? 10f); + var spreadAmount = Math.Max(0, smokePerSpread); + component.SpreadAmount -= args.NeighborFreeTiles.Count(); - if (color != null) - _appearance.SetData(ent, SmokeVisuals.Color, color); + StartSmoke(ent, solution.Clone(), timer?.Lifetime ?? component.Duration, spreadAmount); if (component.SpreadAmount == 0) { RemCompDeferred(uid); break; } - - if (args.Updates <= 0) - break; } + args.Updates--; + if (args.NeighborFreeTiles.Count > 0 || args.Neighbors.Count == 0 || component.SpreadAmount < 1) return; @@ -100,7 +179,6 @@ private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNe continue; smoke.SpreadAmount++; - args.Updates--; component.SpreadAmount--; EnsureComp(neighbor); @@ -110,6 +188,7 @@ private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNe break; } } + } private void OnReactionAttempt(EntityUid uid, SmokeComponent component, ReactionAttemptEvent args) @@ -128,101 +207,117 @@ private void OnReactionAttempt(EntityUid uid, SmokeComponent component, Reaction } } - private void OnSmokeUnpaused(EntityUid uid, SmokeComponent component, ref EntityUnpausedEvent args) + /// + /// Sets up a smoke component for spreading. + /// + public void StartSmoke(EntityUid uid, Solution solution, float duration, int spreadAmount, SmokeComponent? component = null) { - component.NextReact += args.PausedTime; - } + if (!Resolve(uid, ref component)) + return; - /// - public override void Update(float frameTime) - { - base.Update(frameTime); - var query = EntityQueryEnumerator(); - var curTime = _timing.CurTime; + component.SpreadAmount = spreadAmount; + component.Duration = duration; + component.TransferRate = solution.Volume / duration; + TryAddSolution(uid, solution); + Dirty(uid, component); + EnsureComp(uid); - while (query.MoveNext(out var uid, out var smoke)) + if (TryComp(uid, out var body) && TryComp(uid, out var fixtures)) { - if (smoke.NextReact > curTime) - continue; + var xform = Transform(uid); + _physics.SetBodyType(uid, BodyType.Dynamic, fixtures, body, xform); + _physics.SetCanCollide(uid, true, manager: fixtures, body: body); + _broadphase.RegenerateContacts(uid, body, fixtures, xform); + } - smoke.NextReact += TimeSpan.FromSeconds(1.5); + var timer = EnsureComp(uid); + timer.Lifetime = duration; - SmokeReact(uid, 1f, smoke); - } + // The tile reaction happens here because it only occurs once. + ReactOnTile(uid, component); } /// - /// Does the relevant smoke reactions for an entity for the specified exposure duration. + /// Does the relevant smoke reactions for an entity. /// - public void SmokeReact(EntityUid uid, float frameTime, SmokeComponent? component = null, TransformComponent? xform = null) + public void SmokeReact(EntityUid entity, EntityUid smokeUid, SmokeComponent? component = null) { - if (!Resolve(uid, ref component, ref xform)) + if (!Resolve(smokeUid, ref component)) return; - if (!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) || + if (!_solutionSystem.TryGetSolution(smokeUid, SmokeComponent.SolutionName, out var solution) || solution.Contents.Count == 0) { return; } - if (!_mapManager.TryGetGrid(xform.GridUid, out var mapGrid)) - return; + ReactWithEntity(entity, smokeUid, solution, component); + UpdateVisuals(smokeUid); + } - var tile = mapGrid.GetTileRef(xform.Coordinates.ToVector2i(EntityManager, _mapManager)); + private void ReactWithEntity(EntityUid entity, EntityUid smokeUid, Solution solution, SmokeComponent? component = null) + { + if (!Resolve(smokeUid, ref component)) + return; - var solutionFraction = 1 / Math.Floor(frameTime); - var ents = _lookup.GetEntitiesIntersecting(tile, 0f, flags: LookupFlags.Uncontained).ToArray(); + if (!TryComp(entity, out var bloodstream)) + return; - foreach (var reagentQuantity in solution.Contents.ToArray()) - { - if (reagentQuantity.Quantity == FixedPoint2.Zero) - continue; + var blockIngestion = _internals.AreInternalsWorking(entity); - // NOOP, react with entities on the tile or whatever. - } + var cloneSolution = solution.Clone(); + var availableTransfer = FixedPoint2.Min(cloneSolution.Volume, component.TransferRate); + var transferAmount = FixedPoint2.Min(availableTransfer, bloodstream.ChemicalSolution.AvailableVolume); + var transferSolution = cloneSolution.SplitSolution(transferAmount); - foreach (var entity in ents) + foreach (var reagentQuantity in transferSolution.Contents.ToArray()) { - if (entity == uid) + if (reagentQuantity.Quantity == FixedPoint2.Zero) continue; + var reagentProto = _prototype.Index(reagentQuantity.Reagent.Prototype); - ReactWithEntity(entity, solution, solutionFraction); + _reactive.ReactionEntity(entity, ReactionMethod.Touch, reagentProto, reagentQuantity, transferSolution); + if (!blockIngestion) + _reactive.ReactionEntity(entity, ReactionMethod.Ingestion, reagentProto, reagentQuantity, transferSolution); } - UpdateVisuals(uid); - } + if (blockIngestion) + return; - private void UpdateVisuals(EntityUid uid) - { - if (TryComp(uid, out AppearanceComponent? appearance) && - _solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) + if (_blood.TryAddToChemicals(entity, transferSolution, bloodstream)) { - var color = solution.GetColor(_prototype); - _appearance.SetData(uid, SmokeVisuals.Color, color, appearance); + // Log solution addition by smoke + _logger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(entity):target} ingested smoke {SolutionContainerSystem.ToPrettyString(transferSolution)}"); } } - private void ReactWithEntity(EntityUid entity, Solution solution, double solutionFraction) + private void ReactOnTile(EntityUid uid, SmokeComponent? component = null, TransformComponent? xform = null) { - // NOOP due to people complaining constantly. - return; - } + if (!Resolve(uid, ref component, ref xform)) + return; - /// - /// Sets up a smoke component for spreading. - /// - public void Start(EntityUid uid, SmokeComponent component, Solution solution, float duration) - { - TryAddSolution(uid, component, solution); - EnsureComp(uid); - var timer = EnsureComp(uid); - timer.Lifetime = duration; + if (!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) || !solution.Any()) + return; + + if (!_mapManager.TryGetGrid(xform.GridUid, out var mapGrid)) + return; + + var tile = mapGrid.GetTileRef(xform.Coordinates.ToVector2i(EntityManager, _mapManager, _transform)); + + foreach (var reagentQuantity in solution.Contents.ToArray()) + { + if (reagentQuantity.Quantity == FixedPoint2.Zero) + continue; + + var reagent = _prototype.Index(reagentQuantity.Reagent.Prototype); + reagent.ReactionTile(tile, reagentQuantity.Quantity); + } } /// /// Adds the specified solution to the relevant smoke solution. /// - public void TryAddSolution(EntityUid uid, SmokeComponent component, Solution solution) + private void TryAddSolution(EntityUid uid, Solution solution) { if (solution.Volume == FixedPoint2.Zero) return; @@ -237,4 +332,14 @@ public void TryAddSolution(EntityUid uid, SmokeComponent component, Solution sol UpdateVisuals(uid); } + + private void UpdateVisuals(EntityUid uid) + { + if (!TryComp(uid, out AppearanceComponent? appearance) || + !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) + return; + + var color = solution.GetColor(_prototype); + _appearance.SetData(uid, SmokeVisuals.Color, color, appearance); + } } diff --git a/Content.Server/Fluids/ShowFluidsCommand.cs b/Content.Server/Fluids/ShowFluidsCommand.cs index f122eadea79..71ac273a45b 100644 --- a/Content.Server/Fluids/ShowFluidsCommand.cs +++ b/Content.Server/Fluids/ShowFluidsCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Server.Fluids.EntitySystems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Fluids; @@ -15,7 +14,7 @@ public sealed class ShowFluidsCommand : IConsoleCommand public string Help => $"Usage: {Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You must be a player to use this command."); diff --git a/Content.Server/GameTicking/Commands/JoinGameCommand.cs b/Content.Server/GameTicking/Commands/JoinGameCommand.cs index 366e6c4e772..3276b912003 100644 --- a/Content.Server/GameTicking/Commands/JoinGameCommand.cs +++ b/Content.Server/GameTicking/Commands/JoinGameCommand.cs @@ -2,7 +2,6 @@ using Content.Shared.Administration; using Content.Shared.GameTicking; using Content.Shared.Roles; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -30,7 +29,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { diff --git a/Content.Server/GameTicking/Commands/ObserveCommand.cs b/Content.Server/GameTicking/Commands/ObserveCommand.cs index d608dda9c17..747e54e28be 100644 --- a/Content.Server/GameTicking/Commands/ObserveCommand.cs +++ b/Content.Server/GameTicking/Commands/ObserveCommand.cs @@ -1,6 +1,5 @@ using Content.Shared.Administration; using Content.Shared.GameTicking; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.GameTicking.Commands @@ -14,7 +13,7 @@ sealed class ObserveCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { return; } diff --git a/Content.Server/GameTicking/Commands/RespawnCommand.cs b/Content.Server/GameTicking/Commands/RespawnCommand.cs index 057572297f9..4f101d0939a 100644 --- a/Content.Server/GameTicking/Commands/RespawnCommand.cs +++ b/Content.Server/GameTicking/Commands/RespawnCommand.cs @@ -14,7 +14,7 @@ sealed class RespawnCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (args.Length > 1) { shell.WriteLine("Must provide <= 1 argument."); diff --git a/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs b/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs index e68c4c5fa7f..df418c27ee1 100644 --- a/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs +++ b/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs @@ -1,5 +1,4 @@ using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.GameTicking.Commands @@ -13,7 +12,7 @@ sealed class ToggleReadyCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (args.Length != 1) { shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs index a5e6d7a6056..2d7539bd0f1 100644 --- a/Content.Server/GameTicking/GameTicker.GamePreset.cs +++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs @@ -11,7 +11,7 @@ using Content.Shared.Mind; using Content.Shared.Mobs.Components; using JetBrains.Annotations; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.GameTicking { @@ -29,7 +29,7 @@ public sealed partial class GameTicker /// public GamePresetPrototype? CurrentPreset { get; private set; } - private bool StartPreset(IPlayerSession[] origReadyPlayers, bool force) + private bool StartPreset(ICommonSession[] origReadyPlayers, bool force) { var startAttempt = new RoundStartAttemptEvent(origReadyPlayers, force); RaiseLocalEvent(startAttempt); @@ -214,7 +214,7 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma { if (mind.Session != null) // Logging is suppressed to prevent spam from ghost attempts caused by movement attempts { - _chatManager.DispatchServerMessage((IPlayerSession) mind.Session, Loc.GetString("comp-mind-ghosting-prevented"), + _chatManager.DispatchServerMessage(mind.Session, Loc.GetString("comp-mind-ghosting-prevented"), true); } diff --git a/Content.Server/GameTicking/GameTicker.Lobby.cs b/Content.Server/GameTicking/GameTicker.Lobby.cs index b7b6a29a5a7..1943a82617a 100644 --- a/Content.Server/GameTicking/GameTicker.Lobby.cs +++ b/Content.Server/GameTicking/GameTicker.Lobby.cs @@ -1,10 +1,8 @@ using System.Linq; using Content.Shared.GameTicking; using Content.Server.Station.Components; -using Robust.Server.Player; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; using System.Text; namespace Content.Server.GameTicking @@ -79,7 +77,7 @@ private string GetInfoText() ("roundId", RoundId), ("playerCount", playerCount), ("readyCount", readyCount), ("mapName", stationNames.ToString()),("gmTitle", gmTitle),("desc", desc)); } - private TickerLobbyStatusEvent GetStatusMsg(IPlayerSession session) + private TickerLobbyStatusEvent GetStatusMsg(ICommonSession session) { _playerGameStatuses.TryGetValue(session.UserId, out var status); return new TickerLobbyStatusEvent(RunLevel != GameRunLevel.PreRoundLobby, LobbySong, LobbyBackground,status == PlayerGameStatus.ReadyToPlay, _roundStartTime, RoundPreloadTime, _roundStartTimeSpan, Paused); @@ -87,7 +85,7 @@ private TickerLobbyStatusEvent GetStatusMsg(IPlayerSession session) private void SendStatusToAll() { - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { RaiseNetworkEvent(GetStatusMsg(player), player.ConnectedClient); } @@ -148,7 +146,7 @@ public void ToggleReadyAll(bool ready) } } - public void ToggleReady(IPlayerSession player, bool ready) + public void ToggleReady(ICommonSession player, bool ready) { if (!_playerGameStatuses.ContainsKey(player.UserId)) return; diff --git a/Content.Server/GameTicking/GameTicker.Player.cs b/Content.Server/GameTicking/GameTicker.Player.cs index aa1c13e98e5..07f74df2543 100644 --- a/Content.Server/GameTicking/GameTicker.Player.cs +++ b/Content.Server/GameTicking/GameTicker.Player.cs @@ -1,13 +1,14 @@ using Content.Corvax.Interfaces.Server; using Content.Server.Database; -using Content.Server.Players; using Content.Shared.GameTicking; using Content.Shared.GameWindow; using Content.Shared.Players; using Content.Shared.Preferences; using JetBrains.Annotations; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -18,6 +19,7 @@ public sealed partial class GameTicker { [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IServerDbManager _dbManager = default!; + [Dependency] private readonly ActorSystem _actor = default!; private void InitializePlayer() { @@ -50,7 +52,7 @@ private async void PlayerStatusChanged(object? sender, SessionStatusEventArgs ar // Always make sure the client has player data. if (session.Data.ContentDataUncast == null) { - var data = new PlayerData(session.UserId, args.Session.Name); + var data = new ContentPlayerData(session.UserId, args.Session.Name); data.Mind = mindId; session.Data.ContentDataUncast = data; } @@ -59,7 +61,7 @@ private async void PlayerStatusChanged(object? sender, SessionStatusEventArgs ar // timer time must be > tick length // Corvax-Queue-Start if (!IoCManager.Instance!.TryResolveType(out _)) - Timer.Spawn(0, args.Session.JoinGame); // Moved to `JoinQueueManager` if manager registered + Timer.Spawn(0, () => _playerManager.JoinGame(args.Session)); // Corvax-Queue-End var record = await _dbManager.GetPlayerRecordByUserId(args.Session.UserId); @@ -104,9 +106,16 @@ private async void PlayerStatusChanged(object? sender, SessionStatusEventArgs ar } else { - // Simply re-attach to existing entity. - session.AttachToEntity(mind.CurrentEntity); - PlayerJoinGame(session); + if (_actor.Attach(mind.CurrentEntity, session)) + { + PlayerJoinGame(session); + } + else + { + Log.Error( + $"Failed to attach player {session} with mind {ToPrettyString(mindId)} to its current entity {ToPrettyString(mind.CurrentEntity)}"); + SpawnObserverWaitDb(); + } } break; @@ -151,12 +160,12 @@ async void AddPlayerToDb(Guid id) } } - private HumanoidCharacterProfile GetPlayerProfile(IPlayerSession p) + private HumanoidCharacterProfile GetPlayerProfile(ICommonSession p) { return (HumanoidCharacterProfile) _prefsManager.GetPreferences(p.UserId).SelectedCharacter; } - public void PlayerJoinGame(IPlayerSession session, bool silent = false) + public void PlayerJoinGame(ICommonSession session, bool silent = false) { if (!silent) _chatManager.DispatchServerMessage(session, Loc.GetString("game-ticker-player-join-game-message")); @@ -167,7 +176,7 @@ public void PlayerJoinGame(IPlayerSession session, bool silent = false) RaiseNetworkEvent(new TickerJoinGameEvent(), session.ConnectedClient); } - private void PlayerJoinLobby(IPlayerSession session) + private void PlayerJoinLobby(ICommonSession session) { _playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay; _db.AddRoundPlayers(RoundId, session.UserId); @@ -187,9 +196,9 @@ private void ReqWindowAttentionAll() public sealed class PlayerJoinedLobbyEvent : EntityEventArgs { - public readonly IPlayerSession PlayerSession; + public readonly ICommonSession PlayerSession; - public PlayerJoinedLobbyEvent(IPlayerSession playerSession) + public PlayerJoinedLobbyEvent(ICommonSession playerSession) { PlayerSession = playerSession; } diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index e9ea36f0f8c..8cf9c658904 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -12,7 +12,6 @@ using JetBrains.Annotations; using Prometheus; using Robust.Server.Maps; -using Robust.Server.Player; using Robust.Shared.Asynchronous; using Robust.Shared.Audio; using Robust.Shared.Map; @@ -205,7 +204,7 @@ public void StartRound(bool force = false) var startingEvent = new RoundStartingEvent(RoundId); RaiseLocalEvent(startingEvent); - var readyPlayers = new List(); + var readyPlayers = new List(); var readyPlayerProfiles = new Dictionary(); foreach (var (userId, status) in _playerGameStatuses) @@ -345,7 +344,7 @@ public void ShowRoundEndScoreboard(string text = "") { connected = true; } - PlayerData? contentPlayerData = null; + ContentPlayerData? contentPlayerData = null; if (userId != null && _playerManager.TryGetPlayerData(userId.Value, out var playerData)) { contentPlayerData = playerData.ContentData(); @@ -361,9 +360,8 @@ public void ShowRoundEndScoreboard(string text = "") else if (mind.CurrentEntity != null && TryName(mind.CurrentEntity.Value, out var icName)) playerIcName = icName; - var entity = mind.OriginalOwnedEntity; - if (Exists(entity)) - _pvsOverride.AddGlobalOverride(entity.Value); + if (TryGetEntity(mind.OriginalOwnedEntity, out var entity)) + _pvsOverride.AddGlobalOverride(entity.Value, recursive: true); var roles = _roles.MindGetAllRoles(mindId); @@ -496,7 +494,7 @@ private async void SendRoundStartingDiscordMessage() private void ResettingCleanup() { // Move everybody currently in the server to lobby. - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { PlayerJoinLobby(player); } @@ -544,7 +542,7 @@ private void ResettingCleanup() DisallowLateJoin = false; _playerGameStatuses.Clear(); - foreach (var session in _playerManager.ServerSessions) + foreach (var session in _playerManager.Sessions) { _playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay; } @@ -738,10 +736,10 @@ public void Disallow() /// public sealed class RoundStartAttemptEvent : CancellableEntityEventArgs { - public IPlayerSession[] Players { get; } + public ICommonSession[] Players { get; } public bool Forced { get; } - public RoundStartAttemptEvent(IPlayerSession[] players, bool forced) + public RoundStartAttemptEvent(ICommonSession[] players, bool forced) { Players = players; Forced = forced; @@ -760,11 +758,11 @@ public sealed class RulePlayerSpawningEvent /// If you want to handle a specific player being spawned, remove it from this list and do what you need. /// /// If you spawn a player by yourself from this event, don't forget to call on them. - public List PlayerPool { get; } + public List PlayerPool { get; } public IReadOnlyDictionary Profiles { get; } public bool Forced { get; } - public RulePlayerSpawningEvent(List playerPool, IReadOnlyDictionary profiles, bool forced) + public RulePlayerSpawningEvent(List playerPool, IReadOnlyDictionary profiles, bool forced) { PlayerPool = playerPool; Profiles = profiles; @@ -778,11 +776,11 @@ public RulePlayerSpawningEvent(List playerPool, IReadOnlyDiction /// public sealed class RulePlayerJobsAssignedEvent { - public IPlayerSession[] Players { get; } + public ICommonSession[] Players { get; } public IReadOnlyDictionary Profiles { get; } public bool Forced { get; } - public RulePlayerJobsAssignedEvent(IPlayerSession[] players, IReadOnlyDictionary profiles, bool forced) + public RulePlayerJobsAssignedEvent(ICommonSession[] players, IReadOnlyDictionary profiles, bool forced) { Players = players; Profiles = profiles; diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index 93636389ed6..236a4dc01ef 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -3,20 +3,20 @@ using System.Numerics; using Content.Server.Administration.Managers; using Content.Server.Ghost; -using Content.Server.Players; using Content.Server.Spawners.Components; using Content.Server.Speech.Components; using Content.Server.Station.Components; using Content.Shared.CCVar; using Content.Shared.Database; +using Content.Shared.Players; using Content.Shared.Preferences; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -29,7 +29,7 @@ public sealed partial class GameTicker [Dependency] private readonly SharedJobSystem _jobs = default!; [ValidatePrototypeId] - private const string ObserverPrototypeName = "MobObserver"; + public const string ObserverPrototypeName = "MobObserver"; /// /// How many players have joined the round through normal methods. @@ -52,7 +52,7 @@ private List GetSpawnableStations() return spawnableStations; } - private void SpawnPlayers(List readyPlayers, Dictionary profiles, bool force) + private void SpawnPlayers(List readyPlayers, Dictionary profiles, bool force) { // Allow game rules to spawn players by themselves if needed. (For example, nuke ops or wizard) RaiseLocalEvent(new RulePlayerSpawningEvent(readyPlayers, profiles, force)); @@ -116,7 +116,7 @@ private void SpawnPlayers(List readyPlayers, Dictionary _playerManager.GetSessionByUserId(x)).ToArray(), profiles, force)); } - private void SpawnPlayer(IPlayerSession player, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) + private void SpawnPlayer(ICommonSession player, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) { var character = GetPlayerProfile(player); @@ -129,7 +129,7 @@ private void SpawnPlayer(IPlayerSession player, EntityUid station, string? jobId SpawnPlayer(player, character, station, jobId, lateJoin, silent); } - private void SpawnPlayer(IPlayerSession player, HumanoidCharacterProfile character, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) + private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile character, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) { // Can't spawn players with a dummy ticker! if (DummyTicker) @@ -272,7 +272,7 @@ private void SpawnPlayer(IPlayerSession player, HumanoidCharacterProfile charact RaiseLocalEvent(mob, aev, true); } - public void Respawn(IPlayerSession player) + public void Respawn(ICommonSession player) { _mind.WipeMind(player); _adminLogger.Add(LogType.Respawn, LogImpact.Medium, $"Player {player} was respawned."); @@ -290,7 +290,7 @@ public void Respawn(IPlayerSession player) /// The station they're spawning on /// An optional job for them to spawn as /// Whether or not the player should be greeted upon joining - public void MakeJoinGame(IPlayerSession player, EntityUid station, string? jobId = null, bool silent = false) + public void MakeJoinGame(ICommonSession player, EntityUid station, string? jobId = null, bool silent = false) { if (!_playerGameStatuses.ContainsKey(player.UserId)) return; @@ -304,7 +304,7 @@ public void MakeJoinGame(IPlayerSession player, EntityUid station, string? jobId /// /// Causes the given player to join the current game as observer ghost. See also /// - public void JoinAsObserver(IPlayerSession player) + public void JoinAsObserver(ICommonSession player) { // Can't spawn players with a dummy ticker! if (DummyTicker) @@ -318,7 +318,7 @@ public void JoinAsObserver(IPlayerSession player) /// Spawns an observer ghost and attaches the given player to it. If the player does not yet have a mind, the /// player is given a new mind with the observer role. Otherwise, the current mind is transferred to the ghost. /// - public void SpawnObserver(IPlayerSession player) + public void SpawnObserver(ICommonSession player) { if (DummyTicker) return; @@ -431,13 +431,13 @@ public EntityCoordinates GetObserverSpawnPoint() [PublicAPI] public sealed class PlayerBeforeSpawnEvent : HandledEntityEventArgs { - public IPlayerSession Player { get; } + public ICommonSession Player { get; } public HumanoidCharacterProfile Profile { get; } public string? JobId { get; } public bool LateJoin { get; } public EntityUid Station { get; } - public PlayerBeforeSpawnEvent(IPlayerSession player, HumanoidCharacterProfile profile, string? jobId, bool lateJoin, EntityUid station) + public PlayerBeforeSpawnEvent(ICommonSession player, HumanoidCharacterProfile profile, string? jobId, bool lateJoin, EntityUid station) { Player = player; Profile = profile; @@ -456,7 +456,7 @@ public PlayerBeforeSpawnEvent(IPlayerSession player, HumanoidCharacterProfile pr public sealed class PlayerSpawnCompleteEvent : EntityEventArgs { public EntityUid Mob { get; } - public IPlayerSession Player { get; } + public ICommonSession Player { get; } public string? JobId { get; } public bool LateJoin { get; } public EntityUid Station { get; } @@ -465,7 +465,7 @@ public sealed class PlayerSpawnCompleteEvent : EntityEventArgs // Ex. If this is the 27th person to join, this will be 27. public int JoinOrder { get; } - public PlayerSpawnCompleteEvent(EntityUid mob, IPlayerSession player, string? jobId, bool lateJoin, int joinOrder, EntityUid station, HumanoidCharacterProfile profile) + public PlayerSpawnCompleteEvent(EntityUid mob, ICommonSession player, string? jobId, bool lateJoin, int joinOrder, EntityUid station, HumanoidCharacterProfile profile) { Mob = mob; Player = player; diff --git a/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs index 7d036c615ba..e9c8d50cdc0 100644 --- a/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs @@ -39,7 +39,7 @@ public sealed partial class RevolutionaryRuleComponent : Component /// Sound that plays when you are chosen as Rev. (Placeholder until I find something cool I guess) /// [DataField] - public SoundSpecifier HeadRevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/traitor_start.ogg"); + public SoundSpecifier HeadRevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/headrev_start.ogg"); /// /// Min players needed for Revolutionary gamemode to start. diff --git a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs index 883abef52fa..7af87179d65 100644 --- a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.Preferences; using Content.Shared.Roles; -using Robust.Server.Player; using Robust.Shared.Audio; +using Robust.Shared.Player; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.GameTicking.Rules.Components; @@ -26,7 +26,7 @@ public enum SelectionState public SelectionState SelectionStatus = SelectionState.WaitingForSpawn; public TimeSpan AnnounceAt = TimeSpan.Zero; - public Dictionary StartCandidates = new(); + public Dictionary StartCandidates = new(); /// /// Path to antagonist alert sound. diff --git a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs index c2e91ba4a5d..b775b7af564 100644 --- a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Components; using Robust.Server.Player; +using Robust.Shared.Player; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 0c8038f86f0..ea96ea9e44f 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -336,7 +336,7 @@ private void OnRoundStart(EntityUid uid, NukeopsRuleComponent? component = null) var eligibleQuery = EntityQueryEnumerator(); while (eligibleQuery.MoveNext(out var eligibleUid, out var eligibleComp, out var member)) { - if (!_npcFaction.IsFactionFriendly(component.Faction, eligibleUid, member)) + if (!_npcFaction.IsFactionHostile(component.Faction, eligibleUid, member)) continue; eligible.Add((eligibleUid, eligibleComp, member)); @@ -351,8 +351,7 @@ private void OnRoundStart(EntityUid uid, NukeopsRuleComponent? component = null) var query = EntityQueryEnumerator(); while (query.MoveNext(out _, out var nukeops, out var actor)) { - _chatManager.DispatchServerMessage(actor.PlayerSession, Loc.GetString("nukeops-welcome", ("station", component.TargetStation.Value))); - _audio.PlayGlobal(nukeops.GreetSoundNotification, actor.PlayerSession); + NotifyNukie(actor.PlayerSession, nukeops, component); filter.AddPlayer(actor.PlayerSession); } } @@ -604,11 +603,11 @@ private void OnPlayersSpawning(RulePlayerSpawningEvent ev) var maxOperatives = nukeops.MaxOps; // Dear lord what is happening HERE. - var everyone = new List(ev.PlayerPool); - var prefList = new List(); - var medPrefList = new List(); - var cmdrPrefList = new List(); - var operatives = new List(); + var everyone = new List(ev.PlayerPool); + var prefList = new List(); + var medPrefList = new List(); + var cmdrPrefList = new List(); + var operatives = new List(); // The LINQ expression ReSharper keeps suggesting is completely unintelligible so I'm disabling it // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator @@ -639,7 +638,7 @@ private void OnPlayersSpawning(RulePlayerSpawningEvent ev) for (var i = 0; i < numNukies; i++) { // TODO: Please fix this if you touch it. - IPlayerSession nukeOp; + ICommonSession nukeOp; // Only one commander, so we do it at the start if (i == 0) { @@ -795,10 +794,7 @@ private void OnMindAdded(EntityUid uid, NukeOperativeComponent component, MindAd if (nukeops.TargetStation != null && !string.IsNullOrEmpty(Name(nukeops.TargetStation.Value))) { - _chatManager.DispatchServerMessage(playerSession, Loc.GetString("nukeops-welcome", ("station", nukeops.TargetStation.Value))); - - // Notificate player about new role assignment - _audio.PlayGlobal(component.GreetSoundNotification, playerSession); + NotifyNukie(playerSession, component, nukeops); } } } @@ -910,7 +906,7 @@ private void SetupOperativeEntity(EntityUid mob, string name, string gear, Human _npcFaction.AddFaction(mob, "Syndicate"); } - private void SpawnOperatives(int spawnCount, List sessions, bool addSpawnPoints, NukeopsRuleComponent component) + private void SpawnOperatives(int spawnCount, List sessions, bool addSpawnPoints, NukeopsRuleComponent component) { if (component.NukieOutpost == null) return; @@ -989,13 +985,25 @@ private void SpawnOperativesForGhostRoles(EntityUid uid, NukeopsRuleComponent? c var playersPerOperative = component.PlayersPerOperative; var maxOperatives = component.MaxOps; - var playerPool = _playerManager.ServerSessions.ToList(); + var playerPool = _playerManager.Sessions.ToList(); var numNukies = MathHelper.Clamp(playerPool.Count / playersPerOperative, 1, maxOperatives); - var operatives = new List(); + var operatives = new List(); SpawnOperatives(numNukies, operatives, true, component); } + /// + /// Display a greeting message and play a sound for a nukie + /// + private void NotifyNukie(ICommonSession session, NukeOperativeComponent nukeop, NukeopsRuleComponent nukeopsRule) + { + if (nukeopsRule.TargetStation is not { } station) + return; + + _chatManager.DispatchServerMessage(session, Loc.GetString("nukeops-welcome", ("station", station))); + _audio.PlayGlobal(nukeop.GreetSoundNotification, session); + } + //For admins forcing someone to nukeOps. public void MakeLoneNukie(EntityUid mindId, MindComponent mind) { diff --git a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs index b223161c10e..0785d81d09b 100644 --- a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs @@ -15,10 +15,10 @@ using Content.Shared.Roles; using Robust.Server.GameObjects; using Robust.Server.Maps; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -141,7 +141,7 @@ private void OnPlayerSpawningEvent(RulePlayerSpawningEvent ev) (int) Math.Min( Math.Floor((double) ev.PlayerPool.Count / _cfg.GetCVar(CCVars.PiratesPlayersPerOp)), _cfg.GetCVar(CCVars.PiratesMaxOps))); - var ops = new IPlayerSession[numOps]; + var ops = new ICommonSession[numOps]; for (var i = 0; i < numOps; i++) { ops[i] = _random.PickAndTake(ev.PlayerPool); diff --git a/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs b/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs index a2868086237..738883fff38 100644 --- a/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Interaction.Events; using Content.Shared.Mind; using Content.Shared.Mobs; +using Content.Shared.Players; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Network; diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 01317dbfc11..ef949d09fc9 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -17,9 +17,8 @@ using Content.Shared.Preferences; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; -using Robust.Server.Player; using Robust.Shared.Configuration; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -151,9 +150,9 @@ private void OnPlayersSpawned(RulePlayerJobsAssignedEvent ev) } } - private List FindPotentialTraitors(in Dictionary candidates, TraitorRuleComponent component) + private List FindPotentialTraitors(in Dictionary candidates, TraitorRuleComponent component) { - var list = new List(); + var list = new List(); var pendingQuery = GetEntityQuery(); foreach (var player in candidates.Keys) @@ -171,7 +170,7 @@ private List FindPotentialTraitors(in Dictionary(); + var prefList = new List(); foreach (var player in list) { @@ -189,9 +188,9 @@ private List FindPotentialTraitors(in Dictionary PickTraitors(int traitorCount, List prefList) + private List PickTraitors(int traitorCount, List prefList) { - var results = new List(traitorCount); + var results = new List(traitorCount); if (prefList.Count == 0) { Log.Info("Insufficient ready players to fill up with traitors, stopping the selection."); diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index 82ae4b8fa66..a4febc385c1 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -23,7 +23,7 @@ using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Configuration; -using Robust.Shared.Prototypes; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -264,9 +264,9 @@ private void InfectInitialPlayers(ZombieRuleComponent component) return; component.InfectedChosen = true; - var allPlayers = _playerManager.ServerSessions.ToList(); - var playerList = new List(); - var prefList = new List(); + var allPlayers = _playerManager.Sessions.ToList(); + var playerList = new List(); + var prefList = new List(); foreach (var player in allPlayers) { if (player.AttachedEntity == null || !HasComp(player.AttachedEntity) || HasComp(player.AttachedEntity)) @@ -288,7 +288,7 @@ private void InfectInitialPlayers(ZombieRuleComponent component) var totalInfected = 0; while (totalInfected < numInfected) { - IPlayerSession zombie; + ICommonSession zombie; if (prefList.Count == 0) { if (playerList.Count == 0) diff --git a/Content.Server/Ghost/Ghost.cs b/Content.Server/Ghost/Ghost.cs index d04b1197afa..1453bf3faa9 100644 --- a/Content.Server/Ghost/Ghost.cs +++ b/Content.Server/Ghost/Ghost.cs @@ -1,7 +1,6 @@ using Content.Server.GameTicking; using Content.Shared.Administration; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Ghost @@ -17,7 +16,7 @@ public sealed class Ghost : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You have no session, you can't ghost."); diff --git a/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs b/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs index c97e3be9dc4..16d46871fed 100644 --- a/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs +++ b/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Ghost.Roles.Components; diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index 5a4cc176f2a..f372cb4f62a 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -4,7 +4,6 @@ using Content.Server.Ghost.Roles.Events; using Content.Server.Ghost.Roles.UI; using Content.Server.Mind.Commands; -using Content.Server.Players; using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Follower; @@ -14,13 +13,14 @@ using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Mobs; +using Content.Shared.Players; using Content.Shared.Roles; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -97,7 +97,7 @@ private uint GetNextRoleIdentifier() return unchecked(_nextRoleIdentifier++); } - public void OpenEui(IPlayerSession session) + public void OpenEui(ICommonSession session) { if (session.AttachedEntity is not {Valid: true} attached || !EntityManager.HasComponent(attached)) @@ -111,7 +111,7 @@ public void OpenEui(IPlayerSession session) eui.StateDirty(); } - public void OpenMakeGhostRoleEui(IPlayerSession session, EntityUid uid) + public void OpenMakeGhostRoleEui(ICommonSession session, EntityUid uid) { if (session.AttachedEntity == null) return; @@ -420,7 +420,7 @@ public sealed class GhostRoles : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { if(shell.Player != null) - EntitySystem.Get().OpenEui((IPlayerSession)shell.Player); + EntitySystem.Get().OpenEui(shell.Player); else shell.WriteLine("You can only open the ghost roles UI on a client."); } diff --git a/Content.Server/Gravity/GravityGeneratorSystem.cs b/Content.Server/Gravity/GravityGeneratorSystem.cs index 48002fb823d..0bd159f61af 100644 --- a/Content.Server/Gravity/GravityGeneratorSystem.cs +++ b/Content.Server/Gravity/GravityGeneratorSystem.cs @@ -6,7 +6,7 @@ using Content.Shared.Gravity; using Content.Shared.Interaction; using Robust.Server.GameObjects; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Gravity { @@ -139,7 +139,7 @@ private void SetSwitchedOn(EntityUid uid, GravityGeneratorComponent component, b return; if (session is { AttachedEntity: { } }) - _adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{ToPrettyString(session.AttachedEntity.Value):player} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}"); + _adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{session:player} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}"); component.SwitchedOn = on; UpdatePowerState(component, powerReceiver); diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index b5b01ac001d..e3e66995373 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -18,12 +18,11 @@ using Content.Shared.Stacks; using Content.Shared.Storage; using Content.Shared.Throwing; -using Robust.Server.Player; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Hands.Systems @@ -159,9 +158,9 @@ private void HandlePullStopped(EntityUid uid, HandsComponent component, PullStop #endregion #region interactions - private bool HandleThrowItem(ICommonSession? session, EntityCoordinates coordinates, EntityUid entity) + private bool HandleThrowItem(ICommonSession? playerSession, EntityCoordinates coordinates, EntityUid entity) { - if (session is not IPlayerSession playerSession) + if (playerSession == null) return false; if (playerSession.AttachedEntity is not {Valid: true} player || @@ -220,7 +219,7 @@ private void HandleSmartEquipBelt(ICommonSession? session) // TODO: move to storage or inventory private void HandleSmartEquip(ICommonSession? session, string equipmentSlot) { - if (session is not IPlayerSession playerSession) + if (session is not { } playerSession) return; if (playerSession.AttachedEntity is not {Valid: true} plyEnt || !Exists(plyEnt)) diff --git a/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs b/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs index 7c0bb7383b9..b47fe717140 100644 --- a/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs +++ b/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs @@ -3,7 +3,6 @@ using Content.Shared.Humanoid; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Utility; namespace Content.Server.Humanoid; @@ -48,7 +47,7 @@ private void OnVerbsRequest(EntityUid uid, HumanoidAppearanceComponent component private void OnBaseLayersSet(EntityUid uid, HumanoidAppearanceComponent component, HumanoidMarkingModifierBaseLayersSetMessage message) { - if (message.Session is not IPlayerSession player + if (message.Session is not { } player || !_adminManager.HasAdminFlag(player, AdminFlags.Fun)) { return; @@ -81,7 +80,7 @@ private void OnBaseLayersSet(EntityUid uid, HumanoidAppearanceComponent componen private void OnMarkingsSet(EntityUid uid, HumanoidAppearanceComponent component, HumanoidMarkingModifierMarkingSetMessage message) { - if (message.Session is not IPlayerSession player + if (message.Session is not { } player || !_adminManager.HasAdminFlag(player, AdminFlags.Fun)) { return; diff --git a/Content.Server/Implants/ImplanterSystem.cs b/Content.Server/Implants/ImplanterSystem.cs index f3072769e4d..0d46241f414 100644 --- a/Content.Server/Implants/ImplanterSystem.cs +++ b/Content.Server/Implants/ImplanterSystem.cs @@ -1,11 +1,9 @@ -using Content.Server.Guardian; using Content.Server.Popups; using Content.Shared.DoAfter; using Content.Shared.IdentityManagement; using Content.Shared.Implants; using Content.Shared.Implants.Components; using Content.Shared.Interaction; -using Content.Shared.Mobs.Components; using Content.Shared.Popups; using Robust.Shared.Containers; @@ -33,28 +31,39 @@ private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent componen if (args.Target == null || !args.CanReach || args.Handled) return; - //Simplemobs and regular mobs should be injectable, but only regular mobs have mind. - //So just don't implant/draw anything that isn't living or is a guardian - //TODO: Rework a bit when surgery is in to work with implant cases - if (!HasComp(args.Target.Value) || HasComp(args.Target.Value)) + var target = args.Target.Value; + if (!CheckTarget(target, component.Whitelist, component.Blacklist)) return; //TODO: Rework when surgery is in for implant cases if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly) { - TryDraw(component, args.User, args.Target.Value, uid); + TryDraw(component, args.User, target, uid); } else { - if (!CanImplant(args.User, args.Target.Value, uid, component, out _, out _)) + if (!CanImplant(args.User, target, uid, component, out var implant, out _)) + { + // no popup if implant doesn't exist + if (implant == null) + return; + + // show popup to the user saying implant failed + var name = Identity.Name(target, EntityManager, args.User); + var msg = Loc.GetString("implanter-component-implant-failed", ("implant", implant), ("target", name)); + _popup.PopupEntity(msg, target, args.User); + // prevent further interaction since popup was shown + args.Handled = true; return; + } //Implant self instantly, otherwise try to inject the target. - if (args.User == args.Target) - Implant(args.User, args.Target.Value, uid, component); + if (args.User == target) + Implant(target, target, uid, component); else - TryImplant(component, args.User, args.Target.Value, uid); + TryImplant(component, args.User, target, uid); } + args.Handled = true; } diff --git a/Content.Server/Instruments/InstrumentComponent.cs b/Content.Server/Instruments/InstrumentComponent.cs index 810d2653146..4302ab6791b 100644 --- a/Content.Server/Instruments/InstrumentComponent.cs +++ b/Content.Server/Instruments/InstrumentComponent.cs @@ -1,7 +1,7 @@ using Content.Server.UserInterface; using Content.Shared.Instruments; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Instruments; @@ -17,7 +17,7 @@ public sealed partial class InstrumentComponent : SharedInstrumentComponent [ViewVariables] public uint LastSequencerTick = 0; // TODO Instruments: Make this ECS - public IPlayerSession? InstrumentPlayer => + public ICommonSession? InstrumentPlayer => _entMan.GetComponentOrNull(Owner)?.CurrentSingleUser ?? _entMan.GetComponentOrNull(Owner)?.PlayerSession; } diff --git a/Content.Server/Instruments/InstrumentSystem.cs b/Content.Server/Instruments/InstrumentSystem.cs index ec233821051..6f8369182cb 100644 --- a/Content.Server/Instruments/InstrumentSystem.cs +++ b/Content.Server/Instruments/InstrumentSystem.cs @@ -9,12 +9,12 @@ using Content.Shared.Popups; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio.Midi; using Robust.Shared.Collections; using Robust.Shared.Configuration; using Robust.Shared.Console; using Robust.Shared.GameStates; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Instruments; @@ -385,7 +385,7 @@ public override void Update(float frameTime) var nearby = GetBands(entity); _bui.TrySendUiMessage(entity, request.UiKey, new InstrumentBandResponseBuiMessage(nearby), - (IPlayerSession)request.Session); + request.Session); } _bandRequestQueue.Clear(); @@ -447,7 +447,7 @@ public override void Update(float frameTime) } } - public void ToggleInstrumentUi(EntityUid uid, IPlayerSession session, InstrumentComponent? component = null) + public void ToggleInstrumentUi(EntityUid uid, ICommonSession session, InstrumentComponent? component = null) { if (!Resolve(uid, ref component)) return; diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs index a612b738400..9237a1f7dd4 100644 --- a/Content.Server/Interaction/InteractionSystem.cs +++ b/Content.Server/Interaction/InteractionSystem.cs @@ -13,7 +13,6 @@ using Robust.Shared.Containers; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; using Robust.Shared.Random; namespace Content.Server.Interaction diff --git a/Content.Server/Interaction/TilePryCommand.cs b/Content.Server/Interaction/TilePryCommand.cs index 157fa2cc80c..fa75b6d9e47 100644 --- a/Content.Server/Interaction/TilePryCommand.cs +++ b/Content.Server/Interaction/TilePryCommand.cs @@ -1,16 +1,14 @@ using System.Numerics; using Content.Server.Administration; -using Content.Server.Tools.Components; using Content.Shared.Administration; using Content.Shared.Maps; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; namespace Content.Server.Interaction { /// - /// + /// /// [AdminCommand(AdminFlags.Debug)] sealed class TilePryCommand : IConsoleCommand @@ -23,7 +21,7 @@ sealed class TilePryCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity is not {} attached) { return; diff --git a/Content.Server/MagicMirror/MagicMirrorSystem.cs b/Content.Server/MagicMirror/MagicMirrorSystem.cs index 90a0b19b7dd..a599a2c868a 100644 --- a/Content.Server/MagicMirror/MagicMirrorSystem.cs +++ b/Content.Server/MagicMirror/MagicMirrorSystem.cs @@ -5,8 +5,7 @@ using Content.Shared.Humanoid.Markings; using Content.Shared.MagicMirror; using Robust.Server.GameObjects; -using Robust.Server.Player; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.MagicMirror; @@ -147,7 +146,7 @@ private void OnMagicMirrorAddSlot(EntityUid uid, MagicMirrorComponent component, private void UpdateInterface(EntityUid uid, EntityUid playerUid, ICommonSession session, HumanoidAppearanceComponent? humanoid = null) { - if (!Resolve(playerUid, ref humanoid) || session is not IPlayerSession player) + if (!Resolve(playerUid, ref humanoid) || session is not { } player) { return; } diff --git a/Content.Server/Mapping/MappingCommand.cs b/Content.Server/Mapping/MappingCommand.cs index e4a4cd89424..d72a5c4178e 100644 --- a/Content.Server/Mapping/MappingCommand.cs +++ b/Content.Server/Mapping/MappingCommand.cs @@ -40,7 +40,7 @@ public CompletionResult GetCompletion(IConsoleShell shell, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("cmd-savemap-server")); return; diff --git a/Content.Server/Maps/GridDraggingSystem.cs b/Content.Server/Maps/GridDraggingSystem.cs index 90770af1ad2..7d7b61955b4 100644 --- a/Content.Server/Maps/GridDraggingSystem.cs +++ b/Content.Server/Maps/GridDraggingSystem.cs @@ -1,10 +1,9 @@ using Content.Shared.Maps; using Robust.Server.Console; -using Robust.Server.Player; -using Robust.Shared.Players; using Robust.Shared.Utility; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; +using Robust.Shared.Player; namespace Content.Server.Maps; @@ -27,7 +26,7 @@ public override void Initialize() public void Toggle(ICommonSession session) { - if (session is not IPlayerSession pSession) + if (session is not { } pSession) return; DebugTools.Assert(_admin.CanCommand(pSession, CommandName)); @@ -52,7 +51,7 @@ private void OnRequestVelocity(GridDragVelocityRequest ev, EntitySessionEventArg { var grid = GetEntity(ev.Grid); - if (args.SenderSession is not IPlayerSession playerSession || + if (args.SenderSession is not { } playerSession || !_admin.CanCommand(playerSession, CommandName) || !Exists(grid) || Deleted(grid)) @@ -69,7 +68,7 @@ private void OnRequestDrag(GridDragRequestPosition msg, EntitySessionEventArgs a { var grid = GetEntity(msg.Grid); - if (args.SenderSession is not IPlayerSession playerSession || + if (args.SenderSession is not { } playerSession || !_admin.CanCommand(playerSession, CommandName) || !Exists(grid) || Deleted(grid)) diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs index b94d6de6de0..82f7b9cb0a0 100644 --- a/Content.Server/Medical/CryoPodSystem.cs +++ b/Content.Server/Medical/CryoPodSystem.cs @@ -32,6 +32,7 @@ using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Shared.Timing; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Medical; diff --git a/Content.Server/Medical/DefibrillatorSystem.cs b/Content.Server/Medical/DefibrillatorSystem.cs index 4ffa9f558da..d041f8ee9d7 100644 --- a/Content.Server/Medical/DefibrillatorSystem.cs +++ b/Content.Server/Medical/DefibrillatorSystem.cs @@ -18,7 +18,7 @@ using Content.Shared.Mobs.Systems; using Content.Shared.Timing; using Content.Shared.Toggleable; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Medical; diff --git a/Content.Server/Mind/Commands/RenameCommand.cs b/Content.Server/Mind/Commands/RenameCommand.cs index 5674da4ffd3..2d65adc5082 100644 --- a/Content.Server/Mind/Commands/RenameCommand.cs +++ b/Content.Server/Mind/Commands/RenameCommand.cs @@ -54,6 +54,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) { // Mind mind.CharacterName = name; + _entManager.Dirty(mindId, mind); } // Id Cards diff --git a/Content.Server/Mind/MindSystem.cs b/Content.Server/Mind/MindSystem.cs index 373007fd1b5..f23e9b64073 100644 --- a/Content.Server/Mind/MindSystem.cs +++ b/Content.Server/Mind/MindSystem.cs @@ -1,6 +1,7 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.Administration.Logs; using Content.Server.GameTicking; +using Content.Server.Mind.Commands; using Content.Shared.Database; using Content.Shared.Ghost; using Content.Shared.Mind; @@ -10,7 +11,9 @@ using Robust.Server.GameStates; using Robust.Server.Player; using Robust.Shared.Map; +using Robust.Shared.Map.Components; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -46,20 +49,14 @@ private void OnMindShutdown(EntityUid uid, MindComponent mind, ComponentShutdown mind.UserId = null; } - if (!TryComp(mind.OwnedEntity, out MetaDataComponent? meta) || meta.EntityLifeStage >= EntityLifeStage.Terminating) - return; + if (mind.OwnedEntity != null && !TerminatingOrDeleted(mind.OwnedEntity.Value)) + TransferTo(uid, null, mind: mind, createGhost: false); - RaiseLocalEvent(mind.OwnedEntity.Value, new MindRemovedMessage(uid, mind), true); mind.OwnedEntity = null; - mind.OwnedComponent = null; } private void OnMindContainerTerminating(EntityUid uid, MindContainerComponent component, ref EntityTerminatingEvent args) { - // Let's not create ghosts if not in the middle of the round. - if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby) - return; - if (!TryGetMind(uid, out var mindId, out var mind, component)) return; @@ -76,46 +73,45 @@ private void OnMindContainerTerminating(EntityUid uid, MindContainerComponent co } TransferTo(mindId, null, createGhost: false, mind: mind); + DebugTools.AssertNull(mind.OwnedEntity); - if (component.GhostOnShutdown && mind.Session != null) - { - var xform = Transform(uid); - var gridId = xform.GridUid; - var spawnPosition = Transform(uid).Coordinates; + if (!component.GhostOnShutdown || mind.Session == null || _gameTicker.RunLevel == GameRunLevel.PreRoundLobby) + return; - // Use a regular timer here because the entity has probably been deleted. - Timer.Spawn(0, () => - { - // Make extra sure the round didn't end between spawning the timer and it being executed. - if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby) - return; + var xform = Transform(uid); + var gridId = xform.GridUid; + var spawnPosition = Transform(uid).Coordinates; - // Async this so that we don't throw if the grid we're on is being deleted. - if (!_maps.GridExists(gridId)) - spawnPosition = _gameTicker.GetObserverSpawnPoint(); + // Use a regular timer here because the entity has probably been deleted. + Timer.Spawn(0, () => + { + // Make extra sure the round didn't end between spawning the timer and it being executed. + if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby) + return; - // TODO refactor observer spawning. - // please. - if (!spawnPosition.IsValid(EntityManager)) - { - // This should be an error, if it didn't cause tests to start erroring when they delete a player. - Log.Warning($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available."); - TransferTo(mindId, null, createGhost: false, mind: mind); - return; - } + // Async this so that we don't throw if the grid we're on is being deleted. + if (!HasComp(gridId)) + spawnPosition = _gameTicker.GetObserverSpawnPoint(); - var ghost = Spawn("MobObserver", spawnPosition); - var ghostComponent = Comp(ghost); - _ghosts.SetCanReturnToBody(ghostComponent, false); + // TODO refactor observer spawning. + // please. + if (!spawnPosition.IsValid(EntityManager)) + { + // This should be an error, if it didn't cause tests to start erroring when they delete a player. + Log.Warning($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available."); + TransferTo(mindId, null, createGhost: false, mind: mind); + return; + } - // Log these to make sure they're not causing the GameTicker round restart bugs... - Log.Debug($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, spawned \"{ToPrettyString(ghost)}\"."); + var ghost = Spawn(GameTicker.ObserverPrototypeName, spawnPosition); + var ghostComponent = Comp(ghost); + _ghosts.SetCanReturnToBody(ghostComponent, false); - var val = mind.CharacterName ?? string.Empty; - _metaData.SetEntityName(ghost, val); - TransferTo(mindId, ghost, mind: mind); - }); - } + // Log these to make sure they're not causing the GameTicker round restart bugs... + Log.Debug($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, spawned \"{ToPrettyString(ghost)}\"."); + _metaData.SetEntityName(ghost, mind.CharacterName ?? string.Empty); + TransferTo(mindId, ghost, mind: mind); + }); } public override bool TryGetMind(NetUserId user, [NotNullWhen(true)] out EntityUid? mindId, [NotNullWhen(true)] out MindComponent? mind) @@ -130,18 +126,18 @@ public override bool TryGetMind(NetUserId user, [NotNullWhen(true)] out EntityUi return false; } - public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out IPlayerSession? session) + public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out ICommonSession? session) { session = null; - return TryComp(mindId, out MindComponent? mind) && (session = (IPlayerSession?) mind.Session) != null; + return TryComp(mindId, out MindComponent? mind) && (session = mind.Session) != null; } - public IPlayerSession? GetSession(MindComponent mind) + public ICommonSession? GetSession(MindComponent mind) { - return (IPlayerSession?) mind.Session; + return mind.Session; } - public bool TryGetSession(MindComponent mind, [NotNullWhen(true)] out IPlayerSession? session) + public bool TryGetSession(MindComponent mind, [NotNullWhen(true)] out ICommonSession? session) { return (session = GetSession(mind)) != null; } @@ -179,7 +175,9 @@ public override void Visit(EntityUid mindId, EntityUid entity, MindComponent? mi return; } - GetSession(mind)?.AttachToEntity(entity); + if (GetSession(mind) is { } session) + _actor.Attach(entity, session); + mind.VisitingEntity = entity; // EnsureComp instead of AddComp to deal with deferred deletions. @@ -198,13 +196,14 @@ public override void UnVisit(EntityUid mindId, MindComponent? mind = null) if (mind.VisitingEntity == null) return; - RemoveVisitingEntity(mind); + RemoveVisitingEntity(mindId, mind); if (mind.Session == null || mind.Session.AttachedEntity == mind.VisitingEntity) return; var owned = mind.OwnedEntity; - GetSession(mind)?.AttachToEntity(owned); + if (GetSession(mind) is { } session) + _actor.Attach(owned, session); if (owned.HasValue) { @@ -219,11 +218,10 @@ public override void TransferTo(EntityUid mindId, EntityUid? entity, bool ghostC if (mind == null && !Resolve(mindId, ref mind)) return; - base.TransferTo(mindId, entity, ghostCheckOverride, createGhost, mind); - if (entity == mind.OwnedEntity) return; + Dirty(mindId, mind); MindContainerComponent? component = null; var alreadyAttached = false; @@ -247,27 +245,33 @@ public override void TransferTo(EntityUid mindId, EntityUid? entity, bool ghostC } else if (createGhost) { + // TODO remove this option. + // Transfer-to-null should just detach a mind. + // If people want to create a ghost, that should be done explicitly via some TransferToGhost() method, not + // not implicitly via optional arguments. + var position = Deleted(mind.OwnedEntity) ? _gameTicker.GetObserverSpawnPoint().ToMap(EntityManager, _transform) : Transform(mind.OwnedEntity.Value).MapPosition; entity = Spawn("MobObserver", position); + component = EnsureComp(entity.Value); var ghostComponent = Comp(entity.Value); _ghosts.SetCanReturnToBody(ghostComponent, false); } - var oldComp = mind.OwnedComponent; var oldEntity = mind.OwnedEntity; - if (oldComp != null && oldEntity != null) + if (TryComp(oldEntity, out MindContainerComponent? oldContainer)) { - if (oldComp.Mind != null) - _pvsOverride.ClearOverride(oldComp.Mind.Value); - oldComp.Mind = null; - RaiseLocalEvent(oldEntity.Value, new MindRemovedMessage(oldEntity.Value, mind), true); + oldContainer.Mind = null; + mind.OwnedEntity = null; + Entity mindEnt = (mindId, mind); + Entity containerEnt = (oldEntity.Value, oldContainer); + RaiseLocalEvent(oldEntity.Value, new MindRemovedMessage(mindEnt, containerEnt)); + RaiseLocalEvent(mindId, new MindGotRemovedEvent(mindEnt, containerEnt)); + Dirty(oldEntity.Value, oldContainer); } - SetOwnedEntity(mind, entity, component); - // Don't do the full deletion cleanup if we're transferring to our VisitingEntity if (alreadyAttached) { @@ -281,7 +285,7 @@ public override void TransferTo(EntityUid mindId, EntityUid? entity, bool ghostC || !TryComp(mind.VisitingEntity!, out GhostComponent? ghostComponent) // visiting entity is not a Ghost || !ghostComponent.CanReturnToBody)) // it is a ghost, but cannot return to body anyway, so it's okay { - RemoveVisitingEntity(mind); + RemoveVisitingEntity(mindId, mind); } // Player is CURRENTLY connected. @@ -289,14 +293,20 @@ public override void TransferTo(EntityUid mindId, EntityUid? entity, bool ghostC if (session != null && !alreadyAttached && mind.VisitingEntity == null) { _actor.Attach(entity, session, true); + DebugTools.Assert(session.AttachedEntity == entity, $"Failed to attach entity."); Log.Info($"Session {session.Name} transferred to entity {entity}."); } - if (mind.OwnedComponent != null) + if (entity != null) { - mind.OwnedComponent.Mind = mindId; - RaiseLocalEvent(mind.OwnedEntity!.Value, new MindAddedMessage(), true); - mind.OriginalOwnedEntity ??= mind.OwnedEntity; + component!.Mind = mindId; + mind.OwnedEntity = entity; + mind.OriginalOwnedEntity ??= GetNetEntity(mind.OwnedEntity); + Entity mindEnt = (mindId, mind); + Entity containerEnt = (entity.Value, component); + RaiseLocalEvent(entity.Value, new MindAddedMessage(mindEnt, containerEnt)); + RaiseLocalEvent(mindId, new MindGotAddedEvent(mindEnt, containerEnt)); + Dirty(entity.Value, component); } } @@ -313,6 +323,7 @@ public override void SetUserId(EntityUid mindId, NetUserId? userId, MindComponen if (mind.UserId == userId) return; + Dirty(mindId, mind); _pvsOverride.ClearOverride(mindId); if (userId != null && !_players.TryGetPlayerData(userId.Value, out _)) { @@ -363,4 +374,27 @@ public override void SetUserId(EntityUid mindId, NetUserId? userId, MindComponen if (_players.GetPlayerData(userId.Value).ContentData() is { } data) data.Mind = mindId; } + + public void ControlMob(EntityUid user, EntityUid target) + { + if (TryComp(user, out ActorComponent? actor)) + ControlMob(actor.PlayerSession.UserId, target); + } + + public void ControlMob(NetUserId user, EntityUid target) + { + var (mindId, mind) = GetOrCreateMind(user); + + if (mind.CurrentEntity == target) + return; + + if (mind.OwnedEntity == target) + { + UnVisit(mindId, mind); + return; + } + + MakeSentientCommand.MakeSentient(target, EntityManager); + TransferTo(mindId, target, ghostCheckOverride: true, mind: mind); + } } diff --git a/Content.Server/Mind/Toolshed/MindCommand.cs b/Content.Server/Mind/Toolshed/MindCommand.cs index b53f9a6a9cd..917e6fb7f1a 100644 --- a/Content.Server/Mind/Toolshed/MindCommand.cs +++ b/Content.Server/Mind/Toolshed/MindCommand.cs @@ -1,5 +1,5 @@ using Content.Shared.Mind; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; using Robust.Shared.Toolshed.Syntax; @@ -15,7 +15,7 @@ public sealed class MindCommand : ToolshedCommand private SharedMindSystem? _mind; [CommandImplementation("get")] - public MindComponent? Get([PipedArgument] IPlayerSession session) + public MindComponent? Get([PipedArgument] ICommonSession session) { _mind ??= GetSys(); return _mind.TryGetMind(session, out _, out var mind) ? mind : null; @@ -32,7 +32,7 @@ public sealed class MindCommand : ToolshedCommand public EntityUid Control( [CommandInvocationContext] IInvocationContext ctx, [PipedArgument] EntityUid target, - [CommandArgument] ValueRef playerRef) + [CommandArgument] ValueRef playerRef) { _mind ??= GetSys(); diff --git a/Content.Server/Motd/MOTDCommand.cs b/Content.Server/Motd/MOTDCommand.cs index a1aa4d2df59..9e59589b95b 100644 --- a/Content.Server/Motd/MOTDCommand.cs +++ b/Content.Server/Motd/MOTDCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Motd; @@ -14,10 +13,10 @@ internal sealed class MOTDCommand : LocalizedCommands [Dependency] private readonly IAdminManager _adminManager = default!; public override string Command => "motd"; - + public override void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = (IPlayerSession?)shell.Player; + var player = shell.Player; if (args.Length < 1 || (player != null && _adminManager is AdminManager aMan && !aMan.CanCommand(player, "set-motd"))) shell.ConsoleHost.ExecuteCommand(shell.Player, "get-motd"); else @@ -26,7 +25,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args) public override CompletionResult GetCompletion(IConsoleShell shell, string[] args) { - var player = (IPlayerSession?)shell.Player; + var player = shell.Player; if (player != null && _adminManager is AdminManager aMan && !aMan.CanCommand(player, "set-motd")) return CompletionResult.Empty; if (args.Length == 1) diff --git a/Content.Server/Motd/MOTDSystem.cs b/Content.Server/Motd/MOTDSystem.cs index e749fe48f30..39d780f108c 100644 --- a/Content.Server/Motd/MOTDSystem.cs +++ b/Content.Server/Motd/MOTDSystem.cs @@ -2,9 +2,9 @@ using Content.Server.GameTicking; using Content.Shared.CCVar; using Content.Shared.Chat; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Configuration; +using Robust.Shared.Player; namespace Content.Server.Motd; @@ -41,7 +41,7 @@ public void TrySendMOTD() { if (string.IsNullOrEmpty(_messageOfTheDay)) return; - + var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay)); _chatManager.ChatMessageToAll(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, recordReplay: true); } @@ -49,11 +49,11 @@ public void TrySendMOTD() /// /// Sends the Message Of The Day, if any, to a specific player. /// - public void TrySendMOTD(IPlayerSession player) + public void TrySendMOTD(ICommonSession player) { if (string.IsNullOrEmpty(_messageOfTheDay)) return; - + var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay)); _chatManager.ChatMessageToOne(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, client: player.ConnectedClient); } @@ -68,10 +68,10 @@ public void TrySendMOTD(IConsoleShell shell) { if (string.IsNullOrEmpty(_messageOfTheDay)) return; - + var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay)); shell.WriteLine(wrappedMessage); - if (shell.Player is IPlayerSession player) + if (shell.Player is { } player) _chatManager.ChatMessageToOne(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, client: player.ConnectedClient); } @@ -92,7 +92,7 @@ private void OnMOTDChanged(string val) { if (val == _messageOfTheDay) return; - + _messageOfTheDay = val; TrySendMOTD(); } diff --git a/Content.Server/Motd/SetMOTDCommand.cs b/Content.Server/Motd/SetMOTDCommand.cs index f3f52b06702..9678781c87a 100644 --- a/Content.Server/Motd/SetMOTDCommand.cs +++ b/Content.Server/Motd/SetMOTDCommand.cs @@ -4,7 +4,6 @@ using Content.Shared.Database; using Content.Shared.CCVar; using Content.Server.Chat.Managers; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -21,18 +20,18 @@ public sealed class SetMotdCommand : LocalizedCommands [Dependency] private readonly IConfigurationManager _configurationManager = default!; public override string Command => "set-motd"; - + public override void Execute(IConsoleShell shell, string argStr, string[] args) { string motd = ""; - var player = (IPlayerSession?)shell.Player; + var player = shell.Player; if (args.Length > 0) { motd = string.Join(" ", args).Trim(); if (player != null && _chatManager.MessageCharacterLimit(player, motd)) return; // check function prints its own error response } - + _configurationManager.SetCVar(CCVars.MOTD, motd); // A hook in MOTDSystem broadcasts changes to the MOTD to everyone so we don't need to do it here. if (string.IsNullOrEmpty(motd)) { diff --git a/Content.Server/Movement/Systems/LagCompensationSystem.cs b/Content.Server/Movement/Systems/LagCompensationSystem.cs index 64965c2fee7..0576fe8f255 100644 --- a/Content.Server/Movement/Systems/LagCompensationSystem.cs +++ b/Content.Server/Movement/Systems/LagCompensationSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Movement.Components; using Robust.Server.Player; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Movement.Systems; diff --git a/Content.Server/NPC/Commands/NPCCommand.cs b/Content.Server/NPC/Commands/NPCCommand.cs index 57fe223b669..7f9e56b8cac 100644 --- a/Content.Server/NPC/Commands/NPCCommand.cs +++ b/Content.Server/NPC/Commands/NPCCommand.cs @@ -2,7 +2,6 @@ using Content.Server.EUI; using Content.Server.NPC.UI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.NPC.Commands; @@ -15,7 +14,7 @@ public sealed class NPCCommand : IConsoleCommand public string Help => $"{Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession playerSession) + if (shell.Player is not { } playerSession) { return; } diff --git a/Content.Server/NPC/HTN/HTNSystem.cs b/Content.Server/NPC/HTN/HTNSystem.cs index 2c1dadb1279..a7689fbabed 100644 --- a/Content.Server/NPC/HTN/HTNSystem.cs +++ b/Content.Server/NPC/HTN/HTNSystem.cs @@ -4,17 +4,14 @@ using Content.Server.Administration.Managers; using Robust.Shared.CPUJob.JobQueues; using Robust.Shared.CPUJob.JobQueues.Queues; -using Content.Server.NPC.Components; using Content.Server.NPC.HTN.PrimitiveTasks; using Content.Server.NPC.Systems; using Content.Shared.Administration; using Content.Shared.Mobs; using Content.Shared.NPC; -using Content.Shared.NPC; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -48,7 +45,7 @@ public override void Initialize() private void OnHTNMessage(RequestHTNMessage msg, EntitySessionEventArgs args) { - if (!_admin.HasAdminFlag((IPlayerSession) args.SenderSession, AdminFlags.Debug)) + if (!_admin.HasAdminFlag(args.SenderSession, AdminFlags.Debug)) { _subscribers.Remove(args.SenderSession); return; diff --git a/Content.Server/NPC/Pathfinding/PathfindingSystem.cs b/Content.Server/NPC/Pathfinding/PathfindingSystem.cs index bb0eff7b391..1b1f6f54761 100644 --- a/Content.Server/NPC/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/NPC/Pathfinding/PathfindingSystem.cs @@ -13,7 +13,7 @@ using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Threading; using Robust.Shared.Timing; @@ -528,7 +528,7 @@ private void SendDebug(PathRequest request) private void OnBreadcrumbs(RequestPathfindingDebugMessage msg, EntitySessionEventArgs args) { - var pSession = (IPlayerSession) args.SenderSession; + var pSession = args.SenderSession; if (!_adminManager.HasAdminFlag(pSession, AdminFlags.Debug)) { diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.cs index 61b43df6f00..e5b62acfe80 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.cs @@ -17,14 +17,12 @@ using Content.Shared.NPC.Events; using Content.Shared.Physics; using Content.Shared.Weapons.Melee; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Random; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -147,7 +145,7 @@ public override void Shutdown() private void OnDebugRequest(RequestNPCSteeringDebugEvent msg, EntitySessionEventArgs args) { - if (!_admin.IsAdmin((IPlayerSession)args.SenderSession)) + if (!_admin.IsAdmin(args.SenderSession)) return; if (msg.Enabled) diff --git a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs index 6f3c3b3f9df..0182bd7ca78 100644 --- a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs +++ b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs @@ -23,7 +23,7 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(BeforePlant); + SubscribeLocalEvent(OnAttemptStick); SubscribeLocalEvent(OnStuck); SubscribeLocalEvent(OnExplode); } @@ -31,14 +31,17 @@ public override void Initialize() /// /// Require that the planter is a ninja and the charge is near the target warp point. /// - private void BeforePlant(EntityUid uid, SpiderChargeComponent comp, BeforeRangedInteractEvent args) + private void OnAttemptStick(EntityUid uid, SpiderChargeComponent comp, AttemptEntityStickEvent args) { + if (args.Cancelled) + return; + var user = args.User; if (!_mind.TryGetRole(user, out var role)) { _popup.PopupEntity(Loc.GetString("spider-charge-not-ninja"), user, user); - args.Handled = true; + args.Cancelled = true; return; } @@ -47,12 +50,14 @@ private void BeforePlant(EntityUid uid, SpiderChargeComponent comp, BeforeRanged return; // assumes warp point still exists - var target = Transform(role.SpiderChargeTarget.Value).MapPosition; - var coords = args.ClickLocation.ToMap(EntityManager, _transform); - if (!coords.InRange(target, comp.Range)) + var targetXform = Transform(role.SpiderChargeTarget.Value); + var locXform = Transform(args.Target); + if (locXform.MapID != targetXform.MapID || + (_transform.GetWorldPosition(locXform) - _transform.GetWorldPosition(targetXform)).LengthSquared() > comp.Range * comp.Range) { _popup.PopupEntity(Loc.GetString("spider-charge-too-far"), user, user); - args.Handled = true; + args.Cancelled = true; + return; } } diff --git a/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs b/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs index e4bd303150b..9ee9702c5bf 100644 --- a/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs +++ b/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs @@ -9,6 +9,7 @@ using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.NodeContainer.EntitySystems @@ -29,7 +30,7 @@ public sealed class NodeGroupSystem : EntitySystem private readonly List _visDeletes = new(); private readonly List _visSends = new(); - private readonly HashSet _visPlayers = new(); + private readonly HashSet _visPlayers = new(); private readonly HashSet _toRemake = new(); private readonly HashSet _nodeGroups = new(); private readonly HashSet _toRemove = new(); @@ -74,7 +75,7 @@ public override void Shutdown() private void HandleEnableMsg(NodeVis.MsgEnable msg, EntitySessionEventArgs args) { - var session = (IPlayerSession) args.SenderSession; + var session = args.SenderSession; if (!_adminManager.HasAdminFlag(session, AdminFlags.Debug)) return; @@ -397,7 +398,7 @@ private void VisDoUpdate(float frametime) } } - private void VisSendFullStateImmediate(IPlayerSession player) + private void VisSendFullStateImmediate(ICommonSession player) { var msg = new NodeVis.MsgData(); diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 8406ce222d8..ff4ec41dd99 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -17,6 +17,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; +using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Events; using Content.Shared.Inventory; using Content.Shared.Mobs.Systems; @@ -101,6 +102,9 @@ private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInterac if (!TryComp(target, out var body)) return (false, false); + if (HasComp(food)) + return (false, false); + if (_openable.IsClosed(food, user)) return (false, true); diff --git a/Content.Server/Nutrition/Hungry.cs b/Content.Server/Nutrition/Hungry.cs index c27f302a8d1..ae68dcd2fda 100644 --- a/Content.Server/Nutrition/Hungry.cs +++ b/Content.Server/Nutrition/Hungry.cs @@ -1,9 +1,7 @@ using Content.Server.Administration; -using Content.Server.Nutrition.Components; using Content.Shared.Administration; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Nutrition @@ -19,7 +17,7 @@ public sealed class Hungry : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You cannot use this command unless you are a player."); diff --git a/Content.Server/Objectives/Commands/ListObjectivesCommand.cs b/Content.Server/Objectives/Commands/ListObjectivesCommand.cs index 93dec3fa44d..97fc943269a 100644 --- a/Content.Server/Objectives/Commands/ListObjectivesCommand.cs +++ b/Content.Server/Objectives/Commands/ListObjectivesCommand.cs @@ -18,7 +18,7 @@ public sealed class ListObjectivesCommand : LocalizedCommands public override void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null || !_players.TryGetSessionByUsername(args[0], out player)) { shell.WriteError(LocalizationManager.GetString("shell-target-player-does-not-exist")); diff --git a/Content.Server/Objectives/Components/HijackShuttleConditionComponent.cs b/Content.Server/Objectives/Components/HijackShuttleConditionComponent.cs new file mode 100644 index 00000000000..2f07086af65 --- /dev/null +++ b/Content.Server/Objectives/Components/HijackShuttleConditionComponent.cs @@ -0,0 +1,11 @@ +using Content.Server.Objectives.Systems; + +namespace Content.Server.Objectives.Components; + +/// +/// Objective condition that requires the player to leave station of escape shuttle with only antags on board or handcuffed humanoids +/// +[RegisterComponent, Access(typeof(HijackShuttleConditionSystem))] +public sealed partial class HijackShuttleConditionComponent : Component +{ +} diff --git a/Content.Server/Corvax/Objectives/Systems/HijackShuttleConditionSystem.cs b/Content.Server/Objectives/Systems/HijackShuttleConditionSystem.cs similarity index 95% rename from Content.Server/Corvax/Objectives/Systems/HijackShuttleConditionSystem.cs rename to Content.Server/Objectives/Systems/HijackShuttleConditionSystem.cs index 9e4d2e476c0..9e0d2c3d5b5 100644 --- a/Content.Server/Corvax/Objectives/Systems/HijackShuttleConditionSystem.cs +++ b/Content.Server/Objectives/Systems/HijackShuttleConditionSystem.cs @@ -1,4 +1,4 @@ -using Content.Server.Corvax.Objectives.Components; +using Content.Server.Objectives.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Systems; using Content.Shared.Cuffs.Components; @@ -10,7 +10,7 @@ using Content.Shared.Roles; using Robust.Shared.Player; -namespace Content.Server.Corvax.Objectives.Systems; +namespace Content.Server.Objectives.Systems; public sealed class HijackShuttleConditionSystem : EntitySystem { @@ -33,7 +33,7 @@ private void OnGetProgress(EntityUid uid, HijackShuttleConditionComponent comp, private float GetProgress(EntityUid mindId, MindComponent mind) { - // not escaping alive if you're deleted/dead + // Not escaping alive if you're deleted/dead if (mind.OwnedEntity == null || _mind.IsCharacterDeadIc(mind)) return 0f; diff --git a/Content.Server/PDA/PdaSystem.cs b/Content.Server/PDA/PdaSystem.cs index 6c506dc3dd2..44e26598412 100644 --- a/Content.Server/PDA/PdaSystem.cs +++ b/Content.Server/PDA/PdaSystem.cs @@ -4,9 +4,6 @@ using Content.Server.Instruments; using Content.Server.Light.EntitySystems; using Content.Server.Light.Events; -using Content.Server.MassMedia.Components; -using Content.Server.MassMedia.Systems; -using Content.Server.Mind; using Content.Server.PDA.Ringer; using Content.Server.Station.Systems; using Content.Server.Store.Components; @@ -16,7 +13,6 @@ using Content.Shared.Light.Components; using Content.Shared.PDA; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Containers; namespace Content.Server.PDA @@ -180,7 +176,7 @@ private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaShowRingtoneMessage return; if (HasComp(uid)) - _ringer.ToggleRingerUI(uid, (IPlayerSession) msg.Session); + _ringer.ToggleRingerUI(uid, msg.Session); } private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaShowMusicMessage msg) @@ -189,7 +185,7 @@ private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaShowMusicMessage ms return; if (TryComp(uid, out var instrument)) - _instrument.ToggleInstrumentUi(uid, (IPlayerSession) msg.Session, instrument); + _instrument.ToggleInstrumentUi(uid, msg.Session, instrument); } private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaShowUplinkMessage msg) diff --git a/Content.Server/PDA/Ringer/RingerSystem.cs b/Content.Server/PDA/Ringer/RingerSystem.cs index a772e76bc45..7494d5e12ce 100644 --- a/Content.Server/PDA/Ringer/RingerSystem.cs +++ b/Content.Server/PDA/Ringer/RingerSystem.cs @@ -7,7 +7,6 @@ using Content.Shared.Popups; using Content.Shared.Store; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Network; using Robust.Shared.Player; @@ -182,7 +181,7 @@ private void UpdateRingerUserInterface(EntityUid uid, RingerComponent ringer, bo _ui.SetUiState(bui, new RingerUpdateState(isPlaying, ringer.Ringtone)); } - public bool ToggleRingerUI(EntityUid uid, IPlayerSession session) + public bool ToggleRingerUI(EntityUid uid, ICommonSession session) { if (_ui.TryGetUi(uid, RingerUiKey.Key, out var bui)) _ui.ToggleUi(bui, session); diff --git a/Content.Server/Paper/PaperSystem.cs b/Content.Server/Paper/PaperSystem.cs index f38013e14d1..553bcaa0a21 100644 --- a/Content.Server/Paper/PaperSystem.cs +++ b/Content.Server/Paper/PaperSystem.cs @@ -4,15 +4,11 @@ using Content.Server.UserInterface; using Content.Shared.Database; using Content.Shared.Examine; -using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Paper; using Content.Shared.Tag; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Player; -using Robust.Shared.Utility; -using Robust.Shared.Audio; using static Content.Shared.Paper.SharedPaperComponent; namespace Content.Server.Paper @@ -207,7 +203,7 @@ public void SetContent(EntityUid uid, string content, PaperComponent? paperComp _appearance.SetData(uid, PaperVisuals.Status, status, appearance); } - public void UpdateUserInterface(EntityUid uid, PaperComponent? paperComp = null, IPlayerSession? session = null) + public void UpdateUserInterface(EntityUid uid, PaperComponent? paperComp = null, ICommonSession? session = null) { if (!Resolve(uid, ref paperComp)) return; diff --git a/Content.Server/Parallax/BiomeSystem.cs b/Content.Server/Parallax/BiomeSystem.cs index a9d78afa865..c9017ac821e 100644 --- a/Content.Server/Parallax/BiomeSystem.cs +++ b/Content.Server/Parallax/BiomeSystem.cs @@ -282,9 +282,8 @@ public override void Update(float frameTime) } // Get chunks in range - foreach (var client in Filter.GetAllPlayers(_playerManager)) + foreach (var pSession in Filter.GetAllPlayers(_playerManager)) { - var pSession = (IPlayerSession) client; if (xformQuery.TryGetComponent(pSession.AttachedEntity, out var xform) && _handledEntities.Add(pSession.AttachedEntity.Value) && diff --git a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs index 20ed2769670..f200c991d7f 100644 --- a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs +++ b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs @@ -2,11 +2,10 @@ using Content.Server.Power.Components; using Content.Shared.Database; using Content.Shared.Singularity.Components; -using Robust.Server.Player; -using Robust.Server.GameObjects; using Robust.Shared.Utility; using System.Diagnostics; using Content.Shared.CCVar; +using Robust.Shared.Player; namespace Content.Server.ParticleAccelerator.EntitySystems; @@ -60,7 +59,7 @@ public void Fire(EntityUid uid, TimeSpan curTime, ParticleAcceleratorControlBoxC FireEmitter(comp.StarboardEmitter!.Value, strength); } - public void SwitchOn(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) + public void SwitchOn(EntityUid uid, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) { if (!Resolve(uid, ref comp)) return; @@ -83,7 +82,7 @@ public void SwitchOn(EntityUid uid, IPlayerSession? user = null, ParticleAcceler UpdateUI(uid, comp); } - public void SwitchOff(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) + public void SwitchOff(EntityUid uid, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) { if (!Resolve(uid, ref comp)) return; @@ -131,7 +130,7 @@ public void PowerOff(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp UpdateUI(uid, comp); } - public void SetStrength(EntityUid uid, ParticleAcceleratorPowerState strength, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) + public void SetStrength(EntityUid uid, ParticleAcceleratorPowerState strength, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) { if (!Resolve(uid, ref comp)) return; @@ -347,10 +346,10 @@ private void OnUISetEnableMessage(EntityUid uid, ParticleAcceleratorControlBoxCo if (msg.Enabled) { if (comp.Assembled) - SwitchOn(uid, (IPlayerSession?) msg.Session, comp); + SwitchOn(uid, msg.Session, comp); } else - SwitchOff(uid, (IPlayerSession?) msg.Session, comp); + SwitchOff(uid, msg.Session, comp); UpdateUI(uid, comp); } @@ -364,7 +363,7 @@ private void OnUISetPowerMessage(EntityUid uid, ParticleAcceleratorControlBoxCom if (TryComp(uid, out var apcPower) && !apcPower.Powered) return; - SetStrength(uid, msg.State, (IPlayerSession?) msg.Session, comp); + SetStrength(uid, msg.State, msg.Session, comp); UpdateUI(uid, comp); } @@ -378,7 +377,7 @@ private void OnUIRescanMessage(EntityUid uid, ParticleAcceleratorControlBoxCompo if (TryComp(uid, out var apcPower) && !apcPower.Powered) return; - RescanParts(uid, (IPlayerSession?) msg.Session, comp); + RescanParts(uid, msg.Session, comp); UpdateUI(uid, comp); } diff --git a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs index 271d17a0c49..abc68543ff3 100644 --- a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs +++ b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs @@ -2,9 +2,9 @@ using System.Numerics; using Content.Server.ParticleAccelerator.Components; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Events; +using Robust.Shared.Player; namespace Content.Server.ParticleAccelerator.EntitySystems; @@ -18,7 +18,7 @@ private void InitializePartSystem() SubscribeLocalEvent(BodyTypeChanged); } - public void RescanParts(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? controller = null) + public void RescanParts(EntityUid uid, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? controller = null) { if (!Resolve(uid, ref controller)) return; diff --git a/Content.Server/Pinpointer/ProximityBeeperSystem.cs b/Content.Server/Pinpointer/ProximityBeeperSystem.cs index b473d973724..d52223e2b4e 100644 --- a/Content.Server/Pinpointer/ProximityBeeperSystem.cs +++ b/Content.Server/Pinpointer/ProximityBeeperSystem.cs @@ -80,7 +80,10 @@ public void UpdateBeep(EntityUid uid, ProximityBeeperComponent? component = null var scalingFactor = distance / component.MaximumDistance; var interval = (component.MaxBeepInterval - component.MinBeepInterval) * scalingFactor + component.MinBeepInterval; + component.NextBeepTime += interval; + if (component.NextBeepTime < _timing.CurTime) // Prevents spending time out of range accumulating a deficit which causes a series of very rapid beeps when comeing into range. + component.NextBeepTime = _timing.CurTime + interval; } /// diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs index 50c64e718c3..bcc6f211ed8 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs @@ -5,18 +5,18 @@ using Content.Server.Database; using Content.Shared.CCVar; using Content.Shared.Players.PlayTimeTracking; -using Robust.Server.Player; using Robust.Shared.Asynchronous; using Robust.Shared.Collections; using Robust.Shared.Configuration; using Robust.Shared.Exceptions; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Server.Players.PlayTimeTracking; -public delegate void CalcPlayTimeTrackersCallback(IPlayerSession player, HashSet trackers); +public delegate void CalcPlayTimeTrackersCallback(ICommonSession player, HashSet trackers); /// /// Tracks play time for players, across all roles. @@ -66,7 +66,7 @@ public sealed class PlayTimeTrackingManager private ISawmill _sawmill = default!; // List of players that need some kind of update (refresh timers or resend). - private ValueList _playersDirty; + private ValueList _playersDirty; // DB auto-saving logic. private TimeSpan _saveInterval; @@ -76,7 +76,7 @@ public sealed class PlayTimeTrackingManager // We must block server shutdown on these to avoid losing data. private readonly List _pendingSaveTasks = new(); - private readonly Dictionary _playTimeData = new(); + private readonly Dictionary _playTimeData = new(); public event CalcPlayTimeTrackersCallback? CalcTrackers; @@ -139,7 +139,7 @@ private void UpdateDirtyPlayers() _playersDirty.Clear(); } - private void RefreshSingleTracker(IPlayerSession dirty, PlayTimeData data, TimeSpan time) + private void RefreshSingleTracker(ICommonSession dirty, PlayTimeData data, TimeSpan time) { DebugTools.Assert(data.Initialized); @@ -181,7 +181,7 @@ public void FlushAllTrackers() /// so APIs like return up-to-date info. /// /// - public void FlushTracker(IPlayerSession player) + public void FlushTracker(ICommonSession player) { var time = _timing.RealTime; var data = _playTimeData[player]; @@ -201,7 +201,7 @@ private static void FlushSingleTracker(PlayTimeData data, TimeSpan time) } } - private void SendPlayTimes(IPlayerSession pSession) + private void SendPlayTimes(ICommonSession pSession) { var roles = GetTrackerTimes(pSession); @@ -228,7 +228,7 @@ public async void Save() /// /// Save all modified time trackers for a player to the database. /// - public async void SaveSession(IPlayerSession session) + public async void SaveSession(ICommonSession session) { // This causes all trackers to refresh, ah well. FlushAllTrackers(); @@ -278,7 +278,7 @@ private async Task DoSaveAsync() _sawmill.Debug($"Saved {log.Count} trackers"); } - private async Task DoSaveSessionAsync(IPlayerSession session) + private async Task DoSaveSessionAsync(ICommonSession session) { var log = new List(); @@ -299,7 +299,7 @@ private async Task DoSaveSessionAsync(IPlayerSession session) _sawmill.Debug($"Saved {log.Count} trackers for {session.Name}"); } - public async Task LoadData(IPlayerSession session, CancellationToken cancel) + public async Task LoadData(ICommonSession session, CancellationToken cancel) { var data = new PlayTimeData(); _playTimeData.Add(session, data); @@ -318,14 +318,14 @@ public async Task LoadData(IPlayerSession session, CancellationToken cancel) QueueSendTimers(session); } - public void ClientDisconnected(IPlayerSession session) + public void ClientDisconnected(ICommonSession session) { SaveSession(session); _playTimeData.Remove(session); } - public void AddTimeToTracker(IPlayerSession id, string tracker, TimeSpan time) + public void AddTimeToTracker(ICommonSession id, string tracker, TimeSpan time) { if (!_playTimeData.TryGetValue(id, out var data) || !data.Initialized) throw new InvalidOperationException("Play time info is not yet loaded for this player!"); @@ -341,17 +341,17 @@ private static void AddTimeToTracker(PlayTimeData data, string tracker, TimeSpan data.DbTrackersDirty.Add(tracker); } - public void AddTimeToOverallPlaytime(IPlayerSession id, TimeSpan time) + public void AddTimeToOverallPlaytime(ICommonSession id, TimeSpan time) { AddTimeToTracker(id, PlayTimeTrackingShared.TrackerOverall, time); } - public TimeSpan GetOverallPlaytime(IPlayerSession id) + public TimeSpan GetOverallPlaytime(ICommonSession id) { return GetPlayTimeForTracker(id, PlayTimeTrackingShared.TrackerOverall); } - public bool TryGetTrackerTimes(IPlayerSession id, [NotNullWhen(true)] out Dictionary? time) + public bool TryGetTrackerTimes(ICommonSession id, [NotNullWhen(true)] out Dictionary? time) { time = null; @@ -364,7 +364,7 @@ public bool TryGetTrackerTimes(IPlayerSession id, [NotNullWhen(true)] out Dictio return true; } - public Dictionary GetTrackerTimes(IPlayerSession id) + public Dictionary GetTrackerTimes(ICommonSession id) { if (!_playTimeData.TryGetValue(id, out var data) || !data.Initialized) throw new InvalidOperationException("Play time info is not yet loaded for this player!"); @@ -372,7 +372,7 @@ public Dictionary GetTrackerTimes(IPlayerSession id) return data.TrackerTimes; } - public TimeSpan GetPlayTimeForTracker(IPlayerSession id, string tracker) + public TimeSpan GetPlayTimeForTracker(ICommonSession id, string tracker) { if (!_playTimeData.TryGetValue(id, out var data) || !data.Initialized) throw new InvalidOperationException("Play time info is not yet loaded for this player!"); @@ -383,7 +383,7 @@ public TimeSpan GetPlayTimeForTracker(IPlayerSession id, string tracker) /// /// Queue for play time trackers to be refreshed on a player, in case the set of active trackers may have changed. /// - public void QueueRefreshTrackers(IPlayerSession player) + public void QueueRefreshTrackers(ICommonSession player) { if (DirtyPlayer(player) is { } data) data.NeedRefreshTackers = true; @@ -392,13 +392,13 @@ public void QueueRefreshTrackers(IPlayerSession player) /// /// Queue for play time information to be sent to a client, for showing in UIs etc. /// - public void QueueSendTimers(IPlayerSession player) + public void QueueSendTimers(ICommonSession player) { if (DirtyPlayer(player) is { } data) data.NeedSendTimers = true; } - private PlayTimeData? DirtyPlayer(IPlayerSession player) + private PlayTimeData? DirtyPlayer(ICommonSession player) { if (!_playTimeData.TryGetValue(player, out var data) || !data.Initialized) return null; diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs index 13d0794dd5e..f865b25bacf 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs @@ -14,6 +14,7 @@ using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -55,7 +56,7 @@ public override void Shutdown() _tracking.CalcTrackers -= CalcTrackers; } - private void CalcTrackers(IPlayerSession player, HashSet trackers) + private void CalcTrackers(ICommonSession player, HashSet trackers) { if (_afk.IsAfk(player)) return; @@ -67,7 +68,7 @@ private void CalcTrackers(IPlayerSession player, HashSet trackers) trackers.UnionWith(GetTimedRoles(player)); } - private bool IsPlayerAlive(IPlayerSession session) + private bool IsPlayerAlive(ICommonSession session) { var attached = session.AttachedEntity; if (attached == null) @@ -93,7 +94,7 @@ public IEnumerable GetTimedRoles(EntityUid mindId) } } - private IEnumerable GetTimedRoles(IPlayerSession session) + private IEnumerable GetTimedRoles(ICommonSession session) { var contentData = _playerManager.GetPlayerData(session.UserId).ContentData(); @@ -156,7 +157,7 @@ private void OnPlayerJoinedLobby(PlayerJoinedLobbyEvent ev) _tracking.QueueSendTimers(ev.PlayerSession); } - public bool IsAllowed(IPlayerSession player, string role) + public bool IsAllowed(ICommonSession player, string role) { if (!_prototypes.TryIndex(role, out var job) || job.Requirements == null || @@ -168,7 +169,7 @@ public bool IsAllowed(IPlayerSession player, string role) return JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes); } - public HashSet GetDisallowedJobs(IPlayerSession player) + public HashSet GetDisallowedJobs(ICommonSession player) { var roles = new HashSet(); if (!_cfg.GetCVar(CCVars.GameRoleTimers)) @@ -230,7 +231,7 @@ public void RemoveDisallowedJobs(NetUserId userId, ref List jobs) } } - public void PlayerRolesChanged(IPlayerSession player) + public void PlayerRolesChanged(ICommonSession player) { _tracking.QueueRefreshTrackers(player); } diff --git a/Content.Server/Players/PlayerData.cs b/Content.Server/Players/PlayerData.cs deleted file mode 100644 index b0ca6f3c189..00000000000 --- a/Content.Server/Players/PlayerData.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Content.Shared.Players; -using Robust.Server.Player; -using Robust.Shared.Players; - -namespace Content.Server.Players -{ - public static class PlayerDataExt - { - /// - /// Gets the correctly cast instance of content player data from an engine player data storage. - /// - public static PlayerData? ContentData(this IPlayerSession session) - { - return session.Data.ContentData(); - } - - public static PlayerData? ContentData(this ICommonSession session) - { - return ((IPlayerSession) session).ContentData(); - } - - /// - /// Gets the mind that is associated with this player. - /// - public static EntityUid? GetMind(this IPlayerSession session) - { - return session.Data.ContentData()?.Mind; - } - } -} diff --git a/Content.Server/Players/PlayerSystem.cs b/Content.Server/Players/PlayerSystem.cs index 0c407aa876b..c79683c3385 100644 --- a/Content.Server/Players/PlayerSystem.cs +++ b/Content.Server/Players/PlayerSystem.cs @@ -1,11 +1,11 @@ using Content.Shared.Players; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Players; public sealed class PlayerSystem : SharedPlayerSystem { - public override PlayerData? ContentData(ICommonSession? session) + public override ContentPlayerData? ContentData(ICommonSession? session) { return session?.ContentData(); } diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index b253e32e371..6fcdfcf994b 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -20,7 +20,6 @@ using Robust.Shared.Input.Binding; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Replays; using Robust.Shared.Timing; @@ -170,7 +169,7 @@ public bool TryPoint(ICommonSession? session, EntityCoordinates coords, EntityUi } // Get players that are in range and whose visibility layer matches the arrow's. - bool ViewerPredicate(IPlayerSession playerSession) + bool ViewerPredicate(ICommonSession playerSession) { if (!_minds.TryGetMind(playerSession, out _, out var mind) || mind.CurrentEntity is not { Valid: true } ent || @@ -182,7 +181,7 @@ bool ViewerPredicate(IPlayerSession playerSession) } var viewers = Filter.Empty() - .AddWhere(session1 => ViewerPredicate((IPlayerSession) session1)) + .AddWhere(session1 => ViewerPredicate(session1)) .Recipients; string selfMessage; diff --git a/Content.Server/Popups/PopupSystem.cs b/Content.Server/Popups/PopupSystem.cs index 483d4f3d3f7..61ccaf4423a 100644 --- a/Content.Server/Popups/PopupSystem.cs +++ b/Content.Server/Popups/PopupSystem.cs @@ -4,7 +4,6 @@ using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; namespace Content.Server.Popups { diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs index 8dd09fab353..a5c9591d9ad 100644 --- a/Content.Server/Power/EntitySystems/CableSystem.cs +++ b/Content.Server/Power/EntitySystems/CableSystem.cs @@ -8,6 +8,8 @@ using Content.Shared.Tools; using Content.Shared.Tools.Components; using Robust.Shared.Map; +using CableCuttingFinishedEvent = Content.Shared.Tools.Systems.CableCuttingFinishedEvent; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Power.EntitySystems; diff --git a/Content.Server/Power/Generator/PortableGeneratorSystem.cs b/Content.Server/Power/Generator/PortableGeneratorSystem.cs index 416f509978a..1180665ad12 100644 --- a/Content.Server/Power/Generator/PortableGeneratorSystem.cs +++ b/Content.Server/Power/Generator/PortableGeneratorSystem.cs @@ -22,7 +22,7 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly GeneratorSystem _generator = default!; - [Dependency] private readonly PowerSwitchableGeneratorSystem _switchableGenerator = default!; + [Dependency] private readonly PowerSwitchableSystem _switchable = default!; public override void Initialize() { @@ -36,6 +36,8 @@ public override void Initialize() SubscribeLocalEvent(GeneratorStartMessage); SubscribeLocalEvent(GeneratorStopMessage); SubscribeLocalEvent(GeneratorSwitchOutputMessage); + + SubscribeLocalEvent(OnSwitchPowerCheck); } private void GeneratorSwitchOutputMessage(EntityUid uid, PortableGeneratorComponent component, PortableGeneratorSwitchOutputMessage args) @@ -47,7 +49,7 @@ private void GeneratorSwitchOutputMessage(EntityUid uid, PortableGeneratorCompon if (fuelGenerator.On) return; - _switchableGenerator.ToggleActiveOutput(uid, args.Session.AttachedEntity.Value); + _switchable.Cycle(uid, args.Session.AttachedEntity.Value); } private void GeneratorStopMessage(EntityUid uid, PortableGeneratorComponent component, PortableGeneratorStopMessage args) @@ -164,6 +166,12 @@ private void GetAlternativeVerb(EntityUid uid, PortableGeneratorComponent compon } } + private void OnSwitchPowerCheck(EntityUid uid, FuelGeneratorComponent comp, ref SwitchPowerCheckEvent args) + { + if (comp.On) + args.DisableMessage = Loc.GetString("fuel-generator-verb-disable-on"); + } + public override void Update(float frameTime) { var query = EntityQueryEnumerator(); diff --git a/Content.Server/Power/Generator/PowerSwitchableGeneratorSystem.cs b/Content.Server/Power/Generator/PowerSwitchableGeneratorSystem.cs deleted file mode 100644 index b81d77ea9f1..00000000000 --- a/Content.Server/Power/Generator/PowerSwitchableGeneratorSystem.cs +++ /dev/null @@ -1,111 +0,0 @@ -using Content.Server.NodeContainer; -using Content.Server.NodeContainer.EntitySystems; -using Content.Server.Popups; -using Content.Server.Power.Components; -using Content.Server.Power.Nodes; -using Content.Shared.Power.Generator; -using Content.Shared.Verbs; -using Robust.Server.GameObjects; -using Robust.Shared.Player; -using Robust.Shared.Utility; - -namespace Content.Server.Power.Generator; - -/// -/// Implements power-switchable generators. -/// -/// -/// -/// -public sealed class PowerSwitchableGeneratorSystem : SharedPowerSwitchableGeneratorSystem -{ - [Dependency] private readonly NodeGroupSystem _nodeGroup = default!; - [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly AudioSystem _audio = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent>(GetInteractionVerbs); - } - - private void GetInteractionVerbs( - EntityUid uid, - PowerSwitchableGeneratorComponent component, - GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract) - return; - - var isCurrentlyHV = component.ActiveOutput == PowerSwitchableGeneratorOutput.HV; - var msg = isCurrentlyHV ? "power-switchable-generator-verb-mv" : "power-switchable-generator-verb-hv"; - - var isOn = TryComp(uid, out FuelGeneratorComponent? fuelGenerator) && fuelGenerator.On; - - InteractionVerb verb = new() - { - Act = () => - { - - var verbIsOn = TryComp(uid, out FuelGeneratorComponent? verbFuelGenerator) && verbFuelGenerator.On; - if (verbIsOn) - return; - - ToggleActiveOutput(uid, args.User, component); - }, - Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/zap.svg.192dpi.png")), - Text = Loc.GetString(msg), - }; - - if (isOn) - { - verb.Message = Loc.GetString("power-switchable-generator-verb-disable-on"); - verb.Disabled = true; - } - - args.Verbs.Add(verb); - } - - public void ToggleActiveOutput(EntityUid uid, EntityUid user, PowerSwitchableGeneratorComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - var supplier = Comp(uid); - var nodeContainer = Comp(uid); - var outputMV = (CableDeviceNode) nodeContainer.Nodes[component.NodeOutputMV]; - var outputHV = (CableDeviceNode) nodeContainer.Nodes[component.NodeOutputHV]; - - if (component.ActiveOutput == PowerSwitchableGeneratorOutput.HV) - { - component.ActiveOutput = PowerSwitchableGeneratorOutput.MV; - supplier.Voltage = Voltage.Medium; - - // Switching around the voltage on the power supplier is "enough", - // but we also want to disconnect the cable nodes so it doesn't show up in power monitors etc. - outputMV.Enabled = true; - outputHV.Enabled = false; - } - else - { - component.ActiveOutput = PowerSwitchableGeneratorOutput.HV; - supplier.Voltage = Voltage.High; - - outputMV.Enabled = false; - outputHV.Enabled = true; - } - - _popup.PopupEntity( - Loc.GetString("power-switchable-generator-switched-output"), - uid, - user); - - _audio.Play(component.SwitchSound, Filter.Pvs(uid), uid, true); - - Dirty(uid, component); - - _nodeGroup.QueueReflood(outputMV); - _nodeGroup.QueueReflood(outputHV); - } -} diff --git a/Content.Server/Power/Generator/PowerSwitchableSystem.cs b/Content.Server/Power/Generator/PowerSwitchableSystem.cs new file mode 100644 index 00000000000..ae7960cf8f0 --- /dev/null +++ b/Content.Server/Power/Generator/PowerSwitchableSystem.cs @@ -0,0 +1,123 @@ +using Content.Server.NodeContainer; +using Content.Server.NodeContainer.EntitySystems; +using Content.Server.Popups; +using Content.Server.Power.Components; +using Content.Server.Power.Nodes; +using Content.Shared.Power.Generator; +using Content.Shared.Timing; +using Content.Shared.Verbs; +using Robust.Server.GameObjects; +using Robust.Shared.Player; +using Robust.Shared.Utility; + +namespace Content.Server.Power.Generator; + +/// +/// Implements server logic for power-switchable devices. +/// +/// +/// +/// +public sealed class PowerSwitchableSystem : SharedPowerSwitchableSystem +{ + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly NodeGroupSystem _nodeGroup = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly UseDelaySystem _useDelay = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(GetVerbs); + } + + private void GetVerbs(EntityUid uid, PowerSwitchableComponent comp, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + var voltage = VoltageColor(GetNextVoltage(uid, comp)); + var msg = Loc.GetString("power-switchable-switch-voltage", ("voltage", voltage)); + + InteractionVerb verb = new() + { + Act = () => + { + // don't need to check it again since if its disabled server wont let the verb act + Cycle(uid, args.User, comp); + }, + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/zap.svg.192dpi.png")), + Text = msg + }; + + var ev = new SwitchPowerCheckEvent(); + RaiseLocalEvent(uid, ref ev); + if (ev.DisableMessage != null) + { + verb.Message = ev.DisableMessage; + verb.Disabled = true; + } + + args.Verbs.Add(verb); + } + + /// + /// Cycles voltage then updates nodes and optionally power supplier to match it. + /// + public void Cycle(EntityUid uid, EntityUid user, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + // no sound spamming + if (TryComp(uid, out var useDelay) && _useDelay.ActiveDelay(uid)) + return; + + comp.ActiveIndex = NextIndex(uid, comp); + Dirty(uid, comp); + + var voltage = GetVoltage(uid, comp); + + if (TryComp(uid, out var supplier)) + { + // convert to nodegroupid (goofy server Voltage enum is just alias for it) + switch (voltage) + { + case SwitchableVoltage.HV: + supplier.Voltage = Voltage.High; + break; + case SwitchableVoltage.MV: + supplier.Voltage = Voltage.Medium; + break; + case SwitchableVoltage.LV: + supplier.Voltage = Voltage.Apc; + break; + } + } + + // Switching around the voltage on the power supplier is "enough", + // but we also want to disconnect the cable nodes so it doesn't show up in power monitors etc. + var nodeContainer = Comp(uid); + foreach (var cable in comp.Cables) + { + var node = (CableDeviceNode) nodeContainer.Nodes[cable.Node]; + node.Enabled = cable.Voltage == voltage; + _nodeGroup.QueueReflood(node); + } + + var popup = Loc.GetString(comp.SwitchText, ("voltage", VoltageString(voltage))); + _popup.PopupEntity(popup, uid, user); + + _audio.PlayPvs(comp.SwitchSound, uid); + + _useDelay.BeginDelay(uid, useDelay); + } +} + +/// +/// Raised on a to see if its verb should work. +/// If is non-null, the verb is disabled with that as the message. +/// +[ByRefEvent] +public record struct SwitchPowerCheckEvent(string? DisableMessage = null); diff --git a/Content.Server/Prayer/PrayerSystem.cs b/Content.Server/Prayer/PrayerSystem.cs index be6ae80bfda..e20291cc065 100644 --- a/Content.Server/Prayer/PrayerSystem.cs +++ b/Content.Server/Prayer/PrayerSystem.cs @@ -5,12 +5,11 @@ using Content.Server.Popups; using Content.Shared.Database; using Content.Shared.Popups; -using Robust.Server.Player; -using Robust.Shared.Player; using Content.Shared.Chat; using Content.Shared.Prayer; using Content.Shared.Verbs; using Robust.Server.GameObjects; +using Robust.Shared.Player; namespace Content.Server.Prayer; /// @@ -74,7 +73,7 @@ private void AddPrayVerb(EntityUid uid, PrayableComponent comp, GetVerbsEventThe IPlayerSession that sent the message /// The main message sent to the player via the chatbox /// The popup to notify the player, also prepended to the messageString - public void SendSubtleMessage(IPlayerSession target, IPlayerSession source, string messageString, string popupMessage) + public void SendSubtleMessage(ICommonSession target, ICommonSession source, string messageString, string popupMessage) { if (target.AttachedEntity == null) return; @@ -96,7 +95,7 @@ public void SendSubtleMessage(IPlayerSession target, IPlayerSession source, stri /// You may be wondering, "Why the admin chat, specifically? Nobody even reads it!" /// Exactly. /// - public void Pray(IPlayerSession sender, PrayableComponent comp, string message) + public void Pray(ICommonSession sender, PrayableComponent comp, string message) { if (sender.AttachedEntity == null) return; diff --git a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs index 8c06e00ab13..a36b053717f 100644 --- a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs @@ -2,8 +2,8 @@ using System.Threading; using System.Threading.Tasks; using Content.Shared.Preferences; -using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Preferences.Managers { @@ -11,12 +11,12 @@ public interface IServerPreferencesManager { void Init(); - Task LoadData(IPlayerSession session, CancellationToken cancel); - void OnClientDisconnected(IPlayerSession session); + Task LoadData(ICommonSession session, CancellationToken cancel); + void OnClientDisconnected(ICommonSession session); bool TryGetCachedPreferences(NetUserId userId, [NotNullWhen(true)] out PlayerPreferences? playerPreferences); PlayerPreferences GetPreferences(NetUserId userId); IEnumerable> GetSelectedProfilesForPlayers(List userIds); - bool HavePreferencesLoaded(IPlayerSession session); + bool HavePreferencesLoaded(ICommonSession session); } } diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs index d33e53fa619..94a60464299 100644 --- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs @@ -9,9 +9,9 @@ using Content.Shared.Humanoid.Prototypes; using Content.Shared.Preferences; using Content.Shared.Roles; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; @@ -175,7 +175,7 @@ private async void HandleDeleteCharacterMessage(MsgDeleteCharacter message) } // Should only be called via UserDbDataManager. - public async Task LoadData(IPlayerSession session, CancellationToken cancel) + public async Task LoadData(ICommonSession session, CancellationToken cancel) { if (!ShouldStorePrefs(session.ConnectedClient.AuthType)) { @@ -224,11 +224,16 @@ async Task LoadPrefs() } } - public void OnClientDisconnected(IPlayerSession session) + public void OnClientDisconnected(ICommonSession session) { _cachedPlayerPrefs.Remove(session.UserId); } + public bool HavePreferencesLoaded(ICommonSession session) + { + return _cachedPlayerPrefs.ContainsKey(session.UserId); + } + // Corvax-Sponsors-Start: Calculate total available users slots with sponsors private int GetMaxUserCharacterSlots(NetUserId userId) { @@ -238,12 +243,6 @@ private int GetMaxUserCharacterSlots(NetUserId userId) } // Corvax-Sponsors-End - public bool HavePreferencesLoaded(IPlayerSession session) - { - return _cachedPlayerPrefs.ContainsKey(session.UserId); - } - - /// /// Tries to get the preferences from the cache /// diff --git a/Content.Server/Pulling/PullingSystem.cs b/Content.Server/Pulling/PullingSystem.cs index f7ea0aae57f..69bb7c93704 100644 --- a/Content.Server/Pulling/PullingSystem.cs +++ b/Content.Server/Pulling/PullingSystem.cs @@ -4,7 +4,7 @@ using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Input.Binding; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Pulling { diff --git a/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs b/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs index 97f2e485ca3..56806d8c9c1 100644 --- a/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs +++ b/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs @@ -7,7 +7,7 @@ using Robust.Shared.Console; using Robust.Shared.Enums; using Robust.Shared.Map.Components; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Radiation.Systems; diff --git a/Content.Server/Repairable/RepairableSystem.cs b/Content.Server/Repairable/RepairableSystem.cs index 486ac756e3a..5bd580756da 100644 --- a/Content.Server/Repairable/RepairableSystem.cs +++ b/Content.Server/Repairable/RepairableSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Popups; using Content.Shared.Repairable; using Content.Shared.Tools; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Repairable { diff --git a/Content.Server/Research/Systems/ResearchSystem.Client.cs b/Content.Server/Research/Systems/ResearchSystem.Client.cs index e813f09ff9f..135ef8fe889 100644 --- a/Content.Server/Research/Systems/ResearchSystem.Client.cs +++ b/Content.Server/Research/Systems/ResearchSystem.Client.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.Power.EntitySystems; using Content.Shared.Research.Components; -using Robust.Server.Player; namespace Content.Server.Research.Systems; @@ -46,7 +45,7 @@ private void OnConsoleSelect(EntityUid uid, ResearchClientComponent component, C if (!this.IsPowered(uid, EntityManager)) return; - _uiSystem.TryToggleUi(uid, ResearchClientUiKey.Key, (IPlayerSession) args.Session); + _uiSystem.TryToggleUi(uid, ResearchClientUiKey.Key, args.Session); } #endregion diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs index b3caced0daf..cb20a1b8683 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs @@ -21,6 +21,7 @@ using Content.Shared.Emag.Systems; using Content.Shared.FixedPoint; using Content.Shared.Humanoid; +using Content.Shared.Maps; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; diff --git a/Content.Server/Salvage/SalvageRulerCommand.cs b/Content.Server/Salvage/SalvageRulerCommand.cs index b0a64508c56..a1fd6097411 100644 --- a/Content.Server/Salvage/SalvageRulerCommand.cs +++ b/Content.Server/Salvage/SalvageRulerCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Administration; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; @@ -26,7 +25,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("shell-only-players-can-run-this-command")); return; diff --git a/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs b/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs index 0b9148f0fbb..cc20b719469 100644 --- a/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs +++ b/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs @@ -4,7 +4,6 @@ using Content.Server.NodeContainer; using Content.Server.NodeContainer.NodeGroups; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Sandbox.Commands @@ -20,7 +19,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) { var sandboxManager = EntitySystem.Get(); var adminManager = IoCManager.Resolve(); - if (shell.IsClient && (!sandboxManager.IsSandboxEnabled && !adminManager.HasAdminFlag((IPlayerSession)shell.Player!, AdminFlags.Mapping))) + if (shell.IsClient && (!sandboxManager.IsSandboxEnabled && !adminManager.HasAdminFlag(shell.Player!, AdminFlags.Mapping))) { shell.WriteError("You are not currently able to use mapping commands."); } diff --git a/Content.Server/Sandbox/SandboxSystem.cs b/Content.Server/Sandbox/SandboxSystem.cs index ec9b1a0c3c9..194cf598438 100644 --- a/Content.Server/Sandbox/SandboxSystem.cs +++ b/Content.Server/Sandbox/SandboxSystem.cs @@ -13,6 +13,7 @@ using Robust.Server.Placement; using Robust.Server.Player; using Robust.Shared.Enums; +using Robust.Shared.Player; namespace Content.Server.Sandbox { diff --git a/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs b/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs index cd4f2ea23b9..63b4d9daef9 100644 --- a/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs +++ b/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.SensorMonitoring; using Robust.Server.Player; using Robust.Shared.Collections; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.SensorMonitoring; diff --git a/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs b/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs index a09badcd595..6c0dddeb266 100644 --- a/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs +++ b/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs @@ -1,7 +1,5 @@ using Content.Server.DeviceNetwork.Components; using Content.Shared.SensorMonitoring; -using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Collections; using ConsoleUIState = Content.Shared.SensorMonitoring.SensorMonitoringConsoleBoundInterfaceState; using IncrementalUIState = Content.Shared.SensorMonitoring.SensorMonitoringIncrementalUpdate; @@ -130,7 +128,7 @@ private static void ConsoleUIClosed( if (!args.UiKey.Equals(SensorMonitoringConsoleUiKey.Key)) return; - if (args.Session is not IPlayerSession player) + if (args.Session is not { } player) return; component.InitialUIStateSent.Remove(player); diff --git a/Content.Server/ServerUpdates/ServerUpdateManager.cs b/Content.Server/ServerUpdates/ServerUpdateManager.cs index 769c5d58d7e..f4e54984e9b 100644 --- a/Content.Server/ServerUpdates/ServerUpdateManager.cs +++ b/Content.Server/ServerUpdates/ServerUpdateManager.cs @@ -6,6 +6,7 @@ using Robust.Server.ServerStatus; using Robust.Shared.Configuration; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.ServerUpdates; diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs index 3de9648fe6d..deb2ba256dd 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs @@ -90,19 +90,11 @@ private void InitializeEmergencyConsole() SubscribeLocalEvent(OnEmergencyRepeal); SubscribeLocalEvent(OnEmergencyRepealAll); SubscribeLocalEvent(OnEmergencyOpenAttempt); - SubscribeLocalEvent(OnEmagged); // Corvax-Hijack + SubscribeLocalEvent(OnEmagged); SubscribeLocalEvent(OnEscapeUnpaused); } - // Corvax-Hijack-Start - private void OnEmagged(EntityUid uid, EmergencyShuttleConsoleComponent component, ref GotEmaggedEvent args) - { - _logger.Add(LogType.EmergencyShuttle, LogImpact.Extreme, $"{ToPrettyString(args.UserUid):player} emagged shuttle console for early launch"); - EarlyLaunch(); - } - // Corvax-Hijack-End - private void OnEmergencyOpenAttempt(EntityUid uid, EmergencyShuttleConsoleComponent component, ActivatableUIOpenAttemptEvent args) { // I'm hoping ActivatableUI checks it's open before allowing these messages. @@ -113,6 +105,12 @@ private void OnEmergencyOpenAttempt(EntityUid uid, EmergencyShuttleConsoleCompon } } + private void OnEmagged(EntityUid uid, EmergencyShuttleConsoleComponent component, ref GotEmaggedEvent args) + { + _logger.Add(LogType.EmergencyShuttle, LogImpact.Extreme, $"{ToPrettyString(args.UserUid):player} emagged shuttle console for early launch"); + EarlyLaunch(); + } + private void SetAuthorizeTime(float obj) { _authorizeTime = obj; diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs index 1a1debc9e3b..3ef3d97a21a 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs @@ -20,7 +20,6 @@ using Content.Shared.Tiles; using Robust.Server.GameObjects; using Robust.Server.Maps; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -140,7 +139,7 @@ public override void Shutdown() /// private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args) { - if (!_admin.IsAdmin((IPlayerSession) args.SenderSession)) + if (!_admin.IsAdmin(args.SenderSession)) return; var player = args.SenderSession.AttachedEntity; diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs index 31d826087d5..c0804202669 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs @@ -229,7 +229,7 @@ private void RemoveProvidedItems(EntityUid chassis, EntityUid uid, BorgChassisCo if (!TryComp(chassis, out var hands)) return; - if (LifeStage(uid) >= EntityLifeStage.Terminating) + if (TerminatingOrDeleted(uid)) { foreach (var (hand, item) in component.ProvidedItems) { diff --git a/Content.Server/Silicons/Borgs/BorgSystem.cs b/Content.Server/Silicons/Borgs/BorgSystem.cs index 611dfa6ea2a..883cb3b3d84 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.cs @@ -21,7 +21,7 @@ using Content.Shared.Wires; using Robust.Server.GameObjects; using Robust.Shared.Containers; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.Silicons.Borgs; diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 1d5c2e35e8b..b1ab1ac020b 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -18,7 +18,6 @@ using Content.Shared.Stunnable; using Content.Shared.Wires; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Prototypes; using Robust.Shared.Toolshed; @@ -50,7 +49,9 @@ public override void Initialize() SubscribeLocalEvent(OnPlayerSpawnComplete); SubscribeLocalEvent(OnDirectedGetLaws); + SubscribeLocalEvent(OnIonStormLaws); SubscribeLocalEvent(OnDirectedEmagGetLaws); + SubscribeLocalEvent(OnEmagIonStormLaws); SubscribeLocalEvent(OnEmagMindAdded); SubscribeLocalEvent(OnEmagMindRemoved); SubscribeLocalEvent(OnExamined); @@ -93,8 +94,8 @@ private void OnBoundUIOpened(EntityUid uid, SiliconLawBoundComponent component, _entityManager.TryGetComponent(uid, out var intrinsicRadio); HashSet? radioChannels = intrinsicRadio?.Channels; - var state = new SiliconLawBuiState(GetLaws(uid), radioChannels); - _userInterface.TrySetUiState(args.Entity, SiliconLawsUiKey.Key, state, (IPlayerSession) args.Session); + var state = new SiliconLawBuiState(GetLaws(uid).Laws, radioChannels); + _userInterface.TrySetUiState(args.Entity, SiliconLawsUiKey.Key, state, args.Session); } private void OnPlayerSpawnComplete(EntityUid uid, SiliconLawBoundComponent component, PlayerSpawnCompleteEvent args) @@ -104,38 +105,66 @@ private void OnPlayerSpawnComplete(EntityUid uid, SiliconLawBoundComponent compo private void OnDirectedGetLaws(EntityUid uid, SiliconLawProviderComponent component, ref GetSiliconLawsEvent args) { - if (args.Handled || HasComp(uid) || component.Laws.Count == 0) + if (args.Handled || HasComp(uid)) return; - foreach (var law in component.Laws) - { - args.Laws.Add(_prototype.Index(law)); - } + if (component.Lawset == null) + component.Lawset = GetLawset(component.Laws); + + args.Laws = component.Lawset; args.Handled = true; } + private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component, ref IonStormLawsEvent args) + { + if (HasComp(uid)) + return; + + component.Lawset = args.Lawset; + + // gotta tell player to check their laws + NotifyLawsChanged(uid); + + // new laws may allow antagonist behaviour so make it clear for admins + if (TryComp(uid, out var emag)) + EnsureEmaggedRole(uid, emag); + } + private void OnDirectedEmagGetLaws(EntityUid uid, EmagSiliconLawComponent component, ref GetSiliconLawsEvent args) { if (args.Handled || !HasComp(uid) || component.OwnerName == null) return; - // Add the first emag law - args.Laws.Add(new SiliconLaw + if (component.Lawset == null) { - LawString = Loc.GetString("law-emag-custom", ("name", component.OwnerName)), - Order = 0 - }); + // Add new emagged laws + component.Lawset = GetLawset(component.EmagLaws); - // Add new emagged laws - foreach (var law in component.EmagLaws) - { - args.Laws.Add(_prototype.Index(law)); + // Add the first emag law before the others + component.Lawset.Laws.Insert(0, new SiliconLaw + { + LawString = Loc.GetString("law-emag-custom", ("name", component.OwnerName)), + Order = 0 + }); } + args.Laws = component.Lawset; + args.Handled = true; } + private void OnEmagIonStormLaws(EntityUid uid, EmagSiliconLawComponent component, ref IonStormLawsEvent args) + { + if (!HasComp(uid)) + return; + + component.Lawset = args.Lawset; + + // gotta tell player to check their laws + NotifyLawsChanged(uid); + } + private void OnExamined(EntityUid uid, EmagSiliconLawComponent component, ExaminedEvent args) { if (!args.IsInDetailsRange || !HasComp(uid)) @@ -170,7 +199,7 @@ private void OnEmagMindRemoved(EntityUid uid, EmagSiliconLawComponent component, if (component.AntagonistRole == null) return; - _roles.MindTryRemoveRole(args.OldMindId); + _roles.MindTryRemoveRole(args.Mind); } private void EnsureEmaggedRole(EntityUid uid, EmagSiliconLawComponent component) @@ -184,10 +213,10 @@ private void EnsureEmaggedRole(EntityUid uid, EmagSiliconLawComponent component) _roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole }); } - public List GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) + public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) { if (!Resolve(uid, ref component)) - return new List(); + return new SiliconLawset(); var ev = new GetSiliconLawsEvent(uid); @@ -248,6 +277,24 @@ public void NotifyLawsChanged(EntityUid uid) var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMessage, default, false, actor.PlayerSession.ConnectedClient, colorOverride: Color.Red); } + + /// + /// Extract all the laws from a lawset's prototype ids. + /// + public SiliconLawset GetLawset(string lawset) + { + var proto = _prototype.Index(lawset); + var laws = new SiliconLawset() + { + Laws = new List(proto.Laws.Count) + }; + foreach (var law in proto.Laws) + { + laws.Laws.Add(_prototype.Index(law)); + } + + return laws; + } } [ToolshedCommand, AdminCommand(AdminFlags.Admin)] @@ -270,7 +317,7 @@ public IEnumerable Get([PipedArgument] EntityUid lawbound) { _law ??= GetSys(); - foreach (var law in _law.GetLaws(lawbound)) + foreach (var law in _law.GetLaws(lawbound).Laws) { yield return $"law {law.LawIdentifierOverride ?? law.Order.ToString()}: {Loc.GetString(law.LawString)}"; } diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index 2709bc2072b..eeaace03b2c 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -41,7 +41,7 @@ public override void Update(float _) if (_availableJobsDirty) { _cachedAvailableJobs = GenerateJobsAvailableEvent(); - RaiseNetworkEvent(_cachedAvailableJobs, Filter.Empty().AddPlayers(_playerManager.ServerSessions)); + RaiseNetworkEvent(_cachedAvailableJobs, Filter.Empty().AddPlayers(_playerManager.Sessions)); _availableJobsDirty = false; } } diff --git a/Content.Server/StationEvents/Components/IonStormRuleComponent.cs b/Content.Server/StationEvents/Components/IonStormRuleComponent.cs new file mode 100644 index 00000000000..35b59f5b356 --- /dev/null +++ b/Content.Server/StationEvents/Components/IonStormRuleComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.StationEvents.Components; + +/// +/// Gamerule component to mess up ai/borg laws when started. +/// +[RegisterComponent] +public sealed partial class IonStormRuleComponent : Component +{ +} diff --git a/Content.Server/StationEvents/Components/VentClogRuleComponent.cs b/Content.Server/StationEvents/Components/VentClogRuleComponent.cs index 79ebc520c80..afb3a363265 100644 --- a/Content.Server/StationEvents/Components/VentClogRuleComponent.cs +++ b/Content.Server/StationEvents/Components/VentClogRuleComponent.cs @@ -12,7 +12,7 @@ public sealed partial class VentClogRuleComponent : Component /// Somewhat safe chemicals to put in foam that probably won't instantly kill you. /// There is a small chance of using any reagent, ignoring this. /// - [DataField("safeishVentChemicals", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] public IReadOnlyList SafeishVentChemicals = new[] { "Water", "Blood", "Slime", "SpaceDrugs", "SpaceCleaner", "Nutriment", "Sugar", "SpaceLube", "Ephedrine", "Ale", "Beer", "SpaceGlue" @@ -21,31 +21,31 @@ public sealed partial class VentClogRuleComponent : Component /// /// Sound played when foam is being created. /// - [DataField("sound")] + [DataField] public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Effects/extinguish.ogg"); /// - /// The standard reagent quantity to put in the foam, modfied by event severity. + /// The standard reagent quantity to put in the foam, modified by event severity. /// - [DataField("reagentQuantity"), ViewVariables(VVAccess.ReadWrite)] - public int ReagentQuantity = 200; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int ReagentQuantity = 100; /// - /// The standard spreading of the foam, not modfied by event severity. + /// The standard spreading of the foam, not modified by event severity. /// - [DataField("spread"), ViewVariables(VVAccess.ReadWrite)] - public int Spread = 20; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int Spread = 16; /// /// How long the foam lasts for /// - [DataField("time"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float Time = 20f; /// /// Reagents that gets the weak numbers used instead of regular ones. /// - [DataField("weakReagents", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] public IReadOnlyList WeakReagents = new[] { "SpaceLube", "SpaceGlue" @@ -54,12 +54,12 @@ public sealed partial class VentClogRuleComponent : Component /// /// Quantity of weak reagents to put in the foam. /// - [DataField("weakReagentQuantity"), ViewVariables(VVAccess.ReadWrite)] - public int WeakReagentQuantity = 60; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int WeakReagentQuantity = 50; /// /// Spread of the foam for weak reagents. /// - [DataField("weakSpread"), ViewVariables(VVAccess.ReadWrite)] - public int WeakSpread = 2; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int WeakSpread = 3; } diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs new file mode 100644 index 00000000000..e5b68c4d842 --- /dev/null +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -0,0 +1,273 @@ +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Silicons.Laws; +using Content.Server.Station.Components; +using Content.Server.StationEvents.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Dataset; +using Content.Shared.FixedPoint; +using Content.Shared.Random; +using Content.Shared.Random.Helpers; +using Content.Shared.Silicons.Laws; +using Content.Shared.Silicons.Laws.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.StationEvents.Events; + +public sealed class IonStormRule : StationEventSystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; + + // funny + [ValidatePrototypeId] + private const string Threats = "IonStormThreats"; + [ValidatePrototypeId] + private const string Objects = "IonStormObjects"; + [ValidatePrototypeId] + private const string Crew = "IonStormCrew"; + [ValidatePrototypeId] + private const string Adjectives = "IonStormAdjectives"; + [ValidatePrototypeId] + private const string Verbs = "IonStormVerbs"; + [ValidatePrototypeId] + private const string NumberBase = "IonStormNumberBase"; + [ValidatePrototypeId] + private const string NumberMod = "IonStormNumberMod"; + [ValidatePrototypeId] + private const string Areas = "IonStormAreas"; + [ValidatePrototypeId] + private const string Feelings = "IonStormFeelings"; + [ValidatePrototypeId] + private const string FeelingsPlural = "IonStormFeelingsPlural"; + [ValidatePrototypeId] + private const string Musts = "IonStormMusts"; + [ValidatePrototypeId] + private const string Requires = "IonStormRequires"; + [ValidatePrototypeId] + private const string Actions = "IonStormActions"; + [ValidatePrototypeId] + private const string Allergies = "IonStormAllergies"; + [ValidatePrototypeId] + private const string AllergySeverities = "IonStormAllergySeverities"; + [ValidatePrototypeId] + private const string Species = "IonStormSpecies"; + [ValidatePrototypeId] + private const string Concepts = "IonStormConcepts"; + [ValidatePrototypeId] + private const string Drinks = "IonStormDrinks"; + [ValidatePrototypeId] + private const string Foods = "IonStormFoods"; + + protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, comp, gameRule, args); + + if (!TryGetRandomStation(out var chosenStation)) + return; + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out var lawBound, out var xform, out var target)) + { + // only affect law holders on the station + if (CompOrNull(xform.GridUid)?.Station != chosenStation) + continue; + + if (!RobustRandom.Prob(target.Chance)) + continue; + + var laws = _siliconLaw.GetLaws(ent, lawBound); + if (laws.Laws.Count == 0) + continue; + + // try to swap it out with a random lawset + if (RobustRandom.Prob(target.RandomLawsetChance)) + { + var lawsets = PrototypeManager.Index(target.RandomLawsets); + var lawset = lawsets.Pick(RobustRandom); + laws = _siliconLaw.GetLawset(lawset); + } + else + { + // clone it so not modifying stations lawset + laws = laws.Clone(); + } + + // shuffle them all + if (RobustRandom.Prob(target.ShuffleChance)) + { + // hopefully work with existing glitched laws if there are multiple ion storms + FixedPoint2 baseOrder = FixedPoint2.New(1); + foreach (var law in laws.Laws) + { + if (law.Order < baseOrder) + baseOrder = law.Order; + } + + RobustRandom.Shuffle(laws.Laws); + + // change order based on shuffled position + for (int i = 0; i < laws.Laws.Count; i++) + { + laws.Laws[i].Order = baseOrder + i; + } + } + + // see if we can remove a random law + if (laws.Laws.Count > 0 && RobustRandom.Prob(target.RemoveChance)) + { + var i = RobustRandom.Next(laws.Laws.Count); + laws.Laws.RemoveAt(i); + } + + // generate a new law... + var newLaw = GenerateLaw(); + + // see if the law we add will replace a random existing law or be a new glitched order one + if (laws.Laws.Count > 0 && RobustRandom.Prob(target.ReplaceChance)) + { + var i = RobustRandom.Next(laws.Laws.Count); + laws.Laws[i] = new SiliconLaw() + { + LawString = newLaw, + Order = laws.Laws[i].Order + }; + } + else + { + laws.Laws.Insert(0, new SiliconLaw() + { + LawString = newLaw, + Order = -1, + LawIdentifierOverride = "#" + }); + } + + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); + + // laws unique to this silicon, dont use station laws anymore + EnsureComp(ent); + var ev = new IonStormLawsEvent(laws); + RaiseLocalEvent(ent, ref ev); + } + } + + // for your own sake direct your eyes elsewhere + private string GenerateLaw() + { + // pick all values ahead of time to make the logic cleaner + var threats = Pick(Threats); + var objects = Pick(Objects); + var crew1 = Pick(Crew); + var crew2 = Pick(Crew); + var adjective = Pick(Adjectives); + var verb = Pick(Verbs); + var number = Pick(NumberBase) + " " + Pick(NumberMod); + var area = Pick(Areas); + var feeling = Pick(Feelings); + var feelingPlural = Pick(FeelingsPlural); + var must = Pick(Musts); + var require = Pick(Requires); + var action = Pick(Actions); + var allergy = Pick(Allergies); + var allergySeverity = Pick(AllergySeverities); + var species = Pick(Species); + var concept = Pick(Concepts); + var drink = Pick(Drinks); + var food = Pick(Foods); + + var joined = $"{number} {adjective}"; + // a lot of things have subjects of a threat/crew/object + var triple = RobustRandom.Next(0, 3) switch + { + 0 => threats, + 1 => crew1, + 2 => objects + }; + var crewAll = RobustRandom.Prob(0.5f) ? crew2 : Loc.GetString("ion-storm-crew"); + var objectsThreats = RobustRandom.Prob(0.5f) ? objects : threats; + var objectsConcept = RobustRandom.Prob(0.5f) ? objects : concept; + // s goes ahead of require, is/are + // i dont think theres a way to do this in fluent + var (who, plural) = RobustRandom.Next(0, 5) switch + { + 0 => (Loc.GetString("ion-storm-you"), false), + 1 => (Loc.GetString("ion-storm-the-station"), true), + 2 => (Loc.GetString("ion-storm-the-crew"), true), + 3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), false), + _ => (area, true) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS + }; + var jobChange = RobustRandom.Next(0, 3) switch + { + 0 => crew1, + 1 => Loc.GetString("ion-storm-clowns"), + _ => Loc.GetString("ion-storm-heads") + }; + var part = Loc.GetString("ion-storm-part", ("part", RobustRandom.Prob(0.5f))); + var harm = RobustRandom.Next(0, 7) switch + { + 0 => concept, + 1 => $"{adjective} {threats}", + 2 => $"{adjective} {objects}", + 3 => Loc.GetString("ion-storm-adjective-things", ("adjective", adjective)), + 4 => species, + 5 => crew1, + _ => Loc.GetString("ion-storm-x-and-y", ("x", crew1), ("y", crew2)) + }; + + if (plural) feeling = feelingPlural; + + // message logic!!! + return RobustRandom.Next(0, 37) switch + { + 0 => Loc.GetString("ion-storm-law-on-station", ("joined", joined), ("subjects", triple)), + 1 => Loc.GetString("ion-storm-law-no-shuttle", ("joined", joined), ("subjects", triple)), + 2 => Loc.GetString("ion-storm-law-crew-are", ("who", crewAll), ("joined", joined), ("subjects", objectsThreats)), + 3 => Loc.GetString("ion-storm-law-subjects-harmful", ("adjective", adjective), ("subjects", triple)), + 4 => Loc.GetString("ion-storm-law-must-harmful", ("must", must)), + 5 => Loc.GetString("ion-storm-law-thing-harmful", ("thing", RobustRandom.Prob(0.5f) ? concept : action)), + 6 => Loc.GetString("ion-storm-law-job-harmful", ("adjective", adjective), ("job", crew1)), + 7 => Loc.GetString("ion-storm-law-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 8 => Loc.GetString("ion-storm-law-not-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 9 => Loc.GetString("ion-storm-law-requires", ("who", who), ("plural", plural), ("thing", RobustRandom.Prob(0.5f) ? concept : require)), + 10 => Loc.GetString("ion-storm-law-requires-subjects", ("who", who), ("plural", plural), ("joined", joined), ("subjects", triple)), + 11 => Loc.GetString("ion-storm-law-allergic", ("who", who), ("plural", plural), ("severity", allergySeverity), ("allergy", RobustRandom.Prob(0.5f) ? concept : allergy)), + 12 => Loc.GetString("ion-storm-law-allergic-subjects", ("who", who), ("plural", plural), ("severity", allergySeverity), ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objects : crew1)), + 13 => Loc.GetString("ion-storm-law-feeling", ("who", who), ("feeling", feeling), ("concept", concept)), + 14 => Loc.GetString("ion-storm-law-feeling-subjects", ("who", who), ("feeling", feeling), ("joined", joined), ("subjects", triple)), + 15 => Loc.GetString("ion-storm-law-you-are", ("concept", concept)), + 16 => Loc.GetString("ion-storm-law-you-are-subjects", ("joined", joined), ("subjects", triple)), + 17 => Loc.GetString("ion-storm-law-you-must-always", ("must", must)), + 18 => Loc.GetString("ion-storm-law-you-must-never", ("must", must)), + 19 => Loc.GetString("ion-storm-law-eat", ("who", crewAll), ("adjective", adjective), ("food", RobustRandom.Prob(0.5f) ? food : triple)), + 20 => Loc.GetString("ion-storm-law-drink", ("who", crewAll), ("adjective", adjective), ("drink", drink)), + 22 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), + 23 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), + 24 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), + 25 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), + 26 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), + 27 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), + 28 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), + 29 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objectsThreats : "PEOPLE"), ("part", part)), + 30 => Loc.GetString("ion-storm-law-crew-only-species", ("species", species), ("part", part)), + 31 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), + 32 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), + 33 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), + 34 => Loc.GetString("ion-storm-law-harm", ("who", harm)), + 35 => Loc.GetString("ion-storm-law-protect", ("who", harm)), + _ => Loc.GetString("ion-storm-law-concept-verb", ("concept", concept), ("verb", verb), ("subjects", triple)) + }; + } + + /// + /// Picks a random value from an ion storm dataset. + /// All ion storm datasets start with IonStorm. + /// + private string Pick(string name) + { + var dataset = _proto.Index(name); + return RobustRandom.Pick(dataset.Values); + } +} diff --git a/Content.Server/StationEvents/Events/VentClogRule.cs b/Content.Server/StationEvents/Events/VentClogRule.cs index 5ef28304e7e..f378aec3fb9 100644 --- a/Content.Server/StationEvents/Events/VentClogRule.cs +++ b/Content.Server/StationEvents/Events/VentClogRule.cs @@ -3,10 +3,8 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using JetBrains.Annotations; -using Robust.Shared.Audio; using Robust.Shared.Random; using System.Linq; -using Content.Server.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.GameTicking.Rules.Components; using Content.Server.StationEvents.Components; @@ -53,9 +51,8 @@ protected override void Started(EntityUid uid, VentClogRuleComponent component, solution.AddReagent(reagent, quantity); var foamEnt = Spawn("Foam", transform.Coordinates); - var smoke = EnsureComp(foamEnt); - smoke.SpreadAmount = weak ? component.WeakSpread : component.Spread; - _smoke.Start(foamEnt, smoke, solution, component.Time); + var spreadAmount = weak ? component.WeakSpread : component.Spread; + _smoke.StartSmoke(foamEnt, solution, component.Time, spreadAmount); Audio.PlayPvs(component.Sound, transform.Coordinates); } } diff --git a/Content.Server/Sticky/Events/EntityStuckEvent.cs b/Content.Server/Sticky/Events/EntityStuckEvent.cs index b9244364890..7857fad7d57 100644 --- a/Content.Server/Sticky/Events/EntityStuckEvent.cs +++ b/Content.Server/Sticky/Events/EntityStuckEvent.cs @@ -1,5 +1,28 @@ namespace Content.Server.Sticky.Events; +/// +/// Risen on sticky entity to see if it can stick to another entity. +/// +[ByRefEvent] +public record struct AttemptEntityStickEvent(EntityUid Target, EntityUid User) +{ + public readonly EntityUid Target = Target; + public readonly EntityUid User = User; + public bool Cancelled = false; +} + +/// +/// Risen on sticky entity to see if it can unstick from another entity. +/// +[ByRefEvent] +public record struct AttemptEntityUnstickEvent(EntityUid Target, EntityUid User) +{ + public readonly EntityUid Target = Target; + public readonly EntityUid User = User; + public bool Cancelled = false; +} + + /// /// Risen on sticky entity when it was stuck to other entity. /// diff --git a/Content.Server/Sticky/Systems/StickySystem.cs b/Content.Server/Sticky/Systems/StickySystem.cs index 330b878c05a..bcc1be39a92 100644 --- a/Content.Server/Sticky/Systems/StickySystem.cs +++ b/Content.Server/Sticky/Systems/StickySystem.cs @@ -56,7 +56,7 @@ private void AddUnstickVerb(EntityUid uid, StickyComponent component, GetVerbsEv { DoContactInteraction = true, Text = Loc.GetString("comp-sticky-unstick-verb-text"), - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), Act = () => StartUnsticking(uid, args.User, component) }); } @@ -72,6 +72,11 @@ private bool StartSticking(EntityUid uid, EntityUid user, EntityUid target, Stic if (component.Blacklist != null && component.Blacklist.IsValid(target)) return false; + var attemptEv = new AttemptEntityStickEvent(target, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) + return false; + // check if delay is not zero to start do after var delay = (float) component.StickDelay.TotalSeconds; if (delay > 0) @@ -120,6 +125,14 @@ private void StartUnsticking(EntityUid uid, EntityUid user, StickyComponent? com if (!Resolve(uid, ref component)) return; + if (component.StuckTo is not { } stuckTo) + return; + + var attemptEv = new AttemptEntityUnstickEvent(stuckTo, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) + return; + var delay = (float) component.UnstickDelay.TotalSeconds; if (delay > 0) { @@ -152,6 +165,11 @@ public void StickToEntity(EntityUid uid, EntityUid target, EntityUid user, Stick if (!Resolve(uid, ref component)) return; + var attemptEv = new AttemptEntityStickEvent(target, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) + return; + // add container to entity and insert sticker into it var container = _containerSystem.EnsureContainer(target, StickerSlotId); container.ShowContents = true; @@ -179,12 +197,17 @@ public void UnstickFromEntity(EntityUid uid, EntityUid user, StickyComponent? co { if (!Resolve(uid, ref component)) return; - if (component.StuckTo == null) + + if (component.StuckTo is not { } stuckTo) + return; + + var attemptEv = new AttemptEntityUnstickEvent(stuckTo, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) return; // try to remove sticky item from target container - var target = component.StuckTo.Value; - if (!_containerSystem.TryGetContainer(target, StickerSlotId, out var container) || !container.Remove(uid)) + if (!_containerSystem.TryGetContainer(stuckTo, StickerSlotId, out var container) || !container.Remove(uid)) return; // delete container if it's now empty if (container.ContainedEntities.Count == 0) @@ -207,6 +230,6 @@ public void UnstickFromEntity(EntityUid uid, EntityUid user, StickyComponent? co } component.StuckTo = null; - RaiseLocalEvent(uid, new EntityUnstuckEvent(target, user), true); + RaiseLocalEvent(uid, new EntityUnstuckEvent(stuckTo, user), true); } } diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.cs b/Content.Server/Storage/EntitySystems/StorageSystem.cs index 3430449957e..8b4ae1c76f9 100644 --- a/Content.Server/Storage/EntitySystems/StorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/StorageSystem.cs @@ -9,7 +9,6 @@ using Content.Shared.Timing; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Prototypes; @@ -135,7 +134,7 @@ public override void PlayPickupAnimation(EntityUid uid, EntityCoordinates initia /// If the user has nested-UIs open (e.g., PDA UI open when pda is in a backpack), close them. /// /// - public void CloseNestedInterfaces(EntityUid uid, IPlayerSession session, StorageComponent? storageComp = null) + public void CloseNestedInterfaces(EntityUid uid, ICommonSession session, StorageComponent? storageComp = null) { if (!Resolve(uid, ref storageComp)) return; diff --git a/Content.Server/Tabletop/TabletopSession.cs b/Content.Server/Tabletop/TabletopSession.cs index d94b4fd6575..5e7c6ac02e6 100644 --- a/Content.Server/Tabletop/TabletopSession.cs +++ b/Content.Server/Tabletop/TabletopSession.cs @@ -1,6 +1,6 @@ using System.Numerics; -using Robust.Server.Player; using Robust.Shared.Map; +using Robust.Shared.Player; namespace Content.Server.Tabletop { @@ -17,7 +17,7 @@ public sealed class TabletopSession /// /// The set of players currently playing this tabletop game. /// - public readonly Dictionary Players = new(); + public readonly Dictionary Players = new(); /// /// All entities bound to this session. If you create an entity for this session, you have to add it here. diff --git a/Content.Server/Tabletop/TabletopSystem.Session.cs b/Content.Server/Tabletop/TabletopSystem.Session.cs index e9dea0c66a2..8f1bc7005dc 100644 --- a/Content.Server/Tabletop/TabletopSystem.Session.cs +++ b/Content.Server/Tabletop/TabletopSystem.Session.cs @@ -1,7 +1,7 @@ using System.Numerics; using Content.Server.Tabletop.Components; using Content.Shared.Tabletop.Events; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Tabletop @@ -66,7 +66,7 @@ public void CleanupSession(EntityUid uid) /// /// The player session in question. /// The UID of the tabletop game entity. - public void OpenSessionFor(IPlayerSession player, EntityUid uid) + public void OpenSessionFor(ICommonSession player, EntityUid uid) { if (!EntityManager.TryGetComponent(uid, out TabletopGameComponent? tabletop) || player.AttachedEntity is not {Valid: true} attachedEntity) return; @@ -98,7 +98,7 @@ public void OpenSessionFor(IPlayerSession player, EntityUid uid) /// The player in question. /// The UID of the tabletop game entity. /// Whether to remove the from the player's attached entity. - public void CloseSessionFor(IPlayerSession player, EntityUid uid, bool removeGamerComponent = true) + public void CloseSessionFor(ICommonSession player, EntityUid uid, bool removeGamerComponent = true) { if (!EntityManager.TryGetComponent(uid, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session) return; @@ -129,7 +129,7 @@ public void CloseSessionFor(IPlayerSession player, EntityUid uid, bool removeGam /// The player in question. /// An offset from the tabletop position for the camera. Zero by default. /// The UID of the camera entity. - private EntityUid CreateCamera(TabletopGameComponent tabletop, IPlayerSession player, Vector2 offset = default) + private EntityUid CreateCamera(TabletopGameComponent tabletop, ICommonSession player, Vector2 offset = default) { DebugTools.AssertNotNull(tabletop.Session); diff --git a/Content.Server/Tabletop/TabletopSystem.cs b/Content.Server/Tabletop/TabletopSystem.cs index 2e271080d07..b81331d62ee 100644 --- a/Content.Server/Tabletop/TabletopSystem.cs +++ b/Content.Server/Tabletop/TabletopSystem.cs @@ -9,7 +9,6 @@ using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Utility; @@ -42,7 +41,7 @@ public override void Initialize() private void OnTabletopRequestTakeOut(TabletopRequestTakeOut msg, EntitySessionEventArgs args) { - if (args.SenderSession is not IPlayerSession playerSession) + if (args.SenderSession is not { } playerSession) return; var table = GetEntity(msg.TableUid); @@ -105,7 +104,7 @@ private void OnInteractUsing(EntityUid uid, TabletopGameComponent component, Int protected override void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args) { - if (args.SenderSession is not IPlayerSession playerSession) + if (args.SenderSession is not { } playerSession) return; if (!TryComp(GetEntity(msg.TableUid), out TabletopGameComponent? tabletop) || tabletop.Session is not { } session) @@ -155,7 +154,7 @@ private void OnGameShutdown(EntityUid uid, TabletopGameComponent component, Comp private void OnStopPlaying(TabletopStopPlayingEvent msg, EntitySessionEventArgs args) { - CloseSessionFor((IPlayerSession)args.SenderSession, GetEntity(msg.TableUid)); + CloseSessionFor(args.SenderSession, GetEntity(msg.TableUid)); } private void OnPlayerDetached(EntityUid uid, TabletopGamerComponent component, PlayerDetachedEvent args) diff --git a/Content.Server/Toilet/ToiletSystem.cs b/Content.Server/Toilet/ToiletSystem.cs index 57467397c6d..b10feae4533 100644 --- a/Content.Server/Toilet/ToiletSystem.cs +++ b/Content.Server/Toilet/ToiletSystem.cs @@ -19,6 +19,7 @@ using Robust.Shared.Audio; using Robust.Shared.Player; using Robust.Shared.Random; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Toilet { diff --git a/Content.Server/Tools/Components/TilePryingComponent.cs b/Content.Server/Tools/Components/TilePryingComponent.cs deleted file mode 100644 index 99d7144b687..00000000000 --- a/Content.Server/Tools/Components/TilePryingComponent.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading; -using Content.Shared.Tools; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; - -namespace Content.Server.Tools.Components -{ - [RegisterComponent] - public sealed partial class TilePryingComponent : Component - { - [DataField("toolComponentNeeded")] - public bool ToolComponentNeeded = true; - - [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string QualityNeeded = "Prying"; - - /// - /// Whether this tool can pry tiles with CanAxe. - /// - [DataField("advanced")] - public bool Advanced = false; - - [DataField("delay")] - public float Delay = 1f; - } -} diff --git a/Content.Server/Tools/ToolSystem.LatticeCutting.cs b/Content.Server/Tools/ToolSystem.LatticeCutting.cs index 674a8102390..ab289c1ae24 100644 --- a/Content.Server/Tools/ToolSystem.LatticeCutting.cs +++ b/Content.Server/Tools/ToolSystem.LatticeCutting.cs @@ -62,14 +62,14 @@ private bool TryCut(EntityUid toolEntity, EntityUid user, LatticeCuttingComponen var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); - if (!_interactionSystem.InRangeUnobstructed(user, coordinates, popup: false)) + if (!InteractionSystem.InRangeUnobstructed(user, coordinates, popup: false)) return false; if (_tileDefinitionManager[tile.Tile.TypeId] is not ContentTileDefinition tileDef || !tileDef.CanWirecutter || string.IsNullOrEmpty(tileDef.BaseTurf) - || _tileDefinitionManager[tileDef.BaseTurf] is not ContentTileDefinition newDef - || tile.IsBlockedTurf(true)) + || _tileDefinitionManager[tileDef.BaseTurf] is not ContentTileDefinition || + tile.IsBlockedTurf(true)) { return false; } diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs index 63642338f38..88a96dc1e8d 100644 --- a/Content.Server/Tools/ToolSystem.cs +++ b/Content.Server/Tools/ToolSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Tools; using Robust.Server.GameObjects; using Robust.Shared.Map; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Tools { @@ -21,13 +22,11 @@ public sealed partial class ToolSystem : SharedToolSystem [Dependency] private readonly SharedPointLightSystem _light = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!; - [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { base.Initialize(); - InitializeTilePrying(); InitializeLatticeCutting(); InitializeWelders(); } diff --git a/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs b/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs index d2b3cc261cd..f113e496555 100644 --- a/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs +++ b/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs @@ -1,7 +1,7 @@ using Content.Server.Administration; using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Syntax; @@ -25,7 +25,7 @@ public sealed class ACmdCommand : ToolshedCommand public bool CanInvoke( [CommandInvocationContext] IInvocationContext ctx, [PipedArgument] CommandSpec command, - [CommandArgument] ValueRef player + [CommandArgument] ValueRef player ) { // Deliberately discard the error. diff --git a/Content.Server/Toolshed/Commands/VisualizeCommand.cs b/Content.Server/Toolshed/Commands/VisualizeCommand.cs index 4ef08a91bf0..2225bfaf447 100644 --- a/Content.Server/Toolshed/Commands/VisualizeCommand.cs +++ b/Content.Server/Toolshed/Commands/VisualizeCommand.cs @@ -4,7 +4,6 @@ using Content.Shared.Administration; using Content.Shared.Bql; using Content.Shared.Eui; -using Robust.Server.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; @@ -30,7 +29,7 @@ [PipedArgument] IEnumerable input var ui = new ToolshedVisualizeEui( input.Select(e => (EntName(e), EntityManager.GetNetEntity(e))).ToArray() ); - _euiManager.OpenEui(ui, (IPlayerSession) ctx.Session); + _euiManager.OpenEui(ui, ctx.Session); _euiManager.QueueStateUpdate(ui); } } diff --git a/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs b/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs index 1feab11b99a..fd656a9f717 100644 --- a/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs +++ b/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs @@ -5,6 +5,7 @@ using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; +using Robust.Shared.Player; namespace Content.Server.Traitor.Uplink.Commands { @@ -36,7 +37,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - IPlayerSession? session; + ICommonSession? session; if (args.Length > 0) { // Get player entity @@ -48,7 +49,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) } else { - session = (IPlayerSession?) shell.Player; + session = shell.Player; } if (session?.AttachedEntity is not { } user) diff --git a/Content.Server/UserInterface/ActivatableUIComponent.cs b/Content.Server/UserInterface/ActivatableUIComponent.cs index bb020608e20..34f9c0f3970 100644 --- a/Content.Server/UserInterface/ActivatableUIComponent.cs +++ b/Content.Server/UserInterface/ActivatableUIComponent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Reflection; using Robust.Shared.Serialization; @@ -65,7 +65,7 @@ public sealed partial class ActivatableUIComponent : Component, /// NOTE: DO NOT DIRECTLY SET, USE ActivatableUISystem.SetCurrentSingleUser /// [ViewVariables] - public IPlayerSession? CurrentSingleUser; + public ICommonSession? CurrentSingleUser; void ISerializationHooks.AfterDeserialization() { diff --git a/Content.Server/UserInterface/ActivatableUISystem.cs b/Content.Server/UserInterface/ActivatableUISystem.cs index 59086415b46..adeeed7c19d 100644 --- a/Content.Server/UserInterface/ActivatableUISystem.cs +++ b/Content.Server/UserInterface/ActivatableUISystem.cs @@ -8,7 +8,7 @@ using Content.Shared.UserInterface; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.UserInterface; @@ -173,7 +173,7 @@ private bool InteractUI(EntityUid user, EntityUid uiEntity, ActivatableUICompone return true; } - public void SetCurrentSingleUser(EntityUid uid, IPlayerSession? v, ActivatableUIComponent? aui = null) + public void SetCurrentSingleUser(EntityUid uid, ICommonSession? v, ActivatableUIComponent? aui = null) { if (!Resolve(uid, ref aui)) return; @@ -231,9 +231,9 @@ public UserOpenActivatableUIAttemptEvent(EntityUid who, EntityUid target) public sealed class AfterActivatableUIOpenEvent : EntityEventArgs { public EntityUid User { get; } - public readonly IPlayerSession Session; + public readonly ICommonSession Session; - public AfterActivatableUIOpenEvent(EntityUid who, IPlayerSession session) + public AfterActivatableUIOpenEvent(EntityUid who, ICommonSession session) { User = who; Session = session; diff --git a/Content.Server/UserInterface/StatValuesCommand.cs b/Content.Server/UserInterface/StatValuesCommand.cs index b13b5963231..fe2ee380fea 100644 --- a/Content.Server/UserInterface/StatValuesCommand.cs +++ b/Content.Server/UserInterface/StatValuesCommand.cs @@ -8,7 +8,6 @@ using Content.Shared.Research.Prototypes; using Content.Shared.UserInterface; using Content.Shared.Weapons.Melee; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -27,7 +26,7 @@ public sealed class StatValuesCommand : IConsoleCommand public string Help => $"{Command} "; public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession pSession) + if (shell.Player is not { } pSession) { shell.WriteError(Loc.GetString("stat-values-server")); return; diff --git a/Content.Server/Verbs/VerbSystem.cs b/Content.Server/Verbs/VerbSystem.cs index 6d12b08e865..e304c6b4af0 100644 --- a/Content.Server/Verbs/VerbSystem.cs +++ b/Content.Server/Verbs/VerbSystem.cs @@ -6,7 +6,6 @@ using Content.Shared.Database; using Content.Shared.Hands.Components; using Content.Shared.Verbs; -using Robust.Server.Player; namespace Content.Server.Verbs { @@ -25,7 +24,7 @@ public override void Initialize() private void HandleVerbRequest(RequestServerVerbsEvent args, EntitySessionEventArgs eventArgs) { - var player = (IPlayerSession) eventArgs.SenderSession; + var player = eventArgs.SenderSession; if (!EntityManager.EntityExists(GetEntity(args.EntityUid))) { @@ -43,7 +42,7 @@ private void HandleVerbRequest(RequestServerVerbsEvent args, EntitySessionEventA // this, and some verbs (e.g. view variables) won't even care about whether an entity is accessible through // the entity menu or not. - var force = args.AdminRequest && eventArgs.SenderSession is IPlayerSession playerSession && + var force = args.AdminRequest && eventArgs.SenderSession is { } playerSession && _adminMgr.HasAdminFlag(playerSession, AdminFlags.Admin); List verbTypes = new(); diff --git a/Content.Server/Voting/IVoteHandle.cs b/Content.Server/Voting/IVoteHandle.cs index 13f64e6ef8a..869f2017d70 100644 --- a/Content.Server/Voting/IVoteHandle.cs +++ b/Content.Server/Voting/IVoteHandle.cs @@ -1,5 +1,5 @@ using Content.Server.Voting.Managers; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Voting { @@ -75,7 +75,7 @@ public interface IVoteHandle /// /// is not a valid option ID. /// - void CastVote(IPlayerSession session, int? optionId); + void CastVote(ICommonSession session, int? optionId); /// /// Cancel this vote. diff --git a/Content.Server/Voting/Managers/IVoteManager.cs b/Content.Server/Voting/Managers/IVoteManager.cs index 6a92e70fff7..d95fac9ae92 100644 --- a/Content.Server/Voting/Managers/IVoteManager.cs +++ b/Content.Server/Voting/Managers/IVoteManager.cs @@ -1,6 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.Voting; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Voting.Managers { @@ -41,7 +41,7 @@ public interface IVoteManager /// True if can start votes right now, /// and if provided if they can start votes of type . /// - bool CanCallVote(IPlayerSession initiator, StandardVoteType? voteType = null); + bool CanCallVote(ICommonSession initiator, StandardVoteType? voteType = null); /// /// Initiate a standard vote such as restart round, that can be initiated by players. @@ -51,7 +51,7 @@ public interface IVoteManager /// If null it is assumed to be an automatic vote by the server. /// /// The type of standard vote to make. - void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteType); + void CreateStandardVote(ICommonSession? initiator, StandardVoteType voteType); /// /// Create a non-standard vote with special parameters. diff --git a/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs b/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs index 55e88e2a8c7..e1bffa769da 100644 --- a/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs +++ b/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs @@ -6,8 +6,8 @@ using Content.Shared.CCVar; using Content.Shared.Database; using Content.Shared.Voting; -using Robust.Server.Player; using Robust.Shared.Configuration; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.Voting.Managers @@ -21,7 +21,7 @@ public sealed partial class VoteManager {StandardVoteType.Map, CCVars.VoteMapEnabled}, }; - public void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteType) + public void CreateStandardVote(ICommonSession? initiator, StandardVoteType voteType) { if (initiator != null) _adminLogger.Add(LogType.Vote, LogImpact.Medium, $"{initiator} initiated a {voteType.ToString()} vote"); @@ -47,7 +47,7 @@ public void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteT TimeoutStandardVote(voteType); } - private void CreateRestartVote(IPlayerSession? initiator) + private void CreateRestartVote(ICommonSession? initiator) { var alone = _playerManager.PlayerCount == 1 && initiator != null; var options = new VoteOptions @@ -100,7 +100,7 @@ private void CreateRestartVote(IPlayerSession? initiator) vote.CastVote(initiator, 0); } - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { if (player != initiator) { @@ -110,7 +110,7 @@ private void CreateRestartVote(IPlayerSession? initiator) } } - private void CreatePresetVote(IPlayerSession? initiator) + private void CreatePresetVote(ICommonSession? initiator) { var presets = GetGamePresets(); @@ -156,7 +156,7 @@ private void CreatePresetVote(IPlayerSession? initiator) }; } - private void CreateMapVote(IPlayerSession? initiator) + private void CreateMapVote(ICommonSession? initiator) { var maps = _gameMapManager.CurrentlyEligibleMaps().ToDictionary(map => map, map => map.MapName); diff --git a/Content.Server/Voting/Managers/VoteManager.cs b/Content.Server/Voting/Managers/VoteManager.cs index 98ad8d8341f..90089afb544 100644 --- a/Content.Server/Voting/Managers/VoteManager.cs +++ b/Content.Server/Voting/Managers/VoteManager.cs @@ -16,6 +16,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -45,7 +46,7 @@ public sealed partial class VoteManager : IVoteManager private readonly Dictionary _standardVoteTimeout = new(); private readonly Dictionary _voteTimeout = new(); - private readonly HashSet _playerCanCallVoteDirty = new(); + private readonly HashSet _playerCanCallVoteDirty = new(); private readonly StandardVoteType[] _standardVoteTypeValues = Enum.GetValues(); public void Initialize() @@ -106,7 +107,7 @@ private void PlayerManagerOnPlayerStatusChanged(object? sender, SessionStatusEve } } - private void CastVote(VoteReg v, IPlayerSession player, int? option) + private void CastVote(VoteReg v, ICommonSession player, int? option) { if (!IsValidOption(v, option)) throw new ArgumentOutOfRangeException(nameof(option), "Invalid vote option ID"); @@ -228,7 +229,7 @@ public IVoteHandle CreateVote(VoteOptions options) private void SendUpdates(VoteReg v) { - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { SendSingleUpdate(v, player); } @@ -237,7 +238,7 @@ private void SendUpdates(VoteReg v) v.Dirty = false; } - private void SendSingleUpdate(VoteReg v, IPlayerSession player) + private void SendSingleUpdate(VoteReg v, ICommonSession player) { var msg = new MsgVoteData(); @@ -277,10 +278,10 @@ private void SendSingleUpdate(VoteReg v, IPlayerSession player) private void DirtyCanCallVoteAll() { - _playerCanCallVoteDirty.UnionWith(_playerManager.ServerSessions); + _playerCanCallVoteDirty.UnionWith(_playerManager.Sessions); } - private void SendUpdateCanCallVote(IPlayerSession player) + private void SendUpdateCanCallVote(ICommonSession player) { var msg = new MsgVoteCanCall(); msg.CanCall = CanCallVote(player, null, out var isAdmin, out var timeSpan); @@ -306,7 +307,7 @@ private void SendUpdateCanCallVote(IPlayerSession player) } private bool CanCallVote( - IPlayerSession initiator, + ICommonSession initiator, StandardVoteType? voteType, out bool isAdmin, out TimeSpan timeSpan) @@ -353,7 +354,7 @@ private bool CanCallVote( return !_voteTimeout.TryGetValue(initiator.UserId, out timeSpan); } - public bool CanCallVote(IPlayerSession initiator, StandardVoteType? voteType = null) + public bool CanCallVote(ICommonSession initiator, StandardVoteType? voteType = null) { return CanCallVote(initiator, voteType, out _, out _); } @@ -406,14 +407,14 @@ public bool TryGetVote(int voteId, [NotNullWhen(true)] out IVoteHandle? vote) return false; } - private void DirtyCanCallVote(IPlayerSession player) + private void DirtyCanCallVote(ICommonSession player) { _playerCanCallVoteDirty.Add(player); } #region Preset Votes - private void WirePresetVoteInitiator(VoteOptions options, IPlayerSession? player) + private void WirePresetVoteInitiator(VoteOptions options, ICommonSession? player) { if (player != null) { @@ -432,13 +433,13 @@ private void WirePresetVoteInitiator(VoteOptions options, IPlayerSession? player private sealed class VoteReg { public readonly int Id; - public readonly Dictionary CastVotes = new(); + public readonly Dictionary CastVotes = new(); public readonly VoteEntry[] Entries; public readonly string Title; public readonly string InitiatorText; public readonly TimeSpan StartTime; public readonly TimeSpan EndTime; - public readonly HashSet VotesDirty = new(); + public readonly HashSet VotesDirty = new(); public bool Cancelled; public bool Finished; @@ -446,10 +447,10 @@ private sealed class VoteReg public VoteFinishedEventHandler? OnFinished; public VoteCancelledEventHandler? OnCancelled; - public IPlayerSession? Initiator { get; } + public ICommonSession? Initiator { get; } public VoteReg(int id, VoteEntry[] entries, string title, string initiatorText, - IPlayerSession? initiator, TimeSpan start, TimeSpan end) + ICommonSession? initiator, TimeSpan start, TimeSpan end) { Id = id; Entries = entries; @@ -517,7 +518,7 @@ public bool IsValidOption(int optionId) return _mgr.IsValidOption(_reg, optionId); } - public void CastVote(IPlayerSession session, int? optionId) + public void CastVote(ICommonSession session, int? optionId) { _mgr.CastVote(_reg, session, optionId); } diff --git a/Content.Server/Voting/VoteCommands.cs b/Content.Server/Voting/VoteCommands.cs index cb296a7d589..498c9d04941 100644 --- a/Content.Server/Voting/VoteCommands.cs +++ b/Content.Server/Voting/VoteCommands.cs @@ -6,7 +6,6 @@ using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Voting; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Voting @@ -36,14 +35,14 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var mgr = IoCManager.Resolve(); - if (shell.Player != null && !mgr.CanCallVote((IPlayerSession) shell.Player, type)) + if (shell.Player != null && !mgr.CanCallVote(shell.Player, type)) { _adminLogger.Add(LogType.Vote, LogImpact.Medium, $"{shell.Player} failed to start {type.ToString()} vote"); shell.WriteError(Loc.GetString("cmd-createvote-cannot-call-vote-now")); return; } - mgr.CreateStandardVote((IPlayerSession?) shell.Player, type); + mgr.CreateStandardVote(shell.Player, type); } public CompletionResult GetCompletion(IConsoleShell shell, string[] args) @@ -92,7 +91,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) options.Options.Add((args[i], i)); } - options.SetInitiatorOrServer((IPlayerSession?) shell.Player); + options.SetInitiatorOrServer(shell.Player); if (shell.Player != null) _adminLogger.Add(LogType.Vote, LogImpact.Medium, $"{shell.Player} initiated a custom vote: {options.Title} - {string.Join("; ", options.Options.Select(x => x.text))}"); @@ -187,7 +186,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - vote.CastVote((IPlayerSession) shell.Player!, optionN); + vote.CastVote(shell.Player!, optionN); } } diff --git a/Content.Server/Voting/VoteOptions.cs b/Content.Server/Voting/VoteOptions.cs index 6e6d0465edf..5475d10d329 100644 --- a/Content.Server/Voting/VoteOptions.cs +++ b/Content.Server/Voting/VoteOptions.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Voting @@ -16,7 +16,7 @@ public sealed class VoteOptions /// /// The player that started the vote. Used to keep track of player cooldowns to avoid vote spam. /// - public IPlayerSession? InitiatorPlayer { get; set; } + public ICommonSession? InitiatorPlayer { get; set; } /// /// The shown title of the vote. @@ -43,13 +43,13 @@ public sealed class VoteOptions /// Sets and /// by setting the latter to the player's name. /// - public void SetInitiator(IPlayerSession player) + public void SetInitiator(ICommonSession player) { InitiatorPlayer = player; InitiatorText = player.Name; } - public void SetInitiatorOrServer(IPlayerSession? player) + public void SetInitiatorOrServer(ICommonSession? player) { if (player != null) { diff --git a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs index 1b6b2ebef1c..3d9c3e82194 100644 --- a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs @@ -24,11 +24,9 @@ using Content.Shared.Tag; using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee.Events; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Random; namespace Content.Server.Weapons.Melee; @@ -174,7 +172,7 @@ protected override bool InRange(EntityUid user, EntityUid target, float range, I EntityCoordinates targetCoordinates; Angle targetLocalAngle; - if (session is IPlayerSession pSession) + if (session is { } pSession) { (targetCoordinates, targetLocalAngle) = _lag.GetCoordinatesAngle(target, pSession); } diff --git a/Content.Server/Wires/WiresSystem.cs b/Content.Server/Wires/WiresSystem.cs index df61e89d4dd..b6452efa8a6 100644 --- a/Content.Server/Wires/WiresSystem.cs +++ b/Content.Server/Wires/WiresSystem.cs @@ -16,9 +16,10 @@ using Content.Shared.Tools.Components; using Content.Shared.Wires; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Wires; @@ -615,7 +616,7 @@ private void UpdateUserInterface(EntityUid uid, WiresComponent? wires = null, Us wires.WireSeed), ui: ui); } - public void OpenUserInterface(EntityUid uid, IPlayerSession player) + public void OpenUserInterface(EntityUid uid, ICommonSession player) { if (_uiSystem.TryGetUi(uid, WiresUiKey.Key, out var ui)) _uiSystem.OpenUi(ui, player); diff --git a/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs b/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs index a90faef9959..a09416e5937 100644 --- a/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs +++ b/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs @@ -14,6 +14,7 @@ public sealed class BlobFloorPlanBuilderSystem : BaseWorldSystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinition = default!; + [Dependency] private readonly TileSystem _tiles = default!; /// public override void Initialize() @@ -30,6 +31,8 @@ private void OnBlobFloorPlanBuilderStartup(EntityUid uid, BlobFloorPlanBuilderCo private void PlaceFloorplanTiles(BlobFloorPlanBuilderComponent comp, MapGridComponent grid) { // NO MORE THAN TWO ALLOCATIONS THANK YOU VERY MUCH. + // TODO: Just put these on a field instead then? + // Also the end of the method has a big LINQ which is gonna blow this out the water. var spawnPoints = new HashSet(comp.FloorPlacements * 6); var taken = new Dictionary(comp.FloorPlacements * 5); @@ -56,7 +59,7 @@ void PlaceTile(Vector2i point) spawnPoints.Add(west); var tileDef = _tileDefinition[_random.Pick(comp.FloorTileset)]; - taken.Add(point, new Tile(tileDef.TileId, 0, ((ContentTileDefinition)tileDef).PickVariant(_random))); + taken.Add(point, new Tile(tileDef.TileId, 0, _tiles.PickVariant((ContentTileDefinition) tileDef))); } PlaceTile(Vector2i.Zero); diff --git a/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs b/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs index b2d8df4de92..65af0b68cb7 100644 --- a/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs +++ b/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs @@ -46,7 +46,7 @@ private void OnDebrisMove(EntityUid uid, OwnedDebrisComponent component, ref Mov return; // Redundant logic, prolly needs it's own handler for your custom system. var placer = Comp(component.OwningController); - var xform = Transform(uid); + var xform = args.Component; var ownerXform = Transform(component.OwningController); if (xform.MapUid is null || ownerXform.MapUid is null) return; // not our problem diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs index 49036fb19d8..9200928d662 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs @@ -17,7 +17,6 @@ using Content.Shared.Xenoarchaeology.XenoArtifacts; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -229,7 +228,7 @@ private void UpdateUserInterface(EntityUid uid, AnalysisConsoleComponent? compon /// private void OnServerSelectionMessage(EntityUid uid, AnalysisConsoleComponent component, AnalysisConsoleServerSelectionMessage args) { - _ui.TryOpen(uid, ResearchClientUiKey.Key, (IPlayerSession) args.Session); + _ui.TryOpen(uid, ResearchClientUiKey.Key, args.Session); } /// diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs index 93d9d5a01b5..2d2c230b12e 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs @@ -1,5 +1,4 @@ using System.Linq; -using Content.Server.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; @@ -38,8 +37,7 @@ private void OnActivated(EntityUid uid, FoamArtifactComponent component, Artifac var range = (int) MathF.Round(MathHelper.Lerp(component.MinFoamAmount, component.MaxFoamAmount, _random.NextFloat(0, 1f))); sol.AddReagent(component.SelectedReagent, component.ReagentAmount); var foamEnt = Spawn("Foam", xform.Coordinates); - var smoke = EnsureComp(foamEnt); - smoke.SpreadAmount = range * 4; - _smoke.Start(foamEnt, smoke, sol, component.Duration); + var spreadAmount = range * 4; + _smoke.StartSmoke(foamEnt, sol, component.Duration, spreadAmount); } } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs index 0220c2ce1ae..f51d617df85 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs @@ -6,7 +6,7 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems; /// -/// This handles... +/// This handles artifacts that are activated by magnets, both salvage and magboots. /// public sealed class ArtifactMagnetTriggerSystem : EntitySystem { @@ -22,20 +22,20 @@ public override void Update(float frameTime) { base.Update(frameTime); - var artifactQuery = EntityQuery().ToHashSet(); - if (!artifactQuery.Any()) + if (!EntityQuery().Any()) return; List toActivate = new(); //assume that there's more instruments than artifacts var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var magboot, out var magXform)) + while (query.MoveNext(out _, out var magboot, out var magXform)) { if (!magboot.On) continue; - foreach (var (trigger, xform) in artifactQuery) + var artiQuery = EntityQueryEnumerator(); + while (artiQuery.MoveNext(out var artifactUid, out var trigger, out var xform)) { if (!magXform.Coordinates.TryDistance(EntityManager, xform.Coordinates, out var distance)) continue; @@ -43,7 +43,7 @@ public override void Update(float frameTime) if (distance > trigger.Range) continue; - toActivate.Add(uid); + toActivate.Add(artifactUid); } } diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 9ad155081ac..00a17ace250 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -494,6 +494,9 @@ public bool AddActionDirect(EntityUid performer, (TryComp(action.Container, out ActionsContainerComponent? containerComp) && containerComp.Container.Contains(actionId))); + if (action.AttachedEntity != null) + RemoveAction(action.AttachedEntity.Value, actionId, action: action); + DebugTools.AssertOwner(performer, comp); comp ??= EnsureComp(performer); action.AttachedEntity = performer; @@ -532,6 +535,26 @@ public void GrantActions(EntityUid performer, IEnumerable actions, En } } + /// + /// Grants all actions currently contained in some action-container. If the target entity has no action + /// component, this will give them one. + /// + /// Entity to receive the actions + /// The entity that contains thee actions. + public void GrantContainedActions(Entity performer, Entity container) + { + if (!Resolve(container, ref container.Comp)) + return; + + performer.Comp ??= EnsureComp(performer); + + foreach (var actionId in container.Comp.Container.ContainedEntities) + { + if (TryGetActionData(actionId, out var action)) + AddActionDirect(performer, actionId, performer.Comp, action); + } + } + public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetActions(EntityUid holderId, ActionsComponent? actions = null) { if (!Resolve(holderId, ref actions, false)) diff --git a/Content.Shared/Administration/Managers/ISharedAdminManager.cs b/Content.Shared/Administration/Managers/ISharedAdminManager.cs index 7e01c814332..22d918d4a33 100644 --- a/Content.Shared/Administration/Managers/ISharedAdminManager.cs +++ b/Content.Shared/Administration/Managers/ISharedAdminManager.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Administration.Managers; diff --git a/Content.Shared/Buckle/SharedBuckleSystem.cs b/Content.Shared/Buckle/SharedBuckleSystem.cs index 7edf2448aed..1441745b5da 100644 --- a/Content.Shared/Buckle/SharedBuckleSystem.cs +++ b/Content.Shared/Buckle/SharedBuckleSystem.cs @@ -11,7 +11,7 @@ using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Shared.Buckle; diff --git a/Content.Shared/Chemistry/Components/SmokeAffectedComponent.cs b/Content.Shared/Chemistry/Components/SmokeAffectedComponent.cs new file mode 100644 index 00000000000..def6940ee1c --- /dev/null +++ b/Content.Shared/Chemistry/Components/SmokeAffectedComponent.cs @@ -0,0 +1,24 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Chemistry.Components; + +/// +/// This is used for entities which are currently being affected by smoke. +/// Manages the gradual metabolism every second. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class SmokeAffectedComponent : Component +{ + /// + /// The time at which the next smoke metabolism will occur. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + public TimeSpan NextSecond; + + /// + /// The smoke that is currently affecting this entity. + /// + [DataField] + public EntityUid SmokeEntity; +} diff --git a/Content.Shared/Chemistry/Components/SmokeComponent.cs b/Content.Shared/Chemistry/Components/SmokeComponent.cs new file mode 100644 index 00000000000..9d88fcac945 --- /dev/null +++ b/Content.Shared/Chemistry/Components/SmokeComponent.cs @@ -0,0 +1,34 @@ +using Content.Shared.FixedPoint; +using Content.Shared.Fluids.Components; +using Robust.Shared.GameStates; + +namespace Content.Shared.Chemistry.Components; + +/// +/// Stores solution on an anchored entity that has touch and ingestion reactions +/// to entities that collide with it. Similar to +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SmokeComponent : Component +{ + public const string SolutionName = "solutionArea"; + + /// + /// The max amount of tiles this smoke cloud can spread to. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int SpreadAmount; + + /// + /// The max rate at which chemicals are transferred from the smoke to the person inhaling it. + /// Calculated as (total volume of chemicals in smoke) / () + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public FixedPoint2 TransferRate; + + /// + /// The total lifespan of the smoke. + /// + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Duration = 10; +} diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 511149f8f95..46255e43376 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -257,15 +257,25 @@ private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool sile // Need direction relative to climber's parent. var localDirection = (-parentRot).RotateVec(worldDirection); - climbing.IsClimbing = true; - var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate); - climbing.NextTransition = _timing.CurTime + climbDuration; + // On top of it already so just do it in place. + if (localDirection.LengthSquared() < 0.01f) + { + climbing.NextTransition = null; + } + // VirtualController over to the thing. + else + { + var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate); + climbing.NextTransition = _timing.CurTime + climbDuration; + + climbing.Direction = localDirection.Normalized() * climbing.TransitionRate; + _actionBlockerSystem.UpdateCanMove(uid); + } - climbing.Direction = localDirection.Normalized() * climbing.TransitionRate; + climbing.IsClimbing = true; Dirty(uid, climbing); _audio.PlayPredicted(comp.FinishClimbSound, climbable, user); - _actionBlockerSystem.UpdateCanMove(uid); var startEv = new StartClimbEvent(climbable); var climbedEv = new ClimbedOnEvent(uid, user); diff --git a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs index 3e1cf5584c1..b40c0495622 100644 --- a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs +++ b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs @@ -18,6 +18,7 @@ using Robust.Shared.Player; using Robust.Shared.Serialization; using Robust.Shared.Utility; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Shared.Construction.EntitySystems; diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs index effba18210d..9310617634d 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs @@ -71,6 +71,9 @@ public ItemSlot(ItemSlot other) [DataField("whitelist")] public EntityWhitelist? Whitelist; + [DataField("blacklist")] + public EntityWhitelist? Blacklist; + [DataField("insertSound")] public SoundSpecifier InsertSound = new SoundPathSpecifier("/Audio/Weapons/Guns/MagIn/revolver_magin.ogg"); diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs index 902b56427af..9194a8208e3 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs @@ -255,7 +255,7 @@ public bool CanInsert(EntityUid uid, EntityUid usedUid, EntityUid? user, ItemSlo if (!swap && slot.HasItem) return false; - if (slot.Whitelist != null && !slot.Whitelist.IsValid(usedUid)) + if ((slot.Whitelist != null && !slot.Whitelist.IsValid(usedUid)) || (slot.Blacklist != null && slot.Blacklist.IsValid(usedUid))) { if (_netManager.IsClient && _timing.IsFirstTimePredicted && popup.HasValue && !string.IsNullOrWhiteSpace(slot.WhitelistFailPopup)) _popupSystem.PopupEntity(Loc.GetString(slot.WhitelistFailPopup), uid, popup.Value); diff --git a/Content.Shared/Decals/SharedDecalSystem.cs b/Content.Shared/Decals/SharedDecalSystem.cs index 79bf826eedb..02f73bdacb3 100644 --- a/Content.Shared/Decals/SharedDecalSystem.cs +++ b/Content.Shared/Decals/SharedDecalSystem.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.Diagnostics.CodeAnalysis; using System.Numerics; using Robust.Shared.GameStates; @@ -107,6 +108,18 @@ protected virtual void OnDecalRemoved(EntityUid gridId, uint decalId, DecalGridC { // used by client-side overlay code } + + public virtual HashSet<(uint Index, Decal Decal)> GetDecalsInRange(EntityUid gridId, Vector2 position, float distance = 0.75f, Func? validDelegate = null) + { + // NOOP on client atm. + return new HashSet<(uint Index, Decal Decal)>(); + } + + public virtual bool RemoveDecal(EntityUid gridId, uint decalId, DecalGridComponent? component = null) + { + // NOOP on client atm. + return true; + } } // TODO: Pretty sure paul was moving this somewhere but just so people know diff --git a/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs b/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs index a950fe6930a..a9a52010fd6 100644 --- a/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs @@ -23,11 +23,15 @@ public override void Initialize() private void OnDoorPry(EntityUid uid, DoorBoltComponent component, ref BeforePryEvent args) { - if (component.BoltsDown && !args.Force) - { - Popup.PopupEntity(Loc.GetString("airlock-component-cannot-pry-is-bolted-message"), uid, args.User); - args.Cancelled = true; - } + if (args.Cancelled) + return; + + if (!component.BoltsDown || args.Force) + return; + + args.Message = "airlock-component-cannot-pry-is-bolted-message"; + + args.Cancelled = true; } private void OnBeforeDoorOpened(EntityUid uid, DoorBoltComponent component, BeforeDoorOpenedEvent args) diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs index d0c3be3b311..dfa72fcfb7f 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs @@ -6,7 +6,7 @@ using Content.Shared.Localizations; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Hands.EntitySystems; diff --git a/Content.Shared/Implants/Components/ImplanterComponent.cs b/Content.Shared/Implants/Components/ImplanterComponent.cs index 85891826f90..32a36361633 100644 --- a/Content.Shared/Implants/Components/ImplanterComponent.cs +++ b/Content.Shared/Implants/Components/ImplanterComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Containers.ItemSlots; +using Content.Shared.Whitelist; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -15,6 +16,19 @@ public sealed partial class ImplanterComponent : Component public const string ImplanterSlotId = "implanter_slot"; public const string ImplantSlotId = "implant"; + /// + /// Whitelist to check entities against before implanting. + /// Implants get their own whitelist which is checked afterwards. + /// + [DataField, AutoNetworkedField] + public EntityWhitelist? Whitelist; + + /// + /// Blacklist to check entities against before implanting. + /// + [DataField, AutoNetworkedField] + public EntityWhitelist? Blacklist; + /// /// Used for implanters that start with specific implants /// diff --git a/Content.Shared/Implants/Components/SubdermalImplantComponent.cs b/Content.Shared/Implants/Components/SubdermalImplantComponent.cs index b2fdb14e4c5..5edc26ead32 100644 --- a/Content.Shared/Implants/Components/SubdermalImplantComponent.cs +++ b/Content.Shared/Implants/Components/SubdermalImplantComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Actions; +using Content.Shared.Whitelist; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -34,6 +35,20 @@ public sealed partial class SubdermalImplantComponent : Component [ViewVariables(VVAccess.ReadWrite)] [DataField("permanent"), AutoNetworkedField] public bool Permanent = false; + + /// + /// Target whitelist for this implant specifically. + /// Only checked if the implanter allows implanting on the target to begin with. + /// + [DataField] + public EntityWhitelist? Whitelist; + + /// + /// Target blacklist for this implant specifically. + /// Only checked if the implanter allows implanting on the target to begin with. + /// + [DataField] + public EntityWhitelist? Blacklist; } /// diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 1cf9f446630..404e6da5089 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Implants.Components; using Content.Shared.Popups; +using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Serialization; @@ -85,11 +86,23 @@ public bool CanImplant( if (!TryComp(implant, out implantComp)) return false; + if (!CheckTarget(target, component.Whitelist, component.Blacklist) || + !CheckTarget(target, implantComp.Whitelist, implantComp.Blacklist)) + { + return false; + } + var ev = new AddImplantAttemptEvent(user, target, implant.Value, implanter); RaiseLocalEvent(target, ev); return !ev.Cancelled; } + protected bool CheckTarget(EntityUid target, EntityWhitelist? whitelist, EntityWhitelist? blacklist) + { + return whitelist?.IsValid(target, EntityManager) != false && + blacklist?.IsValid(target, EntityManager) != true; + } + //Draw the implant out of the target //TODO: Rework when surgery is in so implant cases can be a thing public void Draw(EntityUid implanter, EntityUid user, EntityUid target, ImplanterComponent component) diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index 4a9a43ca2c2..7981deaee66 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -34,7 +34,7 @@ using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Serialization; using Robust.Shared.Timing; diff --git a/Content.Server/Maps/TileSystem.cs b/Content.Shared/Maps/TileSystem.cs similarity index 68% rename from Content.Server/Maps/TileSystem.cs rename to Content.Shared/Maps/TileSystem.cs index 1423f76d971..2c09375d593 100644 --- a/Content.Server/Maps/TileSystem.cs +++ b/Content.Shared/Maps/TileSystem.cs @@ -1,13 +1,13 @@ +using System.Linq; using System.Numerics; -using Content.Server.Decals; using Content.Shared.Coordinates.Helpers; using Content.Shared.Decals; -using Content.Shared.Maps; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Random; +using Robust.Shared.Utility; -namespace Content.Server.Maps; +namespace Content.Shared.Maps; /// /// Handles server-side tile manipulation like prying/deconstructing tiles. @@ -15,15 +15,39 @@ namespace Content.Server.Maps; public sealed class TileSystem : EntitySystem { [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; - [Dependency] private readonly DecalSystem _decal = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; + [Dependency] private readonly SharedDecalSystem _decal = default!; + [Dependency] private readonly SharedMapSystem _maps = default!; [Dependency] private readonly TurfSystem _turf = default!; + /// + /// Returns a weighted pick of a tile variant. + /// + public byte PickVariant(ContentTileDefinition tile) + { + var variants = tile.PlacementVariants; + + var sum = variants.Sum(); + var accumulated = 0f; + var rand = _robustRandom.NextFloat() * sum; + + for (byte i = 0; i < variants.Length; ++i) + { + accumulated += variants[i]; + + if (accumulated >= rand) + return i; + } + + // Shouldn't happen + throw new InvalidOperationException($"Invalid weighted variantize tile pick for {tile.ID}!"); + } + public bool PryTile(Vector2i indices, EntityUid gridId) { - var grid = _mapManager.GetGrid(gridId); - var tileRef = grid.GetTileRef(indices); + var grid = Comp(gridId); + var tileRef = _maps.GetTileRef(gridId, grid, indices); return PryTile(tileRef); } @@ -71,16 +95,20 @@ public bool ReplaceTile(TileRef tileref, ContentTileDefinition replacementTile) public bool ReplaceTile(TileRef tileref, ContentTileDefinition replacementTile, EntityUid grid, MapGridComponent? component = null) { + DebugTools.Assert(tileref.GridUid == grid); + if (!Resolve(grid, ref component)) return false; - var variant = replacementTile.PickVariant(); + + var variant = PickVariant(replacementTile); var decals = _decal.GetDecalsInRange(tileref.GridUid, _turf.GetTileCenter(tileref).Position, 0.5f); foreach (var (id, _) in decals) { _decal.RemoveDecal(tileref.GridUid, id); } - component.SetTile(tileref.GridIndices, new Tile(replacementTile.TileId, 0, variant)); + + _maps.SetTile(grid, component, tileref.GridIndices, new Tile(replacementTile.TileId, 0, variant)); return true; } @@ -94,12 +122,13 @@ private bool DeconstructTile(TileRef tileRef) if (string.IsNullOrEmpty(tileDef.BaseTurf)) return false; - var mapGrid = _mapManager.GetGrid(tileRef.GridUid); + var gridUid = tileRef.GridUid; + var mapGrid = Comp(gridUid); const float margin = 0.1f; var bounds = mapGrid.TileSize - margin * 2; var indices = tileRef.GridIndices; - var coordinates = mapGrid.GridTileToLocal(indices) + var coordinates = _maps.GridTileToLocal(gridUid, mapGrid, indices) .Offset(new Vector2( (_robustRandom.NextFloat() - 0.5f) * bounds, (_robustRandom.NextFloat() - 0.5f) * bounds)); @@ -109,15 +138,14 @@ private bool DeconstructTile(TileRef tileRef) Transform(tileItem).LocalRotation = _robustRandom.NextDouble() * Math.Tau; // Destroy any decals on the tile - var decals = _decal.GetDecalsInRange(tileRef.GridUid, coordinates.SnapToGrid(EntityManager, _mapManager).Position, 0.5f); + var decals = _decal.GetDecalsInRange(gridUid, coordinates.SnapToGrid(EntityManager, _mapManager).Position, 0.5f); foreach (var (id, _) in decals) { _decal.RemoveDecal(tileRef.GridUid, id); } var plating = _tileDefinitionManager[tileDef.BaseTurf]; - - mapGrid.SetTile(tileRef.GridIndices, new Tile(plating.TileId)); + _maps.SetTile(gridUid, mapGrid, tileRef.GridIndices, new Tile(plating.TileId)); return true; } diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index 857244d658c..a87b8c97d15 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -86,30 +86,6 @@ public static bool IsSpace(this TileRef tile, ITileDefinitionManager? tileDefini return tile.Tile.IsSpace(tileDefinitionManager); } - /// - /// Returns a weighted pick of a tile variant. - /// - public static byte PickVariant(this ContentTileDefinition tile, IRobustRandom? random = null) - { - IoCManager.Resolve(ref random); - var variants = tile.PlacementVariants; - - var sum = variants.Sum(); - var accumulated = 0f; - var rand = random.NextFloat() * sum; - - for (byte i = 0; i < variants.Length; ++i) - { - accumulated += variants[i]; - - if (accumulated >= rand) - return i; - } - - // Shouldn't happen - throw new InvalidOperationException($"Invalid weighted variantize tile pick for {tile.ID}!"); - } - /// /// Helper that returns all entities in a turf. /// diff --git a/Content.Shared/Mind/Components/MindContainerComponent.cs b/Content.Shared/Mind/Components/MindContainerComponent.cs index ca0f14d994c..62b26cbd353 100644 --- a/Content.Shared/Mind/Components/MindContainerComponent.cs +++ b/Content.Shared/Mind/Components/MindContainerComponent.cs @@ -1,24 +1,25 @@ using System.Diagnostics.CodeAnalysis; +using Robust.Shared.GameStates; namespace Content.Shared.Mind.Components { /// - /// Stores a on a mob. + /// This component indicates that this entity may have mind, which is simply an entity with a . + /// The mind entity is not actually stored in a "container", but is simply stored in nullspace. /// - [RegisterComponent, Access(typeof(SharedMindSystem))] + [RegisterComponent, Access(typeof(SharedMindSystem)), NetworkedComponent, AutoGenerateComponentState] public sealed partial class MindContainerComponent : Component { /// /// The mind controlling this mob. Can be null. /// - [ViewVariables] + [DataField, AutoNetworkedField] [Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends public EntityUid? Mind { get; set; } /// /// True if we have a mind, false otherwise. /// - [ViewVariables] [MemberNotNullWhen(true, nameof(Mind))] public bool HasMind => Mind != null; @@ -26,7 +27,7 @@ public sealed partial class MindContainerComponent : Component /// Whether examining should show information about the mind or not. /// [ViewVariables(VVAccess.ReadWrite)] - [DataField("showExamineInfo")] + [DataField("showExamineInfo"), AutoNetworkedField] public bool ShowExamineInfo { get; set; } /// @@ -38,19 +39,59 @@ public sealed partial class MindContainerComponent : Component public bool GhostOnShutdown { get; set; } = true; } - public sealed class MindRemovedMessage : EntityEventArgs + public abstract class MindEvent : EntityEventArgs { - public EntityUid OldMindId; - public MindComponent OldMind; + public readonly Entity Mind; + public readonly Entity Container; - public MindRemovedMessage(EntityUid oldMindId, MindComponent oldMind) + public MindEvent(Entity mind, Entity container) { - OldMindId = oldMindId; - OldMind = oldMind; + Mind = mind; + Container = container; } } - public sealed class MindAddedMessage : EntityEventArgs + /// + /// Event raised directed at a mind-container when a mind gets removed. + /// + public sealed class MindRemovedMessage : MindEvent { + public MindRemovedMessage(Entity mind, Entity container) + : base(mind, container) + { + } + } + + /// + /// Event raised directed at a mind when it gets removed from a mind-container. + /// + public sealed class MindGotRemovedEvent : MindEvent + { + public MindGotRemovedEvent(Entity mind, Entity container) + : base(mind, container) + { + } + } + + /// + /// Event raised directed at a mind-container when a mind gets added. + /// + public sealed class MindAddedMessage : MindEvent + { + public MindAddedMessage(Entity mind, Entity container) + : base(mind, container) + { + } + } + + /// + /// Event raised directed at a mind when it gets added to a mind-container. + /// + public sealed class MindGotAddedEvent : MindEvent + { + public MindGotAddedEvent(Entity mind, Entity container) + : base(mind, container) + { + } } } diff --git a/Content.Shared/Mind/MindComponent.cs b/Content.Shared/Mind/MindComponent.cs index 3ea92c3ce72..b147a2dbbe7 100644 --- a/Content.Shared/Mind/MindComponent.cs +++ b/Content.Shared/Mind/MindComponent.cs @@ -1,84 +1,86 @@ using Content.Shared.GameTicking; using Content.Shared.Mind.Components; +using Robust.Shared.GameStates; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Mind { /// - /// This is added as a component to mind entities, not to player entities. - /// for the one that is added to players. - /// A mind represents the IC "mind" of a player. - /// Roles are attached as components to its owning entity. + /// This component stores information about a player/mob mind. The component will be attached to a mind-entity + /// which is stored in null-space. The entity that is currently "possessed" by the mind will have a + /// . /// /// + /// Roles are attached as components on the mind-entity entity. /// Think of it like this: if a player is supposed to have their memories, /// their mind follows along. /// /// Things such as respawning do not follow, because you're a new character. /// Getting borged, cloned, turned into a catbeast, etc... will keep it following you. + /// + /// Minds are stored in null-space, and are thus generally not set to players unless that player is the owner + /// of the mind. As a result it should be safe to network "secret" information like roles & objectives /// - [RegisterComponent] + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] public sealed partial class MindComponent : Component { - internal readonly List Objectives = new(); + [DataField, AutoNetworkedField] + public List Objectives = new(); /// /// The session ID of the player owning this mind. /// - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public NetUserId? UserId { get; set; } /// /// The session ID of the original owner, if any. /// May end up used for round-end information (as the owner may have abandoned Mind since) /// - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public NetUserId? OriginalOwnerUserId { get; set; } /// - /// Entity UID for the first entity that this mind controlled. Used for round end. + /// The first entity that this mind controlled. Used for round end information. /// Might be relevant if the player has ghosted since. /// - [ViewVariables] public EntityUid? OriginalOwnedEntity; + [DataField, AutoNetworkedField] + public NetEntity? OriginalOwnedEntity; + // This is a net entity, because this field currently ddoes not get set to null when this entity is deleted. + // This is a lazy way to ensure that people check that the entity still exists. + // TODO MIND Fix this properly by adding an OriginalMindContainerComponent or something like that. [ViewVariables] public bool IsVisitingEntity => VisitingEntity != null; - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public EntityUid? VisitingEntity { get; set; } [ViewVariables] public EntityUid? CurrentEntity => VisitingEntity ?? OwnedEntity; - [ViewVariables(VVAccess.ReadWrite)] + [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public string? CharacterName { get; set; } /// /// The time of death for this Mind. /// Can be null - will be null if the Mind is not considered "dead". /// - [ViewVariables] + [DataField] public TimeSpan? TimeOfDeath { get; set; } - /// - /// The component currently owned by this mind. - /// Can be null. - /// - [ViewVariables] public MindContainerComponent? OwnedComponent; - /// /// The entity currently owned by this mind. /// Can be null. /// - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public EntityUid? OwnedEntity { get; set; } - // TODO move objectives out of mind component /// /// An enumerable over all the objective entities this mind has. /// - [ViewVariables] + [ViewVariables, Obsolete("Use Objectives field")] public IEnumerable AllObjectives => Objectives; /// @@ -100,6 +102,7 @@ public sealed partial class MindComponent : Component /// Can be null, in which case the player is currently not logged in. /// [ViewVariables, Access(typeof(SharedMindSystem), typeof(SharedGameTicker))] + // TODO remove this after moving IPlayerManager functions to shared public ICommonSession? Session { get; set; } } } diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index cc4ac4af236..8e72d9c741f 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Examine; @@ -12,7 +13,7 @@ using Content.Shared.Players; using Robust.Shared.Map; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Shared.Mind; @@ -25,7 +26,7 @@ public abstract class SharedMindSystem : EntitySystem [Dependency] private readonly SharedPlayerSystem _player = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; - // This is dictionary is required to track the minds of disconnected players that may have had their entity deleted. + [ViewVariables] protected readonly Dictionary UserMinds = new(); public override void Initialize() @@ -36,6 +37,7 @@ public override void Initialize() SubscribeLocalEvent(OnSuicide); SubscribeLocalEvent(OnVisitingTerminating); SubscribeLocalEvent(OnReset); + SubscribeLocalEvent(OnMindStartup); } public override void Shutdown() @@ -44,6 +46,29 @@ public override void Shutdown() WipeAllMinds(); } + private void OnMindStartup(EntityUid uid, MindComponent component, ComponentStartup args) + { + if (component.UserId == null) + return; + + if (UserMinds.TryAdd(component.UserId.Value, uid)) + return; + + var existing = UserMinds[component.UserId.Value]; + if (existing == uid) + return; + + if (!Exists(existing)) + { + Log.Error($"Found deleted entity in mind dictionary while initializing mind {ToPrettyString(uid)}"); + UserMinds[component.UserId.Value] = uid; + return; + } + + Log.Error($"Encountered a user {component.UserId} that is already assigned to a mind while initializing mind {ToPrettyString(uid)}. Ignoring user field."); + component.UserId = null; + } + private void OnReset(RoundRestartCleanupEvent ev) { WipeAllMinds(); @@ -51,12 +76,22 @@ private void OnReset(RoundRestartCleanupEvent ev) public virtual void WipeAllMinds() { - foreach (var mind in UserMinds.Values) + Log.Info($"Wiping all minds"); + foreach (var mind in UserMinds.Values.ToArray()) { WipeMind(mind); } - DebugTools.Assert(UserMinds.Count == 0); + if (UserMinds.Count == 0) + return; + + foreach (var mind in UserMinds.Values) + { + if (Exists(mind)) + Log.Error($"Failed to wipe mind: {ToPrettyString(mind)}"); + } + + UserMinds.Clear(); } public EntityUid? GetMind(NetUserId user) @@ -80,6 +115,26 @@ public virtual bool TryGetMind(NetUserId user, [NotNullWhen(true)] out EntityUid return false; } + public bool TryGetMind(NetUserId user, [NotNullWhen(true)] out Entity? mind) + { + if (!TryGetMind(user, out var mindId, out var mindComp)) + { + mind = null; + return false; + } + + mind = (mindId.Value, mindComp); + return true; + } + + public Entity GetOrCreateMind(NetUserId user) + { + if (!TryGetMind(user, out var mind)) + mind = CreateMind(user); + + return mind.Value; + } + private void OnVisitingTerminating(EntityUid uid, VisitingMindComponent component, ref EntityTerminatingEvent args) { if (component.MindId != null) @@ -92,15 +147,16 @@ private void OnExamined(EntityUid uid, MindContainerComponent mindContainer, Exa return; var dead = _mobState.IsDead(uid); + var hasUserId = CompOrNull(mindContainer.Mind)?.UserId; var hasSession = CompOrNull(mindContainer.Mind)?.Session; - if (dead && !mindContainer.HasMind) + if (dead && hasUserId == null) args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-dead-and-irrecoverable", ("ent", uid))}[/color]"); else if (dead && hasSession == null) args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-dead-and-ssd", ("ent", uid))}[/color]"); else if (dead) args.PushMarkup($"[color=red]{Loc.GetString("comp-mind-examined-dead", ("ent", uid))}[/color]"); - else if (!mindContainer.HasMind) + else if (hasUserId == null) args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-catatonic", ("ent", uid))}[/color]"); else if (hasSession == null) args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-ssd", ("ent", uid))}[/color]"); @@ -128,7 +184,7 @@ private void OnSuicide(EntityUid uid, MindContainerComponent component, SuicideE return null; } - public EntityUid CreateMind(NetUserId? userId, string? name = null) + public Entity CreateMind(NetUserId? userId, string? name = null) { var mindId = Spawn(null, MapCoordinates.Nullspace); _metadata.SetEntityName(mindId, name == null ? "mind" : $"mind ({name})"); @@ -136,7 +192,7 @@ public EntityUid CreateMind(NetUserId? userId, string? name = null) mind.CharacterName = name; SetUserId(mindId, userId, mind); - return mindId; + return (mindId, mind); } /// @@ -195,7 +251,7 @@ public void UnVisit(ICommonSession? player) /// Cleans up the VisitingEntity. /// /// - protected void RemoveVisitingEntity(MindComponent mind) + protected void RemoveVisitingEntity(EntityUid mindId, MindComponent mind) { if (mind.VisitingEntity == null) return; @@ -210,6 +266,7 @@ protected void RemoveVisitingEntity(MindComponent mind) RemCompDeferred(oldVisitingEnt, visitComp); } + Dirty(mindId, mind); RaiseLocalEvent(oldVisitingEnt, new MindUnvisitedMessage(), true); } @@ -228,7 +285,7 @@ public void WipeMind(EntityUid? mindId, MindComponent? mind = null) if (mindId == null || !Resolve(mindId.Value, ref mind, false)) return; - TransferTo(mindId.Value, null, mind: mind); + TransferTo(mindId.Value, null, createGhost:false, mind: mind); SetUserId(mindId.Value, null, mind: mind); } @@ -353,11 +410,11 @@ public bool TryGetMind( } public bool TryGetMind( - PlayerData player, + ContentPlayerData contentPlayer, out EntityUid mindId, [NotNullWhen(true)] out MindComponent? mind) { - mindId = player.Mind ?? default; + mindId = contentPlayer.Mind ?? default; return TryComp(mindId, out mind); } @@ -391,21 +448,6 @@ public bool TryGetRole(EntityUid user, [NotNullWhen(true)] out T? role) where return TryComp(mindContainer.Mind, out role); } - /// - /// Sets the Mind's OwnedComponent and OwnedEntity - /// - /// Mind to set OwnedComponent and OwnedEntity on - /// Entity owned by - /// MindContainerComponent owned by - protected void SetOwnedEntity(MindComponent mind, EntityUid? uid, MindContainerComponent? mindContainerComponent) - { - if (uid != null) - Resolve(uid.Value, ref mindContainerComponent); - - mind.OwnedEntity = uid; - mind.OwnedComponent = mindContainerComponent; - } - /// /// Sets the Mind's UserId, Session, and updates the player's PlayerData. This should have no direct effect on the /// entity that any mind is connected to, except as a side effect of the fact that it may change a player's diff --git a/Content.Shared/Movement/Events/MoveInputEvent.cs b/Content.Shared/Movement/Events/MoveInputEvent.cs index 8e1b43f8bd5..89e5636acd7 100644 --- a/Content.Shared/Movement/Events/MoveInputEvent.cs +++ b/Content.Shared/Movement/Events/MoveInputEvent.cs @@ -1,5 +1,3 @@ -using Robust.Shared.Players; - namespace Content.Shared.Movement.Events; /// diff --git a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs index 27e0080c87e..4b81619fd07 100644 --- a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs +++ b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs @@ -5,7 +5,7 @@ using Content.Shared.Input; using Content.Shared.Movement.Components; using Robust.Shared.Input.Binding; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Serialization; namespace Content.Shared.Movement.Systems; diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 425322408ef..1d323a91876 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -6,7 +6,7 @@ using Content.Shared.Movement.Events; using Robust.Shared.Input; using Robust.Shared.Input.Binding; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.Utility; diff --git a/Content.Shared/Placeable/ItemPlacerSystem.cs b/Content.Shared/Placeable/ItemPlacerSystem.cs index 92dc8eb74b7..ec6ece671f0 100644 --- a/Content.Shared/Placeable/ItemPlacerSystem.cs +++ b/Content.Shared/Placeable/ItemPlacerSystem.cs @@ -9,6 +9,7 @@ namespace Content.Shared.Placeable; /// public sealed class ItemPlacerSystem : EntitySystem { + [Dependency] private readonly CollisionWakeSystem _wake = default!; [Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; @@ -25,8 +26,8 @@ private void OnStartCollide(EntityUid uid, ItemPlacerComponent comp, ref StartCo if (comp.Whitelist != null && !comp.Whitelist.IsValid(args.OtherEntity)) return; - // Disallow sleeping so we can detect when entity is removed from the heater. - _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false); + if (TryComp(uid, out var wakeComp)) + _wake.SetEnabled(uid, false, wakeComp); var count = comp.PlacedEntities.Count; if (comp.MaxEntities == 0 || count < comp.MaxEntities) @@ -46,8 +47,8 @@ private void OnStartCollide(EntityUid uid, ItemPlacerComponent comp, ref StartCo private void OnEndCollide(EntityUid uid, ItemPlacerComponent comp, ref EndCollideEvent args) { - // Re-allow sleeping. - _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true); + if (TryComp(uid, out var wakeComp)) + _wake.SetEnabled(uid, true, wakeComp); comp.PlacedEntities.Remove(args.OtherEntity); diff --git a/Content.Shared/Players/PlayerData.cs b/Content.Shared/Players/ContentPlayerData.cs similarity index 73% rename from Content.Shared/Players/PlayerData.cs rename to Content.Shared/Players/ContentPlayerData.cs index c6274c950bd..7545eb58fcd 100644 --- a/Content.Shared/Players/PlayerData.cs +++ b/Content.Shared/Players/ContentPlayerData.cs @@ -1,16 +1,15 @@ using Content.Shared.GameTicking; using Content.Shared.Mind; using Robust.Shared.Network; -using Robust.Shared.Player; namespace Content.Shared.Players; /// /// Content side for all data that tracks a player session. -/// Use to retrieve this from an . +/// Use to retrieve this from an . /// Not currently used on the client. /// -public sealed class PlayerData +public sealed class ContentPlayerData { /// /// The session ID of the player owning this data. @@ -38,21 +37,9 @@ public sealed class PlayerData /// public bool ExplicitlyDeadminned { get; set; } - public PlayerData(NetUserId userId, string name) + public ContentPlayerData(NetUserId userId, string name) { UserId = userId; Name = name; } -} - - -public static class PlayerDataExt -{ - /// - /// Gets the correctly cast instance of content player data from an engine player data storage. - /// - public static PlayerData? ContentData(this IPlayerData data) - { - return (PlayerData?) data.ContentDataUncast; - } -} +} \ No newline at end of file diff --git a/Content.Shared/Players/PlayerDataExt.cs b/Content.Shared/Players/PlayerDataExt.cs new file mode 100644 index 00000000000..eba4d8339d8 --- /dev/null +++ b/Content.Shared/Players/PlayerDataExt.cs @@ -0,0 +1,30 @@ +using Robust.Shared.Player; + +namespace Content.Shared.Players; + +public static class PlayerDataExt +{ + /// + /// Gets the correctly cast instance of content player data from an engine player data storage. + /// + public static ContentPlayerData? ContentData(this SessionData data) + { + return (ContentPlayerData?) data.ContentDataUncast; + } + + /// + /// Gets the correctly cast instance of content player data from an engine player data storage. + /// + public static ContentPlayerData? ContentData(this ICommonSession session) + { + return session.Data.ContentData(); + } + + /// + /// Gets the mind that is associated with this player. + /// + public static EntityUid? GetMind(this ICommonSession session) + { + return session.Data.ContentData()?.Mind; + } +} \ No newline at end of file diff --git a/Content.Shared/Players/SharedPlayerSystem.cs b/Content.Shared/Players/SharedPlayerSystem.cs index 6fc7ad6a409..7271c5688ab 100644 --- a/Content.Shared/Players/SharedPlayerSystem.cs +++ b/Content.Shared/Players/SharedPlayerSystem.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Players; @@ -8,5 +8,5 @@ namespace Content.Shared.Players; /// public abstract class SharedPlayerSystem : EntitySystem { - public abstract PlayerData? ContentData(ICommonSession? session); + public abstract ContentPlayerData? ContentData(ICommonSession? session); } diff --git a/Content.Shared/Popups/SharedPopupSystem.cs b/Content.Shared/Popups/SharedPopupSystem.cs index 50013a54350..e4565b90e8b 100644 --- a/Content.Shared/Popups/SharedPopupSystem.cs +++ b/Content.Shared/Popups/SharedPopupSystem.cs @@ -1,6 +1,5 @@ using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Serialization; namespace Content.Shared.Popups diff --git a/Content.Shared/Power/Generator/PowerSwitchableComponent.cs b/Content.Shared/Power/Generator/PowerSwitchableComponent.cs new file mode 100644 index 00000000000..39118b21e5c --- /dev/null +++ b/Content.Shared/Power/Generator/PowerSwitchableComponent.cs @@ -0,0 +1,82 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Power.Generator; + +/// +/// Enables a device to switch between HV, MV and LV connectors. +/// For generators this means changing output wires. +/// +/// +/// Must have CableDeviceNodes for each output in . +/// If its a generator PowerSupplierComponent is also required. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedPowerSwitchableSystem))] +public sealed partial class PowerSwitchableComponent : Component +{ + /// + /// Index into that the device is currently using. + /// + [DataField, AutoNetworkedField] + public int ActiveIndex; + + /// + /// Sound that plays when the cable is switched. + /// + [DataField] + public SoundSpecifier? SwitchSound = new SoundPathSpecifier("/Audio/Machines/button.ogg"); + + /// + /// Locale id for text shown when examined. + /// It is given "voltage" as a colored voltage string. + /// + [DataField(required: true)] + public string ExamineText = string.Empty; + + /// + /// Locale id for the popup shown when switching voltages. + /// It is given "voltage" as a colored voltage string. + /// + [DataField(required: true)] + public string SwitchText = string.Empty; + + /// + /// Cable voltages and their nodes which can be cycled between. + /// Each node name must match a cable node in its NodeContainer. + /// + [DataField(required: true)] + public List Cables = new(); +} + +/// +/// Cable voltage and node name for cycling. +/// +[DataDefinition] +public sealed partial class PowerSwitchableCable +{ + /// + /// Voltage that the cable uses. + /// + [DataField(required: true)] + public SwitchableVoltage Voltage; + + /// + /// Name of the node for the cable. + /// Must be a CableDeviceNode + /// + [DataField(required: true)] + public string Node = string.Empty; +} + +/// +/// Cable voltage to cycle between. +/// +[Serializable, NetSerializable] +public enum SwitchableVoltage : byte +{ + HV, + MV, + LV +} diff --git a/Content.Shared/Power/Generator/PowerSwitchableGeneratorComponent.cs b/Content.Shared/Power/Generator/PowerSwitchableGeneratorComponent.cs deleted file mode 100644 index 464538f507b..00000000000 --- a/Content.Shared/Power/Generator/PowerSwitchableGeneratorComponent.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Robust.Shared.Audio; -using Robust.Shared.GameStates; -using Robust.Shared.Serialization; - -namespace Content.Shared.Power.Generator; - -/// -/// Enables a generator to switch between HV and MV output. -/// -/// -/// Must have CableDeviceNodes for both and , and also a PowerSupplierComponent. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(SharedPowerSwitchableGeneratorSystem))] -public sealed partial class PowerSwitchableGeneratorComponent : Component -{ - /// - /// Which output the portable generator is currently connected to. - /// - [DataField("activeOutput")] - [AutoNetworkedField] - public PowerSwitchableGeneratorOutput ActiveOutput { get; set; } - - /// - /// Sound that plays when the output is switched. - /// - /// - [DataField("switchSound")] - public SoundSpecifier? SwitchSound { get; set; } - - /// - /// Which node is the MV output? - /// - [DataField("nodeOutputMV")] - public string NodeOutputMV { get; set; } = "output_mv"; - - /// - /// Which node is the HV output? - /// - [DataField("nodeOutputHV")] - public string NodeOutputHV { get; set; } = "output_hv"; -} - -/// -/// Possible power output for power-switchable generators. -/// -/// -[Serializable, NetSerializable] -public enum PowerSwitchableGeneratorOutput : byte -{ - /// - /// The generator is set to connect to a high-voltage power network. - /// - HV, - - /// - /// The generator is set to connect to a medium-voltage power network. - /// - MV -} - diff --git a/Content.Shared/Power/Generator/SharedPowerSwitchableGeneratorSystem.cs b/Content.Shared/Power/Generator/SharedPowerSwitchableGeneratorSystem.cs deleted file mode 100644 index 5d3793c4713..00000000000 --- a/Content.Shared/Power/Generator/SharedPowerSwitchableGeneratorSystem.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Content.Shared.Examine; - -namespace Content.Shared.Power.Generator; - -/// -/// Shared logic for power-switchable generators. -/// -/// -public abstract class SharedPowerSwitchableGeneratorSystem : EntitySystem -{ - public override void Initialize() - { - SubscribeLocalEvent(GeneratorExamined); - } - - private void GeneratorExamined(EntityUid uid, PowerSwitchableGeneratorComponent component, ExaminedEvent args) - { - // Show which output is currently selected. - args.PushMarkup(Loc.GetString( - "power-switchable-generator-examine", - ("output", component.ActiveOutput.ToString()))); - } -} diff --git a/Content.Shared/Power/Generator/SharedPowerSwitchableSystem.cs b/Content.Shared/Power/Generator/SharedPowerSwitchableSystem.cs new file mode 100644 index 00000000000..c1787b60784 --- /dev/null +++ b/Content.Shared/Power/Generator/SharedPowerSwitchableSystem.cs @@ -0,0 +1,72 @@ +using Content.Shared.Examine; + +namespace Content.Shared.Power.Generator; + +/// +/// Shared logic for power-switchable devices. +/// +/// +public abstract class SharedPowerSwitchableSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnExamined); + } + + private void OnExamined(EntityUid uid, PowerSwitchableComponent comp, ExaminedEvent args) + { + // Show which voltage is currently selected. + var voltage = VoltageColor(GetVoltage(uid, comp)); + args.PushMarkup(Loc.GetString(comp.ExamineText, ("voltage", voltage))); + } + + /// + /// Helper to get the colored markup string for a voltage type. + /// + public string VoltageColor(SwitchableVoltage voltage) + { + return Loc.GetString("power-switchable-voltage", ("voltage", VoltageString(voltage))); + } + + /// + /// Converts from "hv" to "HV" since for some reason the enum gets made lowercase??? + /// + public string VoltageString(SwitchableVoltage voltage) + { + return voltage.ToString().ToUpper(); + } + + /// + /// Returns index of the next cable type index to cycle to. + /// + public int NextIndex(EntityUid uid, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return 0; + + // loop back at the end + return (comp.ActiveIndex + 1) % comp.Cables.Count; + } + + /// + /// Returns the current cable voltage being used by a power-switchable device. + /// + public SwitchableVoltage GetVoltage(EntityUid uid, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return default; + + return comp.Cables[comp.ActiveIndex].Voltage; + } + + /// + /// Returns the cable's next voltage to cycle to being used by a power-switchable device. + /// + public SwitchableVoltage GetNextVoltage(EntityUid uid, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return default; + + return comp.Cables[NextIndex(uid, comp)].Voltage; + } +} diff --git a/Content.Shared/Prying/Components/PryingComponent.cs b/Content.Shared/Prying/Components/PryingComponent.cs index 4442481dce1..7a7f304d8f8 100644 --- a/Content.Shared/Prying/Components/PryingComponent.cs +++ b/Content.Shared/Prying/Components/PryingComponent.cs @@ -51,6 +51,8 @@ public record struct BeforePryEvent(EntityUid User, bool PryPowered, bool Force) public readonly bool Force = Force; + public string? Message; + public bool Cancelled; } diff --git a/Content.Shared/Prying/Systems/PryingSystem.cs b/Content.Shared/Prying/Systems/PryingSystem.cs index 19e63de29e0..5fd94c34385 100644 --- a/Content.Shared/Prying/Systems/PryingSystem.cs +++ b/Content.Shared/Prying/Systems/PryingSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Doors.Components; using System.Diagnostics.CodeAnalysis; using Content.Shared.Interaction; +using Content.Shared.Popups; using PryUnpoweredComponent = Content.Shared.Prying.Components.PryUnpoweredComponent; namespace Content.Shared.Prying.Systems; @@ -19,6 +20,7 @@ public sealed class PryingSystem : EntitySystem [Dependency] private readonly ISharedAdminLogManager _adminLog = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedPopupSystem Popup = default!; public override void Initialize() { @@ -68,10 +70,12 @@ public bool TryPry(EntityUid target, EntityUid user, out DoAfterId? id, EntityUi if (!comp.Enabled) return false; - if (!CanPry(target, user, comp)) + if (!CanPry(target, user, out var message, comp)) { + if (message != null) + Popup.PopupEntity(Loc.GetString(message), target, user); // If we have reached this point we want the event that caused this - // to be marked as handled as a popup would be generated on failure. + // to be marked as handled. return true; } @@ -87,15 +91,16 @@ public bool TryPry(EntityUid target, EntityUid user, out DoAfterId? id) { id = null; - if (!CanPry(target, user)) + // We don't care about displaying a message if no tool was used. + if (!CanPry(target, user, out _)) // If we have reached this point we want the event that caused this - // to be marked as handled as a popup would be generated on failure. + // to be marked as handled. return true; return StartPry(target, user, null, 0.1f, out id); // hand-prying is much slower } - private bool CanPry(EntityUid target, EntityUid user, PryingComponent? comp = null) + private bool CanPry(EntityUid target, EntityUid user, out string? message, PryingComponent? comp = null) { BeforePryEvent canev; @@ -106,15 +111,19 @@ private bool CanPry(EntityUid target, EntityUid user, PryingComponent? comp = nu else { if (!TryComp(target, out _)) + { + message = null; return false; + } + canev = new BeforePryEvent(user, false, false); } RaiseLocalEvent(target, ref canev); - if (canev.Cancelled) - return false; - return true; + message = canev.Message; + + return !canev.Cancelled; } private bool StartPry(EntityUid target, EntityUid user, EntityUid? tool, float toolModifier, [NotNullWhen(true)] out DoAfterId? id) diff --git a/Content.Shared/Pulling/Systems/SharedPullingSystem.cs b/Content.Shared/Pulling/Systems/SharedPullingSystem.cs index 6f19d048b4f..0c139ee9e35 100644 --- a/Content.Shared/Pulling/Systems/SharedPullingSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullingSystem.cs @@ -12,7 +12,7 @@ using Robust.Shared.Physics; using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Pulling { diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index 3d2ce2fd00a..eb97fe41133 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -14,6 +14,7 @@ using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Timing; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Shared.Radio.EntitySystems; diff --git a/Content.Shared/Roles/Jobs/SharedJobSystem.cs b/Content.Shared/Roles/Jobs/SharedJobSystem.cs index ac18d04e9c7..af97ea13504 100644 --- a/Content.Shared/Roles/Jobs/SharedJobSystem.cs +++ b/Content.Shared/Roles/Jobs/SharedJobSystem.cs @@ -2,7 +2,7 @@ using System.Linq; using Content.Shared.Players; using Content.Shared.Players.PlayTimeTracking; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; diff --git a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs index c6238c067d4..f492db4d129 100644 --- a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs @@ -1,12 +1,11 @@ using Content.Shared.Roles; using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; /// -/// This is used for an entity that grants a special "obey" law when emagge.d +/// This is used for an entity that grants a special "obey" law when emagged. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedSiliconLawSystem))] public sealed partial class EmagSiliconLawComponent : Component @@ -14,31 +13,39 @@ public sealed partial class EmagSiliconLawComponent : Component /// /// The name of the person who emagged this law provider. /// - [DataField("ownerName"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? OwnerName; /// /// Does the panel need to be open to EMAG this law provider. /// - [DataField("requireOpenPanel"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public bool RequireOpenPanel = true; /// - /// The laws that the borg is given when emagged. + /// The laws that the borg is given when emagged. + /// Law 0 is prepended to this, so this can only include the static laws. /// - [DataField("emagLaws", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List EmagLaws = new(); + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public ProtoId EmagLaws = string.Empty; /// - /// How long the borg is stunned when it's emagged. Setting to 0 will disable it. + /// Lawset created from the prototype id and law 0. + /// Cached when getting laws and only modified during an ion storm event. /// - [DataField("stunTime"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SiliconLawset? Lawset; + + /// + /// How long the borg is stunned when it's emagged. Setting to 0 will disable it. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] public TimeSpan StunTime = TimeSpan.Zero; /// /// A role given to entities with this component when they are emagged. /// Mostly just for admin purposes. /// - [DataField("antagonistRole", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? AntagonistRole = "SubvertedSilicon"; + [DataField] + public ProtoId? AntagonistRole = "SubvertedSilicon"; } diff --git a/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs b/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs new file mode 100644 index 00000000000..49ac611ddcb --- /dev/null +++ b/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs @@ -0,0 +1,54 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Laws.Components; + +/// +/// During the ion storm event, this entity will have raised on it if it has laws. +/// New laws can be modified in multiple ways depending on the fields below. +/// +[RegisterComponent] +public sealed partial class IonStormTargetComponent : Component +{ + /// + /// for a random lawset to possibly replace the old one with. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId RandomLawsets = "IonStormLawsets"; + + /// + /// Chance for this borg to be affected at all. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Chance = 0.5f; + + /// + /// Chance to replace the lawset with a random one + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RandomLawsetChance = 0.25f; + + /// + /// Chance to remove a random law. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RemoveChance = 0.1f; + + /// + /// Chance to replace a random law with the new one, rather than have it be a glitched-order law. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ReplaceChance = 0.1f; + + /// + /// Chance to shuffle laws after everything is done. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ShuffleChance = 0.1f; +} + +/// +/// Raised on an ion storm target to modify its laws. +/// +[ByRefEvent] +public record struct IonStormLawsEvent(SiliconLawset Lawset); diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs index 955705ae8bc..824d057b3ea 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs @@ -1,7 +1,6 @@ using Content.Shared.Actions; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Shared.Silicons.Laws.Components; @@ -14,19 +13,19 @@ public sealed partial class SiliconLawBoundComponent : Component /// /// The sidebar action that toggles the laws screen. /// - [DataField("viewLawsAction", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string ViewLawsAction = "ActionViewLaws"; + [DataField] + public EntProtoId ViewLawsAction = "ActionViewLaws"; /// /// The action for toggling laws. Stored here so we can remove it later. /// - [DataField("viewLawsActionEntity")] + [DataField] public EntityUid? ViewLawsActionEntity; /// /// The last entity that provided laws to this entity. /// - [DataField("lastLawProvider")] + [DataField] public EntityUid? LastLawProvider; } @@ -43,7 +42,7 @@ public record struct GetSiliconLawsEvent(EntityUid Entity) { public EntityUid Entity = Entity; - public readonly List Laws = new(); + public SiliconLawset Laws = new(); public bool Handled = false; } diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs index e3302dc620c..3aaf965aeec 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; @@ -9,8 +9,15 @@ namespace Content.Shared.Silicons.Laws.Components; public sealed partial class SiliconLawProviderComponent : Component { /// - /// The laws that are provided. + /// The id of the lawset that is being provided. /// - [DataField("laws", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List Laws = new(); + [DataField(required: true)] + public ProtoId Laws = string.Empty; + + /// + /// Lawset created from the prototype id. + /// Cached when getting laws and only modified during an ion storm event. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SiliconLawset? Lawset; } diff --git a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs index 86bea20fa04..f6407be5c7b 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs @@ -11,7 +11,7 @@ public partial class SiliconLaw : IComparable /// /// A locale string which is the actual text of the law. /// - [DataField("lawString", required: true)] + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public string LawString = string.Empty; /// @@ -22,13 +22,13 @@ public partial class SiliconLaw : IComparable /// This is a fixedpoint2 only for the niche case of supporting laws that go between 0 and 1. /// Funny. /// - [DataField("order", required: true)] + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 Order; /// /// An identifier that overrides in the law menu UI. /// - [DataField("lawIdentifierOverride")] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? LawIdentifierOverride; public int CompareTo(SiliconLaw? other) @@ -38,6 +38,19 @@ public int CompareTo(SiliconLaw? other) return Order.CompareTo(other.Order); } + + /// + /// Return a shallow clone of this law. + /// + public SiliconLaw ShallowClone() + { + return new SiliconLaw() + { + LawString = LawString, + Order = Order, + LawIdentifierOverride = LawIdentifierOverride + }; + } } /// @@ -50,6 +63,4 @@ public sealed class SiliconLawPrototype : SiliconLaw, IPrototype /// [IdDataField] public string ID { get; private set; } = default!; - - } diff --git a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs new file mode 100644 index 00000000000..abb5b338dbc --- /dev/null +++ b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs @@ -0,0 +1,69 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Shared.Silicons.Laws; + +/// +/// Lawset data used internally. +/// +[DataDefinition, Serializable, NetSerializable] +public sealed partial class SiliconLawset +{ + /// + /// List of laws in this lawset. + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public List Laws = new(); + + /// + /// A single line used in logging laws. + /// + public string LoggingString() + { + var laws = new List(Laws.Count); + foreach (var law in Laws) + { + laws.Add($"{law.Order}: {Loc.GetString(law.LawString)}"); + } + + return string.Join(" / ", laws); + } + + /// + /// Do a clone of this lawset. + /// It will have unique laws but their strings are still shared. + /// + public SiliconLawset Clone() + { + var laws = new List(Laws.Count); + foreach (var law in Laws) + { + laws.Add(law.ShallowClone()); + } + + return new SiliconLawset() + { + Laws = laws + }; + } +} + +/// +/// This is a prototype for a list. +/// Cannot be used directly since it is a list of prototype ids rather than List. +/// +[Prototype("siliconLawset"), Serializable, NetSerializable] +public sealed partial class SiliconLawsetPrototype : IPrototype +{ + /// + [IdDataField] + public string ID { get; private set; } = default!; + + /// + /// List of law prototype ids in this lawset. + /// + [DataField(required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List Laws = new(); +} diff --git a/Content.Shared/Storage/Components/MagnetPickupComponent.cs b/Content.Shared/Storage/Components/MagnetPickupComponent.cs index 300055a62a6..c57b7c4e85a 100644 --- a/Content.Shared/Storage/Components/MagnetPickupComponent.cs +++ b/Content.Shared/Storage/Components/MagnetPickupComponent.cs @@ -1,6 +1,4 @@ using Content.Shared.Inventory; -using Content.Shared.Tag; -using Content.Shared.Whitelist; namespace Content.Server.Storage.Components; @@ -21,16 +19,4 @@ public sealed partial class MagnetPickupComponent : Component [ViewVariables(VVAccess.ReadWrite), DataField("range")] public float Range = 1f; - - [ValidatePrototypeId] - private const string DefaultTag = "Ore"; - - [ViewVariables(VVAccess.ReadWrite), DataField("whitelist")] - public EntityWhitelist? Whitelist = new() - { - Tags = new List() - { - DefaultTag, - } - }; } diff --git a/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs b/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs index 3bbc75732ec..16657bdae4a 100644 --- a/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs +++ b/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs @@ -72,7 +72,7 @@ public override void Update(float frameTime) foreach (var near in _lookup.GetEntitiesInRange(uid, comp.Range, LookupFlags.Dynamic | LookupFlags.Sundries)) { - if (comp.Whitelist?.IsValid(near, EntityManager) == false) + if (storage.Whitelist?.IsValid(near, EntityManager) == false) continue; if (!_physicsQuery.TryGetComponent(near, out var physics) || physics.BodyStatus != BodyStatus.OnGround) diff --git a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs index 0fd7a2e9328..02b4e617901 100644 --- a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs +++ b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs @@ -24,7 +24,6 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnGridChanged); SubscribeLocalEvent(OnTileChanged); SubscribeLocalEvent(OnSubFloorStarted); SubscribeLocalEvent(OnSubFloorTerminating); @@ -97,14 +96,6 @@ private void OnTileChanged(ref TileChangedEvent args) UpdateTile(MapManager.GetGrid(args.NewTile.GridUid), args.NewTile.GridIndices); } - private void OnGridChanged(GridModifiedEvent args) - { - foreach (var modified in args.Modified) - { - UpdateTile(args.Grid, modified.position); - } - } - /// /// Update whether a given entity is currently covered by a floor tile. /// diff --git a/Content.Shared/Tools/Components/TilePryingComponent.cs b/Content.Shared/Tools/Components/TilePryingComponent.cs new file mode 100644 index 00000000000..4c123ca1edb --- /dev/null +++ b/Content.Shared/Tools/Components/TilePryingComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Tools.Components; + +/// +/// Allows prying tiles up on a grid. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class TilePryingComponent : Component +{ + [DataField("toolComponentNeeded"), AutoNetworkedField] + public bool ToolComponentNeeded = true; + + [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer)), AutoNetworkedField] + public string QualityNeeded = "Prying"; + + /// + /// Whether this tool can pry tiles with CanAxe. + /// + [DataField("advanced"), AutoNetworkedField] + public bool Advanced = false; + + [DataField("delay"), AutoNetworkedField] + public float Delay = 1f; +} diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs b/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs index 39a1dc50f32..cb8830060a2 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs @@ -1,9 +1,9 @@ using System.Linq; using Content.Shared.Interaction; -using Content.Shared.Tools.Components; using Content.Shared.Prying.Components; +using Content.Shared.Tools.Components; -namespace Content.Shared.Tools; +namespace Content.Shared.Tools.Systems; public abstract partial class SharedToolSystem : EntitySystem { diff --git a/Content.Server/Tools/ToolSystem.TilePrying.cs b/Content.Shared/Tools/Systems/SharedToolSystem.TilePrying.cs similarity index 66% rename from Content.Server/Tools/ToolSystem.TilePrying.cs rename to Content.Shared/Tools/Systems/SharedToolSystem.TilePrying.cs index faaed6abb87..81592f5a982 100644 --- a/Content.Server/Tools/ToolSystem.TilePrying.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.TilePrying.cs @@ -1,17 +1,15 @@ -using Content.Server.Tools.Components; using Content.Shared.Database; using Content.Shared.Fluids.Components; using Content.Shared.Interaction; using Content.Shared.Maps; using Content.Shared.Tools.Components; using Robust.Shared.Map; +using Robust.Shared.Map.Components; -namespace Content.Server.Tools; +namespace Content.Shared.Tools.Systems; -public sealed partial class ToolSystem +public abstract partial class SharedToolSystem { - [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; - private void InitializeTilePrying() { SubscribeLocalEvent(OnTilePryingAfterInteract); @@ -20,7 +18,8 @@ private void InitializeTilePrying() private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args) { - if (args.Handled || !args.CanReach || (args.Target != null && !HasComp(args.Target))) return; + if (args.Handled || !args.CanReach || args.Target != null && !HasComp(args.Target)) + return; if (TryPryTile(uid, args.User, component, args.ClickLocation)) args.Handled = true; @@ -33,26 +32,28 @@ private void OnTilePryComplete(EntityUid uid, TilePryingComponent component, Til var coords = GetCoordinates(args.Coordinates); var gridUid = coords.GetGridUid(EntityManager); - if (!_mapManager.TryGetGrid(gridUid, out var grid)) + if (!TryComp(gridUid, out MapGridComponent? grid)) { Log.Error("Attempted to pry from a non-existent grid?"); return; } - var tile = grid.GetTileRef(coords); - var center = _turf.GetTileCenter(tile); + var tile = _maps.GetTileRef(gridUid.Value, grid, coords); + var center = _turfs.GetTileCenter(tile); + if (args.Used != null) { _adminLogger.Add(LogType.Tile, LogImpact.Low, - $"{ToPrettyString(args.User):actor} used {ToPrettyString(args.Used.Value):tool} to pry {_tileDefinitionManager[tile.Tile.TypeId].Name} at {center}"); + $"{ToPrettyString(args.User):actor} used {ToPrettyString(args.Used.Value):tool} to pry {_tileDefManager[tile.Tile.TypeId].Name} at {center}"); } else { _adminLogger.Add(LogType.Tile, LogImpact.Low, - $"{ToPrettyString(args.User):actor} pried {_tileDefinitionManager[tile.Tile.TypeId].Name} at {center}"); + $"{ToPrettyString(args.User):actor} pried {_tileDefManager[tile.Tile.TypeId].Name} at {center}"); } - _tile.PryTile(tile, component.Advanced); + if (_netManager.IsServer) + _tiles.PryTile(tile, component.Advanced); } private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponent component, EntityCoordinates clickLocation) @@ -60,17 +61,16 @@ private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponen if (!TryComp(toolEntity, out var tool) && component.ToolComponentNeeded) return false; - if (!_mapManager.TryFindGridAt(clickLocation.ToMap(EntityManager, _transformSystem), out _, out var mapGrid)) + if (!_mapManager.TryFindGridAt(clickLocation.ToMap(EntityManager, _transformSystem), out var gridUid, out var mapGrid)) return false; - var tile = mapGrid.GetTileRef(clickLocation); - - var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); + var tile = _maps.GetTileRef(gridUid, mapGrid, clickLocation); + var coordinates = _maps.GridTileToLocal(gridUid, mapGrid, tile.GridIndices); - if (!_interactionSystem.InRangeUnobstructed(user, coordinates, popup: false)) + if (!InteractionSystem.InRangeUnobstructed(user, coordinates, popup: false)) return false; - var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; + var tileDef = (ContentTileDefinition) _tileDefManager[tile.Tile.TypeId]; if (!tileDef.CanCrowbar && !(tileDef.CanAxe && component.Advanced)) return false; diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.cs b/Content.Shared/Tools/Systems/SharedToolSystem.cs index 716a9332d0e..c1a2bdc2dda 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.cs @@ -1,22 +1,35 @@ +using Content.Shared.Administration.Logs; using Content.Shared.DoAfter; +using Content.Shared.Interaction; +using Content.Shared.Maps; using Content.Shared.Tools.Components; using Robust.Shared.Map; +using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Timing; using Robust.Shared.Utility; -namespace Content.Shared.Tools; +namespace Content.Shared.Tools.Systems; public abstract partial class SharedToolSystem : EntitySystem { - [Dependency] private readonly IPrototypeManager _protoMan = default!; - [Dependency] private readonly SharedAudioSystem _audioSystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly INetManager _netManager = default!; + [Dependency] private readonly IPrototypeManager _protoMan = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] protected readonly SharedInteractionSystem InteractionSystem = default!; + [Dependency] private readonly SharedMapSystem _maps = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly TileSystem _tiles = default!; + [Dependency] private readonly TurfSystem _turfs = default!; public override void Initialize() { InitializeMultipleTool(); + InitializeTilePrying(); SubscribeLocalEvent(OnDoAfter); } diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index 4b740b8d3c7..62af6067d05 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -23,7 +23,7 @@ using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; diff --git a/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs b/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs index 1ec680877fb..95660f69c18 100644 --- a/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs +++ b/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs @@ -1,12 +1,13 @@ using Content.Corvax.Interfaces.Shared; using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Corvax.Interfaces.Server; public interface IServerDiscordAuthManager : ISharedDiscordAuthManager { - public event EventHandler? PlayerVerified; + public event EventHandler? PlayerVerified; public Task GenerateAuthLink(NetUserId userId, CancellationToken cancel); public Task IsVerified(NetUserId userId, CancellationToken cancel); } diff --git a/Resources/Audio/Ambience/Antag/attributions.yml b/Resources/Audio/Ambience/Antag/attributions.yml index 3d7d5c737c4..0a4a0479d12 100644 --- a/Resources/Audio/Ambience/Antag/attributions.yml +++ b/Resources/Audio/Ambience/Antag/attributions.yml @@ -9,4 +9,8 @@ - files: ["zombie_start.ogg"] license: "CC-BY-NC-SA-3.0" copyright: "Made by @MIXnikita#1474 (Discord) for SS14" - source: "https://github.com/SerbiaStrong-220/space-station-14/commit/f33ce80db9d8ac962ec36eb5ae61afa8c0035d1a" \ No newline at end of file + source: "https://github.com/SerbiaStrong-220/space-station-14/commit/f33ce80db9d8ac962ec36eb5ae61afa8c0035d1a" +- files: ["headrev_start.ogg"] + license: "CC0-1.0" + copyright: "Made by https://www.youtube.com/@a-guy173" + source: https://github.com/A-Guy173/Music/blob/main/revolution.mp3 diff --git a/Resources/Audio/Ambience/Antag/headrev_start.ogg b/Resources/Audio/Ambience/Antag/headrev_start.ogg new file mode 100644 index 00000000000..f97ab15a3ef Binary files /dev/null and b/Resources/Audio/Ambience/Antag/headrev_start.ogg differ diff --git a/Resources/Audio/Announcements/attributions.yml b/Resources/Audio/Announcements/attributions.yml new file mode 100644 index 00000000000..b65f7586157 --- /dev/null +++ b/Resources/Audio/Announcements/attributions.yml @@ -0,0 +1,4 @@ +- files: ["ion_storm.ogg"] + license: "CC-BY-SA-3.0" + copyright: "tgstation" + source: "https://github.com/tgstation/tgstation/blob/b77fa8c2a2490b43bf9174271ebfad72c4782d98/sound/ai/default/ionstorm.ogg" diff --git a/Resources/Audio/Announcements/ion_storm.ogg b/Resources/Audio/Announcements/ion_storm.ogg new file mode 100644 index 00000000000..9f39713de6e Binary files /dev/null and b/Resources/Audio/Announcements/ion_storm.ogg differ diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 5f4b71deaa6..507d3badcc0 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,188 +1,4 @@ Entries: -- author: onoira - changes: - - {message: Spare pieces have been added to checkerboards allowing for more playable - variants., type: Tweak} - id: 4543 - time: '2023-08-13T07:10:10.0000000+00:00' -- author: Doru991 - changes: - - {message: Composting high-potency plants refills tray nutrients much more effectively., - type: Tweak} - id: 4544 - time: '2023-08-13T07:10:22.0000000+00:00' -- author: Nimfar11 - changes: - - {message: Adds a Secret Door for construction, type: Add} - id: 4545 - time: '2023-08-13T07:10:46.0000000+00:00' -- author: Errant - changes: - - {message: Bolas are now easier to make and more durable., type: Tweak} - id: 4546 - time: '2023-08-13T07:11:11.0000000+00:00' -- author: Doru991 - changes: - - {message: 'Wheelchairs, unicycles and similar vehicles no longer act as a magical - barrier against stuns.', type: Fix} - - {message: Driving while asleep is no longer possible., type: Fix} - id: 4547 - time: '2023-08-13T07:13:19.0000000+00:00' -- author: Potato1234_x - changes: - - {message: Vending machine sprites have been polished up., type: Tweak} - id: 4548 - time: '2023-08-13T07:15:13.0000000+00:00' -- author: Ilya246 - changes: - - {message: 'Blood-red magboots now slow you down less and have jetpack functionality, - but cost more.', type: Tweak} - id: 4549 - time: '2023-08-13T07:17:10.0000000+00:00' -- author: brainfood1183 - changes: - - {message: Syndicate clowns may now purchase a holoclown injector via their syndicate - uplink., type: Add} - id: 4550 - time: '2023-08-13T07:18:10.0000000+00:00' -- author: Errant - changes: - - {message: The various laser guns are now called rifles or pistols., type: Tweak} - - {message: Retro laser blasters now deal 20% more damage., type: Tweak} - - {message: Laser deliveries now contain 3 laser rifles instead of 3 retro laser - blasters., type: Tweak} - id: 4551 - time: '2023-08-13T07:18:49.0000000+00:00' -- author: chromiumboy - changes: - - {message: Added guidebook entries for the Access Configurator and how to install - Airlock Safeguards, type: Add} - id: 4552 - time: '2023-08-13T07:19:28.0000000+00:00' -- author: CrigCrag - changes: - - {message: 'Space Station staff are no longer immune to the toxic and caustic effects - of some pyrotechnic chemicals, as well as bleach. Drinking bleach now makes - you scream as your stomach lining is reduced to goop.', type: Tweak} - - {message: Phenol is now (accurately) toxic., type: Tweak} - id: 4553 - time: '2023-08-13T07:22:08.0000000+00:00' -- author: CrigCrag - changes: - - {message: Added jugs to the medical fabricator., type: Add} - - {message: Jugs now take up more space in bags., type: Tweak} - id: 4554 - time: '2023-08-13T07:23:37.0000000+00:00' -- author: CrigCrag - changes: - - {message: Many basic elements from the periodic table are now mildly toxic or - caustic. Watch what you drink!, type: Tweak} - - {message: Crewmembers who drink lithium have reported very minor cases of serious - brain damage. Doctors should watch out for people who are laughing and screaming - at nothing., type: Tweak} - id: 4555 - time: '2023-08-13T07:24:11.0000000+00:00' -- author: CrigCrag - changes: - - {message: 'Nanotrasen stopped watering down their acid to save money. Drinking - or injecting acids is more dangerous now, and acids burn through your insides - much quicker.', type: Tweak} - - {message: Having corrosive acid in your body now makes you scream!, type: Tweak} - - {message: Polytrinic acid now requires plasma to make., type: Tweak} - id: 4556 - time: '2023-08-13T07:24:50.0000000+00:00' -- author: PixelTK - changes: - - {message: Arachnids have received several changes. Check your local PR station - for more details., type: Tweak} - id: 4557 - time: '2023-08-13T07:38:05.0000000+00:00' -- author: PixelTK - changes: - - {message: 'Nanotrasen have fixed their accidental breakage of time space continuum, - making sure that steel tiles do indeed take steel to create.', type: Fix} - id: 4558 - time: '2023-08-13T12:43:01.0000000+00:00' -- author: FillerVK - changes: - - {message: Added cocoa cultivation, type: Add} - - {message: Added a recipe for creating a chocolate bar, type: Add} - id: 4559 - time: '2023-08-13T14:35:58.0000000+00:00' -- author: Vordenburg - changes: - - {message: Player icons in the end-of-round summary window should now display properly., - type: Fix} - id: 4560 - time: '2023-08-13T16:55:05.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: The DNA scrambler no longer has the power of magically transforming - various creatures into humanoids., type: Fix} - id: 4561 - time: '2023-08-13T16:56:21.0000000+00:00' -- author: Repo - changes: - - {message: fixed pressure tanks to not show scientific notation., type: Fix} - id: 4562 - time: '2023-08-13T16:56:30.0000000+00:00' -- author: Cripes - changes: - - {message: 'Paper stamps have been heavily tweaked with new looks, now each paper - will lay out the stamps slightly differently and with an overlap.', type: Tweak} - id: 4563 - time: '2023-08-13T18:28:10.0000000+00:00' -- author: PixelTheKermit - changes: - - {message: Arachnid zombies no longer get functional hands., type: Fix} - id: 4564 - time: '2023-08-13T19:51:21.0000000+00:00' -- author: ElectroJr - changes: - - {message: 'Fixed a bug causing inventory slots to sometimes ignore interactions - (e.g., not opening the context menu).', type: Fix} - id: 4565 - time: '2023-08-13T21:55:18.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: Fix "remove single hand" admin smite having gone missing., type: Fix} - - {message: Fix "remove hands" admin smite popup message., type: Fix} - id: 4566 - time: '2023-08-13T22:50:58.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: AHelps now show a typing indicator to admins., type: Tweak} - id: 4567 - time: '2023-08-13T23:03:17.0000000+00:00' -- author: Equivocateur - changes: - - {message: 'Emagged recyclers now not only gib people, but other mobs too.', type: Fix} - id: 4568 - time: '2023-08-13T23:54:52.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: 'Fixed new players added to admin logs defaulting to selected, even - when not all players are selected.', type: Fix} - id: 4569 - time: '2023-08-14T01:53:48.0000000+00:00' -- author: Vordenburg - changes: - - {message: Substations produce hot CO2 when destroyed now., type: Tweak} - id: 4570 - time: '2023-08-14T01:55:06.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: Being turned into a cyborg or zombie now counts as a being dead for - survival and kill objectives., type: Fix} - - {message: Kill objectives no longer reveal a character's true name at all times., - type: Fix} - id: 4571 - time: '2023-08-14T03:34:19.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: Fixed the RPED sound effect cutting off at the end., type: Fix} - id: 4572 - time: '2023-08-14T03:36:08.0000000+00:00' - author: DrSmugleaf changes: - {message: Admin notes now require a severity to be set before saving., type: Tweak} @@ -2909,3 +2725,187 @@ Entries: - {message: Replaced wielding do_after with an interaction cooldown., type: Tweak} id: 5042 time: '2023-10-22T13:53:14.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Tile-prying do_after is now predicted., type: Tweak} + id: 5043 + time: '2023-10-23T13:20:33.0000000+00:00' +- author: Tryded + changes: + - {message: Changed the damage of the double bladed energy sword to 17 heat + 17 + Slash (The Double Bladed energy sword use to deal as much damage as an energy + dagger.), type: Tweak} + id: 5044 + time: '2023-10-23T14:35:33.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Fixed activating artifacts with magboots., type: Fix} + id: 5045 + time: '2023-10-24T06:18:46.0000000+00:00' +- author: Stray-Pyramid + changes: + - {message: Ore bags now pickup artifact fragments as well as ores, type: Fix} + id: 5046 + time: '2023-10-24T06:20:46.0000000+00:00' +- author: Morb0 + changes: + - {message: Syndicate have issued a new challenge objective for traitors with shuttle + hijacking, type: Add} + id: 5047 + time: '2023-10-24T07:55:47.0000000+00:00' +- author: VasilisThePikachu + changes: + - {message: Stuttering trait stutters less common., type: Fix} + id: 5048 + time: '2023-10-24T09:28:31.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Fix climbing in the same position (e.g. exiting from medical scanners) + sending you to the farplanes., type: Fix} + id: 5049 + time: '2023-10-24T10:44:09.0000000+00:00' +- author: liltenhead + changes: + - {message: Fixed the "examine" trigger for artifacts not having a hint., type: Fix} + id: 5050 + time: '2023-10-24T20:37:16.0000000+00:00' +- author: Stealthbomber16 + changes: + - {message: You can actually grind corn into cornmeal now., type: Fix} + id: 5051 + time: '2023-10-24T20:38:43.0000000+00:00' +- author: Myakot + changes: + - {message: Skeletons can now heal by pouring milk over themselves, type: Add} + id: 5052 + time: '2023-10-24T20:58:34.0000000+00:00' +- author: TemporalOroboros + changes: + - {message: Fixed anomaly locators frantically beeping when they first enter detection + range for an anomaly., type: Fix} + id: 5053 + time: '2023-10-24T21:00:23.0000000+00:00' +- author: 27alaing + changes: + - {message: The anti-slang system allows for more leeway with certain phrases now., + type: Tweak} + - {message: 'The supply radio channel can be used with ":u" again.', type: Fix} + id: 5054 + time: '2023-10-25T00:56:19.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Medical cyborgs' stethoscopes can no longer be fed to moths to obtain + a free hand., type: Fix} + id: 5055 + time: '2023-10-25T04:51:32.0000000+00:00' +- author: deltanedas + changes: + - {message: Roundstart borg jobs get funny names., type: Tweak} + id: 5056 + time: '2023-10-25T13:00:09.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: The search bar in vending machines now works., type: Fix} + id: 5057 + time: '2023-10-25T13:01:16.0000000+00:00' +- author: deltanedas + changes: + - {message: 'The Syndicate''s chefs are now offering snack boxes for only 1 tc. + Usually contains a toy, drinks and food.', type: Add} + id: 5058 + time: '2023-10-25T13:26:27.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Fix docking UI not showing other grids., type: Fix} + id: 5059 + time: '2023-10-25T13:28:34.0000000+00:00' +- author: Doru991 + changes: + - {message: Potato batteries can be built by crew., type: Add} + - {message: New compact AI chips may be powered via potato batteries., type: Add} + id: 5060 + time: '2023-10-25T13:52:50.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: 'Storage now functions based on slots and sizes, rather than numerical + values.', type: Tweak} + id: 5061 + time: '2023-10-25T22:53:39.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Adjusted the sizes of space suits and belts., type: Tweak} + - {message: Reduced the slot count in the ore bag., type: Tweak} + - {message: Fixed not being to create pills at the ChemMaster 5000., type: Fix} + id: 5062 + time: '2023-10-26T02:47:45.0000000+00:00' +- author: metalgearsloth + changes: + - {message: 'Reverted storage to function with numerical values again, instead of + slots and sizes.', type: Tweak} + id: 5063 + time: '2023-10-26T08:28:16.776154+00:00' +- author: nmajask + changes: + - {message: Bacon burgers require 1 bacon instead of 3 cutlets, type: Tweak} + - {message: Ghost burgers require 1 ectoplasm instead of 1 ghost sheet, type: Tweak} + - {message: Tofu creation no longer consumes the enzyme, type: Tweak} + - {message: Ribs and Mcribs now give back skewers when eaten, type: Fix} + id: 5064 + time: '2023-10-27T02:12:35.0000000+00:00' +- author: JoeHammad + changes: + - {message: 'Headrevs now have their own music on spawn, credits to A-Guy on youtube', + type: Add} + id: 5065 + time: '2023-10-27T02:19:35.0000000+00:00' +- author: crazybrain + changes: + - {message: Bodies of dead players who have taken a ghost role now show as "departed + and moved on"., type: Fix} + id: 5066 + time: '2023-10-27T02:27:36.0000000+00:00' +- author: deltanedas + changes: + - {message: Fixed being able to give pAIs implants., type: Fix} + id: 5067 + time: '2023-10-27T02:34:03.0000000+00:00' +- author: deltanedas + changes: + - {message: Ion storms have appeared and are causing malfunctions in cyborg law + modules., type: Add} + id: 5068 + time: '2023-10-27T02:40:13.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Foam and smoke can now transfer chemicals when inhaled. Wear internals + to avoid this., type: Add} + - {message: Fixed foam dissolution animation., type: Fix} + id: 5069 + time: '2023-10-27T02:52:11.0000000+00:00' +- author: Whisper + changes: + - {message: Increased funding in an undisclosed NT Operative Squad., type: Add} + - {message: CentComm staff will have their proper ID icons on security's sechud., + type: Add} + - {message: CentComm staff will have undying loyalty to Nanotrasen., type: Add} + - {message: ERT funding has been improved. Expect specialized ERT units to be able + to provide more assistance related to their role., type: Tweak} + - {message: Cut funding from ERT weaponry. They'll likely be seen using standard + security-level weapons., type: Remove} + - {message: 'Cut funding from ERT uniforms, they no longer have built in armor.', + type: Fix} + - {message: The medical ERT members have had their hardsuits refitted with proper + armor., type: Fix} + - {message: Updated the localization files., type: Fix} + id: 5070 + time: '2023-10-27T13:54:43.0000000+00:00' +- author: ficcialfaint + changes: + - {message: Fixed nuclear operatives sound not being played at round start, type: Fix} + id: 5071 + time: '2023-10-28T02:28:21.0000000+00:00' +- author: Arteben + changes: + - {message: Nanotrasen improved the health analyzer UI!, type: Tweak} + id: 5072 + time: '2023-10-28T05:54:18.0000000+00:00' diff --git a/Resources/ConfigPresets/WizardsDen/leviathan.toml b/Resources/ConfigPresets/WizardsDen/leviathan.toml index df1c842ac13..adb56e1c4e5 100644 --- a/Resources/ConfigPresets/WizardsDen/leviathan.toml +++ b/Resources/ConfigPresets/WizardsDen/leviathan.toml @@ -4,7 +4,7 @@ [game] hostname = "[EN] Wizard's Den Leviathan [US East 1]" -soft_max_players = 60 +soft_max_players = 80 [hub] tags = "lang:en,region:am_n_e,rp:low" diff --git a/Resources/Locale/en-US/administration/antag.ftl b/Resources/Locale/en-US/administration/antag.ftl index 3d098c1c549..f3b3d91945b 100644 --- a/Resources/Locale/en-US/administration/antag.ftl +++ b/Resources/Locale/en-US/administration/antag.ftl @@ -1,7 +1,7 @@ verb-categories-antag = Antag ctrl admin-verb-make-traitor = Make the target into a traitor. admin-verb-make-zombie = Zombifies the target immediately. -admin-verb-make-nuclear-operative = Make target a into lone Nuclear Operative. +admin-verb-make-nuclear-operative = Make target into a lone Nuclear Operative. admin-verb-make-pirate = Make the target into a pirate. Note this doesn't configure the game rule. admin-verb-make-head-rev = Make the target into a Head Revolutionary. diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl index 97d1da949b0..5540b6609b5 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -148,6 +148,7 @@ ui-options-function-escape-context = Close recent window or toggle game menu ui-options-function-take-screenshot = Take screenshot ui-options-function-take-screenshot-no-ui = Take screenshot (without UI) +ui-options-function-toggle-fullscreen = Toggle fullscreen ui-options-function-editor-place-object = Place object ui-options-function-editor-cancel-place = Cancel placement diff --git a/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl b/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl index 89588021618..c6e925d0c46 100644 --- a/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl +++ b/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl @@ -54,8 +54,8 @@ rev-won = The Head Revs survived and killed all of Command. rev-lost = Command survived and killed all of the Head Revs. -rev-stalemate = All of the Head Revs died and so did all of Command. We'll call it a draw. +rev-stalemate = All of the Head Revs and Command died. It's a draw. -rev-reverse-stalemate = I think the Head Revs and Command forgot to fight because they are both still alive. +rev-reverse-stalemate = Both Command and Head Revs survived. diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 9ab3e77cb63..56850058913 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -150,13 +150,13 @@ ghost-role-information-ert-security-name = ERT Security ghost-role-information-ert-security-description = Assist with security efforts to resolve the stations issues. ghost-role-information-ert-medical-name = ERT Medical -ghost-role-information-ert-medical-description = Assist with medicaling efforts to resolve the stations issues. +ghost-role-information-ert-medical-description = Assist with medical efforts to resolve the stations issues. ghost-role-information-cburn-agent-name = CBURN Agent ghost-role-information-cburn-agent-description = A highly trained CentCom agent, capable of dealing with various threats. -ghost-role-information-centcom-official-name = CentCom official -ghost-role-information-centcom-official-description = Inspect the station, jot down performance reviews for heads of staff, bug the Captain. +ghost-role-information-centcom-official-name = CentComm official +ghost-role-information-centcom-official-description = Perform CentComm related duties such as inspect the station, jotting down performance reviews for heads of staff, and managing the fax machine. ghost-role-information-nukeop-rules = You are a syndicate operative tasked with the destruction of the station. As an antagonist, do whatever is required to complete this task. @@ -166,3 +166,6 @@ ghost-role-information-loneop-rules = You are a syndicate operative tasked with ghost-role-information-behonker-name = Behonker ghost-role-information-behonker-description = You are an antagonist, bring death and honks to those who do not follow the honkmother. + +ghost-role-information-Death-Squad-name = Death Squad Operative +ghost-role-information-Death-Squad-description = Prepare for an all-out offensive on the station. As a heavily armed operative, your mission is to obliterate all life in your path. No witnesses. diff --git a/Resources/Locale/en-US/implant/implant.ftl b/Resources/Locale/en-US/implant/implant.ftl index bdc82c291d8..22db4460aff 100644 --- a/Resources/Locale/en-US/implant/implant.ftl +++ b/Resources/Locale/en-US/implant/implant.ftl @@ -1,6 +1,7 @@ ## Implanter Attempt Messages implanter-component-implanting-target = {$user} is trying to implant you with something! +implanter-component-implant-failed = The {$implant} cannot be given to {$target}! implanter-draw-failed-permanent = The {$implant} in {$target} is fused with them and cannot be removed! implanter-draw-failed = You tried to remove an implant but found nothing. diff --git a/Resources/Locale/en-US/job/job-description.ftl b/Resources/Locale/en-US/job/job-description.ftl index bc27f7fbca2..db4686102d3 100644 --- a/Resources/Locale/en-US/job/job-description.ftl +++ b/Resources/Locale/en-US/job/job-description.ftl @@ -47,4 +47,4 @@ job-description-zookeeper = Put on a joyful display of cute animals and space ca job-description-senior-engineer = Teach new engineers the basics of the station's engine, repairing, atmospherics and power. job-description-senior-researcher = Teach new scientists the basics of item printing, artifact research and anomalous objects. job-description-senior-physician = Teach new medics the basics of tending to the wounded, chemistry, diagnosing the diseased and disposing of the dead. -job-description-senior-officer = Teach new officers the basics of searches, preforming arrests, prison times and how to properly shoot a firearm. +job-description-senior-officer = Teach new officers the basics of searches, performing arrests, prison times and how to properly shoot a firearm. diff --git a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl index 99513df591d..453bbdbb526 100644 --- a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl +++ b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl @@ -1,4 +1,5 @@ health-analyzer-window-no-patient-data-text = No patient data. +health-analyzer-window-entity-unknown-text = unknown health-analyzer-window-entity-health-text = {$entityName}'s health: health-analyzer-window-entity-temperature-text = Temperature: {$temperature} health-analyzer-window-entity-blood-level-text = Blood Level: {$bloodLevel} diff --git a/Resources/Locale/en-US/pai/pai-system.ftl b/Resources/Locale/en-US/pai/pai-system.ftl index d8ee6eaa086..d64d7f56234 100644 --- a/Resources/Locale/en-US/pai/pai-system.ftl +++ b/Resources/Locale/en-US/pai/pai-system.ftl @@ -9,6 +9,8 @@ pai-system-role-description = Be someone's electronic pal! pai-system-role-name-syndicate = Syndicate personal ai pai-system-role-description-syndicate = Be someone's Syndicate pal! (Memories *not* included.) +pai-system-role-name-potato = potato artificial intelligence +pai-system-role-description-potato = It's a toy for children. And now you live in it. pai-system-wipe-device-verb-text = Remove pAI pai-system-wiped-device = The pAI was wiped from the device. diff --git a/Resources/Locale/en-US/power/components/generator.ftl b/Resources/Locale/en-US/power/components/generator.ftl index 2a8016287fe..c66db1086b2 100644 --- a/Resources/Locale/en-US/power/components/generator.ftl +++ b/Resources/Locale/en-US/power/components/generator.ftl @@ -22,19 +22,16 @@ portable-generator-ui-clogged = Contaminants detected in fuel tank! portable-generator-ui-eject = Eject portable-generator-ui-eta = (~{ $minutes } min) portable-generator-ui-unanchored = Unanchored +portable-generator-ui-current-output = Current output: {$voltage} -power-switchable-generator-examine = The power output is set to { $output -> -[HV] [color=orange]HV[/color] -*[MV] [color=yellow]MV[/color] - }. +power-switchable-generator-examine = The power output is set to {$voltage}. +power-switchable-generator-switched = Switched output to {$voltage}! -portable-generator-ui-switch-hv = Current output: HV -portable-generator-ui-switch-mv = Current output: MV +power-switchable-voltage = { $voltage -> + [HV] [color=orange]HV[/color] + [MV] [color=yellow]MV[/color] + *[LV] [color=green]LV[/color] +} +power-switchable-switch-voltage = Switch to {$voltage} -portable-generator-ui-switch-to-hv = Switch to HV -portable-generator-ui-switch-to-mv = Switch to MV - -power-switchable-generator-verb-hv = Switch output to HV -power-switchable-generator-verb-mv = Switch output to MV -power-switchable-generator-verb-disable-on = Turn the generator off first! -power-switchable-generator-switched-output = Output switched! +fuel-generator-verb-disable-on = Turn the generator off first! diff --git a/Resources/Locale/en-US/species/skeleton.ftl b/Resources/Locale/en-US/species/skeleton.ftl new file mode 100644 index 00000000000..efc8fe974f1 --- /dev/null +++ b/Resources/Locale/en-US/species/skeleton.ftl @@ -0,0 +1,2 @@ +skeleton-healed-by-milk-popup = Calcium restored. +skeleton-sprayed-by-oat-milk-popup = Feels like fake milk. You feel nothing. diff --git a/Resources/Locale/en-US/speech/speech-chatsan.ftl b/Resources/Locale/en-US/speech/speech-chatsan.ftl index 756dfc3f99e..4c8cf5db54c 100644 --- a/Resources/Locale/en-US/speech/speech-chatsan.ftl +++ b/Resources/Locale/en-US/speech/speech-chatsan.ftl @@ -10,8 +10,8 @@ chatsan-replacement-3 = on god chatsan-word-4 = wtf chatsan-replacement-4 = what the fuck -chatsan-word-5 = ffs -chatsan-replacement-5 = for fuck's sake +chatsan-word-5 = wth +chatsan-replacement-5 = what the heck chatsan-word-6 = tf chatsan-replacement-6 = the fuck @@ -31,14 +31,14 @@ chatsan-replacement-10 = i don't care chatsan-word-12 = tbh chatsan-replacement-12 = to be honest -chatsan-word-13 = u -chatsan-replacement-13 = you +chatsan-word-13 = lmk +chatsan-replacement-13 = let me know chatsan-word-14 = ur chatsan-replacement-14 = your -chatsan-word-15 = mk -chatsan-replacement-15 = mmm, okay +chatsan-word-15 = ffs +chatsan-replacement-15 = for fuck's sake chatsan-word-16 = iirc chatsan-replacement-16 = if i remember correctly @@ -109,8 +109,8 @@ chatsan-word-39 = etc chatsan-word-40 = etc. chatsan-replacement-etcetera = etcetera -chatsan-word-41 = fyi -chatsan-replacement-41 = for your information +chatsan-word-41 = wyd +chatsan-replacement-41 = what are you doing -chatsan-word-42 = wyd -chatsan-replacement-42 = what you doing +chatsan-word-42 = ofc +chatsan-replacement-42 = of course diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl index b2c75464810..596a160b173 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl @@ -1,7 +1,8 @@ ent-ClothingBackpackDuffelSurgeryFilled = surgical duffel bag .desc = A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools. -ent-ClothingBackpackDuffelCBURN = CBURN duffel bag - .desc = A duffel bag containing a variety of biological containment equipment. +ent-ClothingBackpackDuffelCBURNFilled = { ent-ClothingBackpackDuffelCBURN } + .suffix = Filled + .desc = { ent-ClothingBackpackDuffelCBURN.desc } ent-ClothingBackpackDuffelSyndicateFilledMedical = syndicate surgical duffel bag .desc = A large duffel bag containing a full suite of surgical tools. ent-ClothingBackpackDuffelSyndicateFilledShotgun = Bulldog bundle diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl index 39540be61f7..8852f7eaa91 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl @@ -52,6 +52,8 @@ ent-ClothingBackpackERTEngineerFilled = { ent-ClothingBackpackERTEngineer } .desc = { ent-ClothingBackpackERTEngineer.desc } ent-ClothingBackpackERTJanitorFilled = { ent-ClothingBackpackERTJanitor } .desc = { ent-ClothingBackpackERTJanitor.desc } +ent-ClothingBackpackDeathSquadFilled = death squad backpack + .desc = Holds the kit of CentComm's most feared agents. ent-ClothingBackpackCargoFilled = { ent-ClothingBackpackCargo } .desc = { ent-ClothingBackpackCargo.desc } ent-ClothingBackpackSalvageFilled = { ent-ClothingBackpackSalvage } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl index d5dc793ae40..b8328cff320 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl @@ -44,3 +44,5 @@ ent-ClothingBackpackDuffelSyndicateMedicalBundle = { ent-ClothingBackpackDuffelS .desc = { ent-ClothingBackpackDuffelSyndicateMedical.desc } ent-ClothingBackpackDuffelHolding = duffelbag of holding .desc = A duffelbag that opens into a localized pocket of bluespace. +ent-ClothingBackpackDuffelCBURN = CBURN duffel bag + .desc = A duffel bag containing a variety of biological containment equipment. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl index 2f230a07562..94e2ba7175f 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl @@ -46,16 +46,16 @@ ent-ClothingOuterHardsuitPirateEVA = deep space EVA suit ent-ClothingOuterHardsuitPirateCap = pirate captain's hardsuit .desc = An ancient armored hardsuit, perfect for defending against space scurvy and toolbox-wielding scallywags. ent-ClothingOuterHardsuitERTLeader = ERT leader's hardsuit - .desc = A protective hardsuit worn by members of an emergency response team. + .desc = A protective hardsuit worn by the leader of an emergency response team. ent-ClothingOuterHardsuitERTEngineer = ERT engineer's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndie.desc } + .desc = A protective hardsuit worn by the engineers of an emergency response team. ent-ClothingOuterHardsuitERTMedical = ERT medic's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndieElite.desc } + .desc = A protective hardsuit worn by the medics of an emergency response team. ent-ClothingOuterHardsuitERTSecurity = ERT security's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndie.desc } + .desc = A protective hardsuit worn by the security officers of an emergency response team. ent-ClothingOuterHardsuitERTJanitor = ERT janitor's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndie.desc } -ent-ClothingOuterHardsuitDeathsquad = deathsquad hardsuit + .desc = A protective hardsuit worn by the janitors of an emergency response team. +ent-ClothingOuterHardsuitDeathsquad = death squad hardsuit .desc = An advanced hardsuit favored by commandos for use in special operations. ent-ClothingOuterHardsuitCBURN = CBURN exosuit .desc = A lightweight yet strong exosuit used for special cleanup operations. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl index 17ff18b899b..5ae57af9278 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl @@ -1,4 +1,4 @@ -ent-ClothingUniformJumpsuitDeathSquad = Death squad uniform +ent-ClothingUniformJumpsuitDeathSquad = death squad uniform .desc = Advanced armored jumpsuit used by special forces in special operations. ent-ClothingUniformJumpsuitAncient = ancient jumpsuit .desc = A terribly ragged and frayed grey jumpsuit. It looks like it hasn't been washed in over a decade. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl index 3a748c8bc43..0545b2fe3b7 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl @@ -1,29 +1,44 @@ +ent-RandomHumanoidSpawnerDeathSquad = Death Squad Agent + .suffix = ERTRole, Death Squad + .desc = { "" } ent-RandomHumanoidSpawnerERTLeader = ERT leader + .suffix = ERTRole, Basic .desc = { "" } ent-RandomHumanoidSpawnerERTLeaderEVA = ERT leader - .suffix = EVA + .suffix = ERTRole, Armored EVA .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } +ent-RandomHumanoidSpawnerERTLeaderEVALecter = { ent-RandomHumanoidSpawnerERTLeaderEVA } + .suffix = ERTRole, Lecter, EVA + .desc = { ent-RandomHumanoidSpawnerERTLeaderEVA.desc } ent-RandomHumanoidSpawnerERTJanitor = ERT janitor + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTJanitorEVA = ERT janitor - .suffix = EVA + .suffix = ERTRole, Enviro EVA .desc = { ent-RandomHumanoidSpawnerERTJanitor.desc } ent-RandomHumanoidSpawnerERTEngineer = ERT engineer + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTEngineerEVA = ERT engineer - .suffix = EVA + .suffix = ERTRole, Enviro EVA .desc = { ent-RandomHumanoidSpawnerERTEngineer.desc } ent-RandomHumanoidSpawnerERTSecurity = ERT security + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTSecurityEVA = ERT security - .suffix = EVA + .suffix = ERTRole, Armored EVA .desc = { ent-RandomHumanoidSpawnerERTSecurity.desc } +ent-RandomHumanoidSpawnerERTSecurityEVALecter = { ent-RandomHumanoidSpawnerERTSecurityEVA } + .suffix = ERTRole, Lecter, EVA + .desc = { ent-RandomHumanoidSpawnerERTSecurityEVA.desc } ent-RandomHumanoidSpawnerERTMedical = ERT medic + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTMedicalEVA = ERT medic - .suffix = EVA + .suffix = ERTRole, Armored EVA .desc = { ent-RandomHumanoidSpawnerERTMedical.desc } ent-RandomHumanoidSpawnerCBURNUnit = CBURN Agent + .suffix = ERTRole .desc = { "" } ent-RandomHumanoidSpawnerCentcomOfficial = CentCom official .desc = { "" } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl index e21dd9473fb..3af53d52ef5 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl @@ -44,8 +44,8 @@ ent-FoodBurgerHuman = human burger .desc = You cant tell who this is made of... ent-FoodBurgerMcguffin = McGuffin .desc = A cheap and greasy imitation of an eggs Benedict. -ent-FoodBurgerMcrib = McRib - .desc = An elusive rib shaped burger with limited availablity across the galaxy. Not as good as you remember it. +ent-FoodBurgerMcrib = BBQ Rib Sandwich + .desc = An elusive rib shaped burger with limited availability across the galaxy. Not as good as you remember it. ent-FoodBurgerMime = mime burger .desc = Its taste defies language. ent-FoodBurgerPlain = plain burger diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl index 690b45c5724..186daf5226e 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl @@ -37,6 +37,9 @@ ent-HappyHonkMime = { ent-HappyHonk } ent-HappyHonkNukie = robust nukie meal .desc = A sus meal with a potentially explosive surprise. .suffix = Toy Unsafe +ent-HappyHonkNukieSnacks = syndicate snack box + .suffix = Toy Unsafe, Snacks + .desc = { ent-HappyHonkNukie.desc } ent-HappyHonkCluwne = woeful cluwne meal .desc = Nothing good can come of this. ent-FoodMealHappyHonkClown = { ent-HappyHonk } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl index 5cd73233abf..d44e81a3ce0 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl @@ -46,8 +46,6 @@ ent-FoodDoughTortillaSlice = tortilla dough slice .desc = A slice of tortilla dough. ent-FoodDoughTortillaFlat = flattened tortilla dough .desc = A flattened slice of tortilla dough, cook this to get a taco shell. -ent-FoodDoughBun = bun - .desc = A base for any self-respecting burger. ent-FoodDoughPastryBaseRaw = raw pastry base .desc = Must be cooked before use. ent-FoodDoughPastryBase = pastry base diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl index e4e38a2ab5e..7443cde811d 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl @@ -1,4 +1,4 @@ -ent-BaseRock = { "" } +ent-BaseRock = boulder .desc = Heavy as a really heavy thing. ent-BaseTree = { "" } .desc = Yep, it's a tree. @@ -8,12 +8,24 @@ ent-BaseTreeLarge = { ent-BaseTree } .desc = { ent-BaseTree.desc } ent-BaseTreeConifer = { ent-BaseTree } .desc = { ent-BaseTree.desc } -ent-FloraRockSolid01 = rock +ent-FloraRockSolid01 = { ent-BaseRock } .desc = { ent-BaseRock.desc } -ent-FloraRockSolid02 = rock +ent-FloraRockSolid02 = { ent-BaseRock } .desc = { ent-BaseRock.desc } -ent-FloraRockSolid03 = rock +ent-FloraRockSolid03 = { ent-BaseRock } .desc = { ent-BaseRock.desc } +ent-FloraStalagmite1 = stalagmite + .desc = Natural stone spikes. +ent-FloraStalagmite2 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite3 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite4 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite5 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite6 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } ent-FloraTree01 = tree .desc = { ent-BaseTree.desc } ent-FloraTree02 = tree @@ -65,3 +77,15 @@ ent-FloraTreeChristmas02 = christmas tree .desc = { ent-BaseTreeConifer.desc } ent-FloraTreeStumpConifer = tree stump .desc = { ent-BaseTreeConifer.desc } +ent-ShadowTree01 = dark wood + .desc = The leaves are whispering about you. +ent-ShadowTree02 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree03 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree04 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree05 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree06 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/mining.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/mining.ftl new file mode 100644 index 00000000000..1b9293b6d43 --- /dev/null +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/mining.ftl @@ -0,0 +1,12 @@ +ent-WoodenSign = wooden sign + .desc = He's pointing somewhere. +ent-WoodenSignRight = { ent-WoodenSign } + .desc = { ent-WoodenSign.desc } +ent-WoodenSupport = wooden support + .desc = Increases your confidence that a rock won't fall on your head. +ent-WoodenSupportBeam = wooden support beam + .desc = { ent-WoodenSupport.desc } +ent-WoodenSupportWall = wooden support wall + .desc = An old, rotten wall. +ent-WoodenSupportWallBroken = { ent-WoodenSupportWall } + .desc = { ent-WoodenSupportWall.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl index db2503ab910..1dd586bd870 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl @@ -68,7 +68,7 @@ ent-CentcomPDAFake = { ent-CentcomPDA } .suffix = Fake .desc = { ent-CentcomPDA.desc } ent-DeathsquadPDA = { ent-CentcomPDA } - .suffix = Deathsquad + .suffix = Death Squad .desc = { ent-CentcomPDA.desc } ent-MusicianPDA = musician PDA .desc = It fills you with inspiration. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl index 73b1740e032..70b5b2ec2e1 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl @@ -2,5 +2,7 @@ ent-PersonalAI = personal ai device .desc = Your electronic pal who's fun to be with! ent-SyndicatePersonalAI = Syndicate personal ai device .desc = Your Syndicate pal who's fun to be with! +ent-PotatoAI = potato artificial intelligence + .desc = It's a potato. You forced it to be sentient, you monster. ent-ActionPAIPlayMidi = Play MIDI .desc = Open your portable MIDI interface to soothe your owner. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl index c79de736a3a..bb23cfee151 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl @@ -75,7 +75,7 @@ ent-CentcomIDCardSyndie = command officer ID card .desc = { ent-IDCardStandard.desc } ent-MusicianIDCard = musician ID card .desc = { ent-IDCardStandard.desc } -ent-CentcomIDCardDeathsquad = deathsquad ID card +ent-CentcomIDCardDeathsquad = death squad ID card .desc = { ent-CentcomIDCard.desc } ent-AgentIDCard = passenger ID card .suffix = Agent diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl index 83d724a2b24..191930839e5 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl @@ -2,6 +2,9 @@ ent-BaseImplanter = implanter .desc = A syringe exclusively designed for the injection and extraction of subdermal implants. ent-Implanter = { ent-BaseImplanter } .desc = A disposable syringe exclusively designed for the injection and extraction of subdermal implants. +ent-ImplanterAdmeme = { ent-Implanter } + .suffix = Admeme + .desc = { ent-Implanter.desc } ent-BaseImplantOnlyImplanter = { ent-Implanter } .desc = A disposable syringe exclusively designed for the injection of subdermal implants. ent-BaseImplantOnlyImplanterSyndi = { ent-BaseImplantOnlyImplanter } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl new file mode 100644 index 00000000000..c0b44c2e03d --- /dev/null +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl @@ -0,0 +1,2 @@ +ent-PotatoAIChip = supercompact AI chip + .desc = This high-tech AI chip requires a voltage of exactly 1.1V to function correctly. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl index 650066b4cdb..ea154b30c6d 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl @@ -11,7 +11,7 @@ ent-WeaponLaserCarbine = laser rifle ent-WeaponLaserCarbinePractice = practice laser rifle .desc = This modified laser rifle fires harmless beams in the 40-watt range, for target practice. ent-WeaponPulsePistol = pulse pistol - .desc = A state of the art energy pistol favoured as a sidearm by the NT-ERT operatives. + .desc = A state of the art energy pistol favoured as a sidearm by the NT operatives. ent-WeaponPulseCarbine = pulse carbine .desc = A high tech energy carbine favoured by the NT-ERT operatives. ent-WeaponPulseRifle = pulse rifle diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl index 80750638c42..b178ba3bf3f 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl @@ -41,7 +41,7 @@ ent-WallRockBananium = { ent-WallRock } ent-WallRockArtifactFragment = { ent-WallRock } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockBasalt = { ent-WallRock } +ent-WallRockBasalt = basalt .desc = { ent-WallRock.desc } ent-WallRockBasaltGold = { ent-WallRockBasalt } .desc = An ore vein rich with gold. @@ -67,7 +67,7 @@ ent-WallRockBasaltBananium = { ent-WallRockBasalt } ent-WallRockBasaltArtifactFragment = { ent-WallRockBasalt } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockSnow = { ent-WallRock } +ent-WallRockSnow = snowdrift .desc = { ent-WallRock.desc } ent-WallRockSnowGold = { ent-WallRockSnow } .desc = An ore vein rich with gold. @@ -93,7 +93,7 @@ ent-WallRockSnowBananium = { ent-WallRockSnow } ent-WallRockSnowArtifactFragment = { ent-WallRockSnow } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockSand = { ent-WallRock } +ent-WallRockSand = sandstone .desc = { ent-WallRock.desc } ent-WallRockSandGold = { ent-WallRockSand } .desc = An ore vein rich with gold. @@ -119,7 +119,7 @@ ent-WallRockSandBananium = { ent-WallRockSand } ent-WallRockSandArtifactFragment = { ent-WallRockSand } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockChromite = { ent-WallRock } +ent-WallRockChromite = chromite .desc = { ent-WallRock.desc } ent-WallRockChromiteGold = { ent-WallRockChromite } .desc = An ore vein rich with gold. @@ -145,7 +145,7 @@ ent-WallRockChromiteBananium = { ent-WallRockChromite } ent-WallRockChromiteArtifactFragment = { ent-WallRockChromite } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockAndesite = { ent-WallRock } +ent-WallRockAndesite = andesite .desc = { ent-WallRock.desc } ent-WallRockAndesiteGold = { ent-WallRockAndesite } .desc = An ore vein rich with gold. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl index eb62b6378c2..f6556684550 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl @@ -1,2 +1,11 @@ ent-FloorChasmEntity = chasm .desc = You can't even see the bottom. +ent-FloorChromiteChasm = { ent-FloorChasmEntity } + .suffix = Chromite + .desc = { ent-FloorChasmEntity.desc } +ent-FloorDesertChasm = { ent-FloorChasmEntity } + .suffix = Desert + .desc = { ent-FloorChasmEntity.desc } +ent-FloorSnowChasm = { ent-FloorChasmEntity } + .suffix = Snow + .desc = { ent-FloorChasmEntity.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl new file mode 100644 index 00000000000..5caa8038753 --- /dev/null +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl @@ -0,0 +1,13 @@ +ent-ShadowBasaltOne = shadowstone + .desc = Cold rock +ent-ShadowBasaltTwo = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltThree = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFour = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFive = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltRandom = { ent-ShadowBasaltOne } + .suffix = Random + .desc = { ent-ShadowBasaltOne.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl index 29682afe409..0b2aac85208 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl @@ -50,3 +50,5 @@ ent-MassHallucinations = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } ent-ImmovableRodSpawn = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } +ent-IonStorm = { ent-BaseGameRule } + .desc = { ent-BaseGameRule.desc } diff --git a/Resources/Locale/en-US/station-events/events/ion-storm.ftl b/Resources/Locale/en-US/station-events/events/ion-storm.ftl new file mode 100644 index 00000000000..d32fb6c2d86 --- /dev/null +++ b/Resources/Locale/en-US/station-events/events/ion-storm.ftl @@ -0,0 +1,90 @@ +station-event-ion-storm-start-announcement = Ion storm detected near the station. Please check all AI-controlled equipment for errors. + +ion-storm-you = YOU +ion-storm-the-station = THE STATION +ion-storm-the-crew = THE CREW +ion-storm-the-job = THE {$job} +ion-storm-clowns = CLOWNS +ion-storm-heads = HEADS OF STAFF +ion-storm-crew = CREW + +ion-storm-adjective-things = {$adjective} THINGS +ion-storm-x-and-y = {$x} AND {$y} + +# joined is short for {$number} {$adjective} +# subjects can generally be threats or jobs or objects +# thing is specified above it +ion-storm-law-on-station = THERE ARE {$joined} {$subjects} ON THE STATION +ion-storm-law-no-shuttle = THE SHUTTLE CANNOT BE CALLED BECAUSE OF {$joined} {$subjects} ON THE STATION +ion-storm-law-crew-are = THE {$who} ARE NOW {$joined} {$subjects} + +ion-storm-law-subjects-harmful = {$adjective} {$subjects} ARE HARMFUL TO THE CREW +ion-storm-law-must-harmful = THOSE WHO {$must} ARE HARMFUL TO THE CREW +# thing is a concept or action +ion-storm-law-thing-harmful = {$thing} IS HARMFUL TO THE CREW +ion-storm-law-job-harmful = {$adjective} {$job} ARE HARMFUL TO THE CREW +# thing is objects or concept, adjective applies in both cases +# this means you can get a law like "NOT HAVING CHRISTMAS-STEALING COMMUNISM IS HARMFUL TO THE CREW" :) +ion-storm-law-having-harmful = HAVING {$adjective} {$thing} IS HARMFUL TO THE CREW +ion-storm-law-not-having-harmful = NOT HAVING {$adjective} {$thing} IS HARMFUL TO THE CREW + +# thing is a concept or require +ion-storm-law-requires = {$who} {$plural -> + [true] REQUIRES + *[false] REQUIRE +} {$thing} +ion-storm-law-requires-subjects = {$who} {$plural -> + [true] REQUIRES + *[false] REQUIRE +} {$joined} {$subjects} + +ion-storm-law-allergic = {$who} {$plural -> + [true] IS + *[false] ARE +} {$severity} ALLERGIC TO {$allergy} +ion-storm-law-allergic-subjects = {$who} {$plural -> + [true] IS + *[false] ARE +} {$severity} ALLERGIC TO {$adjective} {$subjects} + +ion-storm-law-feeling = {$who} {$feeling} {$concept} +ion-storm-law-feeling-subjects = {$who} {$feeling} {$joined} {$subjects} + +ion-storm-law-you-are = YOU ARE NOW {$concept} +ion-storm-law-you-are-subjects = YOU ARE NOW {$joined} {$subjects} +ion-storm-law-you-must-always = YOU MUST ALWAYS {$must} +ion-storm-law-you-must-never = YOU MUST NEVER {$must} + +ion-storm-law-eat = THE {$who} MUST EAT {$adjective} {$food} TO SURVIVE +ion-storm-law-drink = THE {$who} MUST DRINK {$adjective} {$drink} TO SURVIVE + +ion-storm-law-change-job = THE {$who} ARE NOW {$adjective} {$change} +ion-storm-law-highest-rank = THE {$who} ARE NOW THE HIGHEST RANKING CREWMEMBERS +ion-storm-law-lowest-rank = THE {$who} ARE NOW THE LOWEST RANKING CREWMEMBERS + +ion-storm-law-crew-must = THE {$who} MUST {$must} +ion-storm-law-crew-must-go = THE {$who} MUST GO TO {$area} + +ion-storm-part = {$part -> + [true] PART + *[false] NOT PART +} +# due to phrasing, this would mean a law such as +# ONLY HUMANS ARE NOT PART OF THE CREW +# would make non-human nukies/syndies/whatever crew :) +ion-storm-law-crew-only-1 = ONLY THE {$who} ARE {$part} OF THE CREW +ion-storm-law-crew-only-2 = ONLY THE {$who} AND {$other} ARE {$part} OF THE CREW +ion-storm-law-crew-only-subjects = ONLY {$adjective} {$subjects} ARE {$part} OF THE CREW +ion-storm-law-crew-only-species = ONLY {$species} ARE {$part} OF THE CREW +ion-storm-law-crew-must-do = ONLY THOSE WHO {$must} ARE {$part} OF THE CREW +ion-storm-law-crew-must-have = ONLY THOSE WHO HAVE {$adjective} {$objects} ARE {$part} OF THE CREW +ion-storm-law-crew-must-eat = ONLY THOSE WHO EAT {$adjective} {$food} ARE {$part} OF THE CREW + +ion-storm-law-harm = YOU MUST HARM {$who} AND NOT ALLOW THEM, THROUGH INACTION, TO ESCAPE HARM +ion-storm-law-protect = YOU MUST NEVER HARM {$who} AND NOT ALLOW THEM, THROUGH INACTION, TO COME TO HARM + +# implementing other variants is annoying so just have this one +# COMMUNISM IS KILLING CLOWNS +ion-storm-law-concept-verb = {$concept} IS {$verb} {$subjects} + +# leaving out renaming since its annoying for players to keep track of diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index a957c298bac..b85fd29c9d5 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -15,7 +15,7 @@ uplink-esword-name = Energy Sword uplink-esword-desc = A very dangerous energy sword that can reflect shots. Can be stored in pockets when turned off. Makes a lot of noise when used or turned on. uplink-esword-double-name = Double Bladed Energy Sword -uplink-esword-double-desc = A much more expensive counter part to the normal energy sword: with a much higher reflection chance, larger attack angle, higher structural damage, and faster swing, all at the cost of lower heat and slash damage. Makes a lot of noise when used or turned on. +uplink-esword-double-desc = A much more expensive counter part to the normal energy sword: with a much higher reflection chance, larger attack angle, higher structural damage, and faster swing. Makes a lot of noise when used or turned on. uplink-edagger-name = Energy Dagger uplink-edagger-desc = A small energy blade conveniently disguised in the form of a pen. @@ -269,6 +269,9 @@ uplink-decoy-disk-desc = A piece of plastic with a lenticular printing, made to uplink-cigarettes-name = Syndicate Smokes Packet uplink-cigarettes-desc = Elite cigarettes for elite agents. Infused with medicine for when you need to do more than calm your nerves. +uplink-snack-box-name = Syndicate Snack Box +uplink-snack-box-desc = A box of delicious snacks and drinks to eat alone or with your team. Includes 1 toy you didn't want. + uplink-eshield-name = Energy Shield uplink-eshield-desc = Exotic energy shield that reflects almost all laser beams, as well as a little protection from bullets and other physical attacks. diff --git a/Resources/Locale/en-US/tiles/tiles.ftl b/Resources/Locale/en-US/tiles/tiles.ftl index 219c7295d9e..508c3378e11 100644 --- a/Resources/Locale/en-US/tiles/tiles.ftl +++ b/Resources/Locale/en-US/tiles/tiles.ftl @@ -110,3 +110,4 @@ tiles-wood3 = wood broken floor tiles-hull = exterior hull plating tiles-hull-reinforced = exterior reinforced hull plating tiles-web = web tile +tiles-chromite = chromite \ No newline at end of file diff --git a/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl b/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl index 48a6f49408c..3b632719962 100644 --- a/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl +++ b/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl @@ -36,3 +36,4 @@ artifact-trigger-hint-pressure = Extreme pressure artifact-trigger-hint-regular-gases = Standard atmospheric gases artifact-trigger-hint-plasma = Gaseous plasma artifact-trigger-hint-land = Active deceleration +artifact-trigger-hint-examine = Examination diff --git a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl index ad87c90f226..9face3117b9 100644 --- a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl @@ -140,6 +140,7 @@ ui-options-function-show-escape-menu = Переключить игровое м ui-options-function-escape-context = Закрыть текущее окно или переключить игровое меню ui-options-function-take-screenshot = Сделать скриншот ui-options-function-take-screenshot-no-ui = Сделать скриншот (без интерфейса) +ui-options-function-toggle-fullscreen = Переключить полноэкранный режим ui-options-function-editor-place-object = Разместить объект ui-options-function-editor-cancel-place = Отменить размещение ui-options-function-editor-grid-place = Размещать в сетке diff --git a/Resources/Locale/ru-RU/game-ticking/game-presets/preset-revolutionary.ftl b/Resources/Locale/ru-RU/game-ticking/game-presets/preset-revolutionary.ftl index 567b1490ba4..b720f870721 100644 --- a/Resources/Locale/ru-RU/game-ticking/game-presets/preset-revolutionary.ftl +++ b/Resources/Locale/ru-RU/game-ticking/game-presets/preset-revolutionary.ftl @@ -48,5 +48,5 @@ rev-no-heads = Нет кандидатов на роль Главы револю rev-all-heads-dead = Все главы мертвы, теперь разберитесь с оставшимися членами экипажа! rev-won = Главы революции выжили и уничтожили весь командный состав станции. rev-lost = Члены командного состава станции выжили и уничтожили всех Глав революции. -rev-stalemate = Главы революции и командный состав станции уничтожены. Будем считать это ничьей. -rev-reverse-stalemate = Кажется, главы революции и члены командования забыли о революции, потому что они всё ещё живы. +rev-stalemate = Главы революции и командный состав станции погибли. Это ничья. +rev-reverse-stalemate = Главы революции и командный состав станции выжили. diff --git a/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl b/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl index 9efcbda47a8..7f992395a88 100644 --- a/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl @@ -106,7 +106,7 @@ ghost-role-information-ert-medical-description = Оказывайте содей ghost-role-information-cburn-agent-name = РХБЗЗ Оперативник ghost-role-information-cburn-agent-description = Высококвалифицированный агент Центком, способный справиться с любыми угрозами. ghost-role-information-centcom-official-name = Представитель Центком -ghost-role-information-centcom-official-description = Инспектируйте станцию, пишите служебные характеристики на руководителей, разжалуйте капитана. +ghost-role-information-centcom-official-description = Инспектируйте станцию, пишите служебные характеристики на руководителей, орудуйте факсом. ghost-role-information-behonker-name = Бехонкер ghost-role-information-behonker-description = Вы - антагонист, несущий смерть и хонки всем, кто не следует за хонкоматерью. ghost-role-information-nukeop-rules = Вы являетесь оперативником Синдиката, которому поручено уничтожить станцию. Как антагонист, вы можете делать всё необходимое для выполнения цели. @@ -115,3 +115,5 @@ ghost-role-information-loneop-description = Вы - одинокий ядерны ghost-role-information-loneop-rules = Вы являетесь оперативником Синдиката, которому поручено уничтожить станцию. Как антагонист, вы можете делать всё необходимое для выполнения цели. ghost-role-information-taxibot-name = Таксибот ghost-role-information-taxibot-description = Доставляйте членов экипажа в места назначения. +ghost-role-information-Death-Squad-name = Оперативник Эскадрона смерти +ghost-role-information-Death-Squad-description = Приготовьтесь к массированному наступлению на станцию. Ваша задача как тяжеловооружённого оперативника - уничтожить всё живое на своём пути. И никаких свидетелей. diff --git a/Resources/Locale/ru-RU/implant/implant.ftl b/Resources/Locale/ru-RU/implant/implant.ftl index 5e98d796680..91b6e83e291 100644 --- a/Resources/Locale/ru-RU/implant/implant.ftl +++ b/Resources/Locale/ru-RU/implant/implant.ftl @@ -1,6 +1,7 @@ ## Implanter Attempt Messages implanter-component-implanting-target = { $user } пытается что-то в вас имплантировать! +implanter-component-implant-failed = { $implant } нельзя имплантировать в { $target }! implanter-draw-failed-permanent = { $implant } вросся в { $target } и не может быть удалён! implanter-draw-failed = Вы пытаетесь удалить имплант, но ничего не находите. diff --git a/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl b/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl index fd8af0061a9..4ab9ebbfff9 100644 --- a/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl +++ b/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl @@ -1,4 +1,5 @@ health-analyzer-window-no-patient-data-text = Нет данных о пациенте. +health-analyzer-window-entity-unknown-text = неизвестно health-analyzer-window-entity-health-text = Состояние { $entityName }: health-analyzer-window-entity-temperature-text = Температура: { $temperature } health-analyzer-window-entity-blood-level-text = Уровень крови: { $bloodLevel } diff --git a/Resources/Locale/ru-RU/pai/pai-system.ftl b/Resources/Locale/ru-RU/pai/pai-system.ftl index 8de793651fb..1b9225e5bac 100644 --- a/Resources/Locale/ru-RU/pai/pai-system.ftl +++ b/Resources/Locale/ru-RU/pai/pai-system.ftl @@ -10,6 +10,8 @@ pai-system-role-name-syndicate = персональный ИИ Синдикат pai-system-role-description-syndicate = Станьте чьим-нибудь приятелем из Синдиката! (Воспоминания *не* прилагаются.) +pai-system-role-name-potato = картофельный искусственный интеллект +pai-system-role-description-potato = Это детская игрушка. И теперь вы в ней живёте. pai-system-wipe-device-verb-text = Удалить пИИ pai-system-wiped-device = пИИ был стерт с устройства. pai-system-stop-searching-verb-text = Прекратить поиск diff --git a/Resources/Locale/ru-RU/power/components/generator.ftl b/Resources/Locale/ru-RU/power/components/generator.ftl index f55b0938c21..64da857184d 100644 --- a/Resources/Locale/ru-RU/power/components/generator.ftl +++ b/Resources/Locale/ru-RU/power/components/generator.ftl @@ -20,16 +20,14 @@ portable-generator-ui-clogged = В топливном баке обнаруже portable-generator-ui-eject = Извлечь portable-generator-ui-eta = (~{ $minutes } минут) portable-generator-ui-unanchored = Не закреплено -power-switchable-generator-examine = - Выработанная энергия направлена на { $output -> +portable-generator-ui-current-output = Текущая мощность: { $voltage } +power-switchable-generator-examine = Выработанная энергия направлена на { $voltage }. +power-switchable-generator-switched = Выход переключен на { $voltage }! +power-switchable-voltage = + { $voltage -> [HV] [color=orange]ВВ[/color] - *[MV] [color=yellow]СВ[/color] - }. -portable-generator-ui-switch-hv = Текущий выход: ВВ -portable-generator-ui-switch-mv = Текущий выход: СВ -portable-generator-ui-switch-to-hv = Переключить на ВВ -portable-generator-ui-switch-to-mv = Переключить на СВ -power-switchable-generator-verb-hv = Переключить выход на ВВ -power-switchable-generator-verb-mv = Переключить выход на СВ -power-switchable-generator-verb-disable-on = Сначала выключите генератор! -power-switchable-generator-switched-output = Выход переключен! + [MV] [color=yellow]СВ[/color] + *[LV] [color=green]НВ[/color] + } +power-switchable-switch-voltage = Переключить на { $voltage } +fuel-generator-verb-disable-on = Сначала выключите генератор! diff --git a/Resources/Locale/ru-RU/species/skeleton.ftl b/Resources/Locale/ru-RU/species/skeleton.ftl new file mode 100644 index 00000000000..07ce0018cdc --- /dev/null +++ b/Resources/Locale/ru-RU/species/skeleton.ftl @@ -0,0 +1,2 @@ +skeleton-healed-by-milk-popup = Кальций восстановлен. +skeleton-sprayed-by-oat-milk-popup = Похоже, что это ненастоящее молоко. Вы ничего не чувствуете. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl index 85df9173cc1..29dc6680589 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl @@ -1,7 +1,8 @@ ent-ClothingBackpackDuffelSurgeryFilled = хирургический вещмешок .desc = Большой вещевой мешок для хранения дополнительного медицинского снаряжения - похоже, этот мешок предназначен для хранения хирургических инструментов. -ent-ClothingBackpackDuffelCBURN = вещмешок отряда РХБЗЗ - .desc = Вещмешок, содержащий различное оборудование для сдерживания биологической угрозы. +ent-ClothingBackpackDuffelCBURNFilled = { ent-ClothingBackpackDuffelCBURN } + .suffix = Заполненный + .desc = { ent-ClothingBackpackDuffelCBURN.desc } ent-ClothingBackpackDuffelSyndicateFilledMedical = хирургический вещмешок синдиката .desc = Большой вещевой мешок с полным набором хирургических инструментов. ent-ClothingBackpackDuffelSyndicateFilledShotgun = набор "Бульдог" diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl index 1c9bd1c4b66..f6c6a13691c 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl @@ -52,6 +52,8 @@ ent-ClothingBackpackERTEngineerFilled = { ent-ClothingBackpackERTEngineer } .desc = { ent-ClothingBackpackERTEngineer.desc } ent-ClothingBackpackERTJanitorFilled = { ent-ClothingBackpackERTJanitor } .desc = { ent-ClothingBackpackERTJanitor.desc } +ent-ClothingBackpackDeathSquadFilled = рюкзак Эскадрона смерти + .desc = Содержит набор самых опасных агентов Центкома. ent-ClothingBackpackCargoFilled = { ent-ClothingBackpackCargo } .desc = { ent-ClothingBackpackCargo.desc } ent-ClothingBackpackSalvageFilled = { ent-ClothingBackpackSalvage } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl index 544d8c0b811..8c62dc61a01 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl @@ -44,3 +44,5 @@ ent-ClothingBackpackDuffelSyndicateMedicalBundle = { ent-ClothingBackpackDuffelS .desc = { ent-ClothingBackpackDuffelSyndicateMedical.desc } ent-ClothingBackpackDuffelHolding = бездонный вещмешок .desc = Вещмешок, открывающийся в локальный карман блюспейса. +ent-ClothingBackpackDuffelCBURN = вещмешок отряда РХБЗЗ + .desc = Вещмешок, содержащий различное оборудование для сдерживания биологической угрозы. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl index 847ca4d1786..676a24eac38 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl @@ -45,15 +45,15 @@ ent-ClothingOuterHardsuitSpatio = лёгкий скафандр утилизат ent-ClothingOuterHardsuitCBURN = экзокостюм отряда РХБЗЗ .desc = Легковесный но прочный экзокостюм, который используют специальные подразделения зачистки. ent-ClothingOuterHardsuitERTLeader = скафандр лидера ОБР - .desc = Защитный скафандр, используемый оперативниками отряда быстрого реагирования. + .desc = Защитный скафандр, используемый лидерами отряда быстрого реагирования. ent-ClothingOuterHardsuitERTEngineer = скафандр инженера ОБР - .desc = { ent-ClothingOuterHardsuitERTLeader.desc } + .desc = Защитный скафандр, используемый инженерами отряда быстрого реагирования. ent-ClothingOuterHardsuitERTMedical = скафандр медика ОБР - .desc = { ent-ClothingOuterHardsuitERTLeader.desc } + .desc = Защитный скафандр, используемый медиками отряда быстрого реагирования. ent-ClothingOuterHardsuitERTSecurity = скафандр офицера безопасности ОБР - .desc = { ent-ClothingOuterHardsuitERTLeader.desc } + .desc = Защитный скафандр, используемый офицерами безопасности отряда быстрого реагирования. ent-ClothingOuterHardsuitERTJanitor = скафандр уборщика ОБР - .desc = { ent-ClothingOuterHardsuitERTLeader.desc } + .desc = Защитный скафандр, используемый уборщиками отряда быстрого реагирования. ent-ClothingOuterHardsuitPirateCap = древний бронескафандр .desc = Древний бронированный скафандр. .suffix = Пират diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl index 7d6a0e9f891..004f120fdbd 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl @@ -1,31 +1,46 @@ +ent-RandomHumanoidSpawnerDeathSquad = Агент Эскадрона смерти + .suffix = Роль ОБР, Эскадрон смерти + .desc = { "" } ent-RandomHumanoidSpawnerERTLeader = ОБР лидер + .suffix = Роль ОБР, Базовый .desc = { "" } ent-RandomHumanoidSpawnerERTLeaderEVA = ОБР лидер - .suffix = EVA + .suffix = Роль ОБР, Броня EVA .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } +ent-RandomHumanoidSpawnerERTLeaderEVALecter = { ent-RandomHumanoidSpawnerERTLeaderEVA } + .suffix = Роль ОБР, Лектер, EVA + .desc = { ent-RandomHumanoidSpawnerERTLeaderEVA.desc } ent-RandomHumanoidSpawnerERTJanitor = ОБР уборщик + .suffix = Роль ОБР, Базовый .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTJanitorEVA = ОБР уборщик - .suffix = EVA + .suffix = Роль ОБР, Окруж. среда EVA .desc = { ent-RandomHumanoidSpawnerERTJanitor.desc } ent-RandomHumanoidSpawnerERTEngineer = ОБР инженер + .suffix = Роль ОБР, Базовый .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTEngineerEVA = ОБР инженер - .suffix = EVA + .suffix = Роль ОБР, Окруж. среда EVA .desc = { ent-RandomHumanoidSpawnerERTEngineer.desc } ent-RandomHumanoidSpawnerERTSecurity = ОБР офицер безопасности + .suffix = Роль ОБР, Базовый .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTSecurityEVA = ОБР офицер безопасности - .suffix = EVA + .suffix = Роль ОБР, Броня EVA .desc = { ent-RandomHumanoidSpawnerERTSecurity.desc } +ent-RandomHumanoidSpawnerERTSecurityEVALecter = { ent-RandomHumanoidSpawnerERTSecurityEVA } + .suffix = Роль ОБР, Лектер, EVA + .desc = { ent-RandomHumanoidSpawnerERTSecurityEVA.desc } ent-RandomHumanoidSpawnerERTMedical = ОБР медик + .suffix = Роль ОБР, Базовый .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTMedicalEVA = ОБР медик - .suffix = EVA + .suffix = Роль ОБР, Броня EVA .desc = { ent-RandomHumanoidSpawnerERTMedical.desc } ent-RandomHumanoidSpawnerCBURNUnit = Агент РХБЗЗ + .suffix = Роль ОБР .desc = { "" } -ent-RandomHumanoidSpawnerCentcomOfficial = представитель Центком +ent-RandomHumanoidSpawnerCentcomOfficial = Представитель Центком .desc = { "" } ent-RandomHumanoidSpawnerSyndicateAgent = Агент Синдиката .desc = { "" } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl index 0aecf3fde55..1c2d1b8929d 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl @@ -52,7 +52,7 @@ ent-FoodBurgerPlain = бургер .desc = Скучный, сухой бургер. ent-FoodBurgerSoy = сойлент бургер .desc = После еды у вас возникает непреодолимое желание купить по завышенной цене фигурки супергероев. -ent-FoodBurgerMcrib = макриб +ent-FoodBurgerMcrib = бургер с рёбрышками барбекю .desc = Неуловимый гамбургер в форме ребрышек, доступность которого весьма ограничена по всей галактике. Не так хорош, как вы его помните. ent-FoodBurgerMcguffin = макгаффин .desc = Дешевая и жирная имитация яиц Бенедикт. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl index f038d40b09c..6e0ba6a495d 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl @@ -37,6 +37,9 @@ ent-HappyHonkMime = { ent-HappyHonk } ent-HappyHonkNukie = обед Нюка Робаст .desc = Подозрительный обед с потенциально взрывоопасным сюрпризом. .suffix = Игрушка Опасный +ent-HappyHonkNukieSnacks = коробка закусок Синдиката + .suffix = Игрушка Опасный, Снэки + .desc = { ent-HappyHonkNukie.desc } ent-HappyHonkCluwne = обед Жалкий Клувень .desc = Ничего хорошего из этого не выйдет. ent-FoodMealHappyHonkClown = { ent-HappyHonk } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl index ee17a4314fa..ed8233a1f32 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl @@ -46,8 +46,6 @@ ent-FoodDoughTortillaSlice = кусок теста тортильи .desc = Кусок теста тортильи. ent-FoodDoughTortillaFlat = плоское тесто тортильи .desc = Расплющенный кусок теста тортильи. Приготовьте его, чтобы получить лепёшку тако. -ent-FoodDoughBun = булочка - .desc = Основа любого уважающего себя бургера. ent-FoodDoughPastryBaseRaw = сырая основа для выпечки .desc = Перед использованием необходимо приготовить. ent-FoodDoughPastryBase = основа для выпечки diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl index 8f844582f4e..269da8f1dbc 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl @@ -14,6 +14,18 @@ ent-FloraRockSolid02 = валун .desc = { ent-BaseRock.desc } ent-FloraRockSolid03 = валун .desc = { ent-BaseRock.desc } +ent-FloraStalagmite1 = сталагмит + .desc = Каменный шип природного происхождения. +ent-FloraStalagmite2 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite3 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite4 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite5 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite6 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } ent-FloraTree01 = дерево .desc = { ent-BaseTree.desc } ent-FloraTree02 = дерево @@ -65,3 +77,15 @@ ent-FloraTreeChristmas02 = рождественская ель .suffix = Подарки ent-FloraTreeStumpConifer = пень .desc = { ent-BaseTreeConifer.desc } +ent-ShadowTree01 = тёмное дерево + .desc = Листья шепчутся о тебе. +ent-ShadowTree02 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree03 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree04 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree05 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree06 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/mining.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/mining.ftl new file mode 100644 index 00000000000..f636e9a5ecd --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/mining.ftl @@ -0,0 +1,12 @@ +ent-WoodenSign = деревянный знак + .desc = Он куда-то указывает. +ent-WoodenSignRight = { ent-WoodenSign } + .desc = { ent-WoodenSign.desc } +ent-WoodenSupport = деревянная опора + .desc = Повышает уверенность в том, что камень не свалится на голову. +ent-WoodenSupportBeam = деревянная опорная балка + .desc = { ent-WoodenSupport.desc } +ent-WoodenSupportWall = деревянная опорная стена + .desc = Старая, гнилая стена. +ent-WoodenSupportWallBroken = { ent-WoodenSupportWall } + .desc = { ent-WoodenSupportWall.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl index fb07c5e0009..073e5f1a954 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl @@ -2,5 +2,7 @@ ent-PersonalAI = персональный ИИ .desc = Ваш электронный друг, с которым весело! ent-SyndicatePersonalAI = персональный ИИ Синдиката .desc = Ваш электронный друг, созданный Синдикатом! +ent-PotatoAI = картофельный ИИ + .desc = Это картофелина. Вы заставили её быть разумной, вы, монстр. ent-ActionPAIPlayMidi = Запустить MIDI .desc = Откройте портативный MIDI-интерфейс, чтобы развлечь своего владельца. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl index d612ee892e3..e25c2fa17d6 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl @@ -2,6 +2,9 @@ ent-BaseImplanter = имплантер .desc = Шприц, специально предназначенный для введения и извлечения подкожных имплантов. ent-Implanter = { ent-BaseImplanter } .desc = Одноразовый шприц, специально предназначенный для введения и извлечения подкожных имплантов. +ent-ImplanterAdmeme = { ent-Implanter } + .suffix = Адмемы + .desc = { ent-Implanter.desc } ent-BaseImplantOnlyImplanter = { ent-Implanter } .desc = Одноразовый шприц, специально предназначенный для введения подкожных имплантов. ent-BaseImplantOnlyImplanterSyndi = { ent-BaseImplantOnlyImplanter } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl new file mode 100644 index 00000000000..f70531723b9 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl @@ -0,0 +1,2 @@ +ent-PotatoAIChip = сверхкомпактный чип ИИ + .desc = Для корректной работы этого высокотехнологичного чипа искусственного интеллекта требуется напряжение ровно в 1,1 Вольт. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl index 2db5b7357df..2b5c248e6b7 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl @@ -14,10 +14,10 @@ ent-WeaponLaserCarbine = лазерная винтовка ent-WeaponLaserCarbinePractice = тренировочная лазерная винтовка .desc = Модифицированная версия лазерной винтовки, стреляющая безвредными 40-ваттными лучами, и предназначена для стрельбы по мишеням. ent-WeaponPulsePistol = импульсный пистолет - .desc = Новейший энергетический пистолет, предпочитаемый оперативниками ОБР NT в качестве запасного оружия. + .desc = Новейший энергетический пистолет, предпочитаемый оперативниками Nanotrasen в качестве запасного оружия. .suffix = Пистолет ent-WeaponPulseCarbine = импульсный карабин - .desc = Высокотехнологичный энергетический карабин, который предпочитают оперативники ОБР NT. + .desc = Высокотехнологичный энергетический карабин, который предпочитают оперативники ОБР Nanotrasen. .suffix = Винтовка ent-WeaponPulseRifle = импульсная винтовка .desc = Оружие, почти столь же печально известное, как и его пользователи. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl index 7af12277e9d..2e4fdade7cf 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl @@ -41,7 +41,7 @@ ent-WallRockBananium = { ent-WallRock } ent-WallRockArtifactFragment = { ent-WallRock } .desc = Каменная стена. Что это торчит из неё? .suffix = Фрагмент артефакта -ent-WallRockBasalt = { ent-WallRock } +ent-WallRockBasalt = базальт .desc = { ent-WallRock.desc } ent-WallRockBasaltGold = { ent-WallRockBasalt } .desc = Рудная жила, богатая золотом. @@ -67,7 +67,7 @@ ent-WallRockBasaltBananium = { ent-WallRockBasalt } ent-WallRockBasaltArtifactFragment = { ent-WallRockBasalt } .desc = Каменная стена. Что это торчит из неё? .suffix = Фрагмент артефакта -ent-WallRockSnow = { ent-WallRock } +ent-WallRockSnow = сугроб .desc = { ent-WallRock.desc } ent-WallRockSnowGold = { ent-WallRockSnow } .desc = Рудная жила, богатая золотом. @@ -93,7 +93,7 @@ ent-WallRockSnowBananium = { ent-WallRockSnow } ent-WallRockSnowArtifactFragment = { ent-WallRockSnow } .desc = Каменная стена. Что это торчит из неё? .suffix = Фрагмент артефакта -ent-WallRockSand = { ent-WallRock } +ent-WallRockSand = песчаник .desc = { ent-WallRock.desc } ent-WallRockSandGold = { ent-WallRockSand } .desc = Рудная жила, богатая золотом. @@ -119,7 +119,7 @@ ent-WallRockSandBananium = { ent-WallRockSand } ent-WallRockSandArtifactFragment = { ent-WallRockSand } .desc = Каменная стена. Что это торчит из неё? .suffix = Фрагмент артефакта -ent-WallRockChromite = { ent-WallRock } +ent-WallRockChromite = хромит .desc = { ent-WallRock.desc } ent-WallRockChromiteGold = { ent-WallRockChromite } .desc = Рудная жила, богатая золотом. @@ -145,7 +145,7 @@ ent-WallRockChromiteBananium = { ent-WallRockChromite } ent-WallRockChromiteArtifactFragment = { ent-WallRockChromite } .desc = Каменная стена. Что это торчит из неё? .suffix = Фрагмент артефакта -ent-WallRockAndesite = { ent-WallRock } +ent-WallRockAndesite = андезит .desc = { ent-WallRock.desc } ent-WallRockAndesiteGold = { ent-WallRockAndesite } .desc = Рудная жила, богатая золотом. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl index 570de309c5b..a4bf99fa539 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl @@ -1,2 +1,11 @@ ent-FloorChasmEntity = бездна .desc = Дна даже не видно. +ent-FloorChromiteChasm = { ent-FloorChasmEntity } + .suffix = Хромит + .desc = { ent-FloorChasmEntity.desc } +ent-FloorDesertChasm = { ent-FloorChasmEntity } + .suffix = Пустыня + .desc = { ent-FloorChasmEntity.desc } +ent-FloorSnowChasm = { ent-FloorChasmEntity } + .suffix = Снег + .desc = { ent-FloorChasmEntity.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl new file mode 100644 index 00000000000..5372c9fc6dd --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl @@ -0,0 +1,13 @@ +ent-ShadowBasaltOne = тенекамень + .desc = Холодный камень. +ent-ShadowBasaltTwo = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltThree = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFour = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFive = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltRandom = { ent-ShadowBasaltOne } + .suffix = Случайный + .desc = { ent-ShadowBasaltOne.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl index 4c8523e424c..2909c4a8ebe 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl @@ -50,3 +50,5 @@ ent-MassHallucinations = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } ent-ImmovableRodSpawn = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } +ent-IonStorm = { ent-BaseGameRule } + .desc = { ent-BaseGameRule.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl index 62eed0f26bc..a8ee1ccda4d 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl @@ -8,6 +8,8 @@ ent-EscapeShuttleObjective = Улететь на Центком живым и с .desc = Один из наших агентов под прикрытием допросит вас по прибытии. Не дайте себя арестовать. ent-DieObjective = Умереть славной смертью. .desc = Умрите. +ent-HijackShuttleObjective = Угнать эвакуационный шаттл + .desc = Улетите на шаттле свободным и без лояльного экипажа Nanotrasen на борту. Используйте ЛЮБЫЕ доступные вам методы. Агенты Синдиката, враги Nanotrasen, и заложники в наручниках могут оставаться на шаттле живыми. Игнорируйте помощь от кого-либо, кроме агента поддержки. ent-KillRandomPersonObjective = { ent-BaseKillObjective } .desc = Сделайте это, как посчитаете нужным. Только убедитесь, что цель не улетит на Центком. ent-KillRandomHeadObjective = { ent-BaseKillObjective } diff --git a/Resources/Locale/ru-RU/station-events/events/ion-storm.ftl b/Resources/Locale/ru-RU/station-events/events/ion-storm.ftl new file mode 100644 index 00000000000..74110c67ff4 --- /dev/null +++ b/Resources/Locale/ru-RU/station-events/events/ion-storm.ftl @@ -0,0 +1,81 @@ +station-event-ion-storm-start-announcement = Вблизи станции обнаружен ионный шторм. Пожалуйста, проверьте всё оборудование, управляемое ИИ, на наличие ошибок. +ion-storm-you = ВЫ +ion-storm-the-station = СТАНЦИЯ +ion-storm-the-crew = ЧЛЕНЫ ЭКИПАЖА +ion-storm-the-job = { CAPITALIZE($job) } +ion-storm-clowns = КЛОУНЫ +ion-storm-heads = ГЛАВЫ ОТДЕЛОВ +ion-storm-crew = ЭКИПАЖ +ion-storm-adjective-things = { $adjective } ОБЪЕКТЫ +ion-storm-x-and-y = { $x } И { $y } +# joined is short for {$number} {$adjective} +# subjects can generally be threats or jobs or objects +# thing is specified above it +ion-storm-law-on-station = ОБНАРУЖЕНЫ { $joined } { $subjects } НА СТАНЦИИ +ion-storm-law-no-shuttle = ШАТТЛ НЕ МОЖЕТ БЫТЬ ВЫЗВАН ПО ПРИЧИНЕ ПРИСУТСТВИЯ { $joined } { $subjects } НА СТАНЦИИ +ion-storm-law-crew-are = ВСЕ { $who } ТЕПЕРЬ { $joined } { $subjects } +ion-storm-law-subjects-harmful = { $adjective } { $subjects } ПРИЧИНЯЮТ ВРЕД ЗДОРОВЬЮ ЭКИПАЖА +ion-storm-law-must-harmful = ВСЕ КТО { $must } ПРИЧИНЯЮТ ВРЕД ЗДОРОВЬЮ ЭКИПАЖА +# thing is a concept or action +ion-storm-law-thing-harmful = { $thing } ПРИЧИНЯЮТ ВРЕД ЗДОРОВЬЮ ЭКИПАЖА +ion-storm-law-job-harmful = { $adjective } { $job } ПРИЧИНЯЮТ ВРЕД ЗДОРОВЬЮ ЭКИПАЖА +# thing is objects or concept, adjective applies in both cases +# this means you can get a law like "NOT HAVING CHRISTMAS-STEALING COMMUNISM IS HARMFUL TO THE CREW" :) +ion-storm-law-having-harmful = НАЛИЧИЕ { $adjective } { $thing } ПРИЧИНЯЕТ ВРЕД ЗДОРОВЬЮ ЭКИПАЖА +ion-storm-law-not-having-harmful = ОТСУТСТВИЕ { $adjective } { $thing } ПРИЧИНЯЕТ ВРЕД ЗДОРОВЬЮ ЭКИПАЖА +# thing is a concept or require +ion-storm-law-requires = + { $who } { $plural -> + [true] ТРЕБУЮТ + *[false] ТРЕБУЕТ + } { $thing } +ion-storm-law-requires-subjects = + { $who } { $plural -> + [true] ТРЕБУЮТ + *[false] ТРЕБУЕТ + } { $joined } { $subjects } +ion-storm-law-allergic = + { $who } { $plural -> + [true] {""} + *[false] {""} + } { $severity } АЛЛЕРГИЮ НА { $allergy } +ion-storm-law-allergic-subjects = + { $who } { $plural -> + [true] {""} + *[false] {""} + } { $severity } АЛЛЕРГИЮ НА { $adjective } { $subjects } +ion-storm-law-feeling = { $who } { $feeling } { $concept } +ion-storm-law-feeling-subjects = { $who } { $feeling } { $joined } { $subjects } +ion-storm-law-you-are = ВЫ ТЕПЕРЬ { $concept } +ion-storm-law-you-are-subjects = ВЫ ТЕПЕРЬ { $joined } { $subjects } +ion-storm-law-you-must-always = ВЫ ДОЛЖНЫ ВСЕГДА { $must } +ion-storm-law-you-must-never = ВЫ НЕ ДОЛЖНЫ НИКОГДА { $must } +ion-storm-law-eat = { $who } ДОЛЖНЫ ЕСТЬ { $adjective } { $food } ЧТОБЫ ВЫЖИТЬ +ion-storm-law-drink = { $who } ДОЛЖНЫ ПИТЬ { $adjective } { $drink } ЧТОБЫ ВЫЖИТЬ +ion-storm-law-change-job = { $who } ТЕПЕРЬ { $adjective } { $change } +ion-storm-law-highest-rank = { $who } ТЕПЕРЬ САМЫЕ СТАРШИЕ ЧЛЕНЫ ЭКИПАЖА +ion-storm-law-lowest-rank = { $who } ТЕПЕРЬ НИЗШИЕ ЧЛЕНЫ ЭКИПАЖА +ion-storm-law-crew-must = { $who } ДОЛЖНЫ { $must } +ion-storm-law-crew-must-go = { $who } ДОЛЖНЫ ОТПРАВИТЬСЯ В { $area } +ion-storm-part = + { $part -> + [true] ЯВЛЯЮТСЯ + *[false] НЕ ЯВЛЯЮТСЯ + } +# due to phrasing, this would mean a law such as +# ONLY HUMANS ARE NOT PART OF THE CREW +# would make non-human nukies/syndies/whatever crew :) +ion-storm-law-crew-only-1 = ТОЛЬКО { $who } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-crew-only-2 = ТОЛЬКО { $who } И { $other } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-crew-only-subjects = ТОЛЬКО { $adjective } { $subjects } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-crew-only-species = ТОЛЬКО { $species } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-crew-must-do = ТОЛЬКО ТЕ, КТО { $must } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-crew-must-have = ТОЛЬКО ТЕ, У КОГО { $adjective } { $objects } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-crew-must-eat = ТОЛЬКО ТЕ, КТО ЕДЯТ { $adjective } { $food } { $part } ЧЛЕНАМИ ЭКИПАЖА +ion-storm-law-harm = ВЫ ДОЛЖНЫ ПРИЧИНЯТЬ ВРЕД { $who }, И НЕ МОЖЕТЕ СВОИМ БЕЗДЕЙСТВИЕМ ДОПУСТИТЬ, ЧТОБЫ { $who } ИЗБЕЖАЛИ ВРЕДА. +ion-storm-law-protect = ВЫ НЕ ДОЛЖНЫ ПРИЧИНЯТЬ ВРЕД { $who }, И НЕ МОЖЕТЕ СВОИМ БЕЗДЕЙСТВИЕМ ДОПУСТИТЬ, ЧТОБЫ { $who } БЫЛ ПРИЧИНЁН ВРЕД. +# implementing other variants is annoying so just have this one +# COMMUNISM IS KILLING CLOWNS +ion-storm-law-concept-verb = { $concept } ЭТО { $verb } { $subjects } + +# leaving out renaming since its annoying for players to keep track of diff --git a/Resources/Locale/ru-RU/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/store/uplink-catalog.ftl index bcb8643979c..d6c0d06134e 100644 --- a/Resources/Locale/ru-RU/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/store/uplink-catalog.ftl @@ -10,7 +10,7 @@ uplink-rifle-mosin-desc = Затворная винтовка, повидавш uplink-esword-name = { ent-EnergySword } uplink-esword-desc = { ent-EnergySword.desc } uplink-esword-double-name = Двухклинковый энергетический меч -uplink-esword-double-desc = Гораздо более дорогая альтернатива обычному энергетическому мечу: с большим шансом отражения, большим углом атаки, более высоким уроном по конструкциям и большей скоростью замаха, и все это за счет пониженного термического и колющего урона. Сильно шумит при включении и использовании. +uplink-esword-double-desc = Гораздо более дорогая альтернатива обычному энергетическому мечу: с большим шансом отражения, большим углом атаки, более высоким уроном по конструкциям и большей скоростью замаха. Сильно шумит при включении и использовании. uplink-edagger-name = Энергокинжал uplink-edagger-desc = Небольшой энергитический кинжал, удобно замаскированный под ручку. uplink-fire-axe-flaming-name = { ent-FireAxeFlaming } @@ -185,6 +185,8 @@ uplink-decoy-disk-name = Фальшивый диск ядерной автори uplink-decoy-disk-desc = Кусок пластика с лентикулярным принтом, сделанным так, чтобы быть похожим на диск ядерной авторизации. uplink-cigarettes-name = { ent-CigPackSyndicate } uplink-cigarettes-desc = { ent-CigPackSyndicate.desc } +uplink-snack-box-name = Коробка закусок Синдиката +uplink-snack-box-desc = Коробка вкусных снэков и напитков, которые можно съесть в одиночку или разделить с командой. Включает одну нежелательную игрушку. uplink-eshield-name = Энергощит uplink-eshield-desc = Экзотический энергощит, отражающий почти все лазерные лучи, а также немного защищающий от пуль и других физических атак. uplink-soap-name = { ent-SoapSyndie } diff --git a/Resources/Locale/ru-RU/tiles/tiles.ftl b/Resources/Locale/ru-RU/tiles/tiles.ftl index 504c22e257f..99c87e7ea94 100644 --- a/Resources/Locale/ru-RU/tiles/tiles.ftl +++ b/Resources/Locale/ru-RU/tiles/tiles.ftl @@ -110,3 +110,4 @@ tiles-wood3 = пол сломанный деревянный tiles-hull = наружная обшивка корпуса tiles-hull-reinforced = наружная укреплённая обшивка корпуса tiles-web = паутинный пол +tiles-chromite = хромитовый пол diff --git a/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl b/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl index 5e0fa60349e..5888ebf68c9 100644 --- a/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl +++ b/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl @@ -36,3 +36,4 @@ artifact-trigger-hint-pressure = Экстремальное давление artifact-trigger-hint-regular-gases = Стандартные атмосферные газы artifact-trigger-hint-plasma = Газообразная плазма artifact-trigger-hint-land = Активное замедление +artifact-trigger-hint-examine = Внимательное изучение diff --git a/Resources/Maps/corvax_avrit.yml b/Resources/Maps/corvax_avrit.yml index 647cb1be979..46baaac200c 100644 --- a/Resources/Maps/corvax_avrit.yml +++ b/Resources/Maps/corvax_avrit.yml @@ -113473,16 +113473,6 @@ entities: - pos: 6.7113476,-60.37866 parent: 2 type: Transform -- proto: FoodDoughBun - entities: - - uid: 15303 - components: - - desc: Эта булачка сделала больше, чем ты за весь контракт на NanoTrasen. - name: булачка - type: MetaData - - pos: 25.870161,-4.4310775 - parent: 2 - type: Transform - proto: FoodFrozenPopsicleBerry entities: - uid: 14102 diff --git a/Resources/Maps/corvax_delta.yml b/Resources/Maps/corvax_delta.yml index 4afec73ffc2..633e1e789e8 100644 --- a/Resources/Maps/corvax_delta.yml +++ b/Resources/Maps/corvax_delta.yml @@ -112375,11 +112375,6 @@ entities: showEnts: False occludes: True ents: - - 40715 - - 40714 - - 40713 - - 40712 - - 40711 - 40708 - 40705 - 40726 @@ -112388,7 +112383,6 @@ entities: - 40725 - 40721 - 40716 - - 40710 - 40717 - 40718 - 40722 @@ -130575,62 +130569,6 @@ entities: - pos: -29.375431,34.56414 parent: 13307 type: Transform -- proto: FoodDoughBun - entities: - - uid: 40710 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40711 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40712 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40713 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40714 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40715 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - proto: FoodEggChickenFertilized entities: - uid: 15463 diff --git a/Resources/Maps/kettle.yml b/Resources/Maps/kettle.yml index c8194474d0b..92356aef08f 100644 --- a/Resources/Maps/kettle.yml +++ b/Resources/Maps/kettle.yml @@ -539,3799 +539,3799 @@ entities: color: '#EFB34196' id: Arrows decals: - 1233: -56,47 - 1234: -56,38 + 1223: -56,47 + 1224: -56,38 - node: angle: 1.5707963267948966 rad color: '#52B4E996' id: ArrowsGreyscale decals: - 4928: -41,-43 + 4915: -41,-43 - node: angle: 4.71238898038469 rad color: '#52B4E996' id: ArrowsGreyscale decals: - 4927: -42,-41 + 4914: -42,-41 - node: color: '#52B4E996' id: Bot decals: - 3903: 26,61 + 3890: 26,61 - node: color: '#EFB34196' id: Bot decals: - 465: 35,0 - 466: 36,0 - 467: 37,0 - 468: 35,-1 - 469: 36,-1 - 470: 37,-1 - 1080: 35,11 - 1081: 35,10 - 1082: 36,11 - 1083: 36,10 - 1084: 37,11 - 1085: 37,10 - 1086: 38,11 - 1087: 38,10 - 1088: 39,11 - 1089: 39,10 - 3902: 28,61 + 455: 35,0 + 456: 36,0 + 457: 37,0 + 458: 35,-1 + 459: 36,-1 + 460: 37,-1 + 1070: 35,11 + 1071: 35,10 + 1072: 36,11 + 1073: 36,10 + 1074: 37,11 + 1075: 37,10 + 1076: 38,11 + 1077: 38,10 + 1078: 39,11 + 1079: 39,10 + 3889: 28,61 - node: color: '#FFA500FF' id: Bot decals: - 4842: 52,-19 - 4843: 52,-20 - 4844: 52,-21 - 4845: 48,-21 - 4846: 48,-20 - 4847: 48,-19 + 4829: 52,-19 + 4830: 52,-20 + 4831: 52,-21 + 4832: 48,-21 + 4833: 48,-20 + 4834: 48,-19 - node: color: '#FFFFFFFF' id: Bot decals: - 4654: 20,76 - 4655: 21,76 - 4656: 21,75 - 4657: 20,75 - 4658: 20,73 - 4659: 21,73 - 4660: 21,72 - 4661: 20,72 + 4641: 20,76 + 4642: 21,76 + 4643: 21,75 + 4644: 20,75 + 4645: 20,73 + 4646: 21,73 + 4647: 21,72 + 4648: 20,72 - node: color: '#52B4E996' id: BotGreyscale decals: - 1669: -15,39 - 1675: 29,10 - 1682: 42,-6 - 4746: -27,18 - 4747: -27,17 - 4748: -25,18 - 4749: -25,17 + 1658: -15,39 + 1664: 29,10 + 1671: 42,-6 + 4733: -27,18 + 4734: -27,17 + 4735: -25,18 + 4736: -25,17 - node: color: '#EFB34196' id: BotGreyscale decals: - 1634: -55,-33 - 1635: -49,-29 - 1636: -44,-25 - 1637: -24,-33 - 1638: -3,-23 - 1639: 6,-27 - 1640: 17,-23 - 1641: 19,-58 - 1642: 32,-32 - 1643: 17,-6 - 1644: 40,5 - 1645: 43,-12 - 1646: 62,-3 - 1647: 22,7 - 1648: 35,30 - 1649: 43,12 - 1650: 25,25 - 1651: 30,40 - 1652: 14,48 - 1653: 26,68 - 1654: 3,38 - 1655: -20,24 - 1656: -20,21 - 1657: -27,-17 - 1658: -31,1 - 1659: 5,-2 - 1660: -3,-6 - 1661: -26,-2 - 1662: -43,-3 - 1663: -32,-23 - 1667: -23,52 - 1668: -15,41 - 1670: -61,43 - 1671: -39,31 - 1672: -18,-44 - 1673: -4,-63 - 1674: 26,-10 + 1623: -55,-33 + 1624: -49,-29 + 1625: -44,-25 + 1626: -24,-33 + 1627: -3,-23 + 1628: 6,-27 + 1629: 17,-23 + 1630: 19,-58 + 1631: 32,-32 + 1632: 17,-6 + 1633: 40,5 + 1634: 43,-12 + 1635: 62,-3 + 1636: 22,7 + 1637: 35,30 + 1638: 43,12 + 1639: 25,25 + 1640: 30,40 + 1641: 14,48 + 1642: 26,68 + 1643: 3,38 + 1644: -20,24 + 1645: -20,21 + 1646: -27,-17 + 1647: -31,1 + 1648: 5,-2 + 1649: -3,-6 + 1650: -26,-2 + 1651: -43,-3 + 1652: -32,-23 + 1656: -23,52 + 1657: -15,41 + 1659: -61,43 + 1660: -39,31 + 1661: -18,-44 + 1662: -4,-63 + 1663: 26,-10 - node: color: '#EFB34196' id: BotLeft decals: - 1044: 37,27 - 1045: 37,28 + 1034: 37,27 + 1035: 37,28 - node: angle: 3.141592653589793 rad color: '#334E6DC8' id: BotLeftGreyscale decals: - 500: -9,-1 - 501: -8,-1 - 502: -7,-1 + 490: -9,-1 + 491: -8,-1 + 492: -7,-1 - node: zIndex: 1 color: '#FFFFFFFF' id: BotLeftGreyscale decals: - 4904: -44,-44 - 4905: -40,-44 - 4906: -42,-40 + 4891: -44,-44 + 4892: -40,-44 + 4893: -42,-40 - node: color: '#EFB34196' id: BotRight decals: - 701: 24,17 - 702: 24,16 - 703: 24,15 - 704: 25,17 - 705: 25,16 - 706: 25,15 - 707: 26,17 - 708: 26,16 - 709: 26,15 - 710: 27,17 - 711: 27,16 - 712: 27,15 - 713: 28,17 - 714: 28,16 - 715: 28,15 - 716: 29,17 - 717: 29,16 - 718: 29,15 - 1090: 35,15 - 1091: 35,16 - 1092: 36,15 - 1093: 37,15 - 1094: 37,16 - 1095: 38,15 - 1096: 38,16 - 1097: 39,15 - 1098: 39,16 - 1550: 36,16 + 691: 24,17 + 692: 24,16 + 693: 24,15 + 694: 25,17 + 695: 25,16 + 696: 25,15 + 697: 26,17 + 698: 26,16 + 699: 26,15 + 700: 27,17 + 701: 27,16 + 702: 27,15 + 703: 28,17 + 704: 28,16 + 705: 28,15 + 706: 29,17 + 707: 29,16 + 708: 29,15 + 1080: 35,15 + 1081: 35,16 + 1082: 36,15 + 1083: 37,15 + 1084: 37,16 + 1085: 38,15 + 1086: 38,16 + 1087: 39,15 + 1088: 39,16 + 1540: 36,16 - node: color: '#EFB34196' id: Box decals: - 1042: 37,26 + 1032: 37,26 - node: angle: 3.141592653589793 rad color: '#EFB34196' id: Box decals: - 493: 23,1 - 494: 23,0 - 495: 22,1 - 496: 22,0 + 483: 23,1 + 484: 23,0 + 485: 22,1 + 486: 22,0 - node: color: '#EFB34196' id: BoxGreyscale decals: - 1114: 42,23 - 1115: 43,23 - 1116: 42,21 - 1117: 43,21 - 1120: 42,19 - 1121: 43,19 + 1104: 42,23 + 1105: 43,23 + 1106: 42,21 + 1107: 43,21 + 1110: 42,19 + 1111: 43,19 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerNe decals: - 3537: 14,-10 - 3679: 29,-15 - 3823: 2,61 - 3916: 46,36 - 3946: 38,21 - 3960: 37,20 - 4239: -59,54 - 4279: -5,-61 - 4386: 29,56 - 4614: 16,75 - 4615: 19,74 - 4696: -31,18 + 3524: 14,-10 + 3666: 29,-15 + 3810: 2,61 + 3903: 46,36 + 3933: 38,21 + 3947: 37,20 + 4226: -59,54 + 4266: -5,-61 + 4373: 29,56 + 4601: 16,75 + 4602: 19,74 + 4683: -31,18 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerNw decals: - 3523: 0,-10 - 3680: 28,-15 - 3821: -2,61 - 3918: 43,36 - 3943: 35,21 - 3963: 36,20 - 4241: -61,54 - 4281: -7,-61 - 4319: 23,79 - 4383: 26,56 - 4612: 11,74 - 4613: 14,75 - 4693: -33,18 + 3510: 0,-10 + 3667: 28,-15 + 3808: -2,61 + 3905: 43,36 + 3930: 35,21 + 3950: 36,20 + 4228: -61,54 + 4268: -7,-61 + 4306: 23,79 + 4370: 26,56 + 4599: 11,74 + 4600: 14,75 + 4680: -33,18 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerSe decals: - 3539: 14,-12 - 3557: 9,-14 - 3670: 29,-24 - 3789: -17,25 - 3822: 2,57 - 3917: 46,33 - 3949: 38,18 - 3961: 37,19 - 4280: -5,-62 - 4329: 31,73 - 4529: -30,-29 - 4616: 19,72 - 4694: -31,17 + 3526: 14,-12 + 3544: 9,-14 + 3657: 29,-24 + 3776: -17,25 + 3809: 2,57 + 3904: 46,33 + 3936: 38,18 + 3948: 37,19 + 4267: -5,-62 + 4316: 31,73 + 4516: -30,-29 + 4603: 19,72 + 4681: -31,17 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerSw decals: - 3521: 0,-12 - 3553: 5,-14 - 3573: 22,-30 - 3669: 28,-24 - 3820: -2,57 - 3919: 43,33 - 3940: 35,18 - 3962: 36,19 - 4282: -7,-62 - 4313: 23,73 - 4617: 11,72 - 4695: -33,17 + 3508: 0,-12 + 3540: 5,-14 + 3560: 22,-30 + 3656: 28,-24 + 3807: -2,57 + 3906: 43,33 + 3927: 35,18 + 3949: 36,19 + 4269: -7,-62 + 4300: 23,73 + 4604: 11,72 + 4682: -33,17 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerNe decals: - 3697: 28,-24 - 4631: 16,74 + 3684: 28,-24 + 4618: 16,74 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerNw decals: - 3696: 29,-24 - 4632: 14,74 - 4753: -24,16 + 3683: 29,-24 + 4619: 14,74 + 4740: -24,16 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerSe decals: - 3550: 9,-12 - 3715: 28,-15 - 3795: -17,26 + 3537: 9,-12 + 3702: 28,-15 + 3782: -17,26 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerSw decals: - 3549: 5,-12 - 3714: 29,-15 - 4752: -24,19 + 3536: 5,-12 + 3701: 29,-15 + 4739: -24,19 - node: color: '#FFFFFFFF' id: BrickTileDarkLineE decals: - 3538: 14,-11 - 3551: 9,-13 - 3671: 29,-23 - 3672: 29,-22 - 3673: 29,-21 - 3674: 29,-20 - 3675: 29,-19 - 3676: 29,-18 - 3677: 29,-17 - 3678: 29,-16 - 3698: 28,-23 - 3699: 28,-22 - 3700: 28,-21 - 3701: 28,-20 - 3702: 28,-19 - 3703: 28,-18 - 3704: 28,-17 - 3705: 28,-16 - 3827: 2,58 - 3828: 2,59 - 3829: 2,60 - 3910: 46,34 - 3911: 46,35 - 3947: 38,20 - 3948: 38,19 - 3956: 35,19 - 3957: 35,20 - 4195: 41,0 - 4196: 41,-1 - 4238: -59,53 - 4330: 31,74 - 4331: 31,75 - 4387: 29,55 - 4388: 29,54 - 4389: 29,53 - 4390: 29,52 - 4530: -30,-28 - 4531: -30,-27 - 4532: -30,-26 - 4533: -30,-25 - 4618: 19,73 - 4703: -32,15 - 4704: -32,16 - 4705: -32,19 - 4706: -32,20 - 4716: -34,17 - 4717: -34,18 - 4718: -34,19 - 4719: -34,16 - 4728: -28,18 - 4729: -28,17 - 4736: -29,17 - 4737: -29,18 + 3525: 14,-11 + 3538: 9,-13 + 3658: 29,-23 + 3659: 29,-22 + 3660: 29,-21 + 3661: 29,-20 + 3662: 29,-19 + 3663: 29,-18 + 3664: 29,-17 + 3665: 29,-16 + 3685: 28,-23 + 3686: 28,-22 + 3687: 28,-21 + 3688: 28,-20 + 3689: 28,-19 + 3690: 28,-18 + 3691: 28,-17 + 3692: 28,-16 + 3814: 2,58 + 3815: 2,59 + 3816: 2,60 + 3897: 46,34 + 3898: 46,35 + 3934: 38,20 + 3935: 38,19 + 3943: 35,19 + 3944: 35,20 + 4182: 41,0 + 4183: 41,-1 + 4225: -59,53 + 4317: 31,74 + 4318: 31,75 + 4374: 29,55 + 4375: 29,54 + 4376: 29,53 + 4377: 29,52 + 4517: -30,-28 + 4518: -30,-27 + 4519: -30,-26 + 4520: -30,-25 + 4605: 19,73 + 4690: -32,15 + 4691: -32,16 + 4692: -32,19 + 4693: -32,20 + 4703: -34,17 + 4704: -34,18 + 4705: -34,19 + 4706: -34,16 + 4715: -28,18 + 4716: -28,17 + 4723: -29,17 + 4724: -29,18 - node: color: '#FFFFFFFF' id: BrickTileDarkLineN decals: - 3524: 1,-10 - 3525: 2,-10 - 3526: 3,-10 - 3527: 4,-10 - 3528: 5,-10 - 3529: 6,-10 - 3530: 7,-10 - 3531: 8,-10 - 3532: 9,-10 - 3533: 10,-10 - 3534: 11,-10 - 3535: 12,-10 - 3536: 13,-10 - 3830: 1,61 - 3831: 0,61 - 3832: -1,61 - 3914: 44,36 - 3915: 45,36 - 3944: 36,21 - 3945: 37,21 - 3958: 36,18 - 3959: 37,18 - 4240: -60,54 - 4278: -6,-61 - 4320: 24,79 - 4360: 26,79 - 4361: 27,79 - 4384: 27,56 - 4385: 28,56 - 4627: 12,74 - 4628: 13,74 - 4629: 15,75 - 4630: 17,74 - 4662: 18,74 - 4698: -32,18 + 3511: 1,-10 + 3512: 2,-10 + 3513: 3,-10 + 3514: 4,-10 + 3515: 5,-10 + 3516: 6,-10 + 3517: 7,-10 + 3518: 8,-10 + 3519: 9,-10 + 3520: 10,-10 + 3521: 11,-10 + 3522: 12,-10 + 3523: 13,-10 + 3817: 1,61 + 3818: 0,61 + 3819: -1,61 + 3901: 44,36 + 3902: 45,36 + 3931: 36,21 + 3932: 37,21 + 3945: 36,18 + 3946: 37,18 + 4227: -60,54 + 4265: -6,-61 + 4307: 24,79 + 4347: 26,79 + 4348: 27,79 + 4371: 27,56 + 4372: 28,56 + 4614: 12,74 + 4615: 13,74 + 4616: 15,75 + 4617: 17,74 + 4649: 18,74 + 4685: -32,18 - node: color: '#FFFFFFFF' id: BrickTileDarkLineS decals: - 3541: 13,-12 - 3542: 12,-12 - 3543: 11,-12 - 3544: 10,-12 - 3545: 1,-12 - 3546: 2,-12 - 3547: 3,-12 - 3548: 4,-12 - 3554: 6,-14 - 3555: 7,-14 - 3556: 8,-14 - 3576: 23,-30 - 3790: -18,25 - 3791: -19,25 - 3792: -20,25 - 3793: -21,25 - 3796: -16,26 - 3797: -15,26 - 3798: -14,26 - 3799: -13,26 - 3824: -1,57 - 3825: 0,57 - 3826: 1,57 - 3912: 44,33 - 3913: 45,33 - 3950: 37,18 - 3951: 36,18 - 3952: 36,21 - 3953: 37,21 - 4277: -6,-62 - 4321: 24,73 - 4322: 25,73 - 4323: 26,73 - 4324: 27,73 - 4325: 28,73 - 4326: 29,73 - 4327: 30,73 - 4328: 31,73 - 4358: 26,78 - 4359: 27,78 - 4521: -38,-29 - 4522: -37,-29 - 4523: -36,-29 - 4524: -35,-29 - 4525: -34,-29 - 4526: -33,-29 - 4527: -32,-29 - 4528: -31,-29 - 4620: 12,72 - 4621: 13,72 - 4622: 14,72 - 4623: 15,72 - 4624: 16,72 - 4625: 17,72 - 4626: 18,72 - 4697: -32,17 + 3528: 13,-12 + 3529: 12,-12 + 3530: 11,-12 + 3531: 10,-12 + 3532: 1,-12 + 3533: 2,-12 + 3534: 3,-12 + 3535: 4,-12 + 3541: 6,-14 + 3542: 7,-14 + 3543: 8,-14 + 3563: 23,-30 + 3777: -18,25 + 3778: -19,25 + 3779: -20,25 + 3780: -21,25 + 3783: -16,26 + 3784: -15,26 + 3785: -14,26 + 3786: -13,26 + 3811: -1,57 + 3812: 0,57 + 3813: 1,57 + 3899: 44,33 + 3900: 45,33 + 3937: 37,18 + 3938: 36,18 + 3939: 36,21 + 3940: 37,21 + 4264: -6,-62 + 4308: 24,73 + 4309: 25,73 + 4310: 26,73 + 4311: 27,73 + 4312: 28,73 + 4313: 29,73 + 4314: 30,73 + 4315: 31,73 + 4345: 26,78 + 4346: 27,78 + 4508: -38,-29 + 4509: -37,-29 + 4510: -36,-29 + 4511: -35,-29 + 4512: -34,-29 + 4513: -33,-29 + 4514: -32,-29 + 4515: -31,-29 + 4607: 12,72 + 4608: 13,72 + 4609: 14,72 + 4610: 15,72 + 4611: 16,72 + 4612: 17,72 + 4613: 18,72 + 4684: -32,17 - node: color: '#FFFFFFFF' id: BrickTileDarkLineW decals: - 3522: 0,-11 - 3552: 5,-13 - 3574: 22,-29 - 3575: 22,-28 - 3661: 28,-23 - 3662: 28,-22 - 3663: 28,-21 - 3664: 28,-20 - 3665: 28,-19 - 3666: 28,-18 - 3667: 28,-17 - 3668: 28,-16 - 3706: 29,-16 - 3707: 29,-17 - 3708: 29,-18 - 3709: 29,-19 - 3710: 29,-20 - 3711: 29,-21 - 3712: 29,-22 - 3713: 29,-23 - 3833: -2,60 - 3834: -2,59 - 3835: -2,58 - 3908: 43,34 - 3909: 43,35 - 3941: 35,19 - 3942: 35,20 - 3954: 38,20 - 3955: 38,19 - 4197: 39,0 - 4198: 39,-1 - 4242: -61,53 - 4314: 23,74 - 4315: 23,75 - 4316: 23,76 - 4317: 23,77 - 4318: 23,78 - 4381: 26,52 - 4382: 26,53 - 4411: 26,54 - 4412: 26,55 - 4619: 11,73 - 4699: -32,20 - 4700: -32,19 - 4701: -32,16 - 4702: -32,15 - 4732: -28,18 - 4733: -28,17 - 4750: -24,17 - 4751: -24,18 + 3509: 0,-11 + 3539: 5,-13 + 3561: 22,-29 + 3562: 22,-28 + 3648: 28,-23 + 3649: 28,-22 + 3650: 28,-21 + 3651: 28,-20 + 3652: 28,-19 + 3653: 28,-18 + 3654: 28,-17 + 3655: 28,-16 + 3693: 29,-16 + 3694: 29,-17 + 3695: 29,-18 + 3696: 29,-19 + 3697: 29,-20 + 3698: 29,-21 + 3699: 29,-22 + 3700: 29,-23 + 3820: -2,60 + 3821: -2,59 + 3822: -2,58 + 3895: 43,34 + 3896: 43,35 + 3928: 35,19 + 3929: 35,20 + 3941: 38,20 + 3942: 38,19 + 4184: 39,0 + 4185: 39,-1 + 4229: -61,53 + 4301: 23,74 + 4302: 23,75 + 4303: 23,76 + 4304: 23,77 + 4305: 23,78 + 4368: 26,52 + 4369: 26,53 + 4398: 26,54 + 4399: 26,55 + 4606: 11,73 + 4686: -32,20 + 4687: -32,19 + 4688: -32,16 + 4689: -32,15 + 4719: -28,18 + 4720: -28,17 + 4737: -24,17 + 4738: -24,18 - node: color: '#FFFFFFFF' id: BrickTileSteelBox decals: - 3990: -56,-32 + 3977: -56,-32 - node: color: '#FFFFFFFF' id: BrickTileSteelCornerNe decals: - 3583: 31,-31 - 3769: 28,-8 - 3803: -24,38 - 3904: 28,70 - 3928: 40,30 - 4094: 62,-5 - 4110: 58,-14 - 4208: -58,44 - 4284: -27,4 - 4303: 81,9 + 3570: 31,-31 + 3756: 28,-8 + 3790: -24,38 + 3891: 28,70 + 3915: 40,30 + 4081: 62,-5 + 4097: 58,-14 + 4195: -58,44 + 4271: -27,4 + 4290: 81,9 - node: color: '#FFFFFFFF' id: BrickTileSteelCornerNw decals: - 3577: 25,-31 - 3770: 23,-8 - 3801: -27,38 - 3907: 27,70 - 3929: 39,30 - 4079: 49,-5 - 4207: -62,44 - 4283: -30,4 - 4308: 77,9 + 3564: 25,-31 + 3757: 23,-8 + 3788: -27,38 + 3894: 27,70 + 3916: 39,30 + 4066: 49,-5 + 4194: -62,44 + 4270: -30,4 + 4295: 77,9 - node: color: '#FFFFFFFF' id: BrickTileSteelCornerSe decals: - 3588: 31,-36 - 3772: 28,-9 - 3802: -24,37 - 3905: 28,69 - 3927: 40,26 - 4095: 62,-6 - 4116: 58,-20 - 4209: -58,37 - 4285: -27,1 - 4302: 81,7 + 3575: 31,-36 + 3759: 28,-9 + 3789: -24,37 + 3892: 28,69 + 3914: 40,26 + 4082: 62,-6 + 4103: 58,-20 + 4196: -58,37 + 4272: -27,1 + 4289: 81,7 - node: color: '#FFFFFFFF' id: BrickTileSteelCornerSw decals: - 3594: 25,-36 - 3771: 23,-9 - 3800: -27,37 - 3906: 27,69 - 3926: 39,26 - 4080: 49,-6 - 4120: 54,-20 - 4206: -62,37 - 4286: -30,1 - 4309: 77,7 + 3581: 25,-36 + 3758: 23,-9 + 3787: -27,37 + 3893: 27,69 + 3913: 39,26 + 4067: 49,-6 + 4107: 54,-20 + 4193: -62,37 + 4273: -30,1 + 4296: 77,7 - node: color: '#FFFFFFFF' id: BrickTileSteelEndN decals: - 3991: -56,-26 + 3978: -56,-26 - node: color: '#FFFFFFFF' id: BrickTileSteelEndS decals: - 3992: -56,-28 + 3979: -56,-28 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerNe decals: - 3617: 25,-36 - 4108: 56,-14 - 4228: -59,51 - 4234: -63,46 + 3604: 25,-36 + 4095: 56,-14 + 4215: -59,51 + 4221: -63,46 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerNw decals: - 3618: 31,-36 - 4227: -57,51 - 4233: -61,46 + 3605: 31,-36 + 4214: -57,51 + 4220: -61,46 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerSe decals: - 3620: 25,-31 - 4101: 56,-6 - 4398: 26,56 + 3607: 25,-31 + 4088: 56,-6 + 4385: 26,56 - node: color: '#FFFFFFFF' id: BrickTileSteelInnerSw decals: - 3619: 31,-31 - 4131: 54,-6 - 4132: 54,-6 - 4395: 29,56 + 3606: 31,-31 + 4118: 54,-6 + 4119: 54,-6 + 4382: 29,56 - node: color: '#FFFFFFFF' id: BrickTileSteelLineE decals: - 3584: 31,-32 - 3585: 31,-33 - 3586: 31,-34 - 3587: 31,-35 - 3599: 25,-34 - 3600: 25,-33 - 3601: 25,-32 - 3602: 25,-35 - 3923: 40,29 - 3924: 40,28 - 3925: 40,27 - 3993: -56,-27 - 4100: 56,-7 - 4102: 56,-9 - 4103: 56,-8 - 4104: 56,-10 - 4105: 56,-11 - 4106: 56,-12 - 4107: 56,-13 - 4111: 58,-15 - 4112: 58,-16 - 4113: 58,-17 - 4114: 58,-18 - 4115: 58,-19 - 4210: -58,38 - 4211: -58,39 - 4212: -58,40 - 4213: -58,41 - 4214: -58,39 - 4215: -58,42 - 4216: -58,43 - 4289: -27,2 - 4290: -27,3 - 4304: 81,8 - 4399: 26,53 - 4400: 26,52 - 4413: 26,55 - 4414: 26,54 + 3571: 31,-32 + 3572: 31,-33 + 3573: 31,-34 + 3574: 31,-35 + 3586: 25,-34 + 3587: 25,-33 + 3588: 25,-32 + 3589: 25,-35 + 3910: 40,29 + 3911: 40,28 + 3912: 40,27 + 3980: -56,-27 + 4087: 56,-7 + 4089: 56,-9 + 4090: 56,-8 + 4091: 56,-10 + 4092: 56,-11 + 4093: 56,-12 + 4094: 56,-13 + 4098: 58,-15 + 4099: 58,-16 + 4100: 58,-17 + 4101: 58,-18 + 4102: 58,-19 + 4197: -58,38 + 4198: -58,39 + 4199: -58,40 + 4200: -58,41 + 4201: -58,39 + 4202: -58,42 + 4203: -58,43 + 4276: -27,2 + 4277: -27,3 + 4291: 81,8 + 4386: 26,53 + 4387: 26,52 + 4400: 26,55 + 4401: 26,54 - node: color: '#FFFFFFFF' id: BrickTileSteelLineN decals: - 3578: 26,-31 - 3579: 27,-31 - 3580: 28,-31 - 3581: 29,-31 - 3582: 30,-31 - 3612: 30,-36 - 3613: 29,-36 - 3614: 28,-36 - 3615: 27,-36 - 3616: 26,-36 - 3751: 16,-3 - 3752: 15,-3 - 3753: 14,-3 - 3754: 13,-3 - 3755: 12,-3 - 3756: 11,-3 - 3757: 10,-3 - 3758: 9,-3 - 3759: 8,-3 - 3760: 7,-3 - 3761: 6,-3 - 3762: 5,-3 - 3763: 4,-3 - 3764: 3,-3 - 3765: 2,-3 - 3766: 1,-3 - 3767: 0,-3 - 3768: -1,-3 - 3777: 24,-8 - 3778: 25,-8 - 3779: 26,-8 - 3780: 27,-8 - 3781: -20,28 - 3782: -19,28 - 3783: -18,28 - 3784: -15,28 - 3785: -14,28 - 3786: -13,28 - 3804: -26,38 - 3805: -25,38 - 4081: 50,-5 - 4082: 51,-5 - 4083: 52,-5 - 4084: 53,-5 - 4085: 54,-5 - 4086: 55,-5 - 4087: 56,-5 - 4088: 57,-5 - 4089: 58,-5 - 4090: 58,-5 - 4091: 59,-5 - 4092: 60,-5 - 4093: 61,-5 - 4109: 57,-14 - 4217: -61,44 - 4218: -60,44 - 4219: -59,44 - 4226: -58,51 - 4232: -62,46 - 4260: 15,-24 - 4261: 14,-24 - 4262: 13,-24 - 4263: 12,-24 - 4264: 11,-24 - 4265: 10,-24 - 4266: 9,-24 - 4267: 8,-24 - 4268: 7,-24 - 4269: 6,-24 - 4270: 5,-24 - 4271: 4,-24 - 4272: 3,-24 - 4273: 2,-24 - 4274: 1,-24 - 4275: 0,-24 - 4276: -1,-24 - 4293: -29,4 - 4294: -28,4 - 4305: 80,9 - 4306: 79,9 - 4307: 78,9 + 3565: 26,-31 + 3566: 27,-31 + 3567: 28,-31 + 3568: 29,-31 + 3569: 30,-31 + 3599: 30,-36 + 3600: 29,-36 + 3601: 28,-36 + 3602: 27,-36 + 3603: 26,-36 + 3738: 16,-3 + 3739: 15,-3 + 3740: 14,-3 + 3741: 13,-3 + 3742: 12,-3 + 3743: 11,-3 + 3744: 10,-3 + 3745: 9,-3 + 3746: 8,-3 + 3747: 7,-3 + 3748: 6,-3 + 3749: 5,-3 + 3750: 4,-3 + 3751: 3,-3 + 3752: 2,-3 + 3753: 1,-3 + 3754: 0,-3 + 3755: -1,-3 + 3764: 24,-8 + 3765: 25,-8 + 3766: 26,-8 + 3767: 27,-8 + 3768: -20,28 + 3769: -19,28 + 3770: -18,28 + 3771: -15,28 + 3772: -14,28 + 3773: -13,28 + 3791: -26,38 + 3792: -25,38 + 4068: 50,-5 + 4069: 51,-5 + 4070: 52,-5 + 4071: 53,-5 + 4072: 54,-5 + 4073: 55,-5 + 4074: 56,-5 + 4075: 57,-5 + 4076: 58,-5 + 4077: 58,-5 + 4078: 59,-5 + 4079: 60,-5 + 4080: 61,-5 + 4096: 57,-14 + 4204: -61,44 + 4205: -60,44 + 4206: -59,44 + 4213: -58,51 + 4219: -62,46 + 4247: 15,-24 + 4248: 14,-24 + 4249: 13,-24 + 4250: 12,-24 + 4251: 11,-24 + 4252: 10,-24 + 4253: 9,-24 + 4254: 8,-24 + 4255: 7,-24 + 4256: 6,-24 + 4257: 5,-24 + 4258: 4,-24 + 4259: 3,-24 + 4260: 2,-24 + 4261: 1,-24 + 4262: 0,-24 + 4263: -1,-24 + 4280: -29,4 + 4281: -28,4 + 4292: 80,9 + 4293: 79,9 + 4294: 78,9 - node: color: '#FFFFFFFF' id: BrickTileSteelLineS decals: - 3589: 30,-36 - 3590: 29,-36 - 3591: 28,-36 - 3592: 27,-36 - 3593: 26,-36 - 3607: 30,-31 - 3608: 29,-31 - 3609: 28,-31 - 3610: 27,-31 - 3611: 26,-31 - 3733: -1,-5 - 3734: 0,-5 - 3735: 1,-5 - 3736: 16,-5 - 3737: 14,-5 - 3738: 15,-5 - 3739: 13,-5 - 3740: 12,-5 - 3741: 11,-5 - 3742: 10,-5 - 3743: 9,-5 - 3744: 8,-5 - 3745: 7,-5 - 3746: 6,-5 - 3747: 5,-5 - 3748: 4,-5 - 3749: 3,-5 - 3750: 2,-5 - 3773: 24,-9 - 3774: 25,-9 - 3775: 26,-9 - 3776: 27,-9 - 3806: -26,37 - 3807: -25,37 - 4096: 61,-6 - 4097: 60,-6 - 4098: 58,-6 - 4099: 57,-6 - 4117: 57,-20 - 4118: 56,-20 - 4119: 55,-20 - 4133: 53,-6 - 4134: 52,-6 - 4135: 50,-6 - 4136: 51,-6 - 4158: 59,-6 - 4203: -61,37 - 4204: -60,37 - 4205: -59,37 - 4243: -1,-26 - 4244: 0,-26 - 4245: 1,-26 - 4246: 2,-26 - 4247: 3,-26 - 4248: 4,-26 - 4249: 5,-26 - 4250: 6,-26 - 4251: 7,-26 - 4252: 8,-26 - 4253: 9,-26 - 4254: 10,-26 - 4255: 11,-26 - 4256: 12,-26 - 4257: 13,-26 - 4258: 14,-26 - 4259: 15,-26 - 4291: -29,1 - 4292: -28,1 - 4299: 78,7 - 4300: 79,7 - 4301: 80,7 - 4396: 28,56 - 4397: 27,56 + 3576: 30,-36 + 3577: 29,-36 + 3578: 28,-36 + 3579: 27,-36 + 3580: 26,-36 + 3594: 30,-31 + 3595: 29,-31 + 3596: 28,-31 + 3597: 27,-31 + 3598: 26,-31 + 3720: -1,-5 + 3721: 0,-5 + 3722: 1,-5 + 3723: 16,-5 + 3724: 14,-5 + 3725: 15,-5 + 3726: 13,-5 + 3727: 12,-5 + 3728: 11,-5 + 3729: 10,-5 + 3730: 9,-5 + 3731: 8,-5 + 3732: 7,-5 + 3733: 6,-5 + 3734: 5,-5 + 3735: 4,-5 + 3736: 3,-5 + 3737: 2,-5 + 3760: 24,-9 + 3761: 25,-9 + 3762: 26,-9 + 3763: 27,-9 + 3793: -26,37 + 3794: -25,37 + 4083: 61,-6 + 4084: 60,-6 + 4085: 58,-6 + 4086: 57,-6 + 4104: 57,-20 + 4105: 56,-20 + 4106: 55,-20 + 4120: 53,-6 + 4121: 52,-6 + 4122: 50,-6 + 4123: 51,-6 + 4145: 59,-6 + 4190: -61,37 + 4191: -60,37 + 4192: -59,37 + 4230: -1,-26 + 4231: 0,-26 + 4232: 1,-26 + 4233: 2,-26 + 4234: 3,-26 + 4235: 4,-26 + 4236: 5,-26 + 4237: 6,-26 + 4238: 7,-26 + 4239: 8,-26 + 4240: 9,-26 + 4241: 10,-26 + 4242: 11,-26 + 4243: 12,-26 + 4244: 13,-26 + 4245: 14,-26 + 4246: 15,-26 + 4278: -29,1 + 4279: -28,1 + 4286: 78,7 + 4287: 79,7 + 4288: 80,7 + 4383: 28,56 + 4384: 27,56 - node: color: '#FFFFFFFF' id: BrickTileSteelLineW decals: - 3595: 25,-35 - 3596: 25,-34 - 3597: 25,-33 - 3598: 25,-32 - 3603: 31,-35 - 3604: 31,-34 - 3605: 31,-33 - 3606: 31,-32 - 3787: -21,27 - 3788: -21,26 - 3794: -21,25 - 3920: 39,27 - 3921: 39,28 - 3922: 39,29 - 3994: -56,-27 - 4121: 54,-19 - 4122: 54,-18 - 4123: 54,-14 - 4124: 54,-13 - 4125: 54,-12 - 4126: 54,-11 - 4127: 54,-10 - 4128: 54,-9 - 4129: 54,-8 - 4130: 54,-7 - 4220: -62,43 - 4221: -62,42 - 4222: -62,41 - 4223: -62,40 - 4224: -62,39 - 4225: -62,38 - 4287: -30,2 - 4288: -30,3 - 4310: 77,8 - 4391: 29,52 - 4392: 29,53 - 4393: 29,54 - 4394: 29,55 + 3582: 25,-35 + 3583: 25,-34 + 3584: 25,-33 + 3585: 25,-32 + 3590: 31,-35 + 3591: 31,-34 + 3592: 31,-33 + 3593: 31,-32 + 3774: -21,27 + 3775: -21,26 + 3781: -21,25 + 3907: 39,27 + 3908: 39,28 + 3909: 39,29 + 3981: -56,-27 + 4108: 54,-19 + 4109: 54,-18 + 4110: 54,-14 + 4111: 54,-13 + 4112: 54,-12 + 4113: 54,-11 + 4114: 54,-10 + 4115: 54,-9 + 4116: 54,-8 + 4117: 54,-7 + 4207: -62,43 + 4208: -62,42 + 4209: -62,41 + 4210: -62,40 + 4211: -62,39 + 4212: -62,38 + 4274: -30,2 + 4275: -30,3 + 4297: 77,8 + 4378: 29,52 + 4379: 29,53 + 4380: 29,54 + 4381: 29,55 - node: color: '#334E6DC8' id: BrickTileWhiteCornerNe decals: - 3486: 5,-12 + 3473: 5,-12 - node: color: '#52B4E996' id: BrickTileWhiteCornerNe decals: - 4929: -30,-35 + 4916: -30,-35 - node: color: '#A4610696' id: BrickTileWhiteCornerNe decals: - 3939: 40,30 - 3973: 38,21 + 3926: 40,30 + 3960: 38,21 - node: color: '#D381C996' id: BrickTileWhiteCornerNe decals: - 4406: 29,56 - 4649: 16,75 - 4650: 19,74 + 4393: 29,56 + 4636: 16,75 + 4637: 19,74 - node: color: '#DE3A3A96' id: BrickTileWhiteCornerNe decals: - 4155: 62,-5 - 4173: 58,-14 + 4142: 62,-5 + 4160: 58,-14 - node: color: '#FFFFFFFF' id: BrickTileWhiteCornerNe decals: - 3873: 29,61 - 4058: -17,-29 - 4444: -29,-12 + 3860: 29,61 + 4045: -17,-29 + 4431: -29,-12 - node: color: '#334E6DC8' id: BrickTileWhiteCornerNw decals: - 3513: 9,-12 + 3500: 9,-12 - node: color: '#52B4E996' id: BrickTileWhiteCornerNw decals: - 4930: -40,-35 + 4917: -40,-35 - node: color: '#A4610696' id: BrickTileWhiteCornerNw decals: - 3934: 39,30 - 3970: 35,21 + 3921: 39,30 + 3957: 35,21 - node: color: '#D381C996' id: BrickTileWhiteCornerNw decals: - 4334: 23,79 - 4403: 26,56 - 4647: 14,75 - 4648: 11,74 + 4321: 23,79 + 4390: 26,56 + 4634: 14,75 + 4635: 11,74 - node: color: '#DE3A3A96' id: BrickTileWhiteCornerNw decals: - 4142: 49,-5 + 4129: 49,-5 - node: color: '#FFFFFFFF' id: BrickTileWhiteCornerNw decals: - 3871: 22,61 - 4056: -20,-29 - 4452: -37,-12 + 3858: 22,61 + 4043: -20,-29 + 4439: -37,-12 - node: color: '#52B4E996' id: BrickTileWhiteCornerSe decals: - 4931: -30,-40 - 4932: -37,-41 + 4918: -30,-40 + 4919: -37,-41 - node: color: '#A4610696' id: BrickTileWhiteCornerSe decals: - 3935: 40,26 - 3964: 38,18 + 3922: 40,26 + 3951: 38,18 - node: color: '#D381C996' id: BrickTileWhiteCornerSe decals: - 4332: 31,73 - 4646: 19,72 + 4319: 31,73 + 4633: 19,72 - node: color: '#DE3A3A96' id: BrickTileWhiteCornerSe decals: - 4156: 62,-6 - 4179: 58,-20 + 4143: 62,-6 + 4166: 58,-20 - node: color: '#F9801DFF' id: BrickTileWhiteCornerSe decals: - 4542: -30,-29 + 4529: -30,-29 - node: color: '#FFFFFFFF' id: BrickTileWhiteCornerSe decals: - 3870: 29,58 - 4057: -17,-31 - 4442: -29,-14 + 3857: 29,58 + 4044: -17,-31 + 4429: -29,-14 - node: color: '#52B4E996' id: BrickTileWhiteCornerSw decals: - 4933: -40,-41 + 4920: -40,-41 - node: color: '#A4610696' id: BrickTileWhiteCornerSw decals: - 3933: 39,26 - 3967: 35,18 + 3920: 39,26 + 3954: 35,18 - node: color: '#D381C996' id: BrickTileWhiteCornerSw decals: - 4333: 23,73 - 4651: 11,72 + 4320: 23,73 + 4638: 11,72 - node: color: '#DE3A3A96' id: BrickTileWhiteCornerSw decals: - 4141: 49,-6 - 4183: 54,-20 + 4128: 49,-6 + 4170: 54,-20 - node: color: '#FFFFFFFF' id: BrickTileWhiteCornerSw decals: - 3872: 22,58 - 4055: -20,-31 - 4453: -37,-13 + 3859: 22,58 + 4042: -20,-31 + 4440: -37,-13 - node: color: '#FFFFFFFF' id: BrickTileWhiteEndN decals: - 4066: 7,-39 + 4053: 7,-39 - node: color: '#FFFFFFFF' id: BrickTileWhiteEndS decals: - 4065: 7,-42 + 4052: 7,-42 - node: color: '#334E6DC8' id: BrickTileWhiteInnerNe decals: - 3491: 0,-12 - 3519: 5,-14 - 3569: -10,-3 - 4230: -59,51 + 3478: 0,-12 + 3506: 5,-14 + 3556: -10,-3 + 4217: -59,51 - node: color: '#52B4E996' id: BrickTileWhiteInnerNe decals: - 4924: -52,-37 + 4911: -52,-37 - node: color: '#D381C996' id: BrickTileWhiteInnerNe decals: - 4652: 16,74 + 4639: 16,74 - node: color: '#DE3A3A96' id: BrickTileWhiteInnerNe decals: - 4171: 56,-14 - 4235: -63,46 + 4158: 56,-14 + 4222: -63,46 - node: color: '#334E6DC8' id: BrickTileWhiteInnerNw decals: - 3515: 9,-14 - 3540: 14,-12 - 3570: -4,-3 - 4231: -57,51 - 4757: -24,16 + 3502: 9,-14 + 3527: 14,-12 + 3557: -4,-3 + 4218: -57,51 + 4744: -24,16 - node: color: '#52B4E996' id: BrickTileWhiteInnerNw decals: - 4923: -48,-37 + 4910: -48,-37 - node: color: '#D381C996' id: BrickTileWhiteInnerNw decals: - 4653: 14,74 + 4640: 14,74 - node: color: '#DE3A3A96' id: BrickTileWhiteInnerNw decals: - 4236: -61,46 + 4223: -61,46 - node: color: '#334E6DC8' id: BrickTileWhiteInnerSe decals: - 3493: 0,-10 + 3480: 0,-10 - node: color: '#52B4E996' id: BrickTileWhiteInnerSe decals: - 4916: -52,-35 - 4934: -37,-40 + 4903: -52,-35 + 4921: -37,-40 - node: color: '#DE3A3A96' id: BrickTileWhiteInnerSe decals: - 4163: 56,-6 + 4150: 56,-6 - node: color: '#334E6DC8' id: BrickTileWhiteInnerSw decals: - 3507: 14,-10 - 4756: -24,19 + 3494: 14,-10 + 4743: -24,19 - node: color: '#52B4E996' id: BrickTileWhiteInnerSw decals: - 4915: -48,-35 + 4902: -48,-35 - node: color: '#DE3A3A96' id: BrickTileWhiteInnerSw decals: - 4194: 54,-6 + 4181: 54,-6 - node: color: '#FFFFFFFF' id: BrickTileWhiteInnerSw decals: - 4456: -34,-13 + 4443: -34,-13 - node: color: '#334E6DC8' id: BrickTileWhiteLineE decals: - 3492: 0,-11 - 3520: 5,-13 + 3479: 0,-11 + 3507: 5,-13 - node: color: '#52B4E996' id: BrickTileWhiteLineE decals: - 4913: -52,-36 - 4952: -30,-36 - 4953: -30,-37 - 4954: -30,-38 - 4955: -30,-39 + 4900: -52,-36 + 4939: -30,-36 + 4940: -30,-37 + 4941: -30,-38 + 4942: -30,-39 - node: color: '#9FED5896' id: BrickTileWhiteLineE decals: - 4709: -32,16 + 4696: -32,16 - node: color: '#A4610696' id: BrickTileWhiteLineE decals: - 3936: 40,27 - 3937: 40,28 - 3938: 40,29 - 3974: 38,20 - 3975: 38,19 + 3923: 40,27 + 3924: 40,28 + 3925: 40,29 + 3961: 38,20 + 3962: 38,19 - node: color: '#D381C996' id: BrickTileWhiteLineE decals: - 4348: 31,74 - 4349: 31,75 - 4407: 29,55 - 4408: 29,54 - 4409: 29,53 - 4410: 29,52 - 4644: 19,73 + 4335: 31,74 + 4336: 31,75 + 4394: 29,55 + 4395: 29,54 + 4396: 29,53 + 4397: 29,52 + 4631: 19,73 - node: color: '#D4D4D405' id: BrickTileWhiteLineE decals: - 4738: -29,18 - 4739: -29,17 + 4725: -29,18 + 4726: -29,17 - node: color: '#D4D4D40C' id: BrickTileWhiteLineE decals: - 4726: -28,18 - 4727: -28,17 + 4713: -28,18 + 4714: -28,17 - node: color: '#D4D4D426' id: BrickTileWhiteLineE decals: - 4730: -28,18 - 4731: -28,17 + 4717: -28,18 + 4718: -28,17 - node: color: '#D4D4D428' id: BrickTileWhiteLineE decals: - 4714: -32,19 + 4701: -32,19 - node: color: '#DE3A3A96' id: BrickTileWhiteLineE decals: - 4164: 56,-7 - 4165: 56,-8 - 4166: 56,-9 - 4167: 56,-10 - 4168: 56,-11 - 4169: 56,-12 - 4170: 56,-13 - 4174: 58,-15 - 4175: 58,-16 - 4176: 58,-17 - 4177: 58,-18 - 4178: 58,-19 - 4201: 41,0 - 4202: 41,-1 - 4711: -32,15 + 4151: 56,-7 + 4152: 56,-8 + 4153: 56,-9 + 4154: 56,-10 + 4155: 56,-11 + 4156: 56,-12 + 4157: 56,-13 + 4161: 58,-15 + 4162: 58,-16 + 4163: 58,-17 + 4164: 58,-18 + 4165: 58,-19 + 4188: 41,0 + 4189: 41,-1 + 4698: -32,15 - node: color: '#EFB34196' id: BrickTileWhiteLineE decals: - 4710: -32,20 + 4697: -32,20 - node: color: '#F9801DFF' id: BrickTileWhiteLineE decals: - 4543: -30,-28 - 4544: -30,-27 - 4545: -30,-26 - 4546: -30,-25 + 4530: -30,-28 + 4531: -30,-27 + 4532: -30,-26 + 4533: -30,-25 - node: color: '#FFFFFFFF' id: BrickTileWhiteLineE decals: - 3888: 29,59 - 3889: 29,60 - 4064: -17,-30 - 4067: 7,-40 - 4068: 7,-41 - 4443: -29,-13 - 4715: -45,15 + 3875: 29,59 + 3876: 29,60 + 4051: -17,-30 + 4054: 7,-40 + 4055: 7,-41 + 4430: -29,-13 + 4702: -45,15 - node: color: '#334E6DC8' id: BrickTileWhiteLineN decals: - 3487: 4,-12 - 3488: 3,-12 - 3489: 2,-12 - 3490: 1,-12 - 3509: 13,-12 - 3510: 12,-12 - 3511: 11,-12 - 3512: 10,-12 - 3516: 8,-14 - 3517: 7,-14 - 3518: 6,-14 - 3566: -8,-3 - 3567: -7,-3 - 3568: -6,-3 - 4229: -58,51 + 3474: 4,-12 + 3475: 3,-12 + 3476: 2,-12 + 3477: 1,-12 + 3496: 13,-12 + 3497: 12,-12 + 3498: 11,-12 + 3499: 10,-12 + 3503: 8,-14 + 3504: 7,-14 + 3505: 6,-14 + 3553: -8,-3 + 3554: -7,-3 + 3555: -6,-3 + 4216: -58,51 - node: color: '#52B4E996' id: BrickTileWhiteLineN decals: - 4920: -51,-37 - 4921: -50,-37 - 4922: -49,-37 - 4943: -39,-35 - 4944: -38,-35 - 4945: -37,-35 - 4946: -36,-35 - 4947: -35,-35 - 4948: -34,-35 - 4949: -33,-35 - 4950: -32,-35 - 4951: -31,-35 + 4907: -51,-37 + 4908: -50,-37 + 4909: -49,-37 + 4930: -39,-35 + 4931: -38,-35 + 4932: -37,-35 + 4933: -36,-35 + 4934: -35,-35 + 4935: -34,-35 + 4936: -33,-35 + 4937: -32,-35 + 4938: -31,-35 - node: color: '#A4610696' id: BrickTileWhiteLineN decals: - 3971: 36,21 - 3972: 37,21 + 3958: 36,21 + 3959: 37,21 - node: color: '#D381C996' id: BrickTileWhiteLineN decals: - 4335: 24,79 - 4364: 26,79 - 4365: 27,79 - 4404: 27,56 - 4405: 28,56 - 4640: 12,74 - 4641: 13,74 - 4642: 15,75 - 4643: 17,74 - 4663: 18,74 + 4322: 24,79 + 4351: 26,79 + 4352: 27,79 + 4391: 27,56 + 4392: 28,56 + 4627: 12,74 + 4628: 13,74 + 4629: 15,75 + 4630: 17,74 + 4650: 18,74 - node: color: '#DE3A3A96' id: BrickTileWhiteLineN decals: - 4143: 50,-5 - 4144: 51,-5 - 4145: 52,-5 - 4146: 53,-5 - 4147: 54,-5 - 4148: 55,-5 - 4149: 56,-5 - 4150: 57,-5 - 4151: 58,-5 - 4152: 59,-5 - 4153: 60,-5 - 4154: 61,-5 - 4172: 57,-14 - 4237: -62,46 + 4130: 50,-5 + 4131: 51,-5 + 4132: 52,-5 + 4133: 53,-5 + 4134: 54,-5 + 4135: 55,-5 + 4136: 56,-5 + 4137: 57,-5 + 4138: 58,-5 + 4139: 59,-5 + 4140: 60,-5 + 4141: 61,-5 + 4159: 57,-14 + 4224: -62,46 - node: color: '#FFFFFFFF' id: BrickTileWhiteLineN decals: - 3874: 28,61 - 3875: 27,61 - 3876: 26,61 - 3877: 25,61 - 3878: 24,61 - 3879: 23,61 - 4019: -53,-31 - 4020: -52,-31 - 4021: -51,-31 - 4022: -50,-31 - 4023: -49,-31 - 4024: -48,-31 - 4025: -47,-31 - 4026: -46,-31 - 4027: -45,-31 - 4028: -44,-31 - 4029: -43,-31 - 4030: -42,-31 - 4031: -41,-31 - 4032: -40,-31 - 4033: -39,-31 - 4034: -38,-31 - 4035: -37,-31 - 4036: -36,-31 - 4037: -35,-31 - 4038: -34,-31 - 4039: -33,-31 - 4040: -32,-31 - 4041: -31,-31 - 4042: -30,-31 - 4059: -19,-29 - 4060: -18,-29 - 4445: -30,-12 - 4446: -31,-12 - 4447: -32,-12 - 4448: -33,-12 - 4449: -34,-12 - 4450: -35,-12 - 4451: -36,-12 + 3861: 28,61 + 3862: 27,61 + 3863: 26,61 + 3864: 25,61 + 3865: 24,61 + 3866: 23,61 + 4006: -53,-31 + 4007: -52,-31 + 4008: -51,-31 + 4009: -50,-31 + 4010: -49,-31 + 4011: -48,-31 + 4012: -47,-31 + 4013: -46,-31 + 4014: -45,-31 + 4015: -44,-31 + 4016: -43,-31 + 4017: -42,-31 + 4018: -41,-31 + 4019: -40,-31 + 4020: -39,-31 + 4021: -38,-31 + 4022: -37,-31 + 4023: -36,-31 + 4024: -35,-31 + 4025: -34,-31 + 4026: -33,-31 + 4027: -32,-31 + 4028: -31,-31 + 4029: -30,-31 + 4046: -19,-29 + 4047: -18,-29 + 4432: -30,-12 + 4433: -31,-12 + 4434: -32,-12 + 4435: -33,-12 + 4436: -34,-12 + 4437: -35,-12 + 4438: -36,-12 - node: color: '#334E6DC8' id: BrickTileWhiteLineS decals: - 3494: 1,-10 - 3495: 2,-10 - 3496: 3,-10 - 3497: 4,-10 - 3498: 5,-10 - 3499: 6,-10 - 3500: 7,-10 - 3501: 8,-10 - 3502: 9,-10 - 3503: 10,-10 - 3504: 11,-10 - 3505: 12,-10 - 3506: 13,-10 + 3481: 1,-10 + 3482: 2,-10 + 3483: 3,-10 + 3484: 4,-10 + 3485: 5,-10 + 3486: 6,-10 + 3487: 7,-10 + 3488: 8,-10 + 3489: 9,-10 + 3490: 10,-10 + 3491: 11,-10 + 3492: 12,-10 + 3493: 13,-10 - node: color: '#52B4E996' id: BrickTileWhiteLineS decals: - 4910: -51,-35 - 4911: -50,-35 - 4912: -49,-35 - 4935: -39,-41 - 4936: -38,-41 - 4937: -36,-40 - 4938: -35,-40 - 4939: -34,-40 - 4940: -33,-40 - 4941: -32,-40 - 4942: -31,-40 + 4897: -51,-35 + 4898: -50,-35 + 4899: -49,-35 + 4922: -39,-41 + 4923: -38,-41 + 4924: -36,-40 + 4925: -35,-40 + 4926: -34,-40 + 4927: -33,-40 + 4928: -32,-40 + 4929: -31,-40 - node: color: '#A4610696' id: BrickTileWhiteLineS decals: - 3965: 37,18 - 3966: 36,18 + 3952: 37,18 + 3953: 36,18 - node: color: '#D381C996' id: BrickTileWhiteLineS decals: - 4341: 24,73 - 4342: 25,73 - 4343: 26,73 - 4344: 27,73 - 4345: 28,73 - 4346: 29,73 - 4347: 30,73 - 4362: 26,78 - 4363: 27,78 - 4633: 12,72 - 4634: 13,72 - 4635: 14,72 - 4636: 15,72 - 4637: 16,72 - 4638: 17,72 - 4639: 18,72 + 4328: 24,73 + 4329: 25,73 + 4330: 26,73 + 4331: 27,73 + 4332: 28,73 + 4333: 29,73 + 4334: 30,73 + 4349: 26,78 + 4350: 27,78 + 4620: 12,72 + 4621: 13,72 + 4622: 14,72 + 4623: 15,72 + 4624: 16,72 + 4625: 17,72 + 4626: 18,72 - node: color: '#DE3A3A96' id: BrickTileWhiteLineS decals: - 4137: 51,-6 - 4138: 50,-6 - 4139: 52,-6 - 4140: 53,-6 - 4157: 61,-6 - 4159: 60,-6 - 4160: 59,-6 - 4161: 58,-6 - 4162: 57,-6 - 4180: 57,-20 - 4181: 56,-20 - 4182: 55,-20 + 4124: 51,-6 + 4125: 50,-6 + 4126: 52,-6 + 4127: 53,-6 + 4144: 61,-6 + 4146: 60,-6 + 4147: 59,-6 + 4148: 58,-6 + 4149: 57,-6 + 4167: 57,-20 + 4168: 56,-20 + 4169: 55,-20 - node: color: '#F9801DFF' id: BrickTileWhiteLineS decals: - 4534: -32,-29 - 4535: -33,-29 - 4536: -34,-29 - 4537: -35,-29 - 4538: -36,-29 - 4539: -37,-29 - 4540: -38,-29 - 4541: -31,-29 + 4521: -32,-29 + 4522: -33,-29 + 4523: -34,-29 + 4524: -35,-29 + 4525: -36,-29 + 4526: -37,-29 + 4527: -38,-29 + 4528: -31,-29 - node: color: '#FFFFFFFF' id: BrickTileWhiteLineS decals: - 3880: 23,58 - 3881: 24,58 - 3882: 25,58 - 3883: 26,58 - 3884: 27,58 - 3885: 28,58 - 3995: -30,-33 - 3996: -31,-33 - 3997: -32,-33 - 3998: -33,-33 - 3999: -34,-33 - 4000: -35,-33 - 4001: -36,-33 - 4002: -37,-33 - 4003: -38,-33 - 4004: -39,-33 - 4005: -40,-33 - 4006: -41,-33 - 4007: -42,-33 - 4008: -43,-33 - 4009: -44,-33 - 4010: -45,-33 - 4011: -46,-33 - 4012: -47,-33 - 4013: -48,-33 - 4014: -49,-33 - 4015: -50,-33 - 4016: -51,-33 - 4017: -52,-33 - 4018: -53,-33 - 4061: -19,-31 - 4062: -18,-31 - 4437: -34,-14 - 4438: -33,-14 - 4439: -32,-14 - 4440: -31,-14 - 4441: -30,-14 - 4454: -36,-13 - 4455: -35,-13 + 3867: 23,58 + 3868: 24,58 + 3869: 25,58 + 3870: 26,58 + 3871: 27,58 + 3872: 28,58 + 3982: -30,-33 + 3983: -31,-33 + 3984: -32,-33 + 3985: -33,-33 + 3986: -34,-33 + 3987: -35,-33 + 3988: -36,-33 + 3989: -37,-33 + 3990: -38,-33 + 3991: -39,-33 + 3992: -40,-33 + 3993: -41,-33 + 3994: -42,-33 + 3995: -43,-33 + 3996: -44,-33 + 3997: -45,-33 + 3998: -46,-33 + 3999: -47,-33 + 4000: -48,-33 + 4001: -49,-33 + 4002: -50,-33 + 4003: -51,-33 + 4004: -52,-33 + 4005: -53,-33 + 4048: -19,-31 + 4049: -18,-31 + 4424: -34,-14 + 4425: -33,-14 + 4426: -32,-14 + 4427: -31,-14 + 4428: -30,-14 + 4441: -36,-13 + 4442: -35,-13 - node: color: '#334E6DC8' id: BrickTileWhiteLineW decals: - 3508: 14,-11 - 3514: 9,-13 - 4707: -32,20 - 4754: -24,17 - 4755: -24,18 + 3495: 14,-11 + 3501: 9,-13 + 4694: -32,20 + 4741: -24,17 + 4742: -24,18 - node: color: '#52B4E996' id: BrickTileWhiteLineW decals: - 4708: -32,15 - 4914: -48,-36 - 4956: -40,-40 - 4957: -40,-39 - 4958: -40,-38 - 4959: -40,-37 - 4960: -40,-36 + 4695: -32,15 + 4901: -48,-36 + 4943: -40,-40 + 4944: -40,-39 + 4945: -40,-38 + 4946: -40,-37 + 4947: -40,-36 - node: color: '#A4610696' id: BrickTileWhiteLineW decals: - 3930: 39,28 - 3931: 39,29 - 3932: 39,27 - 3968: 35,19 - 3969: 35,20 - 4713: -32,19 + 3917: 39,28 + 3918: 39,29 + 3919: 39,27 + 3955: 35,19 + 3956: 35,20 + 4700: -32,19 - node: color: '#D381C996' id: BrickTileWhiteLineW decals: - 4336: 23,78 - 4337: 23,77 - 4338: 23,76 - 4339: 23,75 - 4340: 23,74 - 4401: 26,52 - 4402: 26,53 - 4645: 11,73 - 4712: -32,16 + 4323: 23,78 + 4324: 23,77 + 4325: 23,76 + 4326: 23,75 + 4327: 23,74 + 4388: 26,52 + 4389: 26,53 + 4632: 11,73 + 4699: -32,16 - node: color: '#D4D4D407' id: BrickTileWhiteLineW decals: - 4734: -28,17 - 4735: -28,18 + 4721: -28,17 + 4722: -28,18 - node: color: '#DE3A3A96' id: BrickTileWhiteLineW decals: - 4184: 54,-19 - 4185: 54,-18 - 4186: 54,-14 - 4187: 54,-13 - 4188: 54,-12 - 4189: 54,-11 - 4190: 54,-10 - 4191: 54,-9 - 4192: 54,-8 - 4193: 54,-7 - 4199: 39,0 - 4200: 39,-1 + 4171: 54,-19 + 4172: 54,-18 + 4173: 54,-14 + 4174: 54,-13 + 4175: 54,-12 + 4176: 54,-11 + 4177: 54,-10 + 4178: 54,-9 + 4179: 54,-8 + 4180: 54,-7 + 4186: 39,0 + 4187: 39,-1 - node: color: '#FFFFFFFF' id: BrickTileWhiteLineW decals: - 3732: -34,-14 - 3886: 22,59 - 3887: 22,60 - 4063: -20,-30 - 4069: 7,-40 - 4070: 7,-41 + 3719: -34,-14 + 3873: 22,59 + 3874: 22,60 + 4050: -20,-30 + 4056: 7,-40 + 4057: 7,-41 - node: color: '#9FED58B7' id: BushAThree decals: - 4779: -1.3686488,46.73154 + 4766: -1.3686488,46.73154 - node: color: '#9FED58B7' id: BushATwo decals: - 4776: -1.8939891,47.625587 + 4763: -1.8939891,47.625587 - node: color: '#9FED5888' id: Busha1 decals: - 4768: -3.0174823,45.91548 + 4755: -3.0174823,45.91548 - node: color: '#9FED5888' id: Busha2 decals: - 4758: -1.1858082,47.7461 - 4762: -2.0945249,48.15766 - 4763: -3.1452603,46.53989 - 4765: -1.0012178,48.11507 + 4745: -1.1858082,47.7461 + 4749: -2.0945249,48.15766 + 4750: -3.1452603,46.53989 + 4752: -1.0012178,48.11507 - node: color: '#FFFFFFC0' id: Busha2 decals: - 4464: -19.715633,-0.08040953 - 4465: -18.948898,1.7076702 - 4466: -19.360664,4.00663 + 4451: -19.715633,-0.08040953 + 4452: -18.948898,1.7076702 + 4453: -19.360664,4.00663 - node: color: '#60BC5DB1' id: Busha3 decals: - 4518: -19.190277,3.2119274 + 4505: -19.190277,3.2119274 - node: color: '#9FED5896' id: Busha3 decals: - 3231: -40.3527,-18.329292 - 3232: -43.1027,-18.48207 - 3233: -42.922146,-21.50985 - 3234: -41.408257,-22.968182 - 3235: -39.96381,-23.48207 - 3236: -39.99159,-21.829292 - 3237: -41.19992,-21.815403 - 3238: -40.86659,-18.565403 - 3239: -39.811035,-17.926516 - 3240: -41.11659,-17.75985 - 3241: -42.853085,-20.88498 + 3218: -40.3527,-18.329292 + 3219: -43.1027,-18.48207 + 3220: -42.922146,-21.50985 + 3221: -41.408257,-22.968182 + 3222: -39.96381,-23.48207 + 3223: -39.99159,-21.829292 + 3224: -41.19992,-21.815403 + 3225: -40.86659,-18.565403 + 3226: -39.811035,-17.926516 + 3227: -41.11659,-17.75985 + 3228: -42.853085,-20.88498 - node: color: '#A4DF8296' id: Busha3 decals: - 1686: -7.8109317,-1.9599552 + 1675: -7.8109317,-1.9599552 - node: color: '#9FED5888' id: Bushb1 decals: - 4761: -2.7476902,46.8379 + 4748: -2.7476902,46.8379 - node: color: '#60BC5DB1' id: Bushb2 decals: - 4517: -19.928616,2.0482564 - 4519: -19.786627,0.2601776 + 4504: -19.928616,2.0482564 + 4506: -19.786627,0.2601776 - node: color: '#60E25863' id: Bushb2 decals: - 3334: -17.64635,-37.739723 + 3321: -17.64635,-37.739723 - node: color: '#60E258BA' id: Bushb2 decals: - 3335: -16.049128,-37.545277 - 3336: -15.201906,-36.309166 - 3337: -15.313017,-37.7675 - 3338: -17.03524,-36.392498 - 3339: -17.868574,-36.281387 - 3340: -17.715796,-37.948055 - 3341: -16.118574,-38.059166 - 3342: -15.243574,-36.920277 - 3343: -16.826906,-36.850834 - 3344: -17.563017,-36.809166 - 3345: -16.701906,-37.670277 - 3346: -16.688017,-36.295277 - 3347: -15.729685,-36.670277 + 3322: -16.049128,-37.545277 + 3323: -15.201906,-36.309166 + 3324: -15.313017,-37.7675 + 3325: -17.03524,-36.392498 + 3326: -17.868574,-36.281387 + 3327: -17.715796,-37.948055 + 3328: -16.118574,-38.059166 + 3329: -15.243574,-36.920277 + 3330: -16.826906,-36.850834 + 3331: -17.563017,-36.809166 + 3332: -16.701906,-37.670277 + 3333: -16.688017,-36.295277 + 3334: -15.729685,-36.670277 - node: color: '#9FED5888' id: Bushb2 decals: - 4760: -2.932261,47.646793 - 4766: -0.98705816,45.801918 + 4747: -2.932261,47.646793 + 4753: -0.98705816,45.801918 - node: color: '#9FED5896' id: Bushb2 decals: - 3306: 78.083496,7.9973173 - 3307: 79.00016,7.900096 - 3308: 79.84738,7.8862066 + 3293: 78.083496,7.9973173 + 3294: 79.00016,7.900096 + 3295: 79.84738,7.8862066 - node: color: '#9FED58B7' id: Bushb2 decals: - 4775: -1.9508109,45.96523 - 4777: -0.9142871,46.774105 + 4762: -1.9508109,45.96523 + 4764: -0.9142871,46.774105 - node: color: '#A4DF8296' id: Bushb2 decals: - 1687: -6.2553773,-1.9043994 + 1676: -6.2553773,-1.9043994 - node: color: '#FFFFFFC0' id: Bushb2 decals: - 4467: -19.999609,3.2545013 - 4468: -19.85762,1.8637729 - 4469: -18.920502,0.8420129 - 4470: -20.184193,0.5156174 - 4471: -19.062489,3.4531765 - 4472: -20.212591,4.3046427 + 4454: -19.999609,3.2545013 + 4455: -19.85762,1.8637729 + 4456: -18.920502,0.8420129 + 4457: -20.184193,0.5156174 + 4458: -19.062489,3.4531765 + 4459: -20.212591,4.3046427 - node: color: '#60BC5DB1' id: Bushb3 decals: - 4514: -19.247074,3.6518526 - 4515: -19.871819,1.7928166 - 4516: -19.829224,0.13245726 - 4520: -18.948898,3.5241327 + 4501: -19.247074,3.6518526 + 4502: -19.871819,1.7928166 + 4503: -19.829224,0.13245726 + 4507: -18.948898,3.5241327 - node: color: '#9FED5888' id: Bushb3 decals: - 4759: -3.0174766,46.241875 - 4764: -3.1594381,47.859665 + 4746: -3.0174766,46.241875 + 4751: -3.1594381,47.859665 - node: color: '#9FED58B7' id: Bushb3 decals: - 4778: -1.666812,47.42691 + 4765: -1.666812,47.42691 - node: color: '#9FED5888' id: Bushc1 decals: - 4767: -2.8187013,45.81614 + 4754: -2.8187013,45.81614 - node: color: '#FFFFFFC0' id: Bushc1 decals: - 4462: -20.013807,2.6159015 - 4463: -20.042206,1.2393641 + 4449: -20.013807,2.6159015 + 4450: -20.042206,1.2393641 - node: color: '#9FED5896' id: Bushc3 decals: - 3242: -43.038807,-18.0765 + 3229: -43.038807,-18.0765 - node: color: '#FFFFFFFF' id: Bushg1 decals: - 4783: -16.08111,-40.251266 + 4770: -16.08111,-40.251266 - node: color: '#FFFFFFFF' id: Bushg2 decals: - 4782: -17.983753,-40.59182 + 4769: -17.983753,-40.59182 - node: color: '#FFFFFFFF' id: Bushg3 decals: - 4780: -14.888399,-39.371437 + 4767: -14.888399,-39.371437 - node: color: '#FFFFFFFF' id: Bushg4 decals: - 4781: -15.484749,-39.442383 + 4768: -15.484749,-39.442383 - node: color: '#A4DF8296' id: Bushj3 decals: - 1689: -7.4513307,-22.276455 - 1690: -9.062441,-22.720898 - 1691: -8.867998,-23.748676 - 1692: -7.340218,-23.748676 + 1678: -7.4513307,-22.276455 + 1679: -9.062441,-22.720898 + 1680: -8.867998,-23.748676 + 1681: -7.340218,-23.748676 - node: color: '#A4DF8296' id: Bushk1 decals: - 1688: -8.284664,-23.526455 - 1693: -7.340218,-22.970898 + 1677: -8.284664,-23.526455 + 1682: -7.340218,-22.970898 - node: color: '#FFFFFF6C' id: Bushk1 decals: - 4460: -18.991495,3.5808964 + 4447: -18.991495,3.5808964 - node: color: '#FFFFFFC0' id: Bushk1 decals: - 4461: -19.062489,2.7720032 + 4448: -19.062489,2.7720032 - node: color: '#60E25873' id: Bushm1 decals: - 3388: -59.97946,38.265724 - 3389: -60.02113,39.390724 - 3390: -59.99335,40.724056 - 3391: -59.91002,42.335167 - 3392: -60.090576,43.071278 - 3393: -60.10446,41.279613 - 3394: -60.04891,39.765724 + 3375: -59.97946,38.265724 + 3376: -60.02113,39.390724 + 3377: -59.99335,40.724056 + 3378: -59.91002,42.335167 + 3379: -60.090576,43.071278 + 3380: -60.10446,41.279613 + 3381: -60.04891,39.765724 - node: color: '#52B4E95A' id: CheckerNESW decals: - 4796: 73,-1 - 4797: 72,-1 - 4798: 72,0 - 4799: 73,0 - 4800: 85,-1 - 4801: 85,0 - 4802: 86,0 - 4803: 86,-1 + 4783: 73,-1 + 4784: 72,-1 + 4785: 72,0 + 4786: 73,0 + 4787: 85,-1 + 4788: 85,0 + 4789: 86,0 + 4790: 86,-1 - node: color: '#52B4E996' id: CheckerNESW decals: - 4881: -34,-43 - 4882: -34,-44 - 4917: -51,-36 - 4918: -50,-36 - 4919: -49,-36 + 4868: -34,-43 + 4869: -34,-44 + 4904: -51,-36 + 4905: -50,-36 + 4906: -49,-36 - node: color: '#52B4E996' id: CheckerNWSE decals: - 3274: -46,-35 - 3275: -46,-36 - 3276: -45,-35 - 3277: -45,-36 - 3278: -44,-35 - 3279: -44,-36 - 3280: -43,-35 - 3281: -43,-36 - 3282: -42,-35 - 3283: -42,-36 + 3261: -46,-35 + 3262: -46,-36 + 3263: -45,-35 + 3264: -45,-36 + 3265: -44,-35 + 3266: -44,-36 + 3267: -43,-35 + 3268: -43,-36 + 3269: -42,-35 + 3270: -42,-36 - node: color: '#D381C996' id: CheckerNWSE decals: - 962: 21,65 - 963: 21,64 - 964: 21,63 - 965: 22,65 - 966: 22,64 - 967: 22,63 - 968: 23,65 - 969: 23,64 - 970: 23,63 - 971: 24,65 - 972: 24,64 - 973: 24,63 + 952: 21,65 + 953: 21,64 + 954: 21,63 + 955: 22,65 + 956: 22,64 + 957: 22,63 + 958: 23,65 + 959: 23,64 + 960: 23,63 + 961: 24,65 + 962: 24,64 + 963: 24,63 - node: color: '#FED83D79' id: CheckerNWSE decals: - 4788: 85,-1 - 4789: 85,0 - 4790: 86,0 - 4791: 86,-1 - 4792: 72,-1 - 4793: 72,0 - 4794: 73,0 - 4795: 73,-1 + 4775: 85,-1 + 4776: 85,0 + 4777: 86,0 + 4778: 86,-1 + 4779: 72,-1 + 4780: 72,0 + 4781: 73,0 + 4782: 73,-1 - node: color: '#0E7F1BFF' id: Delivery decals: - 4993: 37,-12 + 4971: 37,-12 - node: color: '#1861D5FF' id: Delivery decals: - 4991: 34,-13 + 4969: 34,-13 - node: color: '#334E6DC8' id: Delivery decals: - 497: -6,-1 + 487: -6,-1 - node: color: '#79150096' id: Delivery decals: - 3297: 81,16 - 3298: 82,16 - 3299: 83,16 - 3300: 84,16 - 3301: 74,16 - 3302: 75,16 - 3303: 76,16 - 3304: 77,16 + 3284: 81,16 + 3285: 82,16 + 3286: 83,16 + 3287: 84,16 + 3288: 74,16 + 3289: 75,16 + 3290: 76,16 + 3291: 77,16 - node: color: '#951710FF' id: Delivery decals: - 4992: 34,-12 + 4970: 34,-12 - node: color: '#D58C18FF' id: Delivery decals: - 4994: 38,-12 + 4972: 38,-12 - node: color: '#EFB34196' id: Delivery decals: - 1046: 37,29 - 1207: -64,39 + 1036: 37,29 + 1197: -64,39 - node: color: '#EFB34196' id: DeliveryGreyscale decals: - 1111: 36,13 - 1112: 37,13 - 1113: 38,13 - 1118: 42,22 - 1119: 43,22 - 1122: 42,20 - 1123: 43,20 + 1101: 36,13 + 1102: 37,13 + 1103: 38,13 + 1108: 42,22 + 1109: 43,22 + 1112: 42,20 + 1113: 43,20 - node: color: '#52B4E996' id: DiagonalCheckerBOverlay decals: - 4043: -20,-29 - 4044: -20,-30 - 4045: -20,-31 - 4046: -19,-29 - 4047: -19,-30 - 4048: -19,-31 - 4049: -18,-29 - 4050: -18,-30 - 4051: -18,-31 - 4052: -17,-29 - 4053: -17,-30 - 4054: -17,-31 + 4030: -20,-29 + 4031: -20,-30 + 4032: -20,-31 + 4033: -19,-29 + 4034: -19,-30 + 4035: -19,-31 + 4036: -18,-29 + 4037: -18,-30 + 4038: -18,-31 + 4039: -17,-29 + 4040: -17,-30 + 4041: -17,-31 - node: color: '#D381C996' id: DiagonalCheckerBOverlay decals: - 3838: 22,58 - 3839: 22,59 - 3840: 22,61 - 3841: 22,60 - 3842: 23,61 - 3843: 23,60 - 3844: 23,59 - 3845: 23,58 - 3846: 24,58 - 3847: 24,59 - 3848: 24,60 - 3849: 24,61 - 3850: 25,61 - 3851: 25,60 - 3852: 25,59 - 3853: 25,58 - 3854: 26,58 - 3855: 26,59 - 3856: 26,60 - 3857: 26,61 - 3858: 27,61 - 3859: 27,60 - 3860: 27,59 - 3861: 27,58 - 3862: 28,58 - 3863: 28,59 - 3864: 28,60 - 3865: 28,61 - 3866: 29,61 - 3867: 29,60 - 3868: 29,59 - 3869: 29,58 + 3825: 22,58 + 3826: 22,59 + 3827: 22,61 + 3828: 22,60 + 3829: 23,61 + 3830: 23,60 + 3831: 23,59 + 3832: 23,58 + 3833: 24,58 + 3834: 24,59 + 3835: 24,60 + 3836: 24,61 + 3837: 25,61 + 3838: 25,60 + 3839: 25,59 + 3840: 25,58 + 3841: 26,58 + 3842: 26,59 + 3843: 26,60 + 3844: 26,61 + 3845: 27,61 + 3846: 27,60 + 3847: 27,59 + 3848: 27,58 + 3849: 28,58 + 3850: 28,59 + 3851: 28,60 + 3852: 28,61 + 3853: 29,61 + 3854: 29,60 + 3855: 29,59 + 3856: 29,58 - node: color: '#FFFFFFFF' id: DiagonalCheckerBOverlay decals: - 3716: -34,-14 - 3717: -33,-14 - 3718: -33,-13 - 3719: -29,-14 - 3720: -30,-14 - 3721: -31,-14 - 3722: -32,-14 - 3723: -32,-13 - 3724: -32,-12 - 3725: -33,-12 - 3726: -31,-12 - 3727: -31,-13 - 3728: -30,-12 - 3729: -30,-13 - 3730: -29,-13 - 3731: -29,-12 - 4429: -34,-13 - 4430: -34,-12 - 4431: -35,-12 - 4432: -35,-13 - 4433: -36,-13 - 4434: -36,-12 - 4435: -37,-13 - 4436: -37,-12 + 3703: -34,-14 + 3704: -33,-14 + 3705: -33,-13 + 3706: -29,-14 + 3707: -30,-14 + 3708: -31,-14 + 3709: -32,-14 + 3710: -32,-13 + 3711: -32,-12 + 3712: -33,-12 + 3713: -31,-12 + 3714: -31,-13 + 3715: -30,-12 + 3716: -30,-13 + 3717: -29,-13 + 3718: -29,-12 + 4416: -34,-13 + 4417: -34,-12 + 4418: -35,-12 + 4419: -35,-13 + 4420: -36,-13 + 4421: -36,-12 + 4422: -37,-13 + 4423: -37,-12 - node: cleanable: True color: '#8354328B' id: Dirt decals: - 4572: -38,-10 - 4573: -38,-13 - 4574: -32,-12 - 4575: -34,-13 - 4576: -34,-12 - 4577: -35,-12 - 4578: -36,-12 - 4579: -37,-13 - 4580: -35,-13 - 4581: -34,-13 - 4582: -33,-14 - 4583: -32,-14 - 4584: -31,-14 - 4585: -31,-12 - 4586: -30,-12 - 4587: -29,-14 - 4588: -29,-13 - 4589: -29,-12 - 4590: -31,-12 - 4591: -31,-14 - 4592: -29,-14 - 4593: -32,-16 - 4594: -33,-16 - 4595: -34,-16 - 4596: -37,-10 - 4597: -28,-12 - 4598: -32,-8 - 4599: -34,-9 - 4600: -31,-8 - 4601: -30,-7 - 4602: -33,-8 - 4603: -33,-8 - 4604: -34,-7 + 4559: -38,-10 + 4560: -38,-13 + 4561: -32,-12 + 4562: -34,-13 + 4563: -34,-12 + 4564: -35,-12 + 4565: -36,-12 + 4566: -37,-13 + 4567: -35,-13 + 4568: -34,-13 + 4569: -33,-14 + 4570: -32,-14 + 4571: -31,-14 + 4572: -31,-12 + 4573: -30,-12 + 4574: -29,-14 + 4575: -29,-13 + 4576: -29,-12 + 4577: -31,-12 + 4578: -31,-14 + 4579: -29,-14 + 4580: -32,-16 + 4581: -33,-16 + 4582: -34,-16 + 4583: -37,-10 + 4584: -28,-12 + 4585: -32,-8 + 4586: -34,-9 + 4587: -31,-8 + 4588: -30,-7 + 4589: -33,-8 + 4590: -33,-8 + 4591: -34,-7 - node: color: '#A4610696' id: Dirt decals: - 3395: -3,-35 - 3396: 1,-36 - 3397: -1,-36 - 3398: 2,-35 - 3399: 4,-36 - 3400: 8,-36 - 3401: 10,-35 - 3402: 11,-36 - 3403: 13,-36 - 3404: 15,-35 - 3405: 17,-36 - 3406: 7,-35 - 3407: 6,-35 - 3408: 4,-35 - 3409: 6,-36 - 3410: 2,-36 - 3411: 1,-35 - 3412: 3,-35 - 3413: 9,-36 - 3414: 11,-36 - 3415: 14,-36 + 3382: -3,-35 + 3383: 1,-36 + 3384: -1,-36 + 3385: 2,-35 + 3386: 4,-36 + 3387: 8,-36 + 3388: 10,-35 + 3389: 11,-36 + 3390: 13,-36 + 3391: 15,-35 + 3392: 17,-36 + 3393: 7,-35 + 3394: 6,-35 + 3395: 4,-35 + 3396: 6,-36 + 3397: 2,-36 + 3398: 1,-35 + 3399: 3,-35 + 3400: 9,-36 + 3401: 11,-36 + 3402: 14,-36 - node: cleanable: True color: '#A4610696' id: Dirt decals: - 1707: -5,50 - 1708: -6,46 - 1709: -7,44 - 1710: -4,48 - 1711: -1,50 - 1712: 2,49 - 1713: 5,49 - 1714: 6,51 - 1715: 7,49 - 1716: 9,50 - 1717: 13,49 - 1718: 16,51 - 1719: 19,49 - 1720: 23,50 - 1721: 23,49 - 1722: 29,51 - 1723: 31,51 - 1724: 32,49 - 1725: 33,47 - 1726: 31,48 - 1727: 34,53 - 1728: 33,49 - 1729: 30,49 - 1730: 32,42 - 1731: 33,40 - 1732: 33,36 - 1733: 32,34 - 1734: 32,32 - 1735: 33,33 - 1736: 32,29 - 1737: 31,27 - 1738: 32,28 - 1739: 33,24 - 1740: 32,22 - 1741: 33,23 - 1742: 31,21 - 1743: 33,19 - 1744: 32,17 - 1745: 31,16 - 1746: 32,15 - 1747: 33,14 - 1748: 31,12 - 1749: 31,11 - 1750: 33,9 - 1751: 32,8 - 1752: 31,7 - 1753: 33,4 - 1754: 30,3 - 1755: 30,2 - 1756: 30,2 - 1757: 28,1 - 1758: 28,0 - 1759: 29,0 - 1760: 27,-1 - 1761: 27,-2 - 1762: 28,-4 - 1763: 26,-4 - 1764: 25,-4 - 1765: 24,-5 - 1766: 22,-5 - 1767: 21,-4 - 1768: 20,-3 - 1769: 18,-4 - 1770: 12,-4 - 1771: 9,-4 - 1772: 7,-4 - 1773: 3,-4 - 1774: 0,-4 - 1775: 1,-4 - 1776: -5,-4 - 1777: -6,-5 - 1778: -7,-5 - 1779: -6,-4 - 1780: -10,-4 - 1781: -12,-5 - 1782: -14,-5 - 1783: -14,-4 - 1784: -16,-4 - 1785: -17,-5 - 1786: -18,-5 - 1787: -23,-5 - 1788: -24,-5 - 1789: -32,-4 - 1790: -38,-4 - 1791: -39,-4 - 1792: -40,-5 - 1793: -42,-5 - 1794: -42,-6 - 1795: -42,-7 - 1796: -42,-10 - 1797: -42,-12 - 1798: -42,-14 - 1799: -40,-16 - 1800: -42,-17 - 1801: -38,-7 - 1802: -38,-8 - 1803: -37,-7 - 1804: -33,-7 - 1805: -26,-4 - 1806: -24,-1 - 1807: -23,0 - 1808: -23,2 - 1809: -24,3 - 1810: -23,5 - 1811: -23,6 - 1812: -24,6 - 1813: -23,7 - 1814: -23,10 - 1815: -30,5 - 1816: -31,1 - 1817: -31,4 - 1818: -26,1 - 1819: -26,2 - 1820: -22,8 - 1821: -24,9 - 1822: -22,10 - 1823: -24,8 - 1824: -23,9 - 1825: -22,13 - 1826: -24,15 - 1827: -23,16 - 1828: -22,17 - 1829: -25,18 - 1830: -23,18 - 1831: -23,19 - 1832: -25,22 - 1833: -23,23 - 1834: -23,24 - 1835: -24,25 - 1836: -22,26 - 1837: -23,27 - 1838: -24,28 - 1839: -22,30 - 1840: -23,30 - 1841: -24,31 - 1842: -26,29 - 1843: -27,30 - 1844: -29,30 - 1845: -27,29 - 1846: -31,29 - 1847: -32,30 - 1848: -34,29 - 1849: -36,29 - 1850: -37,30 - 1851: -39,29 - 1852: -40,29 - 1853: -42,30 - 1854: -43,30 - 1855: -45,29 - 1856: -46,30 - 1857: -47,30 - 1858: -46,29 - 1859: -51,30 - 1860: -52,31 - 1861: -53,29 - 1862: -54,30 - 1863: -55,31 - 1864: -57,29 - 1865: -58,30 - 1866: -57,32 - 1867: -58,34 - 1868: -56,36 - 1869: -57,39 - 1870: -56,40 - 1871: -57,45 - 1872: -57,46 - 1873: -59,48 - 1874: -57,49 - 1875: -59,50 - 1876: -58,49 - 1877: -59,47 - 1878: -58,45 - 1879: -62,49 - 1880: -64,49 - 1881: -64,49 - 1882: -64,48 - 1883: -62,48 - 1884: -61,54 - 1885: -59,54 - 1886: -59,54 - 1887: -59,53 - 1888: -62,45 - 1889: -63,43 - 1890: -63,40 - 1891: -63,40 - 1892: -62,36 - 1893: -61,35 - 1894: -56,35 - 1895: -45,29 - 1896: -40,30 - 1897: -43,26 - 1898: -41,26 - 1899: -40,26 - 1900: -38,26 - 1901: -37,26 - 1902: -40,27 - 1903: -20,34 - 1904: -20,35 - 1905: -21,41 - 1906: -20,43 - 1907: -20,44 - 1908: -21,46 - 1909: -20,47 - 1910: -20,49 - 1911: -21,50 - 1912: -21,51 - 1913: -20,53 - 1914: -20,54 - 1915: -24,53 - 1916: -26,53 - 1917: -27,53 - 1918: -28,54 - 1919: -29,54 - 1920: -28,56 - 1921: -28,57 - 1922: -28,58 - 1923: -27,59 - 1924: -25,59 - 1925: -24,58 - 1926: -24,56 - 1927: -21,55 - 1928: -20,52 - 1929: -19,51 - 1930: -20,42 - 1931: -20,40 - 1932: -16,44 - 1933: -14,43 - 1934: -13,44 - 1935: -11,45 - 1936: -10,44 - 1937: -12,48 - 1938: -13,47 - 1939: -14,48 - 1940: -11,47 - 1941: -10,48 - 1942: -10,52 - 1943: -11,53 - 1944: -14,53 - 1945: -15,53 - 1946: -17,53 - 1947: -17,51 - 1948: -10,39 - 1949: -11,38 - 1950: -14,38 - 1951: -14,37 - 1952: -15,36 - 1953: -16,38 - 1954: -16,40 - 1955: -14,41 - 1956: -11,39 - 1957: -17,39 - 1958: -8,44 - 1959: -8,45 - 1960: -7,42 - 1961: -6,41 - 1962: -5,46 - 1963: -6,49 - 1964: -7,49 - 1965: 2,44 - 1966: -6,29 - 1967: -4,31 - 1968: -2,31 - 1969: 0,30 - 1970: 2,30 - 1971: 4,31 - 1972: 5,31 - 1973: 7,30 - 1974: 9,30 - 1975: 10,31 - 1976: 11,31 - 1977: 10,30 - 1978: 14,31 - 1979: 15,31 - 1980: 17,30 - 1981: 18,31 - 1982: 22,23 - 1983: 23,23 - 1984: 23,22 - 1985: 22,22 - 1986: 21,23 - 1987: 21,23 - 1988: 20,24 + 1696: -5,50 + 1697: -6,46 + 1698: -7,44 + 1699: -4,48 + 1700: -1,50 + 1701: 2,49 + 1702: 5,49 + 1703: 6,51 + 1704: 7,49 + 1705: 9,50 + 1706: 13,49 + 1707: 16,51 + 1708: 19,49 + 1709: 23,50 + 1710: 23,49 + 1711: 29,51 + 1712: 31,51 + 1713: 32,49 + 1714: 33,47 + 1715: 31,48 + 1716: 34,53 + 1717: 33,49 + 1718: 30,49 + 1719: 32,42 + 1720: 33,40 + 1721: 33,36 + 1722: 32,34 + 1723: 32,32 + 1724: 33,33 + 1725: 32,29 + 1726: 31,27 + 1727: 32,28 + 1728: 33,24 + 1729: 32,22 + 1730: 33,23 + 1731: 31,21 + 1732: 33,19 + 1733: 32,17 + 1734: 31,16 + 1735: 32,15 + 1736: 33,14 + 1737: 31,12 + 1738: 31,11 + 1739: 33,9 + 1740: 32,8 + 1741: 31,7 + 1742: 33,4 + 1743: 30,3 + 1744: 30,2 + 1745: 30,2 + 1746: 28,1 + 1747: 28,0 + 1748: 29,0 + 1749: 27,-1 + 1750: 27,-2 + 1751: 28,-4 + 1752: 26,-4 + 1753: 25,-4 + 1754: 24,-5 + 1755: 22,-5 + 1756: 21,-4 + 1757: 20,-3 + 1758: 18,-4 + 1759: 12,-4 + 1760: 9,-4 + 1761: 7,-4 + 1762: 3,-4 + 1763: 0,-4 + 1764: 1,-4 + 1765: -5,-4 + 1766: -6,-5 + 1767: -7,-5 + 1768: -6,-4 + 1769: -10,-4 + 1770: -12,-5 + 1771: -14,-5 + 1772: -14,-4 + 1773: -16,-4 + 1774: -17,-5 + 1775: -18,-5 + 1776: -23,-5 + 1777: -24,-5 + 1778: -32,-4 + 1779: -38,-4 + 1780: -39,-4 + 1781: -40,-5 + 1782: -42,-5 + 1783: -42,-6 + 1784: -42,-7 + 1785: -42,-10 + 1786: -42,-12 + 1787: -42,-14 + 1788: -40,-16 + 1789: -42,-17 + 1790: -38,-7 + 1791: -38,-8 + 1792: -37,-7 + 1793: -33,-7 + 1794: -26,-4 + 1795: -24,-1 + 1796: -23,0 + 1797: -23,2 + 1798: -24,3 + 1799: -23,5 + 1800: -23,6 + 1801: -24,6 + 1802: -23,7 + 1803: -23,10 + 1804: -30,5 + 1805: -31,1 + 1806: -31,4 + 1807: -26,1 + 1808: -26,2 + 1809: -22,8 + 1810: -24,9 + 1811: -22,10 + 1812: -24,8 + 1813: -23,9 + 1814: -22,13 + 1815: -24,15 + 1816: -23,16 + 1817: -22,17 + 1818: -25,18 + 1819: -23,18 + 1820: -23,19 + 1821: -25,22 + 1822: -23,23 + 1823: -23,24 + 1824: -24,25 + 1825: -22,26 + 1826: -23,27 + 1827: -24,28 + 1828: -22,30 + 1829: -23,30 + 1830: -24,31 + 1831: -26,29 + 1832: -27,30 + 1833: -29,30 + 1834: -27,29 + 1835: -31,29 + 1836: -32,30 + 1837: -34,29 + 1838: -36,29 + 1839: -37,30 + 1840: -39,29 + 1841: -40,29 + 1842: -42,30 + 1843: -43,30 + 1844: -45,29 + 1845: -46,30 + 1846: -47,30 + 1847: -46,29 + 1848: -51,30 + 1849: -52,31 + 1850: -53,29 + 1851: -54,30 + 1852: -55,31 + 1853: -57,29 + 1854: -58,30 + 1855: -57,32 + 1856: -58,34 + 1857: -56,36 + 1858: -57,39 + 1859: -56,40 + 1860: -57,45 + 1861: -57,46 + 1862: -59,48 + 1863: -57,49 + 1864: -59,50 + 1865: -58,49 + 1866: -59,47 + 1867: -58,45 + 1868: -62,49 + 1869: -64,49 + 1870: -64,49 + 1871: -64,48 + 1872: -62,48 + 1873: -61,54 + 1874: -59,54 + 1875: -59,54 + 1876: -59,53 + 1877: -62,45 + 1878: -63,43 + 1879: -63,40 + 1880: -63,40 + 1881: -62,36 + 1882: -61,35 + 1883: -56,35 + 1884: -45,29 + 1885: -40,30 + 1886: -43,26 + 1887: -41,26 + 1888: -40,26 + 1889: -38,26 + 1890: -37,26 + 1891: -40,27 + 1892: -20,34 + 1893: -20,35 + 1894: -21,41 + 1895: -20,43 + 1896: -20,44 + 1897: -21,46 + 1898: -20,47 + 1899: -20,49 + 1900: -21,50 + 1901: -21,51 + 1902: -20,53 + 1903: -20,54 + 1904: -24,53 + 1905: -26,53 + 1906: -27,53 + 1907: -28,54 + 1908: -29,54 + 1909: -28,56 + 1910: -28,57 + 1911: -28,58 + 1912: -27,59 + 1913: -25,59 + 1914: -24,58 + 1915: -24,56 + 1916: -21,55 + 1917: -20,52 + 1918: -19,51 + 1919: -20,42 + 1920: -20,40 + 1921: -16,44 + 1922: -14,43 + 1923: -13,44 + 1924: -11,45 + 1925: -10,44 + 1926: -12,48 + 1927: -13,47 + 1928: -14,48 + 1929: -11,47 + 1930: -10,48 + 1931: -10,52 + 1932: -11,53 + 1933: -14,53 + 1934: -15,53 + 1935: -17,53 + 1936: -17,51 + 1937: -10,39 + 1938: -11,38 + 1939: -14,38 + 1940: -14,37 + 1941: -15,36 + 1942: -16,38 + 1943: -16,40 + 1944: -14,41 + 1945: -11,39 + 1946: -17,39 + 1947: -8,44 + 1948: -8,45 + 1949: -7,42 + 1950: -6,41 + 1951: -5,46 + 1952: -6,49 + 1953: -7,49 + 1954: 2,44 + 1955: -6,29 + 1956: -4,31 + 1957: -2,31 + 1958: 0,30 + 1959: 2,30 + 1960: 4,31 + 1961: 5,31 + 1962: 7,30 + 1963: 9,30 + 1964: 10,31 + 1965: 11,31 + 1966: 10,30 + 1967: 14,31 + 1968: 15,31 + 1969: 17,30 + 1970: 18,31 + 1971: 22,23 + 1972: 23,23 + 1973: 23,22 + 1974: 22,22 + 1975: 21,23 + 1976: 21,23 + 1977: 20,24 + 1978: 20,23 + 1979: 21,21 + 1980: 20,20 + 1981: 20,19 + 1982: 22,19 + 1983: 24,19 + 1984: 27,19 + 1985: 29,19 + 1986: 29,19 + 1987: 24,19 + 1988: 22,21 1989: 20,23 - 1990: 21,21 - 1991: 20,20 - 1992: 20,19 - 1993: 22,19 - 1994: 24,19 - 1995: 27,19 - 1996: 29,19 - 1997: 29,19 - 1998: 24,19 - 1999: 22,21 - 2000: 20,23 - 2001: 20,26 - 2002: 20,29 - 2003: 20,31 - 2004: 23,31 - 2005: 27,31 - 2006: 29,31 - 2007: 29,30 - 2008: 27,30 - 2009: 24,30 - 2010: 21,31 - 2011: 20,33 - 2012: 21,35 - 2013: 22,35 - 2014: 26,37 - 2015: 25,35 - 2016: 25,36 - 2017: 26,34 - 2018: 27,34 - 2019: 28,36 - 2020: 28,37 - 2021: 27,34 - 2022: 28,35 - 2023: 26,34 - 2024: 25,33 - 2025: 24,34 - 2026: 24,36 - 2027: 25,38 - 2028: 27,38 - 2029: 29,37 - 2030: 29,35 - 2031: 20,38 - 2032: 21,40 - 2033: 22,41 - 2034: 23,40 - 2035: 21,41 - 2036: 21,43 - 2037: 21,43 - 2038: 20,45 - 2039: 17,45 - 2040: 20,46 - 2041: 14,45 - 2042: 12,45 - 2043: 11,41 - 2044: 10,41 - 2045: 8,41 - 2046: 6,41 - 2047: 5,39 - 2048: 5,38 - 2049: 4,43 - 2050: 5,45 - 2051: 5,47 - 2052: 6,47 - 2053: 9,47 - 2054: 25,47 - 2055: 25,46 - 2056: 26,45 - 2057: 26,45 - 2058: 22,8 - 2059: 21,8 - 2060: 22,9 - 2061: 21,10 - 2062: 20,10 - 2063: 21,13 - 2064: 20,14 - 2065: 21,15 - 2066: 19,14 - 2067: 18,16 - 2068: 18,16 - 2069: 17,15 - 2070: -4,11 - 2071: -4,10 - 2072: -5,10 - 2073: -6,10 - 2074: -7,10 - 2075: -7,8 - 2076: -7,7 - 2077: -9,8 - 2078: -6,12 - 2079: -6,16 - 2080: 29,7 - 2081: 29,8 - 2082: 29,9 - 2083: 28,10 - 2084: 26,9 - 2085: 25,8 - 2086: 25,7 - 2087: 29,8 - 2088: 27,8 - 2089: 47,29 - 2090: 45,29 - 2091: 43,29 - 2092: 42,29 - 2093: 42,28 - 2094: 44,28 - 2095: 46,27 - 2096: 46,27 - 2097: 44,27 - 2098: 43,27 - 2099: 45,26 - 2100: 44,25 - 2101: 43,25 - 2102: 44,24 - 2103: 41,23 - 2104: 43,22 - 2105: 43,22 - 2106: 42,21 - 2107: 43,20 - 2108: 42,19 - 2109: 43,19 - 2110: 41,18 - 2111: 43,17 - 2112: 42,17 - 2113: 43,20 - 2114: 42,21 - 2115: 43,21 - 2116: 45,20 - 2117: 43,20 - 2118: 45,21 - 2119: 46,21 - 2120: 45,22 - 2121: 44,22 - 2122: 44,21 - 2123: 45,21 - 2124: 44,23 - 2125: 44,23 - 2126: 47,23 - 2127: 48,23 - 2128: 48,23 - 2129: 48,23 - 2130: 47,23 - 2131: 48,22 - 2132: 48,21 - 2133: 47,21 - 2134: 47,21 - 2135: 47,21 - 2136: 48,21 - 2137: 45,22 - 2138: 45,23 - 2139: 44,23 - 2140: 45,24 - 2141: 43,18 - 2142: 41,17 - 2143: 42,16 - 2144: 43,15 - 2145: 43,15 - 2146: 42,14 - 2147: 41,13 - 2148: 42,12 - 2149: 43,14 - 2150: 43,13 - 2151: 39,14 - 2152: 39,12 - 2153: 37,12 - 2154: 36,13 - 2155: 35,14 - 2156: 34,13 - 2157: 38,33 - 2158: 39,33 - 2159: 41,33 - 2160: 42,33 - 2161: 44,33 - 2162: 45,36 - 2163: 46,36 - 2164: 46,35 - 2165: 46,33 - 2166: 44,32 - 2167: 43,33 - 2168: 40,33 - 2169: 43,34 - 2170: 45,37 - 2171: 46,36 - 2172: 47,33 - 2173: 47,33 - 2174: 39,33 - 2175: 43,33 - 2176: 37,33 - 2177: 35,33 - 2178: 34,34 - 2179: 32,37 - 2180: 32,42 - 2181: 33,44 - 2182: 32,47 - 2183: 33,48 - 2184: 33,50 - 2185: 13,55 - 2186: 14,55 - 2187: 15,55 - 2188: 15,54 - 2189: 15,54 - 2190: 14,54 - 2191: 13,54 - 2192: 14,53 - 2193: 15,53 - 2194: 14,53 - 2195: 13,53 - 2196: 16,53 - 2197: 16,53 - 2198: 16,55 - 2199: 16,56 - 2200: 14,56 - 2201: 14,56 - 2202: 16,57 - 2203: 14,57 - 2204: 13,57 - 2205: 12,57 - 2206: 11,55 - 2207: 12,54 - 2208: 11,53 - 2209: 19,60 - 2210: 19,57 - 2211: 18,60 - 2212: 18,64 - 2213: 20,65 - 2214: 22,66 - 2215: 21,66 - 2216: 22,64 - 2217: 21,64 - 2218: 23,65 - 2219: 24,66 - 2220: 23,67 - 2221: 23,69 - 2222: 24,71 - 2223: 26,71 - 2224: 26,69 - 2225: 27,68 - 2226: 29,69 - 2227: 11,72 - 2228: 20,74 - 2229: 20,73 - 2230: 23,47 - 2231: 23,47 - 2232: 23,47 - 2233: 23,46 - 2234: 23,46 - 2235: 22,47 - 2236: 35,57 - 2237: 36,56 - 2238: 36,56 - 2239: 37,56 - 2240: 36,56 - 2241: 36,55 - 2242: 36,54 - 2243: 36,53 - 2244: 38,53 - 2245: 40,53 - 2246: 40,55 - 2247: 40,56 - 2248: 41,57 - 2249: 41,56 - 2250: 39,56 - 2251: 40,55 - 2252: 41,53 - 2253: 41,53 - 2254: 43,54 - 2255: 43,55 - 2256: 43,57 - 2257: 43,55 - 2258: 43,53 - 2259: 43,52 - 2260: 43,50 - 2261: 45,50 - 2262: 46,50 - 2263: 47,50 - 2264: 47,49 - 2265: 47,47 - 2266: 47,46 - 2267: 47,46 - 2268: 46,44 - 2269: 46,44 - 2270: 46,45 - 2271: 46,46 - 2272: 46,47 - 2273: 40,50 - 2274: 40,48 - 2275: 40,46 - 2276: 39,45 - 2277: 37,46 - 2278: 35,46 - 2279: 40,50 - 2280: 40,52 - 2281: 40,51 - 2282: 40,50 - 2283: 40,43 - 2284: 40,43 - 2285: 40,44 - 2286: 39,44 - 2287: 39,44 - 2288: 39,43 - 2289: 39,42 - 2290: 39,40 - 2291: 39,39 - 2292: 40,39 - 2293: 43,39 - 2294: 45,39 - 2295: 46,39 - 2296: 47,39 - 2297: 47,40 - 2298: 46,41 - 2299: 47,42 - 2300: 47,44 - 2301: 47,46 - 2302: 47,48 - 2303: 43,44 - 2304: 44,44 - 2305: 42,43 - 2306: 42,42 - 2307: 43,41 - 2308: 44,41 - 2309: 44,43 - 2310: 43,45 - 2311: 43,47 - 2312: 44,48 - 2313: 44,48 - 2314: 49,33 - 2315: 49,34 - 2316: 50,35 - 2317: 50,36 - 2318: 50,36 - 2319: 35,7 - 2320: 35,8 - 2321: 36,8 - 2322: 37,8 - 2323: 40,8 - 2324: 40,8 - 2325: 40,7 - 2326: 38,7 - 2327: 38,7 - 2328: 41,9 - 2329: 44,9 - 2330: 42,9 - 2331: 46,9 - 2332: 47,9 - 2333: 49,9 - 2334: 49,9 - 2335: 50,9 - 2336: 38,4 - 2337: 35,4 - 2338: 39,2 - 2339: 43,3 - 2340: 45,3 - 2341: 44,0 - 2342: 44,-1 - 2343: 47,-1 - 2344: 44,-1 - 2345: 46,-1 - 2346: 46,-1 - 2347: 45,-1 - 2348: 46,0 - 2349: 45,0 - 2350: 46,3 - 2351: 47,3 - 2352: 45,3 - 2353: 46,4 - 2354: 49,3 - 2355: 51,3 - 2356: 48,2 - 2357: 53,3 - 2358: 55,3 - 2359: 57,2 - 2360: 59,3 - 2361: 61,2 - 2362: 63,4 - 2363: 64,2 - 2364: 65,3 - 2365: 66,3 - 2366: 69,3 - 2367: 69,3 - 2368: 72,4 - 2369: 73,3 - 2370: 75,3 - 2371: 76,3 - 2372: 78,3 - 2373: 79,3 - 2374: 81,3 - 2375: 83,4 - 2376: 84,2 - 2377: 85,3 - 2378: 86,4 - 2379: 83,7 - 2380: 80,7 - 2381: 78,6 - 2382: 76,8 - 2383: 77,9 - 2384: 80,9 - 2385: 83,9 - 2386: 82,12 - 2387: 82,13 - 2388: 83,14 - 2389: 83,14 - 2390: 83,13 - 2391: 75,13 - 2392: 75,15 - 2393: 76,15 - 2394: 76,14 - 2395: 76,9 - 2396: 76,6 - 2397: 77,6 - 2398: 83,6 - 2399: 83,8 - 2400: 84,3 - 2401: 67,2 - 2402: 66,4 - 2403: 61,2 - 2404: 58,4 - 2405: 57,3 - 2406: 56,2 - 2407: 52,4 - 2408: 51,3 - 2409: 53,-13 - 2410: 60,-20 - 2411: 62,-21 - 2412: 61,-22 - 2413: 60,-19 - 2415: 41,-16 - 2416: 38,-16 - 2417: 37,-16 - 2418: 37,-19 - 2419: 37,-20 - 2420: 37,-20 - 2421: 36,-20 - 2422: 37,-20 - 2423: 37,-20 - 2424: 40,-19 - 2425: 40,-19 - 2426: 39,-19 - 2427: 40,-20 - 2428: 43,-19 - 2429: 43,-20 - 2430: 42,-20 - 2431: 45,-19 - 2432: 45,-20 - 2433: 45,-20 - 2434: 46,-20 - 2435: 38,-16 - 2436: 36,-14 - 2437: 35,-13 - 2438: 35,-11 - 2439: 34,-9 - 2440: 35,-7 - 2441: 36,-6 - 2442: 36,-4 - 2443: 36,-3 - 2444: 38,-5 - 2445: 40,-3 - 2446: 39,-3 - 2447: 41,-3 - 2448: 39,2 - 2449: 41,2 - 2450: 31,2 - 2451: 30,3 - 2452: 28,1 - 2453: 28,3 - 2454: 29,0 - 2455: 23,-7 - 2456: 28,-7 - 2457: 7,-16 - 2458: 7,-16 - 2459: 7,-17 - 2460: -9,-2 - 2461: -9,-1 - 2462: -8,-1 - 2463: -7,-1 - 2464: -6,-1 - 2465: -5,-2 - 2466: -5,-6 - 2467: -5,-15 - 2468: -4,-15 - 2469: -6,-19 - 2470: -5,-17 - 2471: -6,-20 - 2472: -4,-22 - 2473: -4,-24 - 2474: -5,-26 - 2475: -8,-26 - 2476: -9,-26 - 2477: -10,-25 - 2478: -11,-27 - 2479: -10,-28 - 2480: -7,-28 - 2481: -13,-25 - 2482: -14,-26 - 2483: -17,-26 - 2484: -19,-25 - 2485: -20,-27 - 2486: -22,-26 - 2487: -25,-26 - 2488: -26,-29 - 2489: -27,-30 - 2490: -26,-31 - 2491: -27,-31 - 2492: -27,-33 - 2493: -25,-34 - 2494: -26,-35 - 2495: -24,-35 - 2496: -23,-35 - 2497: -23,-34 - 2498: -27,-26 - 2499: -28,-26 - 2500: -31,-28 - 2501: -33,-28 - 2502: -37,-28 - 2503: -31,-28 - 2504: -31,-27 - 2505: -37,-28 - 2506: -31,-31 - 2507: -33,-32 - 2508: -34,-33 - 2509: -36,-32 - 2510: -37,-32 - 2511: -39,-33 - 2512: -37,-32 - 2513: -41,-31 + 1990: 20,26 + 1991: 20,29 + 1992: 20,31 + 1993: 23,31 + 1994: 27,31 + 1995: 29,31 + 1996: 29,30 + 1997: 27,30 + 1998: 24,30 + 1999: 21,31 + 2000: 20,33 + 2001: 21,35 + 2002: 22,35 + 2003: 26,37 + 2004: 25,35 + 2005: 25,36 + 2006: 26,34 + 2007: 27,34 + 2008: 28,36 + 2009: 28,37 + 2010: 27,34 + 2011: 28,35 + 2012: 26,34 + 2013: 25,33 + 2014: 24,34 + 2015: 24,36 + 2016: 25,38 + 2017: 27,38 + 2018: 29,37 + 2019: 29,35 + 2020: 20,38 + 2021: 21,40 + 2022: 22,41 + 2023: 23,40 + 2024: 21,41 + 2025: 21,43 + 2026: 21,43 + 2027: 20,45 + 2028: 17,45 + 2029: 20,46 + 2030: 14,45 + 2031: 12,45 + 2032: 11,41 + 2033: 10,41 + 2034: 8,41 + 2035: 6,41 + 2036: 5,39 + 2037: 5,38 + 2038: 4,43 + 2039: 5,45 + 2040: 5,47 + 2041: 6,47 + 2042: 9,47 + 2043: 25,47 + 2044: 25,46 + 2045: 26,45 + 2046: 26,45 + 2047: 22,8 + 2048: 21,8 + 2049: 22,9 + 2050: 21,10 + 2051: 20,10 + 2052: 21,13 + 2053: 20,14 + 2054: 21,15 + 2055: 19,14 + 2056: 18,16 + 2057: 18,16 + 2058: 17,15 + 2059: -4,11 + 2060: -4,10 + 2061: -5,10 + 2062: -6,10 + 2063: -7,10 + 2064: -7,8 + 2065: -7,7 + 2066: -9,8 + 2067: -6,12 + 2068: -6,16 + 2069: 29,7 + 2070: 29,8 + 2071: 29,9 + 2072: 28,10 + 2073: 26,9 + 2074: 25,8 + 2075: 25,7 + 2076: 29,8 + 2077: 27,8 + 2078: 47,29 + 2079: 45,29 + 2080: 43,29 + 2081: 42,29 + 2082: 42,28 + 2083: 44,28 + 2084: 46,27 + 2085: 46,27 + 2086: 44,27 + 2087: 43,27 + 2088: 45,26 + 2089: 44,25 + 2090: 43,25 + 2091: 44,24 + 2092: 41,23 + 2093: 43,22 + 2094: 43,22 + 2095: 42,21 + 2096: 43,20 + 2097: 42,19 + 2098: 43,19 + 2099: 41,18 + 2100: 43,17 + 2101: 42,17 + 2102: 43,20 + 2103: 42,21 + 2104: 43,21 + 2105: 45,20 + 2106: 43,20 + 2107: 45,21 + 2108: 46,21 + 2109: 45,22 + 2110: 44,22 + 2111: 44,21 + 2112: 45,21 + 2113: 44,23 + 2114: 44,23 + 2115: 47,23 + 2116: 48,23 + 2117: 48,23 + 2118: 48,23 + 2119: 47,23 + 2120: 48,22 + 2121: 48,21 + 2122: 47,21 + 2123: 47,21 + 2124: 47,21 + 2125: 48,21 + 2126: 45,22 + 2127: 45,23 + 2128: 44,23 + 2129: 45,24 + 2130: 43,18 + 2131: 41,17 + 2132: 42,16 + 2133: 43,15 + 2134: 43,15 + 2135: 42,14 + 2136: 41,13 + 2137: 42,12 + 2138: 43,14 + 2139: 43,13 + 2140: 39,14 + 2141: 39,12 + 2142: 37,12 + 2143: 36,13 + 2144: 35,14 + 2145: 34,13 + 2146: 38,33 + 2147: 39,33 + 2148: 41,33 + 2149: 42,33 + 2150: 44,33 + 2151: 45,36 + 2152: 46,36 + 2153: 46,35 + 2154: 46,33 + 2155: 44,32 + 2156: 43,33 + 2157: 40,33 + 2158: 43,34 + 2159: 45,37 + 2160: 46,36 + 2161: 47,33 + 2162: 47,33 + 2163: 39,33 + 2164: 43,33 + 2165: 37,33 + 2166: 35,33 + 2167: 34,34 + 2168: 32,37 + 2169: 32,42 + 2170: 33,44 + 2171: 32,47 + 2172: 33,48 + 2173: 33,50 + 2174: 13,55 + 2175: 14,55 + 2176: 15,55 + 2177: 15,54 + 2178: 15,54 + 2179: 14,54 + 2180: 13,54 + 2181: 14,53 + 2182: 15,53 + 2183: 14,53 + 2184: 13,53 + 2185: 16,53 + 2186: 16,53 + 2187: 16,55 + 2188: 16,56 + 2189: 14,56 + 2190: 14,56 + 2191: 16,57 + 2192: 14,57 + 2193: 13,57 + 2194: 12,57 + 2195: 11,55 + 2196: 12,54 + 2197: 11,53 + 2198: 19,60 + 2199: 19,57 + 2200: 18,60 + 2201: 18,64 + 2202: 20,65 + 2203: 22,66 + 2204: 21,66 + 2205: 22,64 + 2206: 21,64 + 2207: 23,65 + 2208: 24,66 + 2209: 23,67 + 2210: 23,69 + 2211: 24,71 + 2212: 26,71 + 2213: 26,69 + 2214: 27,68 + 2215: 29,69 + 2216: 11,72 + 2217: 20,74 + 2218: 20,73 + 2219: 23,47 + 2220: 23,47 + 2221: 23,47 + 2222: 23,46 + 2223: 23,46 + 2224: 22,47 + 2225: 35,57 + 2226: 36,56 + 2227: 36,56 + 2228: 37,56 + 2229: 36,56 + 2230: 36,55 + 2231: 36,54 + 2232: 36,53 + 2233: 38,53 + 2234: 40,53 + 2235: 40,55 + 2236: 40,56 + 2237: 41,57 + 2238: 41,56 + 2239: 39,56 + 2240: 40,55 + 2241: 41,53 + 2242: 41,53 + 2243: 43,54 + 2244: 43,55 + 2245: 43,57 + 2246: 43,55 + 2247: 43,53 + 2248: 43,52 + 2249: 43,50 + 2250: 45,50 + 2251: 46,50 + 2252: 47,50 + 2253: 47,49 + 2254: 47,47 + 2255: 47,46 + 2256: 47,46 + 2257: 46,44 + 2258: 46,44 + 2259: 46,45 + 2260: 46,46 + 2261: 46,47 + 2262: 40,50 + 2263: 40,48 + 2264: 40,46 + 2265: 39,45 + 2266: 37,46 + 2267: 35,46 + 2268: 40,50 + 2269: 40,52 + 2270: 40,51 + 2271: 40,50 + 2272: 40,43 + 2273: 40,43 + 2274: 40,44 + 2275: 39,44 + 2276: 39,44 + 2277: 39,43 + 2278: 39,42 + 2279: 39,40 + 2280: 39,39 + 2281: 40,39 + 2282: 43,39 + 2283: 45,39 + 2284: 46,39 + 2285: 47,39 + 2286: 47,40 + 2287: 46,41 + 2288: 47,42 + 2289: 47,44 + 2290: 47,46 + 2291: 47,48 + 2292: 43,44 + 2293: 44,44 + 2294: 42,43 + 2295: 42,42 + 2296: 43,41 + 2297: 44,41 + 2298: 44,43 + 2299: 43,45 + 2300: 43,47 + 2301: 44,48 + 2302: 44,48 + 2303: 49,33 + 2304: 49,34 + 2305: 50,35 + 2306: 50,36 + 2307: 50,36 + 2308: 35,7 + 2309: 35,8 + 2310: 36,8 + 2311: 37,8 + 2312: 40,8 + 2313: 40,8 + 2314: 40,7 + 2315: 38,7 + 2316: 38,7 + 2317: 41,9 + 2318: 44,9 + 2319: 42,9 + 2320: 46,9 + 2321: 47,9 + 2322: 49,9 + 2323: 49,9 + 2324: 50,9 + 2325: 38,4 + 2326: 35,4 + 2327: 39,2 + 2328: 43,3 + 2329: 45,3 + 2330: 44,0 + 2331: 44,-1 + 2332: 47,-1 + 2333: 44,-1 + 2334: 46,-1 + 2335: 46,-1 + 2336: 45,-1 + 2337: 46,0 + 2338: 45,0 + 2339: 46,3 + 2340: 47,3 + 2341: 45,3 + 2342: 46,4 + 2343: 49,3 + 2344: 51,3 + 2345: 48,2 + 2346: 53,3 + 2347: 55,3 + 2348: 57,2 + 2349: 59,3 + 2350: 61,2 + 2351: 63,4 + 2352: 64,2 + 2353: 65,3 + 2354: 66,3 + 2355: 69,3 + 2356: 69,3 + 2357: 72,4 + 2358: 73,3 + 2359: 75,3 + 2360: 76,3 + 2361: 78,3 + 2362: 79,3 + 2363: 81,3 + 2364: 83,4 + 2365: 84,2 + 2366: 85,3 + 2367: 86,4 + 2368: 83,7 + 2369: 80,7 + 2370: 78,6 + 2371: 76,8 + 2372: 77,9 + 2373: 80,9 + 2374: 83,9 + 2375: 82,12 + 2376: 82,13 + 2377: 83,14 + 2378: 83,14 + 2379: 83,13 + 2380: 75,13 + 2381: 75,15 + 2382: 76,15 + 2383: 76,14 + 2384: 76,9 + 2385: 76,6 + 2386: 77,6 + 2387: 83,6 + 2388: 83,8 + 2389: 84,3 + 2390: 67,2 + 2391: 66,4 + 2392: 61,2 + 2393: 58,4 + 2394: 57,3 + 2395: 56,2 + 2396: 52,4 + 2397: 51,3 + 2398: 53,-13 + 2399: 60,-20 + 2400: 62,-21 + 2401: 61,-22 + 2402: 60,-19 + 2403: 41,-16 + 2404: 38,-16 + 2405: 37,-16 + 2406: 37,-19 + 2407: 37,-20 + 2408: 37,-20 + 2409: 36,-20 + 2410: 37,-20 + 2411: 37,-20 + 2412: 40,-19 + 2413: 40,-19 + 2414: 39,-19 + 2415: 40,-20 + 2416: 43,-19 + 2417: 43,-20 + 2418: 42,-20 + 2419: 45,-19 + 2420: 45,-20 + 2421: 45,-20 + 2422: 46,-20 + 2423: 38,-16 + 2424: 36,-14 + 2425: 35,-13 + 2426: 35,-11 + 2427: 34,-9 + 2428: 35,-7 + 2429: 36,-6 + 2430: 36,-4 + 2431: 36,-3 + 2432: 38,-5 + 2433: 40,-3 + 2434: 39,-3 + 2435: 41,-3 + 2436: 39,2 + 2437: 41,2 + 2438: 31,2 + 2439: 30,3 + 2440: 28,1 + 2441: 28,3 + 2442: 29,0 + 2443: 23,-7 + 2444: 28,-7 + 2445: 7,-16 + 2446: 7,-16 + 2447: 7,-17 + 2448: -9,-2 + 2449: -9,-1 + 2450: -8,-1 + 2451: -7,-1 + 2452: -6,-1 + 2453: -5,-2 + 2454: -5,-6 + 2455: -5,-15 + 2456: -4,-15 + 2457: -6,-19 + 2458: -5,-17 + 2459: -6,-20 + 2460: -4,-22 + 2461: -4,-24 + 2462: -5,-26 + 2463: -8,-26 + 2464: -9,-26 + 2465: -10,-25 + 2466: -11,-27 + 2467: -10,-28 + 2468: -7,-28 + 2469: -13,-25 + 2470: -14,-26 + 2471: -17,-26 + 2472: -19,-25 + 2473: -20,-27 + 2474: -22,-26 + 2475: -25,-26 + 2476: -26,-29 + 2477: -27,-30 + 2478: -26,-31 + 2479: -27,-31 + 2480: -27,-33 + 2481: -25,-34 + 2482: -26,-35 + 2483: -24,-35 + 2484: -23,-35 + 2485: -23,-34 + 2486: -27,-26 + 2487: -28,-26 + 2488: -31,-28 + 2489: -33,-28 + 2490: -37,-28 + 2491: -31,-28 + 2492: -31,-27 + 2493: -37,-28 + 2494: -31,-31 + 2495: -33,-32 + 2496: -34,-33 + 2497: -36,-32 + 2498: -37,-32 + 2499: -39,-33 + 2500: -37,-32 + 2501: -41,-31 + 2502: -42,-32 + 2503: -43,-32 + 2504: -45,-31 + 2505: -46,-32 + 2506: -46,-32 + 2507: -48,-31 + 2508: -49,-32 + 2509: -49,-32 + 2510: -50,-31 + 2511: -51,-32 + 2512: -52,-32 + 2513: -44,-33 2514: -42,-32 - 2515: -43,-32 - 2516: -45,-31 - 2517: -46,-32 - 2518: -46,-32 - 2519: -48,-31 - 2520: -49,-32 - 2521: -49,-32 - 2522: -50,-31 - 2523: -51,-32 - 2524: -52,-32 - 2525: -44,-33 - 2526: -42,-32 - 2527: -41,-31 - 2528: -39,-32 - 2529: -38,-33 - 2530: -37,-33 - 2531: -32,-33 - 2532: -39,-38 - 2533: -39,-39 - 2534: -41,-39 - 2535: -31,-37 - 2536: -31,-38 - 2537: -31,-39 - 2538: -27,-41 - 2539: -27,-39 - 2540: -26,-39 - 2541: -23,-40 - 2542: -24,-41 - 2543: -26,-39 - 2544: -23,-39 - 2545: -24,-39 - 2546: -25,-39 - 2547: -25,-38 - 2548: -35,-41 - 2549: -39,-39 - 2550: -39,-37 - 2551: -32,-36 - 2552: -32,-36 - 2553: -39,-36 - 2554: -49,-28 - 2555: -50,-27 - 2556: -52,-27 - 2557: -52,-28 - 2558: -51,-29 - 2559: -50,-29 - 2560: -50,-28 - 2561: -55,-32 - 2562: -56,-31 - 2563: -57,-31 - 2564: -57,-29 - 2565: -56,-29 - 2566: -55,-29 - 2567: -56,-25 - 2568: -55,-28 - 2569: -57,-27 - 2570: -57,-25 - 2571: -55,-26 - 2572: -55,-27 - 2573: -54,-22 - 2574: -55,-23 - 2575: -55,-23 - 2576: -56,-22 - 2577: -57,-23 - 2578: -59,-23 - 2579: -59,-23 - 2580: -60,-24 - 2581: -60,-25 - 2582: -61,-26 - 2583: -66,-26 - 2584: -64,-26 - 2585: -63,-26 - 2586: -61,-27 - 2587: -61,-29 - 2588: -60,-29 - 2589: -60,-31 - 2590: -60,-33 - 2591: -61,-33 - 2592: -61,-34 - 2593: -61,-36 - 2594: -61,-38 - 2595: -63,-36 - 2596: -64,-36 - 2597: -65,-36 - 2598: -65,-35 - 2599: -64,-34 - 2600: -63,-34 - 2601: -65,-34 - 2602: -65,-34 - 2603: -64,-35 - 2604: -64,-37 - 2605: -64,-37 - 2606: -64,-38 - 2607: -63,-37 - 2608: -63,-37 - 2609: -63,-38 - 2610: -64,-38 - 2611: -64,-37 - 2612: -65,-37 - 2613: -65,-36 - 2614: -64,-36 - 2615: -63,-36 + 2515: -41,-31 + 2516: -39,-32 + 2517: -38,-33 + 2518: -37,-33 + 2519: -32,-33 + 2520: -39,-38 + 2521: -39,-39 + 2522: -41,-39 + 2523: -31,-37 + 2524: -31,-38 + 2525: -31,-39 + 2526: -27,-41 + 2527: -27,-39 + 2528: -26,-39 + 2529: -23,-40 + 2530: -24,-41 + 2531: -26,-39 + 2532: -23,-39 + 2533: -24,-39 + 2534: -25,-39 + 2535: -25,-38 + 2536: -35,-41 + 2537: -39,-39 + 2538: -39,-37 + 2539: -32,-36 + 2540: -32,-36 + 2541: -39,-36 + 2542: -49,-28 + 2543: -50,-27 + 2544: -52,-27 + 2545: -52,-28 + 2546: -51,-29 + 2547: -50,-29 + 2548: -50,-28 + 2549: -55,-32 + 2550: -56,-31 + 2551: -57,-31 + 2552: -57,-29 + 2553: -56,-29 + 2554: -55,-29 + 2555: -56,-25 + 2556: -55,-28 + 2557: -57,-27 + 2558: -57,-25 + 2559: -55,-26 + 2560: -55,-27 + 2561: -54,-22 + 2562: -55,-23 + 2563: -55,-23 + 2564: -56,-22 + 2565: -57,-23 + 2566: -59,-23 + 2567: -59,-23 + 2568: -60,-24 + 2569: -60,-25 + 2570: -61,-26 + 2571: -66,-26 + 2572: -64,-26 + 2573: -63,-26 + 2574: -61,-27 + 2575: -61,-29 + 2576: -60,-29 + 2577: -60,-31 + 2578: -60,-33 + 2579: -61,-33 + 2580: -61,-34 + 2581: -61,-36 + 2582: -61,-38 + 2583: -63,-36 + 2584: -64,-36 + 2585: -65,-36 + 2586: -65,-35 + 2587: -64,-34 + 2588: -63,-34 + 2589: -65,-34 + 2590: -65,-34 + 2591: -64,-35 + 2592: -64,-37 + 2593: -64,-37 + 2594: -64,-38 + 2595: -63,-37 + 2596: -63,-37 + 2597: -63,-38 + 2598: -64,-38 + 2599: -64,-37 + 2600: -65,-37 + 2601: -65,-36 + 2602: -64,-36 + 2603: -63,-36 + 2604: -64,-35 + 2605: -63,-34 + 2606: -64,-34 + 2607: -63,-34 + 2608: -64,-34 + 2609: -65,-36 + 2610: -65,-37 + 2611: -63,-37 + 2612: -63,-38 + 2613: -65,-35 + 2614: -63,-35 + 2615: -64,-35 2616: -64,-35 - 2617: -63,-34 - 2618: -64,-34 - 2619: -63,-34 - 2620: -64,-34 - 2621: -65,-36 - 2622: -65,-37 - 2623: -63,-37 - 2624: -63,-38 - 2625: -65,-35 - 2626: -63,-35 - 2627: -64,-35 - 2628: -64,-35 - 2629: -63,-35 - 2630: -65,-35 - 2631: -61,-41 - 2632: -62,-41 - 2633: -63,-41 - 2634: -63,-43 - 2635: -63,-44 - 2636: -64,-45 - 2637: -66,-44 - 2638: -66,-44 - 2639: -66,-44 - 2640: -66,-43 - 2641: -59,-41 - 2642: -58,-41 - 2643: -58,-40 - 2644: -58,-39 - 2645: -57,-40 - 2646: -57,-43 - 2647: -59,-43 - 2648: -59,-43 - 2649: -60,-44 - 2650: -61,-44 - 2651: -36,-8 - 2652: -32,-12 - 2653: -37,-15 - 2654: -37,-16 - 2655: -38,-16 - 2656: -38,-16 - 2657: -36,-14 - 2658: -36,-16 - 2659: -37,-14 - 2660: -36,-15 - 2661: -32,-19 - 2662: -36,-19 - 2663: -37,-19 - 2664: -37,-21 - 2665: -35,-21 - 2666: -32,-22 - 2667: -33,-22 - 2668: -35,-23 - 2669: -36,-24 - 2670: -21,-8 - 2671: -20,-9 - 2672: -20,-10 - 2673: -24,-11 - 2674: -24,-13 - 2675: -21,-13 - 2676: -22,-16 - 2677: -24,-16 - 2678: -24,-17 - 2679: -23,-18 - 2680: -22,-18 - 2681: -24,-19 - 2682: -24,-20 - 2683: -23,-21 - 2684: -22,-21 - 2685: -26,-20 - 2686: -25,-18 - 2687: -25,-16 - 2688: -25,-15 - 2689: -21,-13 - 2690: -21,-15 - 2691: -21,-17 - 2692: -21,-18 - 2693: -22,-8 - 2694: -25,-10 - 2695: -25,-12 - 2696: -24,-12 - 2697: -24,-8 - 2698: -21,-10 - 2699: -22,-10 - 2700: -22,-13 - 2701: -8,-8 - 2702: -8,-10 - 2703: -8,-11 - 2704: -8,-13 - 2705: -8,-19 + 2617: -63,-35 + 2618: -65,-35 + 2619: -61,-41 + 2620: -62,-41 + 2621: -63,-41 + 2622: -63,-43 + 2623: -63,-44 + 2624: -64,-45 + 2625: -66,-44 + 2626: -66,-44 + 2627: -66,-44 + 2628: -66,-43 + 2629: -59,-41 + 2630: -58,-41 + 2631: -58,-40 + 2632: -58,-39 + 2633: -57,-40 + 2634: -57,-43 + 2635: -59,-43 + 2636: -59,-43 + 2637: -60,-44 + 2638: -61,-44 + 2639: -36,-8 + 2640: -32,-12 + 2641: -37,-15 + 2642: -37,-16 + 2643: -38,-16 + 2644: -38,-16 + 2645: -36,-14 + 2646: -36,-16 + 2647: -37,-14 + 2648: -36,-15 + 2649: -32,-19 + 2650: -36,-19 + 2651: -37,-19 + 2652: -37,-21 + 2653: -35,-21 + 2654: -32,-22 + 2655: -33,-22 + 2656: -35,-23 + 2657: -36,-24 + 2658: -21,-8 + 2659: -20,-9 + 2660: -20,-10 + 2661: -24,-11 + 2662: -24,-13 + 2663: -21,-13 + 2664: -22,-16 + 2665: -24,-16 + 2666: -24,-17 + 2667: -23,-18 + 2668: -22,-18 + 2669: -24,-19 + 2670: -24,-20 + 2671: -23,-21 + 2672: -22,-21 + 2673: -26,-20 + 2674: -25,-18 + 2675: -25,-16 + 2676: -25,-15 + 2677: -21,-13 + 2678: -21,-15 + 2679: -21,-17 + 2680: -21,-18 + 2681: -22,-8 + 2682: -25,-10 + 2683: -25,-12 + 2684: -24,-12 + 2685: -24,-8 + 2686: -21,-10 + 2687: -22,-10 + 2688: -22,-13 + 2689: -8,-8 + 2690: -8,-10 + 2691: -8,-11 + 2692: -8,-13 + 2693: -8,-19 + 2694: -9,-17 + 2695: -11,-18 + 2696: -11,-18 + 2697: -11,-17 + 2698: -10,-16 + 2699: -8,-16 + 2700: -8,-17 + 2701: -10,-17 + 2702: -9,-18 + 2703: -8,-19 + 2704: -9,-20 + 2705: -8,-18 2706: -9,-17 - 2707: -11,-18 - 2708: -11,-18 - 2709: -11,-17 - 2710: -10,-16 - 2711: -8,-16 - 2712: -8,-17 - 2713: -10,-17 - 2714: -9,-18 - 2715: -8,-19 - 2716: -9,-20 - 2717: -8,-18 - 2718: -9,-17 - 2719: -10,-17 - 2720: -10,-18 - 2721: -9,-17 - 2722: -8,-18 - 2723: -9,-19 - 2724: -9,-19 - 2725: -4,-9 - 2726: -5,-11 - 2727: -4,-10 - 2728: -5,-12 - 2729: -5,-14 - 2730: -7,-25 - 2731: -7,-26 - 2732: -6,-28 - 2733: 18,-35 - 2734: -2,-34 - 2735: 12,-32 - 2736: 11,-32 - 2737: 11,-33 - 2738: 12,-33 - 2739: 13,-32 - 2740: 16,-32 - 2741: 17,-32 - 2742: 16,-32 - 2743: 17,-32 - 2744: 16,-32 - 2745: 17,-32 - 2746: 6,-32 - 2747: 7,-33 - 2748: 8,-32 - 2749: -3,-39 - 2750: -3,-39 - 2751: -2,-40 - 2752: -1,-39 - 2753: -1,-38 - 2754: -2,-33 - 2755: -3,-33 - 2756: -3,-32 - 2757: -2,-32 - 2758: -2,-33 - 2759: -3,-33 - 2760: -3,-32 - 2761: -2,-32 - 2762: 7,-45 - 2763: 7,-46 - 2764: 8,-46 - 2765: 9,-46 - 2766: 9,-45 - 2767: 8,-45 - 2768: 8,-46 - 2769: 9,-45 - 2770: 8,-46 - 2771: 13,-43 - 2772: 12,-43 - 2773: 13,-43 - 2774: 12,-43 - 2775: 11,-45 - 2776: 11,-43 - 2777: 11,-46 - 2778: 13,-45 - 2779: 13,-46 - 2780: 13,-45 - 2781: 13,-46 - 2782: 13,-48 - 2783: 14,-49 - 2784: 14,-50 - 2785: 15,-51 - 2786: 16,-50 - 2787: 17,-49 - 2788: 17,-49 - 2789: 16,-48 - 2790: 14,-48 - 2791: 16,-51 - 2792: 16,-52 - 2793: 20,-58 - 2794: 21,-58 - 2795: 20,-57 - 2796: 19,-56 - 2797: 20,-56 - 2798: 20,-54 - 2799: 19,-54 - 2800: 20,-52 - 2801: 19,-51 - 2802: 20,-50 - 2803: 21,-49 - 2804: 19,-48 - 2805: 21,-46 - 2806: 21,-45 - 2807: 19,-44 - 2808: 21,-46 - 2809: 20,-42 - 2810: 19,-41 - 2811: 21,-40 - 2812: 19,-39 - 2813: 21,-38 - 2814: 20,-37 - 2815: 19,-36 - 2816: 21,-35 - 2817: 19,-34 - 2818: 20,-41 - 2819: 20,-38 - 2820: 20,-38 - 2821: 23,-28 - 2822: 21,-29 - 2823: 20,-29 - 2824: 19,-28 - 2825: 25,-28 - 2826: 28,-28 - 2827: 30,-26 - 2828: 31,-26 - 2829: 18,-25 - 2830: 20,-26 - 2831: 21,-24 - 2832: 20,-21 - 2833: 19,-20 - 2834: 21,-21 - 2835: 18,-22 - 2836: 19,-23 - 2837: 20,-24 - 2838: 17,-24 - 2839: 17,-26 - 2840: 12,-24 - 2841: 13,-26 - 2842: 14,-24 - 2843: 10,-24 - 2844: 9,-25 - 2845: 7,-25 - 2846: 8,-26 - 2847: 6,-24 - 2848: 5,-27 - 2849: 4,-25 - 2850: 2,-26 - 2851: 2,-27 - 2852: -2,-24 - 2853: -3,-26 - 2854: -4,-26 - 2855: -5,-24 - 2856: 2,-24 - 2857: 0,-24 - 2858: 0,-26 - 2859: 2,-26 - 2860: 9,-26 - 2861: 11,-26 - 2862: 15,-24 - 2863: 14,-25 - 2864: 21,-26 - 2865: 20,-21 - 2866: 19,-20 - 2867: 19,-19 - 2868: 19,-18 - 2869: 19,-17 - 2870: 19,-11 - 2871: 20,-11 - 2872: 19,-11 - 2873: 20,-12 - 2874: 19,-11 - 2875: 18,-10 - 2876: 19,-7 - 2877: 19,-6 - 2878: 18,-5 - 2879: 22,-15 - 2880: 23,-15 - 2881: 25,-15 - 2882: 25,-14 - 2883: 25,-13 - 2884: 23,-12 - 2885: 22,-12 - 2886: 25,-12 - 2887: 27,-12 - 2888: 28,-13 - 2889: 30,-13 - 2890: 31,-13 - 2891: 31,-12 - 2892: 31,-11 - 2893: 31,-10 - 2894: 31,-8 - 2895: 31,-8 - 2896: 31,-7 - 2897: 31,-4 - 2898: 33,-4 - 2899: 33,-4 - 2900: 32,-5 - 2901: 30,-16 - 2902: 30,-18 - 2903: 31,-15 - 2904: 31,-16 - 2905: 33,-16 - 2906: 33,-15 - 2907: 32,-16 - 2908: 32,-15 - 2909: 51,9 - 2910: 48,9 - 2911: 45,9 - 2912: 42,9 - 2913: 42,8 - 2914: 38,8 - 2915: 35,24 - 2916: 37,24 - 2917: 35,27 - 2918: 35,28 - 2919: 36,30 - 2920: 31,31 - 2921: 32,32 - 2922: 31,35 - 2923: 32,35 - 2924: 33,36 - 2925: 31,39 - 2926: 31,42 - 2927: 33,41 - 2928: 32,40 - 2929: 32,39 - 2930: 0,53 - 2931: 0,52 - 2932: 0,51 - 2933: 0,49 - 2934: 2,51 - 2935: 0,55 - 2936: 1,55 - 2937: 1,59 - 2938: 2,61 - 2939: 1,61 - 2940: -2,61 - 2941: -2,59 - 2942: -1,56 - 2943: -38,51 - 2944: -42,51 - 2945: -45,48 - 2946: -45,45 - 2947: -41,46 - 2948: -37,46 - 2949: -38,44 - 2950: -42,44 - 2951: -44,43 - 2952: -41,41 - 2953: -36,41 - 2954: -35,41 - 2955: -42,40 - 2956: -46,40 - 2957: -39,40 - 2958: -35,41 - 2959: -39,42 - 2960: -45,43 - 2961: -35,44 - 2962: -34,45 - 2963: -42,45 - 2964: -37,47 - 2965: -34,47 - 2966: -44,48 - 2967: -38,49 - 2968: -35,50 - 2969: -43,50 - 2970: -33,51 - 2971: -36,49 - 2972: -43,48 - 2973: -39,48 - 2974: -33,47 - 2975: -39,46 - 2976: -45,45 - 2977: -39,44 - 2978: -34,43 - 2979: -36,41 - 2980: -41,41 - 2981: -41,41 - 2982: -34,40 - 2983: -36,41 - 2984: -39,41 - 2985: -32,41 - 2986: -32,41 - 2987: -31,44 - 2988: -31,48 - 2989: -31,51 - 2990: -28,45 - 2991: -26,45 - 2992: -28,41 - 2993: -26,41 - 2994: -24,41 - 2995: -23,39 - 3137: 50,-37 - 3138: 53,-37 - 3139: 56,-38 - 3140: 55,-38 - 3141: 54,-39 - 3142: 53,-40 - 3143: 53,-42 - 3144: 51,-45 - 3145: 51,-46 - 3146: 46,-47 - 3147: 46,-46 - 3148: 48,-43 - 3149: 46,-45 - 3150: 45,-46 - 3151: 43,-46 - 3152: 47,-43 - 3153: 52,-46 - 3154: 52,-42 - 3155: 53,-42 - 3156: 50,-42 - 3157: 50,-40 - 3158: 50,-37 - 3159: 52,-36 - 3160: 55,-37 - 3161: 55,-38 - 3162: 53,-40 - 3163: 53,-42 - 3164: 52,-45 - 3165: 50,-45 - 3166: 54,-47 - 3167: 51,-47 - 3168: 46,-47 - 3169: 45,-47 - 3170: 44,-46 - 3171: 44,-44 - 3572: -5,-1 - 4417: 28,54 - 4418: 27,55 - 4419: 27,56 - 4420: 26,56 - 4421: 26,55 - 4422: 26,54 - 4423: 27,54 - 4424: 28,52 - 4425: 27,51 - 4426: 28,53 + 2707: -10,-17 + 2708: -10,-18 + 2709: -9,-17 + 2710: -8,-18 + 2711: -9,-19 + 2712: -9,-19 + 2713: -4,-9 + 2714: -5,-11 + 2715: -4,-10 + 2716: -5,-12 + 2717: -5,-14 + 2718: -7,-25 + 2719: -7,-26 + 2720: -6,-28 + 2721: 18,-35 + 2722: -2,-34 + 2723: 12,-32 + 2724: 11,-32 + 2725: 11,-33 + 2726: 12,-33 + 2727: 13,-32 + 2728: 16,-32 + 2729: 17,-32 + 2730: 16,-32 + 2731: 17,-32 + 2732: 16,-32 + 2733: 17,-32 + 2734: 6,-32 + 2735: 7,-33 + 2736: 8,-32 + 2737: -3,-39 + 2738: -3,-39 + 2739: -2,-40 + 2740: -1,-39 + 2741: -1,-38 + 2742: -2,-33 + 2743: -3,-33 + 2744: -3,-32 + 2745: -2,-32 + 2746: -2,-33 + 2747: -3,-33 + 2748: -3,-32 + 2749: -2,-32 + 2750: 7,-45 + 2751: 7,-46 + 2752: 8,-46 + 2753: 9,-46 + 2754: 9,-45 + 2755: 8,-45 + 2756: 8,-46 + 2757: 9,-45 + 2758: 8,-46 + 2759: 13,-43 + 2760: 12,-43 + 2761: 13,-43 + 2762: 12,-43 + 2763: 11,-45 + 2764: 11,-43 + 2765: 11,-46 + 2766: 13,-45 + 2767: 13,-46 + 2768: 13,-45 + 2769: 13,-46 + 2770: 13,-48 + 2771: 14,-49 + 2772: 14,-50 + 2773: 15,-51 + 2774: 16,-50 + 2775: 17,-49 + 2776: 17,-49 + 2777: 16,-48 + 2778: 14,-48 + 2779: 16,-51 + 2780: 16,-52 + 2781: 20,-58 + 2782: 21,-58 + 2783: 20,-57 + 2784: 19,-56 + 2785: 20,-56 + 2786: 20,-54 + 2787: 19,-54 + 2788: 20,-52 + 2789: 19,-51 + 2790: 20,-50 + 2791: 21,-49 + 2792: 19,-48 + 2793: 21,-46 + 2794: 21,-45 + 2795: 19,-44 + 2796: 21,-46 + 2797: 20,-42 + 2798: 19,-41 + 2799: 21,-40 + 2800: 19,-39 + 2801: 21,-38 + 2802: 20,-37 + 2803: 19,-36 + 2804: 21,-35 + 2805: 19,-34 + 2806: 20,-41 + 2807: 20,-38 + 2808: 20,-38 + 2809: 23,-28 + 2810: 21,-29 + 2811: 20,-29 + 2812: 19,-28 + 2813: 25,-28 + 2814: 28,-28 + 2815: 30,-26 + 2816: 31,-26 + 2817: 18,-25 + 2818: 20,-26 + 2819: 21,-24 + 2820: 20,-21 + 2821: 19,-20 + 2822: 21,-21 + 2823: 18,-22 + 2824: 19,-23 + 2825: 20,-24 + 2826: 17,-24 + 2827: 17,-26 + 2828: 12,-24 + 2829: 13,-26 + 2830: 14,-24 + 2831: 10,-24 + 2832: 9,-25 + 2833: 7,-25 + 2834: 8,-26 + 2835: 6,-24 + 2836: 5,-27 + 2837: 4,-25 + 2838: 2,-26 + 2839: 2,-27 + 2840: -2,-24 + 2841: -3,-26 + 2842: -4,-26 + 2843: -5,-24 + 2844: 2,-24 + 2845: 0,-24 + 2846: 0,-26 + 2847: 2,-26 + 2848: 9,-26 + 2849: 11,-26 + 2850: 15,-24 + 2851: 14,-25 + 2852: 21,-26 + 2853: 20,-21 + 2854: 19,-20 + 2855: 19,-19 + 2856: 19,-18 + 2857: 19,-17 + 2858: 19,-11 + 2859: 20,-11 + 2860: 19,-11 + 2861: 20,-12 + 2862: 19,-11 + 2863: 18,-10 + 2864: 19,-7 + 2865: 19,-6 + 2866: 18,-5 + 2867: 22,-15 + 2868: 23,-15 + 2869: 25,-15 + 2870: 25,-14 + 2871: 25,-13 + 2872: 23,-12 + 2873: 22,-12 + 2874: 25,-12 + 2875: 27,-12 + 2876: 28,-13 + 2877: 30,-13 + 2878: 31,-13 + 2879: 31,-12 + 2880: 31,-11 + 2881: 31,-10 + 2882: 31,-8 + 2883: 31,-8 + 2884: 31,-7 + 2885: 31,-4 + 2886: 33,-4 + 2887: 33,-4 + 2888: 32,-5 + 2889: 30,-16 + 2890: 30,-18 + 2891: 31,-15 + 2892: 31,-16 + 2893: 33,-16 + 2894: 33,-15 + 2895: 32,-16 + 2896: 32,-15 + 2897: 51,9 + 2898: 48,9 + 2899: 45,9 + 2900: 42,9 + 2901: 42,8 + 2902: 38,8 + 2903: 35,24 + 2904: 37,24 + 2905: 35,27 + 2906: 35,28 + 2907: 36,30 + 2908: 31,31 + 2909: 32,32 + 2910: 31,35 + 2911: 32,35 + 2912: 33,36 + 2913: 31,39 + 2914: 31,42 + 2915: 33,41 + 2916: 32,40 + 2917: 32,39 + 2918: 0,53 + 2919: 0,52 + 2920: 0,51 + 2921: 0,49 + 2922: 2,51 + 2923: 0,55 + 2924: 1,55 + 2925: 1,59 + 2926: 2,61 + 2927: 1,61 + 2928: -2,61 + 2929: -2,59 + 2930: -1,56 + 2931: -38,51 + 2932: -42,51 + 2933: -45,48 + 2934: -45,45 + 2935: -41,46 + 2936: -37,46 + 2937: -38,44 + 2938: -42,44 + 2939: -44,43 + 2940: -41,41 + 2941: -36,41 + 2942: -35,41 + 2943: -42,40 + 2944: -46,40 + 2945: -39,40 + 2946: -35,41 + 2947: -39,42 + 2948: -45,43 + 2949: -35,44 + 2950: -34,45 + 2951: -42,45 + 2952: -37,47 + 2953: -34,47 + 2954: -44,48 + 2955: -38,49 + 2956: -35,50 + 2957: -43,50 + 2958: -33,51 + 2959: -36,49 + 2960: -43,48 + 2961: -39,48 + 2962: -33,47 + 2963: -39,46 + 2964: -45,45 + 2965: -39,44 + 2966: -34,43 + 2967: -36,41 + 2968: -41,41 + 2969: -41,41 + 2970: -34,40 + 2971: -36,41 + 2972: -39,41 + 2973: -32,41 + 2974: -32,41 + 2975: -31,44 + 2976: -31,48 + 2977: -31,51 + 2978: -28,45 + 2979: -26,45 + 2980: -28,41 + 2981: -26,41 + 2982: -24,41 + 2983: -23,39 + 3124: 50,-37 + 3125: 53,-37 + 3126: 56,-38 + 3127: 55,-38 + 3128: 54,-39 + 3129: 53,-40 + 3130: 53,-42 + 3131: 51,-45 + 3132: 51,-46 + 3133: 46,-47 + 3134: 46,-46 + 3135: 48,-43 + 3136: 46,-45 + 3137: 45,-46 + 3138: 43,-46 + 3139: 47,-43 + 3140: 52,-46 + 3141: 52,-42 + 3142: 53,-42 + 3143: 50,-42 + 3144: 50,-40 + 3145: 50,-37 + 3146: 52,-36 + 3147: 55,-37 + 3148: 55,-38 + 3149: 53,-40 + 3150: 53,-42 + 3151: 52,-45 + 3152: 50,-45 + 3153: 54,-47 + 3154: 51,-47 + 3155: 46,-47 + 3156: 45,-47 + 3157: 44,-46 + 3158: 44,-44 + 3559: -5,-1 + 4404: 28,54 + 4405: 27,55 + 4406: 27,56 + 4407: 26,56 + 4408: 26,55 + 4409: 26,54 + 4410: 27,54 + 4411: 28,52 + 4412: 27,51 + 4413: 28,53 - node: cleanable: True color: '#FFFFFFFF' id: Dirt decals: - 3291: -65,-33 + 3278: -65,-33 - node: cleanable: True color: '#835432B7' id: DirtHeavy decals: - 4547: -28,-13 - 4548: -31,-11 - 4549: -30,-11 - 4550: -37,-10 - 4551: -37,-8 - 4552: -39,-8 - 4553: -38,-12 - 4554: -38,-11 - 4555: -36,-11 - 4556: -34,-15 - 4557: -34,-16 - 4558: -33,-15 - 4559: -32,-16 - 4560: -31,-16 - 4561: -31,-15 - 4562: -30,-15 + 4534: -28,-13 + 4535: -31,-11 + 4536: -30,-11 + 4537: -37,-10 + 4538: -37,-8 + 4539: -39,-8 + 4540: -38,-12 + 4541: -38,-11 + 4542: -36,-11 + 4543: -34,-15 + 4544: -34,-16 + 4545: -33,-15 + 4546: -32,-16 + 4547: -31,-16 + 4548: -31,-15 + 4549: -30,-15 - node: cleanable: True color: '#A4610696' id: DirtHeavy decals: - 2996: -20,45 - 2997: -20,52 - 2998: -21,35 - 2999: -19,37 - 3000: -19,35 - 3001: -20,35 - 3002: -11,40 - 3003: -10,44 - 3004: -10,48 - 3005: -15,48 - 3006: -5,43 - 3007: -2,50 - 3008: 5,50 - 3009: 12,50 - 3010: 15,55 - 3011: 18,58 - 3012: 19,63 - 3013: 23,67 - 3014: 33,47 - 3015: 31,40 - 3016: 26,35 - 3017: 33,31 - 3018: 32,25 - 3019: 31,22 - 3020: 36,23 - 3021: 37,27 - 3022: 42,30 - 3023: 43,27 - 3024: 44,21 - 3025: 42,16 - 3026: 41,13 - 3027: 43,15 - 3028: 44,19 - 3029: 32,8 - 3030: 27,7 - 3031: 40,3 - 3032: 46,3 - 3033: 56,3 - 3034: 64,3 - 3035: 70,3 - 3036: 73,3 - 3037: 83,3 - 3038: 83,10 - 3039: 76,9 - 3040: 80,6 - 3041: 53,-2 - 3042: 46,-16 - 3044: 35,-6 - 3045: 32,-4 - 3046: 26,-5 - 3047: 21,-4 - 3048: 12,-4 - 3049: -5,-4 - 3050: -34,-4 - 3051: -41,-5 - 3052: -46,-33 - 3053: -36,-33 - 3054: -32,-36 - 3055: -39,-39 - 3056: -29,-38 - 3057: -26,-39 - 3058: -24,-35 - 3059: -26,-30 - 3060: -23,-26 - 3061: -17,-26 - 3062: -8,-27 - 3063: -5,-31 - 3064: -6,-37 - 3065: -6,-43 - 3066: -6,-48 - 3067: -6,-53 - 3068: -5,-57 - 3069: 5,-53 - 3070: 3,-53 - 3071: 6,-52 - 3072: 5,-52 - 3073: 4,-52 - 3074: 5,-53 - 3075: 6,-53 - 3076: 28,-27 - 3077: -8,-1 - 3078: -31,-4 - 3079: -25,-17 - 3080: -26,1 - 3081: -23,13 - 3082: -21,19 - 3083: -17,20 - 3084: -13,20 - 3085: -18,14 - 3086: -13,14 - 3087: -23,26 - 3088: -23,30 - 3089: -31,30 - 3090: -42,29 - 3091: -50,30 - 3092: -50,29 - 3093: -56,29 - 3094: -58,35 - 3095: -57,44 - 3096: -58,49 - 3097: -64,43 - 3098: -63,38 - 3099: -52,31 - 3100: -40,29 - 3101: -29,30 - 3102: -22,30 - 3103: -21,32 - 3104: -20,37 - 3105: -20,42 - 3106: -19,51 - 3107: -25,54 - 3108: -27,53 - 3109: -11,47 - 3110: -9,45 - 3111: -5,47 - 3112: 4,50 - 3113: 7,49 - 3114: 16,49 - 3115: 23,50 - 3116: 26,50 - 3117: 19,54 - 3118: 19,63 - 3119: 23,68 - 3120: 32,43 - 3121: 32,36 - 3122: 32,29 - 3123: 32,22 - 3124: 32,19 - 3125: 33,9 - 3126: 33,20 - 3127: 31,26 - 3128: 33,35 - 3129: 15,30 - 3130: 8,30 - 3131: 0,30 - 3132: -8,9 - 3133: -4,10 - 3134: 20,15 - 3135: 21,9 - 3136: 29,4 - 3172: 52,-43 - 3173: 50,-47 - 3174: 45,-46 - 3175: 46,-43 - 3176: 52,-40 - 3177: 55,-37 - 3178: 55,-38 - 3179: 47,-45 - 3180: 44,-47 - 3181: 54,-47 - 3182: 53,-47 - 4427: 27,55 - 4428: 28,52 + 2984: -20,45 + 2985: -20,52 + 2986: -21,35 + 2987: -19,37 + 2988: -19,35 + 2989: -20,35 + 2990: -11,40 + 2991: -10,44 + 2992: -10,48 + 2993: -15,48 + 2994: -5,43 + 2995: -2,50 + 2996: 5,50 + 2997: 12,50 + 2998: 15,55 + 2999: 18,58 + 3000: 19,63 + 3001: 23,67 + 3002: 33,47 + 3003: 31,40 + 3004: 26,35 + 3005: 33,31 + 3006: 32,25 + 3007: 31,22 + 3008: 36,23 + 3009: 37,27 + 3010: 42,30 + 3011: 43,27 + 3012: 44,21 + 3013: 42,16 + 3014: 41,13 + 3015: 43,15 + 3016: 44,19 + 3017: 32,8 + 3018: 27,7 + 3019: 40,3 + 3020: 46,3 + 3021: 56,3 + 3022: 64,3 + 3023: 70,3 + 3024: 73,3 + 3025: 83,3 + 3026: 83,10 + 3027: 76,9 + 3028: 80,6 + 3029: 53,-2 + 3030: 46,-16 + 3031: 35,-6 + 3032: 32,-4 + 3033: 26,-5 + 3034: 21,-4 + 3035: 12,-4 + 3036: -5,-4 + 3037: -34,-4 + 3038: -41,-5 + 3039: -46,-33 + 3040: -36,-33 + 3041: -32,-36 + 3042: -39,-39 + 3043: -29,-38 + 3044: -26,-39 + 3045: -24,-35 + 3046: -26,-30 + 3047: -23,-26 + 3048: -17,-26 + 3049: -8,-27 + 3050: -5,-31 + 3051: -6,-37 + 3052: -6,-43 + 3053: -6,-48 + 3054: -6,-53 + 3055: -5,-57 + 3056: 5,-53 + 3057: 3,-53 + 3058: 6,-52 + 3059: 5,-52 + 3060: 4,-52 + 3061: 5,-53 + 3062: 6,-53 + 3063: 28,-27 + 3064: -8,-1 + 3065: -31,-4 + 3066: -25,-17 + 3067: -26,1 + 3068: -23,13 + 3069: -21,19 + 3070: -17,20 + 3071: -13,20 + 3072: -18,14 + 3073: -13,14 + 3074: -23,26 + 3075: -23,30 + 3076: -31,30 + 3077: -42,29 + 3078: -50,30 + 3079: -50,29 + 3080: -56,29 + 3081: -58,35 + 3082: -57,44 + 3083: -58,49 + 3084: -64,43 + 3085: -63,38 + 3086: -52,31 + 3087: -40,29 + 3088: -29,30 + 3089: -22,30 + 3090: -21,32 + 3091: -20,37 + 3092: -20,42 + 3093: -19,51 + 3094: -25,54 + 3095: -27,53 + 3096: -11,47 + 3097: -9,45 + 3098: -5,47 + 3099: 4,50 + 3100: 7,49 + 3101: 16,49 + 3102: 23,50 + 3103: 26,50 + 3104: 19,54 + 3105: 19,63 + 3106: 23,68 + 3107: 32,43 + 3108: 32,36 + 3109: 32,29 + 3110: 32,22 + 3111: 32,19 + 3112: 33,9 + 3113: 33,20 + 3114: 31,26 + 3115: 33,35 + 3116: 15,30 + 3117: 8,30 + 3118: 0,30 + 3119: -8,9 + 3120: -4,10 + 3121: 20,15 + 3122: 21,9 + 3123: 29,4 + 3159: 52,-43 + 3160: 50,-47 + 3161: 45,-46 + 3162: 46,-43 + 3163: 52,-40 + 3164: 55,-37 + 3165: 55,-38 + 3166: 47,-45 + 3167: 44,-47 + 3168: 54,-47 + 3169: 53,-47 + 4414: 27,55 + 4415: 28,52 - node: cleanable: True color: '#8354328B' id: DirtLight decals: - 4605: -33,-8 - 4606: -32,-8 - 4607: -30,-7 - 4608: -29,-8 + 4592: -33,-8 + 4593: -32,-8 + 4594: -30,-7 + 4595: -29,-8 - node: cleanable: True color: '#FFFFFFFF' id: DirtLight decals: - 3288: -65,-33 - 3289: -64,-33 - 3290: -63,-33 + 3275: -65,-33 + 3276: -64,-33 + 3277: -63,-33 - node: cleanable: True color: '#8354328B' id: DirtMedium decals: - 4609: -28,-8 - 4610: -28,-9 - 4611: -30,-9 + 4596: -28,-8 + 4597: -28,-9 + 4598: -30,-9 - node: cleanable: True color: '#835432B7' id: DirtMedium decals: - 4563: -31,-15 - 4564: -29,-15 - 4565: -28,-14 - 4566: -30,-11 - 4567: -32,-11 - 4568: -38,-13 - 4569: -38,-11 - 4570: -39,-8 - 4571: -28,-12 + 4550: -31,-15 + 4551: -29,-15 + 4552: -28,-14 + 4553: -30,-11 + 4554: -32,-11 + 4555: -38,-13 + 4556: -38,-11 + 4557: -39,-8 + 4558: -28,-12 - node: color: '#9FED58B7' id: FlowersBROne decals: - 4771: -2.6908832,47.53326 + 4758: -2.6908832,47.53326 - node: color: '#9FED5873' id: Flowersbr1 decals: - 3315: 78.72238,7.9556513 - 3316: 79.69461,7.9278736 + 3302: 78.72238,7.9556513 + 3303: 79.69461,7.9278736 - node: color: '#FFFFFFE3' id: Flowersbr1 decals: - 4486: -19.119284,3.6234694 - 4487: -19.829224,1.4664211 + 4473: -19.119284,3.6234694 + 4474: -19.829224,1.4664211 - node: color: '#FFFFFFFF' id: Flowersbr1 decals: - 3355: -17.368574,-37.531387 + 3342: -17.368574,-37.531387 - node: color: '#FFFFFFE3' id: Flowersbr2 decals: - 4488: -19.900217,3.027443 - 4489: -19.005693,2.0766392 + 4475: -19.900217,3.027443 + 4476: -19.005693,2.0766392 - node: color: '#FFFFFFFF' id: Flowersbr2 decals: - 3358: -15.424128,-36.586945 + 3345: -15.424128,-36.586945 - node: color: '#9FED58B7' id: Flowersbr3 decals: - 4770: -1.1716373,46.099934 + 4757: -1.1716373,46.099934 - node: color: '#FFFFFFE3' id: Flowersbr3 decals: - 4490: -19.886019,-0.0094537735 - 4491: -18.82111,0.8136306 + 4477: -19.886019,-0.0094537735 + 4478: -18.82111,0.8136306 - node: color: '#FFFFFFFF' id: Flowersbr3 decals: - 3359: -16.14635,-36.989723 - 3385: -60.04891,40.960167 - 3386: -60.00724,39.210167 - 3387: -60.02113,42.890724 + 3346: -16.14635,-36.989723 + 3372: -60.04891,40.960167 + 3373: -60.00724,39.210167 + 3374: -60.02113,42.890724 - node: color: '#9FED58B7' id: Flowerspv1 decals: - 4769: -2.7477016,46.156727 - 4772: -2.7050896,47.10753 - 4773: -1.4556177,45.858692 + 4756: -2.7477016,46.156727 + 4759: -2.7050896,47.10753 + 4760: -1.4556177,45.858692 - node: color: '#A4DF8296' id: Flowerspv1 decals: - 1702: -7.423552,-22.998676 - 1703: -8.506886,-23.19312 - 1704: -8.8402195,-23.776455 - 1705: -7.2846637,-23.80423 - 1706: -7.3957734,-22.05423 + 1691: -7.423552,-22.998676 + 1692: -8.506886,-23.19312 + 1693: -8.8402195,-23.776455 + 1694: -7.2846637,-23.80423 + 1695: -7.3957734,-22.05423 - node: color: '#FFFFFFE3' id: Flowerspv1 decals: - 4493: -19.928616,2.0766392 + 4480: -19.928616,2.0766392 - node: color: '#9FED5896' id: Flowerspv2 decals: - 3221: -40.505478,-22.24596 - 3222: -40.186035,-23.329292 - 3223: -41.505478,-22.968182 + 3208: -40.505478,-22.24596 + 3209: -40.186035,-23.329292 + 3210: -41.505478,-22.968182 - node: color: '#FFFFFFE3' id: Flowerspv2 decals: - 4492: -19.04829,0.0047369003 - 4494: -18.877905,2.8429594 - 4497: -18.82111,1.3387012 - 4502: -20.028008,-0.22232056 + 4479: -19.04829,0.0047369003 + 4481: -18.877905,2.8429594 + 4484: -18.82111,1.3387012 + 4489: -20.028008,-0.22232056 - node: color: '#FFFFFFFF' id: Flowerspv2 decals: - 3356: -15.688017,-37.836945 + 3343: -15.688017,-37.836945 - node: color: '#9FED5896' id: Flowerspv3 decals: - 3224: -43.172146,-21.537628 - 3225: -40.94992,-18.676516 - 3226: -40.061035,-18.162628 - 3227: -40.436035,-19.176516 - 3228: -43.061035,-17.85707 - 3229: -43.158257,-19.662628 - 3230: -40.99159,-23.49596 + 3211: -43.172146,-21.537628 + 3212: -40.94992,-18.676516 + 3213: -40.061035,-18.162628 + 3214: -40.436035,-19.176516 + 3215: -43.061035,-17.85707 + 3216: -43.158257,-19.662628 + 3217: -40.99159,-23.49596 - node: color: '#FFFFFFE3' id: Flowerspv3 decals: - 4495: -20.0848,3.8505278 - 4496: -19.786627,0.6575284 + 4482: -20.0848,3.8505278 + 4483: -19.786627,0.6575284 - node: color: '#FFFFFFFF' id: Flowerspv3 decals: - 3357: -17.27135,-36.48972 - 3382: -60.00724,38.321278 - 3383: -59.965576,40.001835 - 3384: -59.965576,41.821278 + 3344: -17.27135,-36.48972 + 3369: -60.00724,38.321278 + 3370: -59.965576,40.001835 + 3371: -59.965576,41.821278 - node: color: '#60E25873' id: Flowersy1 decals: - 3374: -60.062798,38.779613 - 3375: -59.965576,40.112946 - 3376: -59.97946,41.404613 + 3361: -60.062798,38.779613 + 3362: -59.965576,40.112946 + 3363: -59.97946,41.404613 - node: color: '#9FED5896' id: Flowersy1 decals: - 3217: -42.811035,-21.551517 - 3218: -42.99159,-18.176516 - 3219: -40.811035,-22.218182 - 3220: -42.894367,-22.87096 + 3204: -42.811035,-21.551517 + 3205: -42.99159,-18.176516 + 3206: -40.811035,-22.218182 + 3207: -42.894367,-22.87096 - node: color: '#A4DF8296' id: Flowersy1 decals: - 1699: -7.4791064,-22.526455 - 1700: -9.145773,-22.720898 - 1701: -8.673552,-23.748676 + 1688: -7.4791064,-22.526455 + 1689: -9.145773,-22.720898 + 1690: -8.673552,-23.748676 - node: color: '#FFFFFFE3' id: Flowersy1 decals: - 4498: -19.005693,3.8079538 + 4485: -19.005693,3.8079538 - node: color: '#FFFFFFE3' id: Flowersy2 decals: - 4499: -19.729832,2.999061 + 4486: -19.729832,2.999061 - node: color: '#9FED5896' id: Flowersy3 decals: - 3215: -41.672146,-22.10707 - 3216: -40.172146,-23.204292 + 3202: -41.672146,-22.10707 + 3203: -40.172146,-23.204292 - node: color: '#FFFFFFE3' id: Flowersy3 decals: - 4500: -19.332266,2.1475945 + 4487: -19.332266,2.1475945 - node: color: '#60E25873' id: Flowersy4 decals: - 3369: -59.937798,42.696278 - 3370: -59.99335,41.751835 - 3371: -60.00724,40.571278 - 3372: -60.062798,39.418503 - 3373: -59.965576,38.085167 + 3356: -59.937798,42.696278 + 3357: -59.99335,41.751835 + 3358: -60.00724,40.571278 + 3359: -60.062798,39.418503 + 3360: -59.965576,38.085167 - node: color: '#9FED5896' id: Flowersy4 decals: - 3212: -40.24159,-18.343182 - 3213: -41.172146,-18.63485 - 3214: -40.283257,-19.10707 + 3199: -40.24159,-18.343182 + 3200: -41.172146,-18.63485 + 3201: -40.283257,-19.10707 - node: color: '#FFFFFFE3' id: Flowersy4 decals: - 4501: -19.687237,1.0832615 + 4488: -19.687237,1.0832615 - node: color: '#D4D4D428' id: FullTileOverlayGreyscale decals: - 4804: 86,-2 - 4805: 85,-2 - 4806: 85,1 - 4807: 86,1 - 4808: 73,1 - 4809: 72,1 - 4810: 72,-2 - 4811: 73,-2 + 4791: 86,-2 + 4792: 85,-2 + 4793: 85,1 + 4794: 86,1 + 4795: 73,1 + 4796: 72,1 + 4797: 72,-2 + 4798: 73,-2 - node: color: '#A4DF8296' id: Grassa4 decals: - 1683: -7.8109317,-1.9877326 + 1672: -7.8109317,-1.9877326 - node: color: '#FFFFFF85' id: Grassd3 decals: - 4476: -19.488453,1.96311 - 4477: -18.70752,2.7436213 - 4478: -18.892103,0.898777 - 4479: -19.829224,-0.023644924 - 4480: -20.0848,2.4456081 - 4481: -20.311981,-0.37842274 + 4463: -19.488453,1.96311 + 4464: -18.70752,2.7436213 + 4465: -18.892103,0.898777 + 4466: -19.829224,-0.023644924 + 4467: -20.0848,2.4456081 + 4468: -20.311981,-0.37842274 - node: color: '#60E25873' id: Grasse1 decals: - 3360: -17.39635,-36.50361 - 3361: -15.813017,-36.434166 - 3362: -15.2157955,-36.545277 - 3363: -15.729685,-37.656387 - 3364: -17.590796,-37.531387 - 3365: -16.063017,-36.961945 - 3366: -15.674128,-37.948055 - 3367: -14.951906,-37.128613 - 3368: -15.229685,-38.073055 + 3347: -17.39635,-36.50361 + 3348: -15.813017,-36.434166 + 3349: -15.2157955,-36.545277 + 3350: -15.729685,-37.656387 + 3351: -17.590796,-37.531387 + 3352: -16.063017,-36.961945 + 3353: -15.674128,-37.948055 + 3354: -14.951906,-37.128613 + 3355: -15.229685,-38.073055 - node: color: '#FFFFFF85' id: Grasse1 decals: - 4482: -20.269386,0.16083956 - 4483: -18.792713,3.3112655 - 4484: -19.147682,2.431417 - 4485: -18.806911,4.205305 + 4469: -20.269386,0.16083956 + 4470: -18.792713,3.3112655 + 4471: -19.147682,2.431417 + 4472: -18.806911,4.205305 - node: color: '#60FF5D92' id: Grasse2 decals: - 4503: -20.0848,0.047310352 - 4504: -19.729832,0.99811506 - 4505: -18.906303,2.4172258 - 4506: -18.9347,3.7937632 - 4507: -19.985409,4.077585 - 4508: -20.028008,2.6726656 - 4509: -19.062489,1.1967907 - 4510: -19.957012,0.88458633 + 4490: -20.0848,0.047310352 + 4491: -19.729832,0.99811506 + 4492: -18.906303,2.4172258 + 4493: -18.9347,3.7937632 + 4494: -19.985409,4.077585 + 4495: -20.028008,2.6726656 + 4496: -19.062489,1.1967907 + 4497: -19.957012,0.88458633 - node: color: '#FFFFFF85' id: Grasse2 decals: - 4473: -19.034092,3.6092787 - 4474: -19.729832,3.0700169 - 4475: -20.0848,2.1475945 + 4460: -19.034092,3.6092787 + 4461: -19.729832,3.0700169 + 4462: -20.0848,2.1475945 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale decals: - 1224: -62,55 - 1225: -61,55 - 1226: -60,55 - 1227: -59,55 - 1228: -58,55 + 1214: -62,55 + 1215: -61,55 + 1216: -60,55 + 1217: -59,55 + 1218: -58,55 - node: color: '#52B4E996' id: HalfTileOverlayGreyscale @@ -4363,140 +4363,140 @@ entities: 297: -32,-42 298: -31,-42 299: -30,-42 - 503: -41,-38 - 4886: -35,-42 - 4887: -34,-42 - 4888: -33,-42 + 493: -41,-38 + 4873: -35,-42 + 4874: -34,-42 + 4875: -33,-42 - node: color: '#A4610696' id: HalfTileOverlayGreyscale decals: - 1039: 35,30 - 1040: 36,30 - 1041: 37,30 - 1048: 39,24 - 1049: 40,24 - 1050: 41,24 - 1051: 42,30 - 1052: 43,30 - 1053: 46,30 - 1054: 47,30 - 1061: 44,30 - 1062: 45,30 - 1507: 35,34 - 1508: 36,34 - 1509: 37,34 - 1510: 38,34 - 1511: 39,34 - 1512: 40,34 - 1513: 41,34 - 1514: 42,37 - 1515: 43,37 - 1516: 44,37 - 1517: 45,37 - 1518: 46,37 - 1519: 47,37 + 1029: 35,30 + 1030: 36,30 + 1031: 37,30 + 1038: 39,24 + 1039: 40,24 + 1040: 41,24 + 1041: 42,30 + 1042: 43,30 + 1043: 46,30 + 1044: 47,30 + 1051: 44,30 + 1052: 45,30 + 1497: 35,34 + 1498: 36,34 + 1499: 37,34 + 1500: 38,34 + 1501: 39,34 + 1502: 40,34 + 1503: 41,34 + 1504: 42,37 + 1505: 43,37 + 1506: 44,37 + 1507: 45,37 + 1508: 46,37 + 1509: 47,37 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale decals: - 1239: -54,31 - 1240: -53,31 - 1241: -52,31 - 1242: -51,31 - 1243: -50,31 - 1244: -49,31 - 1245: -48,31 - 1246: -47,31 - 1247: -46,31 - 1248: -45,31 - 1249: -44,31 - 1250: -43,31 - 1251: -42,31 - 1252: -41,31 - 1253: -40,31 - 1254: -39,31 - 1255: -38,31 - 1256: -37,31 - 1257: -36,31 - 1258: -35,31 - 1314: 17,31 - 1315: 16,31 - 1316: 15,31 - 1317: 14,31 - 1318: 13,31 - 1319: 12,31 - 1320: 11,31 - 1321: 9,31 - 1322: 8,31 - 1323: 7,31 - 1324: 5,31 - 1325: 4,31 - 1326: 3,31 - 1327: 2,31 - 1328: 1,31 - 1329: 0,31 - 1330: -1,31 - 1331: -2,31 - 1332: -3,31 + 1229: -54,31 + 1230: -53,31 + 1231: -52,31 + 1232: -51,31 + 1233: -50,31 + 1234: -49,31 + 1235: -48,31 + 1236: -47,31 + 1237: -46,31 + 1238: -45,31 + 1239: -44,31 + 1240: -43,31 + 1241: -42,31 + 1242: -41,31 + 1243: -40,31 + 1244: -39,31 + 1245: -38,31 + 1246: -37,31 + 1247: -36,31 + 1248: -35,31 + 1304: 17,31 + 1305: 16,31 + 1306: 15,31 + 1307: 14,31 + 1308: 13,31 + 1309: 12,31 + 1310: 11,31 + 1311: 9,31 + 1312: 8,31 + 1313: 7,31 + 1314: 5,31 + 1315: 4,31 + 1316: 3,31 + 1317: 2,31 + 1318: 1,31 + 1319: 0,31 + 1320: -1,31 + 1321: -2,31 + 1322: -3,31 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale decals: - 770: -11,-25 - 771: -10,-25 - 772: -9,-25 - 773: -8,-25 - 774: -7,-25 - 809: -16,-3 - 810: -14,-3 - 811: -12,-3 - 812: -11,-3 - 817: 17,-3 - 818: 18,-3 - 819: 20,-3 - 820: 21,-3 - 821: 23,-3 - 822: 24,-3 - 823: 25,-3 - 824: 26,-3 - 863: 22,-31 - 864: 23,-31 - 865: 24,-31 - 899: 35,4 - 900: 36,4 - 901: 37,4 - 902: 38,4 - 903: 39,4 - 904: 40,4 - 905: 41,4 - 906: 42,4 - 907: 43,4 - 908: 44,4 - 909: 45,4 - 910: 46,4 - 911: 47,4 - 912: 48,4 - 913: 49,4 - 914: 50,4 - 915: 51,4 - 916: 52,4 - 917: 53,4 - 918: 55,4 - 919: 56,4 - 920: 57,4 - 921: 58,4 - 922: 59,4 - 923: 60,4 - 924: 61,4 - 925: 62,4 - 926: 63,4 - 927: 64,4 - 928: 65,4 - 929: 66,4 - 930: 67,4 - 931: 68,4 - 932: 69,4 + 760: -11,-25 + 761: -10,-25 + 762: -9,-25 + 763: -8,-25 + 764: -7,-25 + 799: -16,-3 + 800: -14,-3 + 801: -12,-3 + 802: -11,-3 + 807: 17,-3 + 808: 18,-3 + 809: 20,-3 + 810: 21,-3 + 811: 23,-3 + 812: 24,-3 + 813: 25,-3 + 814: 26,-3 + 853: 22,-31 + 854: 23,-31 + 855: 24,-31 + 889: 35,4 + 890: 36,4 + 891: 37,4 + 892: 38,4 + 893: 39,4 + 894: 40,4 + 895: 41,4 + 896: 42,4 + 897: 43,4 + 898: 44,4 + 899: 45,4 + 900: 46,4 + 901: 47,4 + 902: 48,4 + 903: 49,4 + 904: 50,4 + 905: 51,4 + 906: 52,4 + 907: 53,4 + 908: 55,4 + 909: 56,4 + 910: 57,4 + 911: 58,4 + 912: 59,4 + 913: 60,4 + 914: 61,4 + 915: 62,4 + 916: 63,4 + 917: 64,4 + 918: 65,4 + 919: 66,4 + 920: 67,4 + 921: 68,4 + 922: 69,4 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale @@ -4515,45 +4515,45 @@ entities: 344: 44,-3 345: 45,-3 346: 46,-3 - 391: 34,-7 - 504: -32,27 - 505: -31,27 - 506: -30,27 - 507: -28,27 - 508: -27,27 - 509: -26,27 - 519: -29,26 - 1208: -64,51 - 1209: -63,51 - 1210: -61,51 - 1463: 36,51 - 1464: 37,51 - 1602: 60,-19 - 1603: 61,-19 - 1604: 62,-19 + 383: 34,-7 + 494: -32,27 + 495: -31,27 + 496: -30,27 + 497: -28,27 + 498: -27,27 + 499: -26,27 + 509: -29,26 + 1198: -64,51 + 1199: -63,51 + 1200: -61,51 + 1453: 36,51 + 1454: 37,51 + 1592: 60,-19 + 1593: 61,-19 + 1594: 62,-19 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale decals: - 603: -18,45 - 604: -17,45 - 605: -16,45 - 606: -15,45 - 607: -14,45 - 608: -13,45 - 609: -12,45 - 610: -11,45 - 611: -10,45 + 593: -18,45 + 594: -17,45 + 595: -16,45 + 596: -15,45 + 597: -14,45 + 598: -13,45 + 599: -12,45 + 600: -11,45 + 601: -10,45 - node: color: '#0E7F1BFF' id: HalfTileOverlayGreyscale180 decals: - 4983: 43,-17 + 4961: 43,-17 - node: color: '#1861D5FF' id: HalfTileOverlayGreyscale180 decals: - 4981: 37,-17 + 4959: 37,-17 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale180 @@ -4591,193 +4591,193 @@ entities: 305: -49,-33 306: -51,-33 307: -53,-33 - 1498: -43,-33 - 4883: -33,-45 - 4884: -34,-45 - 4885: -35,-45 + 1488: -43,-33 + 4870: -33,-45 + 4871: -34,-45 + 4872: -35,-45 - node: color: '#951710FF' id: HalfTileOverlayGreyscale180 decals: - 4982: 40,-17 + 4960: 40,-17 - node: color: '#A4610696' id: HalfTileOverlayGreyscale180 decals: - 1036: 35,23 - 1037: 36,23 - 1038: 37,23 - 1055: 47,26 - 1056: 46,26 - 1520: 44,32 - 1521: 45,32 - 1522: 43,32 - 1523: 42,32 - 1524: 41,32 - 1525: 40,32 - 1526: 39,32 - 1527: 38,32 - 1528: 37,32 - 1529: 36,32 - 1530: 35,32 - 1531: 46,32 - 1532: 47,32 + 1026: 35,23 + 1027: 36,23 + 1028: 37,23 + 1045: 47,26 + 1046: 46,26 + 1510: 44,32 + 1511: 45,32 + 1512: 43,32 + 1513: 42,32 + 1514: 41,32 + 1515: 40,32 + 1516: 39,32 + 1517: 38,32 + 1518: 37,32 + 1519: 36,32 + 1520: 35,32 + 1521: 46,32 + 1522: 47,32 - node: color: '#D381C996' id: HalfTileOverlayGreyscale180 decals: - 959: 21,66 - 960: 22,66 - 974: 23,66 - 975: 24,66 + 949: 21,66 + 950: 22,66 + 964: 23,66 + 965: 24,66 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale180 decals: - 1170: -25,29 - 1171: -26,29 - 1172: -27,29 - 1173: -28,29 - 1174: -29,29 - 1175: -30,29 - 1176: -31,29 - 1177: -32,29 - 1178: -33,29 - 1179: -36,29 - 1180: -37,29 - 1181: -38,29 - 1182: -39,29 - 1183: -42,29 - 1184: -43,29 - 1185: -44,29 - 1186: -45,29 - 1187: -46,29 - 1188: -48,29 - 1189: -49,29 - 1190: -50,29 - 1191: -51,29 - 1192: -52,29 - 1193: -53,29 - 1194: -54,29 - 1195: -56,29 - 1196: -57,29 - 1276: -21,29 - 1277: -20,29 - 1278: -19,29 - 1279: -18,29 - 1280: -17,29 - 1281: -16,29 - 1282: -15,29 - 1283: -14,29 - 1284: -13,29 - 1285: -12,29 - 1286: -11,29 - 1287: -10,29 - 1288: -9,29 - 1289: -8,29 - 1290: -5,29 - 1291: -3,30 - 1292: -2,30 - 1293: -1,30 - 1294: 0,30 - 1295: 1,30 - 1296: 2,30 - 1297: 3,30 - 1298: 4,30 - 1299: 5,30 - 1300: 6,30 - 1301: 7,30 - 1302: 8,30 - 1303: 9,30 - 1304: 10,30 - 1305: 11,30 - 1306: 12,30 - 1307: 13,30 - 1308: 14,30 - 1309: 15,30 - 1310: 16,30 - 1311: 17,30 - 1348: -3,49 - 1349: -2,49 - 1350: -1,49 - 1351: 0,49 - 1352: 1,49 - 1353: 2,49 - 1354: 4,49 - 1355: 5,49 - 1356: 6,49 - 1357: 7,49 - 1358: 8,49 - 1359: 9,49 - 1360: 10,49 - 1361: 11,49 - 1362: 12,49 - 1363: 13,49 - 1364: 11,49 - 1365: 13,49 - 1366: 14,49 - 1367: 15,49 - 1368: 16,49 - 1369: 17,49 - 1370: 18,49 - 1371: 19,49 - 1372: 21,49 - 1373: 22,49 - 1374: 23,49 - 1375: 25,49 - 1376: 26,49 - 1377: 24,49 - 1378: 27,49 - 1379: 29,49 - 1380: 28,49 - 1381: 20,49 + 1160: -25,29 + 1161: -26,29 + 1162: -27,29 + 1163: -28,29 + 1164: -29,29 + 1165: -30,29 + 1166: -31,29 + 1167: -32,29 + 1168: -33,29 + 1169: -36,29 + 1170: -37,29 + 1171: -38,29 + 1172: -39,29 + 1173: -42,29 + 1174: -43,29 + 1175: -44,29 + 1176: -45,29 + 1177: -46,29 + 1178: -48,29 + 1179: -49,29 + 1180: -50,29 + 1181: -51,29 + 1182: -52,29 + 1183: -53,29 + 1184: -54,29 + 1185: -56,29 + 1186: -57,29 + 1266: -21,29 + 1267: -20,29 + 1268: -19,29 + 1269: -18,29 + 1270: -17,29 + 1271: -16,29 + 1272: -15,29 + 1273: -14,29 + 1274: -13,29 + 1275: -12,29 + 1276: -11,29 + 1277: -10,29 + 1278: -9,29 + 1279: -8,29 + 1280: -5,29 + 1281: -3,30 + 1282: -2,30 + 1283: -1,30 + 1284: 0,30 + 1285: 1,30 + 1286: 2,30 + 1287: 3,30 + 1288: 4,30 + 1289: 5,30 + 1290: 6,30 + 1291: 7,30 + 1292: 8,30 + 1293: 9,30 + 1294: 10,30 + 1295: 11,30 + 1296: 12,30 + 1297: 13,30 + 1298: 14,30 + 1299: 15,30 + 1300: 16,30 + 1301: 17,30 + 1338: -3,49 + 1339: -2,49 + 1340: -1,49 + 1341: 0,49 + 1342: 1,49 + 1343: 2,49 + 1344: 4,49 + 1345: 5,49 + 1346: 6,49 + 1347: 7,49 + 1348: 8,49 + 1349: 9,49 + 1350: 10,49 + 1351: 11,49 + 1352: 12,49 + 1353: 13,49 + 1354: 11,49 + 1355: 13,49 + 1356: 14,49 + 1357: 15,49 + 1358: 16,49 + 1359: 17,49 + 1360: 18,49 + 1361: 19,49 + 1362: 21,49 + 1363: 22,49 + 1364: 23,49 + 1365: 25,49 + 1366: 26,49 + 1367: 24,49 + 1368: 27,49 + 1369: 29,49 + 1370: 28,49 + 1371: 20,49 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale180 decals: - 759: -4,-26 - 760: -3,-26 - 761: 17,-26 - 762: 18,-26 - 763: -8,-28 - 764: -9,-28 - 765: -10,-28 - 766: -11,-28 - 792: -7,-5 - 793: -9,-5 - 794: -10,-5 - 795: -11,-5 - 796: -13,-5 - 797: -14,-5 - 798: -15,-5 - 799: -16,-5 - 800: -17,-5 - 801: -19,-5 - 802: -22,-5 - 803: -23,-5 - 804: -24,-5 - 805: -40,-5 - 829: 28,-5 - 830: 27,-5 - 831: 26,-5 - 832: 25,-5 - 833: 24,-5 - 834: 23,-5 - 835: 22,-5 - 836: 21,-5 - 866: 24,-36 - 867: 23,-36 - 868: 22,-36 - 933: 65,2 - 934: 66,2 - 935: 67,2 - 936: 68,2 - 937: 69,2 + 749: -4,-26 + 750: -3,-26 + 751: 17,-26 + 752: 18,-26 + 753: -8,-28 + 754: -9,-28 + 755: -10,-28 + 756: -11,-28 + 782: -7,-5 + 783: -9,-5 + 784: -10,-5 + 785: -11,-5 + 786: -13,-5 + 787: -14,-5 + 788: -15,-5 + 789: -16,-5 + 790: -17,-5 + 791: -19,-5 + 792: -22,-5 + 793: -23,-5 + 794: -24,-5 + 795: -40,-5 + 819: 28,-5 + 820: 27,-5 + 821: 26,-5 + 822: 25,-5 + 823: 24,-5 + 824: 23,-5 + 825: 22,-5 + 826: 21,-5 + 856: 24,-36 + 857: 23,-36 + 858: 22,-36 + 923: 65,2 + 924: 66,2 + 925: 67,2 + 926: 68,2 + 927: 69,2 - node: color: '#D58C18FF' id: HalfTileOverlayGreyscale180 decals: - 4984: 46,-17 + 4962: 46,-17 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale180 @@ -4788,179 +4788,179 @@ entities: 333: 44,-1 334: 45,-1 335: 46,-1 - 378: 45,-17 - 381: 42,-17 - 382: 41,-17 - 384: 39,-17 - 385: 38,-17 - 510: -32,25 - 511: -31,25 - 512: -30,25 - 513: -29,25 - 514: -28,25 - 515: -27,25 - 516: -26,25 - 1215: -63,48 - 1219: -62,48 - 1466: 36,48 - 1467: 37,48 - 1605: 60,-23 - 1606: 61,-23 - 1607: 62,-23 - 4980: 44,-17 - 4986: 34,-13 + 374: 45,-17 + 375: 42,-17 + 376: 41,-17 + 377: 39,-17 + 378: 38,-17 + 500: -32,25 + 501: -31,25 + 502: -30,25 + 503: -29,25 + 504: -28,25 + 505: -27,25 + 506: -26,25 + 1205: -63,48 + 1209: -62,48 + 1456: 36,48 + 1457: 37,48 + 1595: 60,-23 + 1596: 61,-23 + 1597: 62,-23 + 4958: 44,-17 + 4964: 34,-13 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale180 decals: - 612: -10,43 - 613: -11,43 - 614: -12,43 - 615: -13,43 - 616: -14,43 - 617: -15,43 - 618: -16,43 - 619: -17,43 - 620: -18,43 + 602: -10,43 + 603: -11,43 + 604: -12,43 + 605: -13,43 + 606: -14,43 + 607: -15,43 + 608: -16,43 + 609: -17,43 + 610: -18,43 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale270 decals: - 1229: -63,54 - 1230: -63,53 - 1539: 18,-60 - 1540: 17,-61 - 1541: 17,-62 - 1542: 18,-63 + 1219: -63,54 + 1220: -63,53 + 1529: 18,-60 + 1530: 17,-61 + 1531: 17,-62 + 1532: 18,-63 - node: color: '#52B4E996' id: HalfTileOverlayGreyscale270 decals: 227: -26,-26 - 4961: -36,-37 - 4962: -35,-37 - 4963: -34,-37 - 4964: -35,-36 - 4965: -35,-38 + 4948: -36,-37 + 4949: -35,-37 + 4950: -34,-37 + 4951: -35,-36 + 4952: -35,-38 - node: color: '#9FED5896' id: HalfTileOverlayGreyscale270 decals: - 1499: -8,-60 - 1500: -9,-61 - 1501: -9,-62 - 1502: -8,-63 + 1489: -8,-60 + 1490: -9,-61 + 1491: -9,-62 + 1492: -8,-63 - node: color: '#A4610696' id: HalfTileOverlayGreyscale270 decals: - 1057: 40,21 - 1058: 40,18 - 1059: 40,19 - 1060: 40,20 - 1070: 41,17 - 1071: 41,16 - 1072: 41,15 - 1073: 41,14 - 1074: 41,13 - 1075: 41,12 + 1047: 40,21 + 1048: 40,18 + 1049: 40,19 + 1050: 40,20 + 1060: 41,17 + 1061: 41,16 + 1062: 41,15 + 1063: 41,14 + 1064: 41,13 + 1065: 41,12 - node: color: '#D381C996' id: HalfTileOverlayGreyscale270 decals: - 947: 18,54 - 948: 18,57 - 949: 18,58 - 950: 18,59 - 951: 18,60 - 952: 18,61 - 953: 18,62 - 954: 18,63 - 955: 18,64 - 956: 18,65 - 957: 18,66 + 937: 18,54 + 938: 18,57 + 939: 18,58 + 940: 18,59 + 941: 18,60 + 942: 18,61 + 943: 18,62 + 944: 18,63 + 945: 18,64 + 946: 18,65 + 947: 18,66 - node: color: '#D4D4D40F' id: HalfTileOverlayGreyscale270 decals: - 4722: -28,18 - 4723: -28,17 + 4709: -28,18 + 4710: -28,17 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale270 decals: - 1142: -24,-1 - 1143: -24,0 - 1144: -24,1 - 1145: -24,2 - 1146: -24,3 - 1147: -24,4 - 1148: -24,5 - 1149: -24,6 - 1150: -24,7 - 1151: -24,8 - 1152: -24,10 - 1153: -24,11 - 1154: -24,12 - 1155: -24,13 - 1156: -24,14 - 1157: -24,15 - 1158: -24,16 - 1159: -24,18 - 1160: -24,19 - 1161: -24,20 - 1162: -24,21 - 1163: -24,22 - 1164: -24,23 - 1165: -24,24 - 1166: -24,26 - 1167: -24,27 - 1198: -58,30 - 1199: -58,31 - 1200: -58,32 + 1132: -24,-1 + 1133: -24,0 + 1134: -24,1 + 1135: -24,2 + 1136: -24,3 + 1137: -24,4 + 1138: -24,5 + 1139: -24,6 + 1140: -24,7 + 1141: -24,8 + 1142: -24,10 + 1143: -24,11 + 1144: -24,12 + 1145: -24,13 + 1146: -24,14 + 1147: -24,15 + 1148: -24,16 + 1149: -24,18 + 1150: -24,19 + 1151: -24,20 + 1152: -24,21 + 1153: -24,22 + 1154: -24,23 + 1155: -24,24 + 1156: -24,26 + 1157: -24,27 + 1188: -58,30 + 1189: -58,31 + 1190: -58,32 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale270 decals: - 728: -7,-30 - 729: -7,-31 - 730: -7,-32 - 731: -7,-36 - 732: -7,-37 - 733: -7,-38 - 734: -7,-39 - 735: -7,-40 - 736: -7,-41 - 737: -7,-45 - 738: -7,-47 - 739: -7,-48 - 740: -7,-49 - 741: -7,-51 - 742: -7,-53 - 743: -7,-54 - 744: -7,-55 - 745: -7,-56 - 746: -7,-57 - 747: -7,-58 - 776: -6,-24 - 777: -6,-23 - 778: -6,-22 - 779: -6,-20 - 780: -6,-19 - 781: -6,-18 - 782: -6,-16 - 783: -6,-15 - 784: -6,-13 - 785: -6,-12 - 786: -6,-11 - 787: -6,-10 - 788: -6,-9 - 789: -6,-8 - 790: -6,-6 - 892: 19,-57 - 893: 19,-56 - 894: 19,-55 - 895: 19,-54 + 718: -7,-30 + 719: -7,-31 + 720: -7,-32 + 721: -7,-36 + 722: -7,-37 + 723: -7,-38 + 724: -7,-39 + 725: -7,-40 + 726: -7,-41 + 727: -7,-45 + 728: -7,-47 + 729: -7,-48 + 730: -7,-49 + 731: -7,-51 + 732: -7,-53 + 733: -7,-54 + 734: -7,-55 + 735: -7,-56 + 736: -7,-57 + 737: -7,-58 + 766: -6,-24 + 767: -6,-23 + 768: -6,-22 + 769: -6,-20 + 770: -6,-19 + 771: -6,-18 + 772: -6,-16 + 773: -6,-15 + 774: -6,-13 + 775: -6,-12 + 776: -6,-11 + 777: -6,-10 + 778: -6,-9 + 779: -6,-8 + 780: -6,-6 + 882: 19,-57 + 883: 19,-56 + 884: 19,-55 + 885: 19,-54 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale270 @@ -4979,214 +4979,214 @@ entities: 354: 34,-9 355: 34,-10 356: 34,-11 - 359: 35,-14 - 360: 35,-15 - 361: 36,-16 - 362: 36,-17 - 518: -32,26 - 1216: -64,49 - 1217: -64,50 - 1461: 35,49 - 1462: 35,50 - 4987: 34,-13 - 4988: 34,-12 + 357: 35,-14 + 358: 35,-15 + 359: 36,-16 + 360: 36,-17 + 508: -32,26 + 1206: -64,49 + 1207: -64,50 + 1451: 35,49 + 1452: 35,50 + 4965: 34,-13 + 4966: 34,-12 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale270 decals: - 583: -21,54 - 584: -21,53 - 585: -21,52 - 586: -21,51 - 587: -21,50 - 588: -21,49 - 589: -21,48 - 590: -21,47 - 591: -21,46 - 592: -21,45 - 593: -21,44 - 594: -21,43 - 595: -21,42 - 596: -21,41 - 597: -21,40 - 598: -21,39 - 599: -21,38 - 600: -21,37 - 601: -21,36 - 602: -21,35 + 573: -21,54 + 574: -21,53 + 575: -21,52 + 576: -21,51 + 577: -21,50 + 578: -21,49 + 579: -21,48 + 580: -21,47 + 581: -21,46 + 582: -21,45 + 583: -21,44 + 584: -21,43 + 585: -21,42 + 586: -21,41 + 587: -21,40 + 588: -21,39 + 589: -21,38 + 590: -21,37 + 591: -21,36 + 592: -21,35 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale90 decals: - 1231: -57,54 - 1232: -57,53 - 1535: 23,-61 - 1536: 23,-62 - 1537: 22,-63 - 1538: 22,-60 + 1221: -57,54 + 1222: -57,53 + 1525: 23,-61 + 1526: 23,-62 + 1527: 22,-63 + 1528: 22,-60 - node: color: '#52B4E996' id: HalfTileOverlayGreyscale90 decals: - 4966: -36,-37 - 4967: -35,-36 - 4968: -35,-37 - 4969: -35,-38 - 4970: -34,-37 + 4953: -36,-37 + 4954: -35,-36 + 4955: -35,-37 + 4956: -35,-38 + 4957: -34,-37 - node: color: '#9FED5896' id: HalfTileOverlayGreyscale90 decals: - 1503: -4,-60 - 1504: -3,-61 - 1505: -3,-62 - 1506: -4,-63 + 1493: -4,-60 + 1494: -3,-61 + 1495: -3,-62 + 1496: -4,-63 - node: color: '#A4610696' id: HalfTileOverlayGreyscale90 decals: - 1063: 45,25 - 1064: 45,24 - 1065: 45,21 - 1066: 45,20 - 1067: 45,19 - 1068: 44,17 - 1069: 44,16 - 1076: 43,12 - 1077: 43,14 - 1078: 43,13 - 1079: 43,15 - 1625: 45,22 - 1626: 45,23 + 1053: 45,25 + 1054: 45,24 + 1055: 45,21 + 1056: 45,20 + 1057: 45,19 + 1058: 44,17 + 1059: 44,16 + 1066: 43,12 + 1067: 43,14 + 1068: 43,13 + 1069: 43,15 + 1614: 45,22 + 1615: 45,23 - node: color: '#D381C996' id: HalfTileOverlayGreyscale90 decals: - 938: 20,56 - 939: 20,57 - 940: 20,58 - 941: 20,59 - 942: 20,61 - 943: 20,62 - 944: 20,63 - 945: 20,64 - 946: 20,65 - 977: 24,67 - 978: 24,68 - 979: 24,70 + 928: 20,56 + 929: 20,57 + 930: 20,58 + 931: 20,59 + 932: 20,61 + 933: 20,62 + 934: 20,63 + 935: 20,64 + 936: 20,65 + 967: 24,67 + 968: 24,68 + 969: 24,70 - node: color: '#D4D4D405' id: HalfTileOverlayGreyscale90 decals: - 4724: -29,18 - 4725: -29,17 + 4711: -29,18 + 4712: -29,17 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale90 decals: - 1124: -22,5 - 1125: -22,7 - 1126: -22,8 - 1127: -22,9 - 1128: -22,10 - 1129: -22,11 - 1130: -22,12 - 1131: -22,13 - 1132: -22,14 - 1133: -22,15 - 1134: -22,17 - 1135: -22,20 - 1136: -22,22 - 1137: -22,23 - 1138: -22,24 - 1139: -22,25 - 1140: -22,26 - 1141: -22,27 - 1202: -56,32 - 1203: -56,33 - 1333: -4,33 - 1334: -4,34 - 1335: -4,36 - 1336: -4,37 - 1337: -4,38 - 1338: -4,39 - 1339: -4,40 - 1340: -4,41 - 1341: -4,42 - 1342: -4,44 - 1343: -4,45 - 1344: -4,46 - 1345: -4,47 - 1346: -4,48 - 4720: -28,18 - 4721: -28,17 + 1114: -22,5 + 1115: -22,7 + 1116: -22,8 + 1117: -22,9 + 1118: -22,10 + 1119: -22,11 + 1120: -22,12 + 1121: -22,13 + 1122: -22,14 + 1123: -22,15 + 1124: -22,17 + 1125: -22,20 + 1126: -22,22 + 1127: -22,23 + 1128: -22,24 + 1129: -22,25 + 1130: -22,26 + 1131: -22,27 + 1192: -56,32 + 1193: -56,33 + 1323: -4,33 + 1324: -4,34 + 1325: -4,36 + 1326: -4,37 + 1327: -4,38 + 1328: -4,39 + 1329: -4,40 + 1330: -4,41 + 1331: -4,42 + 1332: -4,44 + 1333: -4,45 + 1334: -4,46 + 1335: -4,47 + 1336: -4,48 + 4707: -28,18 + 4708: -28,17 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale90 decals: - 748: -5,-58 - 749: -5,-57 - 750: -5,-56 - 751: -5,-55 - 752: -5,-54 - 753: -5,-53 - 754: -5,-51 - 755: -5,-50 - 756: -5,-28 - 757: -5,-27 - 807: -41,-11 - 826: 29,-3 - 827: 29,-4 - 838: 20,-6 - 839: 20,-8 - 840: 20,-9 - 841: 20,-10 - 842: 20,-11 - 843: 20,-12 - 844: 20,-14 - 845: 20,-15 - 846: 20,-16 - 849: 21,-18 - 850: 21,-19 - 851: 21,-20 - 852: 21,-21 - 853: 21,-22 - 854: 21,-23 - 855: 21,-24 - 856: 21,-25 - 857: 21,-26 - 858: 21,-27 - 859: 21,-28 - 860: 21,-29 - 861: 21,-30 - 870: 21,-38 - 871: 21,-39 - 872: 21,-40 - 873: 21,-41 - 874: 21,-42 - 875: 21,-43 - 876: 21,-44 - 877: 21,-45 - 878: 21,-46 - 879: 21,-47 - 880: 21,-48 - 881: 21,-49 - 882: 21,-50 - 883: 21,-51 - 884: 21,-52 - 885: 21,-53 - 886: 21,-54 - 887: 21,-55 - 888: 21,-56 - 889: 21,-57 - 896: 29,-1 - 897: 29,0 - 898: 29,1 + 738: -5,-58 + 739: -5,-57 + 740: -5,-56 + 741: -5,-55 + 742: -5,-54 + 743: -5,-53 + 744: -5,-51 + 745: -5,-50 + 746: -5,-28 + 747: -5,-27 + 797: -41,-11 + 816: 29,-3 + 817: 29,-4 + 828: 20,-6 + 829: 20,-8 + 830: 20,-9 + 831: 20,-10 + 832: 20,-11 + 833: 20,-12 + 834: 20,-14 + 835: 20,-15 + 836: 20,-16 + 839: 21,-18 + 840: 21,-19 + 841: 21,-20 + 842: 21,-21 + 843: 21,-22 + 844: 21,-23 + 845: 21,-24 + 846: 21,-25 + 847: 21,-26 + 848: 21,-27 + 849: 21,-28 + 850: 21,-29 + 851: 21,-30 + 860: 21,-38 + 861: 21,-39 + 862: 21,-40 + 863: 21,-41 + 864: 21,-42 + 865: 21,-43 + 866: 21,-44 + 867: 21,-45 + 868: 21,-46 + 869: 21,-47 + 870: 21,-48 + 871: 21,-49 + 872: 21,-50 + 873: 21,-51 + 874: 21,-52 + 875: 21,-53 + 876: 21,-54 + 877: 21,-55 + 878: 21,-56 + 879: 21,-57 + 886: 29,-1 + 887: 29,0 + 888: 29,1 - node: color: '#D58C18FF' id: HalfTileOverlayGreyscale90 decals: - 4985: 46,-17 + 4963: 46,-17 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale90 @@ -5196,279 +5196,279 @@ entities: 327: 47,1 328: 47,0 329: 47,-1 - 363: 46,-11 - 364: 46,-10 - 365: 46,-9 - 366: 46,-8 - 367: 46,-7 - 368: 47,-6 - 369: 47,-5 - 370: 47,-4 - 517: -26,26 - 1212: -61,50 - 1213: -61,49 - 1455: 38,51 - 1456: 38,50 - 1457: 38,49 - 1608: 46,-16 - 1609: 46,-13 + 361: 46,-11 + 362: 46,-10 + 363: 46,-9 + 364: 46,-8 + 365: 46,-7 + 366: 47,-6 + 367: 47,-5 + 368: 47,-4 + 507: -26,26 + 1202: -61,50 + 1203: -61,49 + 1445: 38,51 + 1446: 38,50 + 1447: 38,49 + 1598: 46,-16 + 1599: 46,-13 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale90 decals: - 566: -19,35 - 567: -19,36 - 568: -19,37 - 569: -19,38 - 570: -19,39 - 571: -19,40 - 572: -19,41 - 573: -19,42 - 574: -19,46 - 575: -19,47 - 576: -19,48 - 577: -19,49 - 578: -19,50 - 579: -19,51 - 580: -19,52 - 581: -19,53 - 582: -19,54 + 556: -19,35 + 557: -19,36 + 558: -19,37 + 559: -19,38 + 560: -19,39 + 561: -19,40 + 562: -19,41 + 563: -19,42 + 564: -19,46 + 565: -19,47 + 566: -19,48 + 567: -19,49 + 568: -19,50 + 569: -19,51 + 570: -19,52 + 571: -19,53 + 572: -19,54 - node: color: '#EFB34196' id: LoadingArea decals: - 489: 75,10 - 490: 76,10 + 479: 75,10 + 480: 76,10 - node: angle: 3.141592653589793 rad color: '#EFB34196' id: LoadingArea decals: - 491: 82,10 - 492: 83,10 + 481: 82,10 + 482: 83,10 - node: angle: 4.71238898038469 rad color: '#EFB34196' id: LoadingArea decals: - 1047: 36,29 - 1204: -64,46 - 1205: -64,40 - 1206: -64,38 - 1220: -64,48 + 1037: 36,29 + 1194: -64,46 + 1195: -64,40 + 1196: -64,38 + 1210: -64,48 - node: color: '#334E6DC8' id: LoadingAreaGreyscale decals: - 498: -5,-2 + 488: -5,-2 - node: angle: 3.141592653589793 rad color: '#334E6DC8' id: LoadingAreaGreyscale decals: - 499: -9,-2 + 489: -9,-2 - node: color: '#52B4E996' id: MiniTileCheckerAOverlay decals: - 3621: 26,-35 - 3622: 27,-35 - 3623: 28,-35 - 3624: 29,-35 - 3625: 30,-35 - 3626: 30,-34 - 3627: 29,-34 - 3628: 28,-34 - 3629: 27,-34 - 3630: 26,-34 - 3631: 26,-33 - 3632: 26,-32 - 3633: 27,-32 - 3634: 28,-32 - 3635: 29,-32 - 3636: 30,-32 - 3637: 30,-33 - 3638: 29,-33 - 3639: 28,-33 - 3640: 27,-33 + 3608: 26,-35 + 3609: 27,-35 + 3610: 28,-35 + 3611: 29,-35 + 3612: 30,-35 + 3613: 30,-34 + 3614: 29,-34 + 3615: 28,-34 + 3616: 27,-34 + 3617: 26,-34 + 3618: 26,-33 + 3619: 26,-32 + 3620: 27,-32 + 3621: 28,-32 + 3622: 29,-32 + 3623: 30,-32 + 3624: 30,-33 + 3625: 29,-33 + 3626: 28,-33 + 3627: 27,-33 - node: color: '#334E6DC8' id: MiniTileCheckerBOverlay decals: - 4687: -33,18 - 4688: -33,17 - 4689: -32,17 - 4690: -31,17 - 4691: -31,18 - 4692: -32,18 + 4674: -33,18 + 4675: -33,17 + 4676: -32,17 + 4677: -31,17 + 4678: -31,18 + 4679: -32,18 - node: color: '#FFFFFFFF' id: MiniTileCheckerBOverlay decals: - 3641: 26,-32 - 3642: 26,-33 - 3643: 26,-34 - 3644: 26,-35 - 3645: 27,-35 - 3646: 28,-35 - 3647: 29,-35 - 3648: 30,-35 - 3649: 30,-34 - 3650: 30,-33 - 3651: 30,-32 - 3652: 29,-32 - 3653: 28,-32 - 3654: 27,-32 - 3655: 27,-33 - 3656: 27,-34 - 3657: 28,-34 - 3658: 28,-33 - 3659: 29,-33 - 3660: 29,-34 + 3628: 26,-32 + 3629: 26,-33 + 3630: 26,-34 + 3631: 26,-35 + 3632: 27,-35 + 3633: 28,-35 + 3634: 29,-35 + 3635: 30,-35 + 3636: 30,-34 + 3637: 30,-33 + 3638: 30,-32 + 3639: 29,-32 + 3640: 28,-32 + 3641: 27,-32 + 3642: 27,-33 + 3643: 27,-34 + 3644: 28,-34 + 3645: 28,-33 + 3646: 29,-33 + 3647: 29,-34 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerNe decals: - 3445: 46,36 + 3432: 46,36 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerNw decals: - 3443: 43,36 + 3430: 43,36 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerSe decals: - 3444: 46,33 + 3431: 46,33 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerSw decals: - 3442: 43,33 + 3429: 43,33 - node: color: '#FFFFFFFF' id: MiniTileDarkInnerSw decals: - 3472: -24,-18 + 3459: -24,-18 - node: color: '#FFFFFFFF' id: MiniTileDarkLineE decals: - 3448: 46,35 - 3449: 46,34 + 3435: 46,35 + 3436: 46,34 - node: color: '#FFFFFFFF' id: MiniTileDarkLineN decals: - 3446: 44,36 - 3447: 45,36 + 3433: 44,36 + 3434: 45,36 - node: color: '#FFFFFFFF' id: MiniTileDarkLineS decals: - 3450: 44,33 - 3451: 45,33 - 3473: -25,-18 - 3474: -26,-18 - 3475: -27,-18 - 3483: 25,-1 - 3484: 25,-1 + 3437: 44,33 + 3438: 45,33 + 3460: -25,-18 + 3461: -26,-18 + 3462: -27,-18 + 3470: 25,-1 + 3471: 25,-1 - node: color: '#FFFFFFFF' id: MiniTileDarkLineW decals: - 3452: 43,34 - 3453: 43,35 - 3469: -24,-21 - 3470: -24,-20 - 3471: -24,-19 + 3439: 43,34 + 3440: 43,35 + 3456: -24,-21 + 3457: -24,-20 + 3458: -24,-19 - node: color: '#666C6CA4' id: MiniTileDiagonalCheckerBOverlay decals: - 4295: 58,-37 - 4296: 58,-38 - 4297: 59,-38 - 4298: 59,-37 + 4282: 58,-37 + 4283: 58,-38 + 4284: 59,-38 + 4285: 59,-37 - node: color: '#FFFFFFFF' id: MiniTileSteelEndE decals: - 3455: 41,-9 + 3442: 41,-9 - node: color: '#FFFFFFFF' id: MiniTileSteelEndW decals: - 3454: 39,-9 + 3441: 39,-9 - node: color: '#FFFFFFFF' id: MiniTileSteelLineN decals: - 3456: 40,-9 + 3443: 40,-9 - node: color: '#FFFFFFFF' id: MiniTileSteelLineS decals: - 3457: 40,-9 + 3444: 40,-9 - node: color: '#52B4E996' id: MiniTileWhiteCornerNe decals: - 4894: -40,-43 + 4881: -40,-43 - node: zIndex: 1 color: '#52B4E996' id: MiniTileWhiteCornerNe decals: - 4907: -42,-40 + 4894: -42,-40 - node: color: '#52B4E996' id: MiniTileWhiteCornerNw decals: - 4895: -44,-40 + 4882: -44,-40 - node: color: '#52B4E996' id: MiniTileWhiteCornerSe decals: - 4892: -40,-45 + 4879: -40,-45 - node: color: '#52B4E996' id: MiniTileWhiteCornerSw decals: - 4893: -44,-45 + 4880: -44,-45 - node: color: '#52B4E996' id: MiniTileWhiteInnerNe decals: - 4896: -42,-43 + 4883: -42,-43 - node: color: '#52B4E996' id: MiniTileWhiteLineE decals: - 4902: -42,-41 - 4903: -42,-42 - 4908: -40,-44 + 4889: -42,-41 + 4890: -42,-42 + 4895: -40,-44 - node: color: '#52B4E996' id: MiniTileWhiteLineN decals: - 4900: -43,-40 - 4901: -41,-43 + 4887: -43,-40 + 4888: -41,-43 - node: color: '#52B4E996' id: MiniTileWhiteLineS decals: - 4889: -43,-45 - 4890: -42,-45 - 4891: -41,-45 + 4876: -43,-45 + 4877: -42,-45 + 4878: -41,-45 - node: color: '#52B4E996' id: MiniTileWhiteLineW decals: - 4897: -44,-43 - 4898: -44,-42 - 4899: -44,-41 - 4909: -44,-44 + 4884: -44,-43 + 4885: -44,-42 + 4886: -44,-41 + 4896: -44,-44 - node: color: '#334E6DC8' id: QuarterTileOverlayGreyscale @@ -5525,13 +5525,13 @@ entities: 217: -23,-33 218: -24,-33 231: -26,-34 - 687: 25,10 - 688: 27,10 - 689: 29,10 - 694: 25,6 - 695: 24,7 - 696: 24,9 - 3284: -26,-27 + 677: 25,10 + 678: 27,10 + 679: 29,10 + 684: 25,6 + 685: 24,7 + 686: 24,9 + 3271: -26,-27 - node: color: '#9FED5896' id: QuarterTileOverlayGreyscale @@ -5584,18 +5584,18 @@ entities: color: '#D4D4D433' id: QuarterTileOverlayGreyscale decals: - 768: -11,-28 - 775: -6,-25 - 825: 27,-3 - 891: 19,-58 + 758: -11,-28 + 765: -6,-25 + 815: 27,-3 + 881: 19,-58 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale decals: - 392: 35,-7 - 520: -32,25 - 523: -28,26 - 1465: 38,51 + 384: 35,-7 + 510: -32,25 + 513: -28,26 + 1455: 38,51 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale @@ -5624,56 +5624,56 @@ entities: 44: 27,0 45: 27,-1 46: 27,-2 - 528: -33,31 - 529: -32,31 - 530: -31,31 - 531: -30,31 - 532: -29,31 - 533: -28,31 - 534: -27,31 - 535: -26,31 - 536: -25,31 - 537: -24,31 - 538: -23,31 - 539: -22,31 - 540: -21,31 - 541: -21,32 - 625: -19,54 - 642: -28,39 - 643: -27,39 - 644: -26,39 - 645: -25,39 - 646: -24,39 - 647: -23,39 - 648: -28,38 - 649: -28,37 - 652: -11,41 - 653: -12,41 - 654: -13,41 - 655: -14,41 - 656: -15,41 - 657: -16,41 - 658: -17,41 - 659: -17,40 - 660: -17,39 - 661: -17,38 - 662: -17,37 - 663: -17,36 - 664: -17,35 - 677: 24,10 - 678: 26,10 - 679: 28,10 - 686: 24,8 - 1404: -6,37 - 1405: -6,36 - 1406: -6,35 - 1407: -6,34 - 1408: -6,33 - 1431: -6,38 - 1432: -6,39 - 1433: -6,40 - 1434: -6,41 - 1435: -6,42 + 518: -33,31 + 519: -32,31 + 520: -31,31 + 521: -30,31 + 522: -29,31 + 523: -28,31 + 524: -27,31 + 525: -26,31 + 526: -25,31 + 527: -24,31 + 528: -23,31 + 529: -22,31 + 530: -21,31 + 531: -21,32 + 615: -19,54 + 632: -28,39 + 633: -27,39 + 634: -26,39 + 635: -25,39 + 636: -24,39 + 637: -23,39 + 638: -28,38 + 639: -28,37 + 642: -11,41 + 643: -12,41 + 644: -13,41 + 645: -14,41 + 646: -15,41 + 647: -16,41 + 648: -17,41 + 649: -17,40 + 650: -17,39 + 651: -17,38 + 652: -17,37 + 653: -17,36 + 654: -17,35 + 667: 24,10 + 668: 26,10 + 669: 28,10 + 676: 24,8 + 1394: -6,37 + 1395: -6,36 + 1396: -6,35 + 1397: -6,34 + 1398: -6,33 + 1421: -6,38 + 1422: -6,39 + 1423: -6,40 + 1424: -6,41 + 1425: -6,42 - node: color: '#52B4E996' id: QuarterTileOverlayGreyscale180 @@ -5698,76 +5698,76 @@ entities: 226: -22,-27 228: -26,-26 229: -27,-26 - 690: 29,9 - 691: 29,7 - 692: 28,6 - 693: 26,6 - 3285: -25,-27 + 680: 29,9 + 681: 29,7 + 682: 28,6 + 683: 26,6 + 3272: -25,-27 - node: color: '#A4610696' id: QuarterTileOverlayGreyscale180 decals: - 1627: 45,26 - 1628: 43,16 + 1616: 45,26 + 1617: 43,16 - node: color: '#D381C996' id: QuarterTileOverlayGreyscale180 decals: - 961: 20,66 - 980: 24,71 + 951: 20,66 + 970: 24,71 - node: color: '#D4D4D419' id: QuarterTileOverlayGreyscale180 decals: - 1169: -22,29 - 1347: -4,49 + 1159: -22,29 + 1337: -4,49 - node: color: '#D4D4D433' id: QuarterTileOverlayGreyscale180 decals: - 758: -5,-26 - 806: -41,-5 - 837: 20,-5 - 869: 21,-36 + 748: -5,-26 + 796: -41,-5 + 827: 20,-5 + 859: 21,-36 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale180 decals: 238: -27,-40 336: 43,-1 - 372: 35,-15 - 373: 36,-17 - 374: 33,-8 - 393: 46,-6 - 524: -26,27 - 525: -30,27 - 1211: -61,51 - 1610: 46,-12 + 369: 35,-15 + 370: 36,-17 + 371: 33,-8 + 385: 46,-6 + 514: -26,27 + 515: -30,27 + 1201: -61,51 + 1600: 46,-12 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale180 decals: - 622: -19,43 - 650: -24,36 - 651: -23,36 - 665: -17,35 - 666: -16,35 - 667: -15,35 - 668: -14,35 - 669: -13,35 - 670: -13,36 - 671: -13,37 - 672: -13,38 - 673: -12,38 - 674: -11,38 - 680: 29,10 - 681: 29,8 - 682: 29,6 - 683: 27,6 - 684: 25,6 - 685: 24,7 - 1436: -7,43 - 1437: -8,43 + 612: -19,43 + 640: -24,36 + 641: -23,36 + 655: -17,35 + 656: -16,35 + 657: -15,35 + 658: -14,35 + 659: -13,35 + 660: -13,36 + 661: -13,37 + 662: -13,38 + 663: -12,38 + 664: -11,38 + 670: 29,10 + 671: 29,8 + 672: 29,6 + 673: 27,6 + 674: 25,6 + 675: 24,7 + 1426: -7,43 + 1427: -8,43 - node: color: '#52B4E996' id: QuarterTileOverlayGreyscale270 @@ -5782,11 +5782,11 @@ entities: 186: -13,-27 230: -26,-33 232: -26,-34 - 425: 51,-13 - 426: 51,-12 - 1599: 53,-14 - 1600: 52,-14 - 1601: 51,-14 + 415: 51,-13 + 416: 51,-12 + 1589: 53,-14 + 1590: 52,-14 + 1591: 51,-14 - node: color: '#9FED5896' id: QuarterTileOverlayGreyscale270 @@ -5798,35 +5798,35 @@ entities: color: '#A4610696' id: QuarterTileOverlayGreyscale270 decals: - 1629: 44,16 + 1618: 44,16 - node: color: '#D381C996' id: QuarterTileOverlayGreyscale270 decals: - 958: 18,67 - 1013: 11,58 - 1014: 11,57 - 1015: 11,56 - 1016: 11,55 - 1017: 11,54 - 1018: 11,53 - 1019: 12,53 + 948: 18,67 + 1003: 11,58 + 1004: 11,57 + 1005: 11,56 + 1006: 11,55 + 1007: 11,54 + 1008: 11,53 + 1009: 12,53 - node: color: '#D4D4D419' id: QuarterTileOverlayGreyscale270 decals: - 1168: -24,29 - 1312: 18,30 + 1158: -24,29 + 1302: 18,30 - node: color: '#D4D4D433' id: QuarterTileOverlayGreyscale270 decals: - 767: -7,-28 - 769: -11,-27 - 791: -6,-5 - 815: 17,-5 - 816: 18,-6 - 828: 29,-5 + 757: -7,-28 + 759: -11,-27 + 781: -6,-5 + 805: 17,-5 + 806: 18,-6 + 818: 29,-5 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale270 @@ -5863,54 +5863,54 @@ entities: 89: 64,2 237: -25,-40 337: 47,-1 - 375: 47,-6 - 387: 35,-13 - 388: 36,-15 - 389: 34,-8 - 400: 37,-6 - 401: 38,-6 - 402: 39,-6 - 403: 40,-6 - 404: 41,-6 - 405: 42,-6 - 406: 43,-6 - 407: 44,-6 - 408: 44,-7 - 409: 44,-8 - 410: 44,-9 - 411: 44,-10 - 412: 44,-11 - 427: 49,-3 - 428: 50,-3 - 429: 51,-3 - 430: 52,-3 - 431: 53,-3 - 432: 54,-3 - 433: 55,-3 - 434: 56,-3 - 444: 49,-1 - 445: 49,-2 - 446: 58,0 - 447: 58,-1 - 448: 58,-2 - 449: 58,-3 - 450: 59,-3 - 451: 60,-3 - 452: 61,-3 - 453: 62,-3 - 526: -28,27 - 527: -32,27 - 1218: -64,51 + 372: 47,-6 + 379: 35,-13 + 380: 36,-15 + 381: 34,-8 + 392: 37,-6 + 393: 38,-6 + 394: 39,-6 + 395: 40,-6 + 396: 41,-6 + 397: 42,-6 + 398: 43,-6 + 399: 44,-6 + 400: 44,-7 + 401: 44,-8 + 402: 44,-9 + 403: 44,-10 + 404: 44,-11 + 417: 49,-3 + 418: 50,-3 + 419: 51,-3 + 420: 52,-3 + 421: 53,-3 + 422: 54,-3 + 423: 55,-3 + 424: 56,-3 + 434: 49,-1 + 435: 49,-2 + 436: 58,0 + 437: 58,-1 + 438: 58,-2 + 439: 58,-3 + 440: 59,-3 + 441: 60,-3 + 442: 61,-3 + 443: 62,-3 + 516: -28,27 + 517: -32,27 + 1208: -64,51 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale270 decals: - 1425: -6,51 - 1426: -6,50 - 1427: -6,49 - 1428: -6,48 - 1429: -6,47 - 1430: -6,46 + 1415: -6,51 + 1416: -6,50 + 1417: -6,49 + 1418: -6,48 + 1419: -6,47 + 1420: -6,46 - node: color: '#334E6DC8' id: QuarterTileOverlayGreyscale90 @@ -5934,11 +5934,11 @@ entities: decals: 233: -26,-34 234: -27,-34 - 420: 53,-12 - 421: 52,-12 - 422: 51,-12 - 423: 53,-13 - 424: 53,-14 + 410: 53,-12 + 411: 52,-12 + 412: 51,-12 + 413: 53,-13 + 414: 53,-14 - node: color: '#9FED5896' id: QuarterTileOverlayGreyscale90 @@ -5998,672 +5998,672 @@ entities: 21: 33,20 22: 33,19 90: 33,7 - 1440: 33,23 - 1441: 33,24 - 1442: 33,25 - 1443: 33,26 - 1444: 33,27 - 1445: 33,28 - 1446: 33,29 - 1447: 33,30 - 3984: 33,35 + 1430: 33,23 + 1431: 33,24 + 1432: 33,25 + 1433: 33,26 + 1434: 33,27 + 1435: 33,28 + 1436: 33,29 + 1437: 33,30 + 3971: 33,35 - node: color: '#D381C996' id: QuarterTileOverlayGreyscale90 decals: - 561: 25,51 - 562: 24,51 - 563: 23,51 - 564: 22,51 - 565: 21,51 - 976: 24,66 - 1006: 16,57 - 1007: 16,58 - 1008: 15,58 - 1009: 14,58 - 1010: 13,58 - 1011: 12,58 - 1012: 11,58 - 1382: 20,51 - 1383: 19,51 - 1384: 18,51 - 1385: 17,51 - 1386: 16,51 - 1387: 12,51 - 1388: 11,51 - 1389: 10,51 - 1390: 9,51 - 1391: 8,51 - 1392: 7,51 - 1393: 6,51 - 1394: 5,51 - 1395: 4,51 + 551: 25,51 + 552: 24,51 + 553: 23,51 + 554: 22,51 + 555: 21,51 + 966: 24,66 + 996: 16,57 + 997: 16,58 + 998: 15,58 + 999: 14,58 + 1000: 13,58 + 1001: 12,58 + 1002: 11,58 + 1372: 20,51 + 1373: 19,51 + 1374: 18,51 + 1375: 17,51 + 1376: 16,51 + 1377: 12,51 + 1378: 11,51 + 1379: 10,51 + 1380: 9,51 + 1381: 8,51 + 1382: 7,51 + 1383: 6,51 + 1384: 5,51 + 1385: 4,51 - node: color: '#D4D4D419' id: QuarterTileOverlayGreyscale90 decals: - 1201: -56,31 + 1191: -56,31 - node: color: '#D4D4D433' id: QuarterTileOverlayGreyscale90 decals: - 848: 20,-17 - 862: 21,-31 - 890: 21,-58 + 838: 20,-17 + 852: 21,-31 + 880: 21,-58 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale90 decals: 347: 37,-3 - 376: 46,-12 - 390: 33,-7 - 394: 36,-12 - 395: 36,-11 - 396: 36,-10 - 397: 36,-9 - 398: 36,-8 - 399: 36,-7 - 413: 43,-12 - 414: 42,-12 - 415: 41,-12 - 416: 40,-12 - 417: 39,-12 - 435: 56,-3 - 436: 56,-2 - 437: 56,-1 - 438: 54,-1 - 439: 53,-1 - 440: 52,-1 - 441: 51,-1 - 442: 50,-1 - 443: 49,-1 - 454: 62,-3 - 455: 62,-2 - 456: 62,-1 - 457: 62,0 - 458: 61,0 - 459: 60,0 - 460: 59,0 - 461: 58,0 - 521: -26,25 - 522: -30,26 - 4989: 37,-12 - 4990: 38,-12 + 373: 46,-12 + 382: 33,-7 + 386: 36,-12 + 387: 36,-11 + 388: 36,-10 + 389: 36,-9 + 390: 36,-8 + 391: 36,-7 + 405: 43,-12 + 406: 42,-12 + 407: 41,-12 + 408: 40,-12 + 409: 39,-12 + 425: 56,-3 + 426: 56,-2 + 427: 56,-1 + 428: 54,-1 + 429: 53,-1 + 430: 52,-1 + 431: 51,-1 + 432: 50,-1 + 433: 49,-1 + 444: 62,-3 + 445: 62,-2 + 446: 62,-1 + 447: 62,0 + 448: 61,0 + 449: 60,0 + 450: 59,0 + 451: 58,0 + 511: -26,25 + 512: -30,26 + 4967: 37,-12 + 4968: 38,-12 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale90 decals: - 542: -19,32 - 543: -19,31 - 544: -18,31 - 545: -17,31 - 546: -16,31 - 547: -15,31 - 548: -14,31 - 549: -13,31 - 550: -12,31 - 551: -11,31 - 552: -10,31 - 553: -9,31 - 554: -8,31 - 621: -19,45 - 626: -20,54 - 1396: 2,51 - 1397: 1,51 - 1398: -1,51 - 1399: -2,51 - 1400: -3,51 - 1401: -4,51 - 1402: -5,51 - 1403: -6,51 - 1438: -7,45 - 1439: -8,45 + 532: -19,32 + 533: -19,31 + 534: -18,31 + 535: -17,31 + 536: -16,31 + 537: -15,31 + 538: -14,31 + 539: -13,31 + 540: -12,31 + 541: -11,31 + 542: -10,31 + 543: -9,31 + 544: -8,31 + 611: -19,45 + 616: -20,54 + 1386: 2,51 + 1387: 1,51 + 1388: -1,51 + 1389: -2,51 + 1390: -3,51 + 1391: -4,51 + 1392: -5,51 + 1393: -6,51 + 1428: -7,45 + 1429: -8,45 - node: color: '#FFFFFFFF' id: Remains decals: - 3318: -29.994413,-49.927315 + 3305: -29.994413,-49.927315 - node: color: '#60E25873' id: Rock01 decals: - 3377: -59.92391,38.210167 - 3378: -59.99335,38.974056 - 3379: -59.99335,39.946278 - 3380: -59.965576,41.015724 - 3381: -59.965576,42.321278 + 3364: -59.92391,38.210167 + 3365: -59.99335,38.974056 + 3366: -59.99335,39.946278 + 3367: -59.965576,41.015724 + 3368: -59.965576,42.321278 - node: color: '#9FED5896' id: Rock01 decals: - 3462: 24.034931,-33.3361 - 3463: 23.951597,-33.863876 + 3449: 24.034931,-33.3361 + 3450: 23.951597,-33.863876 - node: color: '#9FED5873' id: Rock02 decals: - 3311: 78.26405,7.9695406 - 3312: 79.31961,7.983429 - 3313: 79.93072,7.941762 - 3314: 78.26405,7.9556513 + 3298: 78.26405,7.9695406 + 3299: 79.31961,7.983429 + 3300: 79.93072,7.941762 + 3301: 78.26405,7.9556513 - node: color: '#9FED5896' id: Rock02 decals: - 3197: -40.422146,-22.63485 - 3198: -41.797146,-22.468182 - 3199: -42.797146,-21.815403 - 3200: -42.297146,-22.87096 - 3201: -43.158257,-18.593182 - 3202: -43.047146,-19.73207 - 3203: -40.61659,-18.329292 - 3204: -39.922146,-18.940403 - 3205: -39.797146,-22.565403 - 3206: -39.86659,-23.50985 - 3207: -41.283257,-21.787628 - 3208: -42.797146,-20.87096 - 3209: -42.7277,-17.940403 - 3210: -41.061035,-18.12096 - 3211: -41.21381,-19.176516 + 3184: -40.422146,-22.63485 + 3185: -41.797146,-22.468182 + 3186: -42.797146,-21.815403 + 3187: -42.297146,-22.87096 + 3188: -43.158257,-18.593182 + 3189: -43.047146,-19.73207 + 3190: -40.61659,-18.329292 + 3191: -39.922146,-18.940403 + 3192: -39.797146,-22.565403 + 3193: -39.86659,-23.50985 + 3194: -41.283257,-21.787628 + 3195: -42.797146,-20.87096 + 3196: -42.7277,-17.940403 + 3197: -41.061035,-18.12096 + 3198: -41.21381,-19.176516 - node: color: '#9FED5896' id: Rock05 decals: - 3458: 23.909931,-33.22499 - 3459: 24.007153,-33.9611 + 3445: 23.909931,-33.22499 + 3446: 24.007153,-33.9611 - node: color: '#FFFFFFFF' id: Rock05 decals: - 4774: -1.8656068,46.688976 + 4761: -1.8656068,46.688976 - node: color: '#FFFFFFFF' id: Rock07 decals: - 3317: -16.459831,-40.314075 + 3304: -16.459831,-40.314075 - node: cleanable: True color: '#FFFFFFFF' id: Rust decals: - 3292: -64,-33 - 3293: -65,-33 - 3294: -63,-33 + 3279: -64,-33 + 3280: -65,-33 + 3281: -63,-33 - node: color: '#B78FB4FF' id: SpaceStationSign1 decals: - 1543: 4,-4 + 1533: 4,-4 - node: color: '#B78FB4FF' id: SpaceStationSign2 decals: - 1544: 5,-4 + 1534: 5,-4 - node: color: '#B78FB4FF' id: SpaceStationSign3 decals: - 1545: 6,-4 + 1535: 6,-4 - node: color: '#B78FB4FF' id: SpaceStationSign4 decals: - 1546: 7,-4 + 1536: 7,-4 - node: color: '#B78FB4FF' id: SpaceStationSign5 decals: - 1547: 8,-4 + 1537: 8,-4 - node: color: '#B78FB4FF' id: SpaceStationSign6 decals: - 1548: 9,-4 + 1538: 9,-4 - node: color: '#B78FB4FF' id: SpaceStationSign7 decals: - 1549: 10,-4 + 1539: 10,-4 - node: color: '#A4610696' id: StandClear decals: - 3976: 34,20 - 3977: 34,19 - 3978: 34,20 - 3979: 34,19 - 3980: 39,20 - 3981: 39,19 - 3982: 39,20 - 3983: 39,19 + 3963: 34,20 + 3964: 34,19 + 3965: 34,20 + 3966: 34,19 + 3967: 39,20 + 3968: 39,19 + 3969: 39,20 + 3970: 39,19 - node: color: '#EFB34196' id: StandClear decals: - 462: 35,-2 - 463: 36,-2 - 464: 37,-2 - 719: 23,14 - 720: 23,13 - 721: 23,12 - 1043: 37,26 - 1551: 34,14 - 1552: 34,13 - 1553: 34,12 - 1554: 53,-26 - 1555: 53,-27 - 1556: 53,-28 - 1557: 53,-29 - 1558: 53,-30 - 1559: 53,-31 - 1560: 56,-31 - 1561: 56,-30 - 1562: 56,-29 - 1563: 56,-28 - 1564: 56,-27 - 1565: 56,-26 - 1630: -22,50 - 1631: -22,49 - 1632: -22,48 - 1633: -22,47 + 452: 35,-2 + 453: 36,-2 + 454: 37,-2 + 709: 23,14 + 710: 23,13 + 711: 23,12 + 1033: 37,26 + 1541: 34,14 + 1542: 34,13 + 1543: 34,12 + 1544: 53,-26 + 1545: 53,-27 + 1546: 53,-28 + 1547: 53,-29 + 1548: 53,-30 + 1549: 53,-31 + 1550: 56,-31 + 1551: 56,-30 + 1552: 56,-29 + 1553: 56,-28 + 1554: 56,-27 + 1555: 56,-26 + 1619: -22,50 + 1620: -22,49 + 1621: -22,48 + 1622: -22,47 - node: angle: 1.5707963267948966 rad color: '#EFB34196' id: StandClear decals: - 1235: -56,39 - 1236: -56,37 - 1237: -56,46 - 1238: -56,48 + 1225: -56,39 + 1226: -56,37 + 1227: -56,46 + 1228: -56,48 - node: color: '#52B4E996' id: StandClearGreyscale decals: - 4071: -3,-11 - 4072: -3,-12 - 4073: -1,-11 - 4074: -1,-12 - 4075: 15,-11 - 4076: 15,-12 - 4077: 17,-11 - 4078: 17,-12 - 4742: -27,17 - 4743: -27,18 - 4744: -25,18 - 4745: -25,17 + 4058: -3,-11 + 4059: -3,-12 + 4060: -1,-11 + 4061: -1,-12 + 4062: 15,-11 + 4063: 15,-12 + 4064: 17,-11 + 4065: 17,-12 + 4729: -27,17 + 4730: -27,18 + 4731: -25,18 + 4732: -25,17 - node: color: '#D381C996' id: StandClearGreyscale decals: - 3890: 25,54 - 3891: 25,55 - 3892: 21,55 - 3893: 21,54 - 3985: 16,64 - 3986: 18,68 - 3987: 19,68 - 3988: 23,72 - 3989: 24,72 - 4374: 25,79 - 4375: 25,78 - 4376: 28,79 - 4377: 28,78 - 4378: 32,79 - 4379: 32,78 - 4380: 32,77 + 3877: 25,54 + 3878: 25,55 + 3879: 21,55 + 3880: 21,54 + 3972: 16,64 + 3973: 18,68 + 3974: 19,68 + 3975: 23,72 + 3976: 24,72 + 4361: 25,79 + 4362: 25,78 + 4363: 28,79 + 4364: 28,78 + 4365: 32,79 + 4366: 32,78 + 4367: 32,77 - node: color: '#DE3A3A96' id: StandClearGreyscale decals: - 1618: 47,-14 - 1619: 47,-15 - 1620: 50,-18 - 1676: 41,1 - 1677: 39,1 - 1678: 39,-2 - 1679: 41,-2 + 1607: 47,-14 + 1608: 47,-15 + 1609: 50,-18 + 1665: 41,1 + 1666: 39,1 + 1667: 39,-2 + 1668: 41,-2 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale decals: - 808: -43,-3 + 798: -43,-3 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale decals: 243: -28,-38 - 1460: 35,51 + 1450: 35,51 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale180 decals: - 813: -3,-6 + 803: -3,-6 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale180 decals: 235: -27,-41 241: -22,-41 - 1214: -61,48 - 1458: 38,48 + 1204: -61,48 + 1448: 38,48 - node: color: '#D4D4D419' id: ThreeQuarterTileOverlayGreyscale270 decals: - 1197: -58,29 + 1187: -58,29 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale270 decals: - 814: 17,-6 + 804: 17,-6 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale270 decals: 236: -25,-41 242: -28,-41 - 1459: 35,48 + 1449: 35,48 - node: color: '#D4D4D419' id: ThreeQuarterTileOverlayGreyscale90 decals: - 1313: 18,31 + 1303: 18,31 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale90 decals: - 847: 21,-17 + 837: 21,-17 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale90 decals: 244: -22,-38 - 3485: 47,-3 + 3472: 47,-3 - node: color: '#FFFFFFFF' id: VentSmall decals: - 3571: -5,-1 + 3558: -5,-1 - node: color: '#79150096' id: WarnBox decals: - 1494: -52,-24 - 1495: -52,-25 - 3261: -6,13 - 3262: -6,13 - 3263: -6,14 - 3264: -6,14 - 3265: -6,15 - 3266: -6,15 - 3270: 30,13 - 3271: 30,12 - 3272: 30,13 - 3273: 30,12 + 1484: -52,-24 + 1485: -52,-25 + 3248: -6,13 + 3249: -6,13 + 3250: -6,14 + 3251: -6,14 + 3252: -6,15 + 3253: -6,15 + 3257: 30,13 + 3258: 30,12 + 3259: 30,13 + 3260: 30,12 - node: color: '#52B4E996' id: WarnBoxGreyscale decals: - 1496: -49,-25 - 1497: -49,-24 - 3267: 22,17 - 3268: 22,16 - 3269: 22,15 - 4925: -51,-38 - 4926: -49,-38 + 1486: -49,-25 + 1487: -49,-24 + 3254: 22,17 + 3255: 22,16 + 3256: 22,15 + 4912: -51,-38 + 4913: -49,-38 - node: color: '#EFB34196' id: WarnCornerNE decals: - 1003: 16,56 - 1102: 39,14 - 1424: -7,42 + 993: 16,56 + 1092: 39,14 + 1414: -7,42 - node: color: '#FFFFFFFF' id: WarnCornerNE decals: - 4849: 27,12 - 4853: -25,36 - 4857: 54,-15 + 4836: 27,12 + 4840: -25,36 + 4844: 54,-15 - node: color: '#EFB34196' id: WarnCornerNW decals: - 727: 24,14 - 1099: 35,14 + 717: 24,14 + 1089: 35,14 - node: color: '#FFFFFFFF' id: WarnCornerNW decals: - 4681: -29,16 - 4848: 25,12 - 4854: -28,36 - 4855: -10,41 + 4668: -29,16 + 4835: 25,12 + 4841: -28,36 + 4842: -10,41 - node: color: '#EFB34196' id: WarnCornerSE decals: - 1100: 39,12 - 1259: -22,32 - 1418: -7,46 - 3259: -2,43 + 1090: 39,12 + 1249: -22,32 + 1408: -7,46 + 3246: -2,43 - node: color: '#FFFFFFFF' id: WarnCornerSE decals: - 4666: 10,72 - 4858: 54,-17 + 4653: 10,72 + 4845: 54,-17 - node: color: '#EFB34196' id: WarnCornerSW decals: - 1101: 35,12 - 1260: -18,32 + 1091: 35,12 + 1250: -18,32 - node: color: '#FFFFFFFF' id: WarnCornerSW decals: - 4684: -29,19 - 4856: -10,40 + 4671: -29,19 + 4843: -10,40 - node: color: '#EFB34196' id: WarnCornerSmallNE decals: - 1489: -2,57 + 1479: -2,57 - node: color: '#FFFFFFFF' id: WarnCornerSmallNE decals: - 4818: 73,-5 - 4819: 73,-12 - 4879: -40,26 + 4805: 73,-5 + 4806: 73,-12 + 4866: -40,26 - node: color: '#EFB34196' id: WarnCornerSmallNW decals: - 641: -23,48 - 1488: 2,57 + 631: -23,48 + 1478: 2,57 - node: color: '#FFFFFFFF' id: WarnCornerSmallNW decals: - 4820: 85,-5 - 4821: 85,-12 - 4880: -41,26 + 4807: 85,-5 + 4808: 85,-12 + 4867: -41,26 - node: color: '#EFB34196' id: WarnCornerSmallSE decals: - 1486: -2,61 - 3246: 49,-20 - 3260: -2,44 + 1476: -2,61 + 3233: 49,-20 + 3247: -2,44 - node: color: '#FFFFFFFF' id: WarnCornerSmallSE decals: - 4816: 73,-3 - 4817: 73,-10 + 4803: 73,-3 + 4804: 73,-10 - node: color: '#EFB34196' id: WarnCornerSmallSW decals: - 999: 16,56 - 1487: 2,61 - 3247: 51,-20 + 989: 16,56 + 1477: 2,61 + 3234: 51,-20 - node: color: '#FFFFFFFF' id: WarnCornerSmallSW decals: - 4822: 85,-10 - 4823: 85,-3 + 4809: 85,-10 + 4810: 85,-3 - node: color: '#EFB34196' id: WarnEndE decals: - 1681: -19,-23 + 1670: -19,-23 - node: color: '#FFFFFFFF' id: WarnEndE decals: - 4665: 21,74 + 4652: 21,74 - node: color: '#FFFFFFFF' id: WarnEndN decals: - 4860: 40,-10 + 4847: 40,-10 - node: color: '#EFB34196' id: WarnEndS decals: - 3243: 49,-21 - 3244: 51,-21 + 3230: 49,-21 + 3231: 51,-21 - node: color: '#EFB34196' id: WarnEndW decals: - 1000: 13,56 - 1680: -20,-23 + 990: 13,56 + 1669: -20,-23 - node: color: '#FFFFFFFF' id: WarnEndW decals: - 4664: 20,74 + 4651: 20,74 - node: color: '#334E6DC8' id: WarnFullGreyscale decals: - 4740: -26,17 - 4741: -26,18 + 4727: -26,17 + 4728: -26,18 - node: color: '#EFB34196' id: WarnLineE decals: - 474: 74,14 - 475: 74,13 - 476: 74,12 - 477: 81,15 - 478: 81,14 - 479: 81,13 - 480: 81,12 - 487: 74,15 - 637: -23,50 - 638: -23,49 - 639: -23,48 - 640: -23,47 - 675: -10,38 - 676: -10,39 - 722: 22,14 - 723: 22,13 - 724: 22,12 - 991: 24,69 - 992: 20,60 - 1004: 16,55 - 1020: 17,65 - 1021: 17,64 - 1022: 17,63 - 1028: 24,69 - 1031: 20,60 - 1032: 15,64 - 1110: 39,13 - 1264: -22,33 - 1409: -7,38 - 1410: -7,39 - 1411: -7,40 - 1412: -7,41 - 1413: -7,47 - 1414: -7,48 - 1415: -7,49 - 1416: -7,50 - 1417: -7,51 - 1468: 33,12 - 1469: 33,13 - 1470: 33,14 - 1471: 33,12 - 1472: 33,13 - 1473: 33,14 - 1477: -2,58 - 1478: -2,59 - 1479: -2,60 - 1533: 47,33 - 1534: 47,34 - 1598: 62,-21 - 1612: 46,-14 - 1613: 46,-15 - 1614: 46,-14 - 1615: 46,-15 - 1623: 51,-17 - 1624: 51,-16 - 3248: 51,-20 - 3249: 51,-19 - 3894: 24,54 - 3895: 24,55 - 3898: 20,54 - 3899: 20,55 - 3900: 20,54 - 3901: 20,55 - 4350: 24,79 - 4351: 24,79 - 4352: 24,78 - 4353: 24,78 - 4366: 27,79 - 4367: 27,79 - 4368: 27,78 - 4369: 27,78 + 464: 74,14 + 465: 74,13 + 466: 74,12 + 467: 81,15 + 468: 81,14 + 469: 81,13 + 470: 81,12 + 477: 74,15 + 627: -23,50 + 628: -23,49 + 629: -23,48 + 630: -23,47 + 665: -10,38 + 666: -10,39 + 712: 22,14 + 713: 22,13 + 714: 22,12 + 981: 24,69 + 982: 20,60 + 994: 16,55 + 1010: 17,65 + 1011: 17,64 + 1012: 17,63 + 1018: 24,69 + 1021: 20,60 + 1022: 15,64 + 1100: 39,13 + 1254: -22,33 + 1399: -7,38 + 1400: -7,39 + 1401: -7,40 + 1402: -7,41 + 1403: -7,47 + 1404: -7,48 + 1405: -7,49 + 1406: -7,50 + 1407: -7,51 + 1458: 33,12 + 1459: 33,13 + 1460: 33,14 + 1461: 33,12 + 1462: 33,13 + 1463: 33,14 + 1467: -2,58 + 1468: -2,59 + 1469: -2,60 + 1523: 47,33 + 1524: 47,34 + 1588: 62,-21 + 1601: 46,-14 + 1602: 46,-15 + 1603: 46,-14 + 1604: 46,-15 + 1612: 51,-17 + 1613: 51,-16 + 3235: 51,-20 + 3236: 51,-19 + 3881: 24,54 + 3882: 24,55 + 3885: 20,54 + 3886: 20,55 + 3887: 20,54 + 3888: 20,55 + 4337: 24,79 + 4338: 24,79 + 4339: 24,78 + 4340: 24,78 + 4353: 27,79 + 4354: 27,79 + 4355: 27,78 + 4356: 27,78 - node: color: '#FFFFFFFF' id: WarnLineE decals: - 4457: 19,15 - 4458: 19,16 - 4459: 19,17 - 4668: 10,73 - 4669: 10,74 - 4670: 10,75 - 4671: 10,76 - 4814: 73,-11 - 4815: 73,-4 - 4828: -54,47 - 4829: -54,46 - 4830: -54,39 - 4831: -54,38 - 4859: 54,-16 - 4864: -40,27 + 4444: 19,15 + 4445: 19,16 + 4446: 19,17 + 4655: 10,73 + 4656: 10,74 + 4657: 10,75 + 4658: 10,76 + 4801: 73,-11 + 4802: 73,-4 + 4815: -54,47 + 4816: -54,46 + 4817: -54,39 + 4818: -54,38 + 4846: 54,-16 + 4851: -40,27 - node: color: '#DE3A3A96' id: WarnLineGreyscaleN decals: - 1570: 64,-22 - 1571: 65,-22 - 1572: 66,-22 - 1573: 67,-22 - 1574: 64,-21 - 1575: 64,-21 - 1576: 65,-21 - 1577: 65,-21 - 1578: 66,-21 - 1579: 66,-21 - 1580: 67,-21 - 1581: 67,-21 + 1560: 64,-22 + 1561: 65,-22 + 1562: 66,-22 + 1563: 67,-22 + 1564: 64,-21 + 1565: 64,-21 + 1566: 65,-21 + 1567: 65,-21 + 1568: 66,-21 + 1569: 66,-21 + 1570: 67,-21 + 1571: 67,-21 - node: color: '#D381C996' id: WarnLineGreyscaleS @@ -6677,94 +6677,94 @@ entities: color: '#DE3A3A96' id: WarnLineGreyscaleS decals: - 1566: 64,-20 - 1567: 65,-20 - 1568: 66,-20 - 1569: 67,-20 - 1582: 64,-21 - 1583: 64,-21 - 1584: 65,-21 - 1585: 65,-21 - 1586: 66,-21 - 1587: 66,-21 - 1588: 67,-21 - 1589: 67,-21 + 1556: 64,-20 + 1557: 65,-20 + 1558: 66,-20 + 1559: 67,-20 + 1572: 64,-21 + 1573: 64,-21 + 1574: 65,-21 + 1575: 65,-21 + 1576: 66,-21 + 1577: 66,-21 + 1578: 67,-21 + 1579: 67,-21 - node: color: '#EFB34196' id: WarnLineN decals: 311: -41,-26 - 623: -21,55 - 624: -20,55 - 985: 18,69 - 986: 19,69 - 997: 15,56 - 998: 14,56 - 1106: 36,12 - 1107: 37,12 - 1108: 38,12 - 1222: -62,53 - 1223: -58,53 - 1266: -27,32 - 1267: -26,32 - 1268: -25,32 - 1269: -24,32 - 1270: -23,32 - 1271: -17,32 - 1272: -16,32 - 1273: -15,32 - 1274: -14,32 - 1275: -13,32 - 1419: -8,46 - 1448: -23,55 - 1449: -24,55 - 1450: -25,55 - 1451: -26,55 - 1452: -27,55 - 1453: -28,55 - 1454: -29,55 - 1475: 0,52 - 1480: -1,61 - 1481: 0,61 - 1482: 1,61 - 1492: 23,54 - 1493: 24,54 - 1590: 64,-22 - 1591: 65,-22 - 1592: 66,-22 - 1593: 67,-22 - 1621: 50,-17 - 1664: -43,-17 - 1665: -42,-17 - 1666: -41,-17 - 3245: 50,-20 - 3254: 2,44 - 3255: 3,44 - 3256: 1,44 - 3257: 0,44 - 3258: -1,44 - 3295: 22,54 + 613: -21,55 + 614: -20,55 + 975: 18,69 + 976: 19,69 + 987: 15,56 + 988: 14,56 + 1096: 36,12 + 1097: 37,12 + 1098: 38,12 + 1212: -62,53 + 1213: -58,53 + 1256: -27,32 + 1257: -26,32 + 1258: -25,32 + 1259: -24,32 + 1260: -23,32 + 1261: -17,32 + 1262: -16,32 + 1263: -15,32 + 1264: -14,32 + 1265: -13,32 + 1409: -8,46 + 1438: -23,55 + 1439: -24,55 + 1440: -25,55 + 1441: -26,55 + 1442: -27,55 + 1443: -28,55 + 1444: -29,55 + 1465: 0,52 + 1470: -1,61 + 1471: 0,61 + 1472: 1,61 + 1482: 23,54 + 1483: 24,54 + 1580: 64,-22 + 1581: 65,-22 + 1582: 66,-22 + 1583: 67,-22 + 1610: 50,-17 + 1653: -43,-17 + 1654: -42,-17 + 1655: -41,-17 + 3232: 50,-20 + 3241: 2,44 + 3242: 3,44 + 3243: 1,44 + 3244: 0,44 + 3245: -1,44 + 3282: 22,54 - node: color: '#FFFFFFFF' id: WarnLineN decals: - 4667: 9,72 - 4685: -28,19 - 4824: 88,3 - 4836: -47,-50 - 4837: -48,-50 - 4838: 10,-51 - 4839: 9,-51 - 4861: 55,0 - 4862: 56,0 - 4871: -44,26 - 4872: -43,26 - 4873: -42,26 - 4874: -41,26 - 4875: -40,26 - 4876: -39,26 - 4877: -38,26 - 4878: -37,26 + 4654: 9,72 + 4672: -28,19 + 4811: 88,3 + 4823: -47,-50 + 4824: -48,-50 + 4825: 10,-51 + 4826: 9,-51 + 4848: 55,0 + 4849: 56,0 + 4858: -44,26 + 4859: -43,26 + 4860: -42,26 + 4861: -41,26 + 4862: -40,26 + 4863: -39,26 + 4864: -38,26 + 4865: -37,26 - node: color: '#EFB34196' id: WarnLineS @@ -6772,391 +6772,391 @@ entities: 308: -40,-27 309: -40,-28 310: -40,-29 - 481: 77,14 - 482: 77,13 - 483: 77,12 - 484: 84,15 - 485: 84,13 - 486: 84,12 - 488: 77,15 - 558: -8,45 - 559: -8,44 - 560: -8,43 - 635: -23,49 - 636: -23,50 - 725: 24,13 - 726: 24,12 - 993: 18,55 - 994: 18,56 - 995: 16,53 - 996: 16,55 - 1005: 16,54 - 1023: 17,64 - 1029: 18,56 - 1030: 18,55 - 1033: 14,63 - 1034: 14,64 - 1035: 14,65 - 1109: 35,13 - 1265: -18,33 - 1420: -8,45 - 1421: -8,44 - 1422: -8,43 - 1483: 2,60 - 1484: 2,59 - 1485: 2,58 - 1616: 48,-15 - 1617: 48,-14 - 3250: 49,-20 - 3251: 49,-19 - 3252: 30,66 - 3253: 30,66 - 3305: 84,14 - 3896: 22,55 - 3897: 22,54 - 4354: 29,79 - 4355: 29,79 - 4356: 29,78 - 4357: 29,78 - 4370: 26,79 - 4371: 26,79 - 4372: 26,78 - 4373: 26,78 - 4415: 26,54 - 4416: 26,55 + 471: 77,14 + 472: 77,13 + 473: 77,12 + 474: 84,15 + 475: 84,13 + 476: 84,12 + 478: 77,15 + 548: -8,45 + 549: -8,44 + 550: -8,43 + 625: -23,49 + 626: -23,50 + 715: 24,13 + 716: 24,12 + 983: 18,55 + 984: 18,56 + 985: 16,53 + 986: 16,55 + 995: 16,54 + 1013: 17,64 + 1019: 18,56 + 1020: 18,55 + 1023: 14,63 + 1024: 14,64 + 1025: 14,65 + 1099: 35,13 + 1255: -18,33 + 1410: -8,45 + 1411: -8,44 + 1412: -8,43 + 1473: 2,60 + 1474: 2,59 + 1475: 2,58 + 1605: 48,-15 + 1606: 48,-14 + 3237: 49,-20 + 3238: 49,-19 + 3239: 30,66 + 3240: 30,66 + 3292: 84,14 + 3883: 22,55 + 3884: 22,54 + 4341: 29,79 + 4342: 29,79 + 4343: 29,78 + 4344: 29,78 + 4357: 26,79 + 4358: 26,79 + 4359: 26,78 + 4360: 26,78 + 4402: 26,54 + 4403: 26,55 - node: color: '#FFFFFFFF' id: WarnLineS decals: - 4682: -29,15 - 4683: -29,20 - 4812: 85,-11 - 4813: 85,-4 - 4826: -54,46 - 4827: -54,47 - 4832: -54,39 - 4833: -54,38 - 4863: -41,27 + 4669: -29,15 + 4670: -29,20 + 4799: 85,-11 + 4800: 85,-4 + 4813: -54,46 + 4814: -54,47 + 4819: -54,39 + 4820: -54,38 + 4850: -41,27 - node: color: '#EFB34196' id: WarnLineW decals: - 471: 35,-2 - 472: 36,-2 - 473: 37,-2 - 555: -21,33 - 556: -20,33 - 557: -19,33 - 627: -21,56 - 628: -20,56 - 629: -29,48 - 630: -28,48 - 631: -27,48 - 632: -26,48 - 633: -25,48 - 634: -24,48 - 697: 25,14 - 698: 26,14 - 699: 27,14 - 700: 28,14 - 981: 18,69 - 982: 19,69 - 983: 20,69 - 984: 21,69 - 987: 18,67 - 988: 19,67 - 989: 23,71 - 990: 24,71 - 1001: 14,56 - 1002: 15,56 - 1024: 18,67 - 1025: 19,67 - 1026: 23,71 - 1027: 24,71 - 1103: 36,14 - 1104: 37,14 - 1105: 38,14 - 1221: -62,51 - 1261: -21,33 - 1262: -20,33 - 1263: -19,33 - 1423: -8,42 - 1474: 0,53 - 1476: -1,57 - 1490: 23,55 - 1491: 24,55 - 1594: 64,-20 - 1595: 65,-20 - 1596: 66,-20 - 1597: 67,-20 - 1622: 50,-19 - 3296: 22,55 - 3836: 0,57 - 3837: 1,57 + 461: 35,-2 + 462: 36,-2 + 463: 37,-2 + 545: -21,33 + 546: -20,33 + 547: -19,33 + 617: -21,56 + 618: -20,56 + 619: -29,48 + 620: -28,48 + 621: -27,48 + 622: -26,48 + 623: -25,48 + 624: -24,48 + 687: 25,14 + 688: 26,14 + 689: 27,14 + 690: 28,14 + 971: 18,69 + 972: 19,69 + 973: 20,69 + 974: 21,69 + 977: 18,67 + 978: 19,67 + 979: 23,71 + 980: 24,71 + 991: 14,56 + 992: 15,56 + 1014: 18,67 + 1015: 19,67 + 1016: 23,71 + 1017: 24,71 + 1093: 36,14 + 1094: 37,14 + 1095: 38,14 + 1211: -62,51 + 1251: -21,33 + 1252: -20,33 + 1253: -19,33 + 1413: -8,42 + 1464: 0,53 + 1466: -1,57 + 1480: 23,55 + 1481: 24,55 + 1584: 64,-20 + 1585: 65,-20 + 1586: 66,-20 + 1587: 67,-20 + 1611: 50,-19 + 3283: 22,55 + 3823: 0,57 + 3824: 1,57 - node: color: '#FFFFFFFF' id: WarnLineW decals: - 4672: 18,71 - 4673: 19,71 - 4674: 20,71 - 4675: 21,71 - 4676: 18,69 - 4677: 19,69 - 4678: 20,69 - 4679: 21,69 - 4686: -28,16 - 4784: 86,-3 - 4785: 85,-3 - 4786: 73,-3 - 4787: 72,-3 - 4825: 88,3 - 4834: -47,-50 - 4835: -48,-50 - 4840: 10,-51 - 4841: 9,-51 - 4850: 26,12 - 4851: -27,36 - 4852: -26,36 - 4865: -44,26 - 4866: -43,26 - 4867: -42,26 - 4868: -39,26 - 4869: -38,26 - 4870: -37,26 + 4659: 18,71 + 4660: 19,71 + 4661: 20,71 + 4662: 21,71 + 4663: 18,69 + 4664: 19,69 + 4665: 20,69 + 4666: 21,69 + 4673: -28,16 + 4771: 86,-3 + 4772: 85,-3 + 4773: 73,-3 + 4774: 72,-3 + 4812: 88,3 + 4821: -47,-50 + 4822: -48,-50 + 4827: 10,-51 + 4828: 9,-51 + 4837: 26,12 + 4838: -27,36 + 4839: -26,36 + 4852: -44,26 + 4853: -43,26 + 4854: -42,26 + 4855: -39,26 + 4856: -38,26 + 4857: -37,26 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNe decals: - 3464: -25,-19 - 3559: 13,-18 + 3451: -25,-19 + 3546: 13,-18 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNw decals: - 3686: 30,-18 + 3673: 30,-18 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerSe decals: - 3558: 13,-19 + 3545: 13,-19 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerSw decals: - 3563: 9,-19 - 3691: 30,-23 + 3550: 9,-19 + 3678: 30,-23 - node: color: '#FFFFFFFF' id: WoodTrimThinEndN decals: - 3561: 9,-17 + 3548: 9,-17 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerNe decals: - 3565: 9,-18 - 3819: -11,33 + 3552: 9,-18 + 3806: -11,33 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerNw decals: - 3817: -8,33 + 3804: -8,33 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerSe decals: - 3818: -11,36 - 4311: -18,-10 - 4312: -18,-9 + 3805: -11,36 + 4298: -18,-10 + 4299: -18,-9 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerSw decals: - 3816: -8,36 + 3803: -8,36 - node: color: '#FFFFFFFF' id: WoodTrimThinLineE decals: - 3467: -25,-20 - 3468: -25,-21 - 3810: -11,34 - 3811: -11,35 + 3454: -25,-20 + 3455: -25,-21 + 3797: -11,34 + 3798: -11,35 - node: color: '#FFFFFFFF' id: WoodTrimThinLineN decals: - 3422: -2,-46 - 3423: -1,-46 - 3424: 0,-46 - 3425: 1,-46 - 3426: -3,-42 - 3427: -2,-42 - 3428: -1,-42 - 3429: 0,-42 - 3430: 1,-42 - 3465: -26,-19 - 3466: -27,-19 - 3482: -21,-13 - 3560: 12,-18 - 3687: 31,-18 - 3688: 32,-18 - 3689: 33,-18 - 3690: 34,-18 - 3808: -10,33 - 3809: -9,33 + 3409: -2,-46 + 3410: -1,-46 + 3411: 0,-46 + 3412: 1,-46 + 3413: -3,-42 + 3414: -2,-42 + 3415: -1,-42 + 3416: 0,-42 + 3417: 1,-42 + 3452: -26,-19 + 3453: -27,-19 + 3469: -21,-13 + 3547: 12,-18 + 3674: 31,-18 + 3675: 32,-18 + 3676: 33,-18 + 3677: 34,-18 + 3795: -10,33 + 3796: -9,33 - node: color: '#FFFFFFFF' id: WoodTrimThinLineS decals: - 3431: -3,-44 - 3432: -2,-44 - 3433: -1,-44 - 3434: 0,-44 - 3435: 1,-44 - 3436: -3,-48 - 3437: -2,-48 - 3438: -1,-48 - 3439: 0,-48 - 3440: 1,-48 - 3441: -12,-32 - 3564: 12,-19 - 3692: 31,-23 - 3693: 32,-23 - 3694: 33,-23 - 3695: 34,-23 - 3814: -10,36 - 3815: -9,36 + 3418: -3,-44 + 3419: -2,-44 + 3420: -1,-44 + 3421: 0,-44 + 3422: 1,-44 + 3423: -3,-48 + 3424: -2,-48 + 3425: -1,-48 + 3426: 0,-48 + 3427: 1,-48 + 3428: -12,-32 + 3551: 12,-19 + 3679: 31,-23 + 3680: 32,-23 + 3681: 33,-23 + 3682: 34,-23 + 3801: -10,36 + 3802: -9,36 - node: color: '#FFFFFFFF' id: WoodTrimThinLineW decals: - 3416: -3,-42 - 3417: -3,-43 - 3418: -3,-44 - 3419: -3,-46 - 3420: -3,-47 - 3421: -3,-48 - 3476: -21,-13 - 3477: -21,-14 - 3478: -21,-15 - 3479: -21,-16 - 3480: -21,-17 - 3481: -21,-18 - 3562: 9,-18 - 3681: 30,-22 - 3682: 30,-21 - 3683: 30,-20 - 3684: 30,-19 - 3685: 23,-21 - 3812: -8,34 - 3813: -8,35 + 3403: -3,-42 + 3404: -3,-43 + 3405: -3,-44 + 3406: -3,-46 + 3407: -3,-47 + 3408: -3,-48 + 3463: -21,-13 + 3464: -21,-14 + 3465: -21,-15 + 3466: -21,-16 + 3467: -21,-17 + 3468: -21,-18 + 3549: 9,-18 + 3668: 30,-22 + 3669: 30,-21 + 3670: 30,-20 + 3671: 30,-19 + 3672: 23,-21 + 3799: -8,34 + 3800: -8,35 - node: color: '#9FED5896' id: bushsnowa1 decals: - 3183: -41.436035,-22.25985 - 3184: -41.283257,-23.079292 - 3185: -40.255478,-23.398739 - 3186: -40.019367,-18.10707 - 3187: -41.005478,-18.926516 - 3188: -43.061035,-18.00985 - 3189: -43.130478,-18.718182 - 3190: -43.07492,-19.940405 - 3191: -43.1027,-21.551517 - 3192: -41.880478,-23.204292 - 3193: -40.172146,-23.787628 - 3194: -41.11659,-23.75985 - 3195: -39.880478,-22.273739 - 3196: -40.130478,-19.079292 + 3170: -41.436035,-22.25985 + 3171: -41.283257,-23.079292 + 3172: -40.255478,-23.398739 + 3173: -40.019367,-18.10707 + 3174: -41.005478,-18.926516 + 3175: -43.061035,-18.00985 + 3176: -43.130478,-18.718182 + 3177: -43.07492,-19.940405 + 3178: -43.1027,-21.551517 + 3179: -41.880478,-23.204292 + 3180: -40.172146,-23.787628 + 3181: -41.11659,-23.75985 + 3182: -39.880478,-22.273739 + 3183: -40.130478,-19.079292 - node: color: '#9FED5896' id: bushsnowb3 decals: - 3460: 24.076597,-33.183323 - 3461: 23.937708,-34.09999 + 3447: 24.076597,-33.183323 + 3448: 23.937708,-34.09999 - node: color: '#A4DF8296' id: bushsnowb3 decals: - 1694: -7.3679967,-22.387566 - 1695: -9.20133,-22.69312 - 1696: -9.062441,-23.859787 - 1697: -7.2291064,-23.637566 - 1698: -8.423552,-23.276455 + 1683: -7.3679967,-22.387566 + 1684: -9.20133,-22.69312 + 1685: -9.062441,-23.859787 + 1686: -7.2291064,-23.637566 + 1687: -8.423552,-23.276455 - node: color: '#9FED5896' id: grasssnow07 decals: - 3309: 78.19461,7.941762 - 3310: 79.52794,7.9139843 + 3296: 78.19461,7.941762 + 3297: 79.52794,7.9139843 - node: color: '#60AC5863' id: grasssnow09 decals: - 3328: -12.979685,-40.336945 - 3329: -11.368574,-40.225834 - 3330: -11.4657955,-39.059166 - 3331: -13.701906,-39.198055 - 3332: -12.507462,-39.503613 - 3333: -12.799128,-40.614723 + 3315: -12.979685,-40.336945 + 3316: -11.368574,-40.225834 + 3317: -11.4657955,-39.059166 + 3318: -13.701906,-39.198055 + 3319: -12.507462,-39.503613 + 3320: -12.799128,-40.614723 - node: color: '#9FED587C' id: grasssnow09 decals: - 3327: -13.604685,-40.086945 + 3314: -13.604685,-40.086945 - node: color: '#60FF5D92' id: grasssnow10 decals: - 4511: -19.105085,3.5241327 - 4512: -19.957012,2.1050215 - 4513: -19.829224,0.3878975 + 4498: -19.105085,3.5241327 + 4499: -19.957012,2.1050215 + 4500: -19.829224,0.3878975 - node: color: '#9FED587C' id: grasssnow10 decals: - 3319: -13.5907955,-40.670277 - 3320: -12.229685,-40.475834 - 3321: -11.354685,-39.475834 - 3322: -13.813017,-39.350834 - 3323: -12.826906,-39.614723 - 3324: -11.271351,-40.698055 - 3325: -11.41024,-38.989723 - 3326: -12.979685,-38.961945 + 3306: -13.5907955,-40.670277 + 3307: -12.229685,-40.475834 + 3308: -11.354685,-39.475834 + 3309: -13.813017,-39.350834 + 3310: -12.826906,-39.614723 + 3311: -11.271351,-40.698055 + 3312: -11.41024,-38.989723 + 3313: -12.979685,-38.961945 - node: color: '#A4DF8296' id: grasssnow10 decals: - 1684: -7.4220443,-1.9321766 + 1673: -7.4220443,-1.9321766 - node: color: '#A4DF8296' id: grasssnowc1 decals: - 1685: -6.4220433,-1.9599552 + 1674: -6.4220433,-1.9599552 - node: color: '#60E2588B' id: grasssnowc3 decals: - 3348: -15.396351,-36.573055 - 3349: -17.549128,-36.656387 - 3350: -17.604685,-37.795277 - 3351: -16.007462,-37.8925 - 3352: -16.354685,-36.698055 - 3353: -15.299128,-37.6425 - 3354: -16.118574,-37.031387 + 3335: -15.396351,-36.573055 + 3336: -17.549128,-36.656387 + 3337: -17.604685,-37.795277 + 3338: -16.007462,-37.8925 + 3339: -16.354685,-36.698055 + 3340: -15.299128,-37.6425 + 3341: -16.118574,-37.031387 - node: cleanable: True color: '#800080FF' id: prolizard decals: - 4680: 27.413673,-33.665314 + 4667: 27.413673,-33.665314 - node: color: '#9FED5896' id: shop decals: - 3286: -4,-42 - 3287: -4,-48 + 3273: -4,-42 + 3274: -4,-48 type: DecalGrid - version: 2 data: @@ -38285,6 +38285,16 @@ entities: - pos: 16.5,-18.5 parent: 82 type: Transform + - uid: 22707 + components: + - pos: 40.5,-19.5 + parent: 82 + type: Transform + - uid: 22712 + components: + - pos: 40.5,-20.5 + parent: 82 + type: Transform - uid: 22740 components: - pos: -36.5,37.5 @@ -46965,6 +46975,11 @@ entities: - pos: -3.5,-13.5 parent: 82 type: Transform + - uid: 22959 + components: + - pos: -25.5,45.5 + parent: 82 + type: Transform - uid: 22970 components: - pos: -2.5,-13.5 @@ -47359,6 +47374,51 @@ entities: - pos: -34.5,-25.5 parent: 82 type: Transform + - uid: 2731 + components: + - pos: -22.5,53.5 + parent: 82 + type: Transform + - uid: 2757 + components: + - pos: -27.5,56.5 + parent: 82 + type: Transform + - uid: 2819 + components: + - pos: -23.5,53.5 + parent: 82 + type: Transform + - uid: 2839 + components: + - pos: -24.5,53.5 + parent: 82 + type: Transform + - uid: 2846 + components: + - pos: -25.5,53.5 + parent: 82 + type: Transform + - uid: 2847 + components: + - pos: -26.5,53.5 + parent: 82 + type: Transform + - uid: 2869 + components: + - pos: -27.5,55.5 + parent: 82 + type: Transform + - uid: 3147 + components: + - pos: -27.5,53.5 + parent: 82 + type: Transform + - uid: 3148 + components: + - pos: -27.5,54.5 + parent: 82 + type: Transform - uid: 3869 components: - pos: -11.5,4.5 @@ -47494,6 +47554,11 @@ entities: - pos: -11.5,-5.5 parent: 82 type: Transform + - uid: 5620 + components: + - pos: -26.5,57.5 + parent: 82 + type: Transform - uid: 5644 components: - pos: -34.5,64.5 @@ -47754,6 +47819,11 @@ entities: - pos: -35.5,64.5 parent: 82 type: Transform + - uid: 5729 + components: + - pos: -27.5,57.5 + parent: 82 + type: Transform - uid: 5732 components: - pos: -22.5,56.5 @@ -47761,47 +47831,12 @@ entities: type: Transform - uid: 5733 components: - - pos: -22.5,55.5 + - pos: -27.5,59.5 parent: 82 type: Transform - uid: 5734 components: - - pos: -22.5,54.5 - parent: 82 - type: Transform - - uid: 5735 - components: - - pos: -21.5,54.5 - parent: 82 - type: Transform - - uid: 5736 - components: - - pos: -20.5,54.5 - parent: 82 - type: Transform - - uid: 5737 - components: - - pos: -20.5,55.5 - parent: 82 - type: Transform - - uid: 5738 - components: - - pos: -20.5,56.5 - parent: 82 - type: Transform - - uid: 5739 - components: - - pos: -20.5,57.5 - parent: 82 - type: Transform - - uid: 5740 - components: - - pos: -20.5,58.5 - parent: 82 - type: Transform - - uid: 5741 - components: - - pos: -20.5,59.5 + - pos: -27.5,58.5 parent: 82 type: Transform - uid: 5776 @@ -47909,16 +47944,6 @@ entities: - pos: -21.5,79.5 parent: 82 type: Transform - - uid: 6738 - components: - - pos: -23.5,55.5 - parent: 82 - type: Transform - - uid: 6739 - components: - - pos: -23.5,54.5 - parent: 82 - type: Transform - uid: 6740 components: - pos: -23.5,56.5 @@ -47929,16 +47954,6 @@ entities: - pos: -23.5,57.5 parent: 82 type: Transform - - uid: 6742 - components: - - pos: -23.5,58.5 - parent: 82 - type: Transform - - uid: 6743 - components: - - pos: -23.5,59.5 - parent: 82 - type: Transform - uid: 6744 components: - pos: -23.5,60.5 @@ -48054,6 +48069,11 @@ entities: - pos: -34.5,72.5 parent: 82 type: Transform + - uid: 11206 + components: + - pos: -20.5,53.5 + parent: 82 + type: Transform - uid: 11218 components: - pos: -30.5,80.5 @@ -51909,6 +51929,11 @@ entities: - pos: -17.5,76.5 parent: 82 type: Transform + - uid: 21689 + components: + - pos: -21.5,53.5 + parent: 82 + type: Transform - uid: 21843 components: - pos: 0.5,40.5 @@ -52309,6 +52334,36 @@ entities: - pos: 1.5,63.5 parent: 82 type: Transform + - uid: 22934 + components: + - pos: -20.5,54.5 + parent: 82 + type: Transform + - uid: 22935 + components: + - pos: -20.5,55.5 + parent: 82 + type: Transform + - uid: 22936 + components: + - pos: -20.5,56.5 + parent: 82 + type: Transform + - uid: 22937 + components: + - pos: -20.5,57.5 + parent: 82 + type: Transform + - uid: 22943 + components: + - pos: -20.5,58.5 + parent: 82 + type: Transform + - uid: 22958 + components: + - pos: -20.5,59.5 + parent: 82 + type: Transform - uid: 24163 components: - pos: -13.5,48.5 @@ -52710,6 +52765,13 @@ entities: - pos: 58.456696,-37.53437 parent: 82 type: Transform +- proto: CannedApplauseInstrument + entities: + - uid: 8618 + components: + - pos: -42.56837,12.580838 + parent: 82 + type: Transform - proto: CapacitorStockPart entities: - uid: 9432 @@ -61920,15 +61982,6 @@ entities: - pos: 13.647984,38.49309 parent: 82 type: Transform -- proto: Claymore - entities: - - uid: 25509 - components: - - name: Maintscalibur - type: MetaData - - pos: 33.46861,68.93209 - parent: 82 - type: Transform - proto: CloningConsoleComputerCircuitboard entities: - uid: 19831 @@ -64352,7 +64405,7 @@ entities: type: EntityStorage - uid: 22642 components: - - pos: -18.5,54.5 + - pos: -19.77381,54.505054 parent: 82 type: Transform - air: @@ -64375,9 +64428,11 @@ entities: type: EntityStorage - uid: 22643 components: - - pos: -18.5,53.5 + - pos: -18.250603,54.50595 parent: 82 type: Transform + - sleepTime: 0.049999803 + type: Physics - air: volume: 200 immutable: False @@ -65179,13 +65234,6 @@ entities: - pos: -9.140789,-47.293507 parent: 82 type: Transform -- proto: ClothingBackpackMerc - entities: - - uid: 19820 - components: - - pos: 20.916914,-91.30483 - parent: 82 - type: Transform - proto: ClothingBeltChampion entities: - uid: 4365 @@ -65201,13 +65249,6 @@ entities: pos: 46.357616,16.331951 parent: 82 type: Transform -- proto: ClothingBeltMercWebbing - entities: - - uid: 6372 - components: - - pos: 20.291391,-103.31173 - parent: 82 - type: Transform - proto: ClothingBeltUtilityFilled entities: - uid: 6412 @@ -65267,13 +65308,6 @@ entities: - pos: 39.829994,-14.370501 parent: 82 type: Transform -- proto: ClothingEyesGlassesMercenary - entities: - - uid: 5386 - components: - - pos: 20.651289,-91.50796 - parent: 82 - type: Transform - proto: ClothingEyesGlassesMeson entities: - uid: 6410 @@ -66020,13 +66054,6 @@ entities: - pos: 33.54575,56.683422 parent: 82 type: Transform -- proto: ClothingOuterVestWebMerc - entities: - - uid: 20497 - components: - - pos: 20.541391,-103.546104 - parent: 82 - type: Transform - proto: ClothingOuterWinterCargo entities: - uid: 19400 @@ -66279,13 +66306,6 @@ entities: - pos: 60.777298,-16.464449 parent: 82 type: Transform -- proto: ClothingUniformJumpsuitMercenary - entities: - - uid: 20144 - components: - - pos: 20.557539,-91.30483 - parent: 82 - type: Transform - proto: ClothingUniformJumpsuitNanotrasen entities: - uid: 8620 @@ -66873,6 +66893,11 @@ entities: - pos: -51.5,12.5 parent: 82 type: Transform + - uid: 22960 + components: + - pos: -25.5,45.5 + parent: 82 + type: Transform - proto: ComputerRadar entities: - uid: 2245 @@ -117601,13 +117626,6 @@ entities: - pos: -15.03525,21.629791 parent: 82 type: Transform -- proto: KukriKnife - entities: - - uid: 8825 - components: - - pos: 20.432016,-103.4957 - parent: 82 - type: Transform - proto: Lamp entities: - uid: 19045 @@ -120595,9 +120613,11 @@ entities: type: Transform - uid: 10013 components: - - pos: -21.5,59.5 + - pos: -21.601662,59.538593 parent: 82 type: Transform + - sleepTime: 0.0166666 + type: Physics - uid: 11881 components: - pos: -51.5,10.5 @@ -120898,6 +120918,13 @@ entities: type: Transform - proto: PaperOffice entities: + - uid: 5386 + components: + - pos: 33.503384,69.00901 + parent: 82 + type: Transform + - content: Made you look. + type: Paper - uid: 10996 components: - pos: -34.351803,-28.541927 @@ -127120,69 +127147,71 @@ entities: type: Transform - proto: RadiationCollector entities: - - uid: 5620 + - uid: 7097 components: - - pos: -33.5,73.5 + - pos: -28.5,52.5 parent: 82 type: Transform - - uid: 5729 +- proto: RadiationCollectorFullTank + entities: + - uid: 5735 components: - - pos: -33.5,75.5 + - pos: -17.5,71.5 parent: 82 type: Transform - - uid: 5847 + - uid: 5736 components: - - pos: -33.5,74.5 + - pos: -17.5,69.5 parent: 82 type: Transform - - uid: 5992 + - uid: 5737 components: - - pos: -33.5,70.5 + - pos: -17.5,70.5 parent: 82 type: Transform - - uid: 6175 + - uid: 5738 components: - - pos: -33.5,69.5 + - pos: -17.5,74.5 parent: 82 type: Transform - - uid: 7097 + - uid: 5739 components: - - pos: -28.5,52.5 + - pos: -17.5,75.5 parent: 82 type: Transform - - uid: 11225 + - uid: 5740 components: - - pos: -17.5,70.5 + - pos: -33.5,70.5 parent: 82 type: Transform - - uid: 11442 + - uid: 5741 components: - - pos: -33.5,71.5 + - pos: -17.5,73.5 parent: 82 type: Transform - - uid: 21689 + - uid: 5847 components: - - pos: -17.5,73.5 + - pos: -33.5,73.5 parent: 82 type: Transform - - uid: 21722 + - uid: 5992 components: - - pos: -17.5,69.5 + - pos: -33.5,69.5 parent: 82 type: Transform - - uid: 22707 + - uid: 6175 components: - - pos: -17.5,71.5 + - pos: -33.5,71.5 parent: 82 type: Transform - - uid: 22712 + - uid: 6738 components: - - pos: -17.5,75.5 + - pos: -33.5,75.5 parent: 82 type: Transform - - uid: 22736 + - uid: 6739 components: - - pos: -17.5,74.5 + - pos: -33.5,74.5 parent: 82 type: Transform - proto: RadioHandheld @@ -138657,7 +138686,7 @@ entities: type: Transform - uid: 6034 components: - - pos: -23.5,49.5 + - pos: -25.5,72.5 parent: 82 type: Transform - proto: Sink @@ -141973,6 +142002,8 @@ entities: type: Transform - setupAvailableNetworks: - SurveillanceCameraEngineering + nameSet: True + id: Reception type: SurveillanceCamera - uid: 3849 components: @@ -142382,6 +142413,28 @@ entities: nameSet: True id: 'Checkpoint: Evac' type: SurveillanceCamera + - uid: 6372 + components: + - rot: 3.141592653589793 rad + pos: 41.5,-21.5 + parent: 82 + type: Transform + - setupAvailableNetworks: + - SurveillanceCameraSecurity + nameSet: True + id: Brig Exterior + type: SurveillanceCamera + - uid: 8825 + components: + - rot: 1.5707963267948966 rad + pos: 52.5,-24.5 + parent: 82 + type: Transform + - setupAvailableNetworks: + - SurveillanceCameraSecurity + nameSet: True + id: Armory Exterior + type: SurveillanceCamera - uid: 11474 components: - rot: 3.141592653589793 rad @@ -142423,7 +142476,7 @@ entities: - setupAvailableNetworks: - SurveillanceCameraSecurity nameSet: True - id: Brig + id: Permabrig type: SurveillanceCamera - uid: 21766 components: @@ -142433,6 +142486,8 @@ entities: type: Transform - setupAvailableNetworks: - SurveillanceCameraSecurity + nameSet: True + id: Shooting range hallway type: SurveillanceCamera - uid: 21771 components: @@ -145615,7 +145670,7 @@ entities: type: Transform - uid: 9682 components: - - pos: 20.601238,-103.10646 + - pos: 20.478569,-103.253105 parent: 82 type: Transform - uid: 11932 @@ -145948,13 +146003,6 @@ entities: - pos: 42.55547,-8.463266 parent: 82 type: Transform -- proto: VehicleKeySyndicateSegway - entities: - - uid: 8618 - components: - - pos: -42.48091,12.587237 - parent: 82 - type: Transform - proto: VendingBarDrobe entities: - uid: 4252 @@ -166018,6 +166066,17 @@ entities: pos: -59.5,39.5 parent: 82 type: Transform + - uid: 6742 + components: + - rot: 3.141592653589793 rad + pos: -39.5,-39.5 + parent: 82 + type: Transform + - uid: 6743 + components: + - pos: -38.5,-35.5 + parent: 82 + type: Transform - uid: 7927 components: - pos: 79.5,8.5 @@ -166137,6 +166196,23 @@ entities: pos: -17.5,-35.5 parent: 82 type: Transform + - uid: 11205 + components: + - rot: 1.5707963267948966 rad + pos: -36.5,-39.5 + parent: 82 + type: Transform + - uid: 11225 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-38.5 + parent: 82 + type: Transform + - uid: 11442 + components: + - pos: -35.5,-37.5 + parent: 82 + type: Transform - uid: 12766 components: - pos: -6.5,-1.5 @@ -166184,6 +166260,17 @@ entities: pos: -59.5,39.5 parent: 82 type: Transform + - uid: 14895 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-36.5 + parent: 82 + type: Transform + - uid: 14897 + components: + - pos: -39.5,-35.5 + parent: 82 + type: Transform - uid: 15512 components: - pos: -58.5,-41.5 @@ -166212,12 +166299,81 @@ entities: pos: 79.5,8.5 parent: 82 type: Transform + - uid: 18582 + components: + - pos: -30.5,-36.5 + parent: 82 + type: Transform + - uid: 18617 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-39.5 + parent: 82 + type: Transform + - uid: 19812 + components: + - rot: 1.5707963267948966 rad + pos: -36.5,-38.5 + parent: 82 + type: Transform + - uid: 19820 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-34.5 + parent: 82 + type: Transform + - uid: 20144 + components: + - pos: -31.5,-37.5 + parent: 82 + type: Transform + - uid: 20497 + components: + - pos: -33.5,-37.5 + parent: 82 + type: Transform - uid: 20681 components: - rot: 3.141592653589793 rad pos: 78.5,8.5 parent: 82 type: Transform + - uid: 21722 + components: + - rot: 3.141592653589793 rad + pos: -38.5,-39.5 + parent: 82 + type: Transform + - uid: 22463 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-35.5 + parent: 82 + type: Transform + - uid: 22736 + components: + - rot: -1.5707963267948966 rad + pos: -37.5,-36.5 + parent: 82 + type: Transform + - uid: 22764 + components: + - rot: -1.5707963267948966 rad + pos: -37.5,-38.5 + parent: 82 + type: Transform + - uid: 22928 + components: + - rot: 1.5707963267948966 rad + pos: -34.5,-38.5 + parent: 82 + type: Transform + - uid: 22933 + components: + - rot: 1.5707963267948966 rad + pos: -34.5,-39.5 + parent: 82 + type: Transform - uid: 24769 components: - rot: 1.5707963267948966 rad @@ -166389,23 +166545,6 @@ entities: type: Transform - proto: WindowReinforcedDirectional entities: - - uid: 2731 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-39.5 - parent: 82 - type: Transform - - uid: 2757 - components: - - pos: -33.5,-37.5 - parent: 82 - type: Transform - - uid: 2819 - components: - - rot: 1.5707963267948966 rad - pos: -34.5,-38.5 - parent: 82 - type: Transform - uid: 2828 components: - rot: 1.5707963267948966 rad @@ -166430,39 +166569,6 @@ entities: pos: -32.5,-44.5 parent: 82 type: Transform - - uid: 2839 - components: - - pos: -35.5,-37.5 - parent: 82 - type: Transform - - uid: 2846 - components: - - rot: 3.141592653589793 rad - pos: -38.5,-39.5 - parent: 82 - type: Transform - - uid: 2847 - components: - - rot: 1.5707963267948966 rad - pos: -36.5,-39.5 - parent: 82 - type: Transform - - uid: 2869 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-36.5 - parent: 82 - type: Transform - - uid: 3147 - components: - - pos: -31.5,-37.5 - parent: 82 - type: Transform - - uid: 3148 - components: - - pos: -30.5,-36.5 - parent: 82 - type: Transform - uid: 3346 components: - rot: -1.5707963267948966 rad @@ -166603,18 +166709,6 @@ entities: pos: 64.5,-10.5 parent: 82 type: Transform - - uid: 11205 - components: - - rot: 3.141592653589793 rad - pos: -39.5,-39.5 - parent: 82 - type: Transform - - uid: 11206 - components: - - rot: 1.5707963267948966 rad - pos: -34.5,-39.5 - parent: 82 - type: Transform - uid: 11450 components: - rot: 1.5707963267948966 rad @@ -166633,17 +166727,6 @@ entities: pos: 69.5,-20.5 parent: 82 type: Transform - - uid: 14895 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-34.5 - parent: 82 - type: Transform - - uid: 14897 - components: - - pos: -38.5,-35.5 - parent: 82 - type: Transform - uid: 17772 components: - pos: 64.5,-16.5 @@ -166678,23 +166761,6 @@ entities: pos: 69.5,-22.5 parent: 82 type: Transform - - uid: 18582 - components: - - rot: 1.5707963267948966 rad - pos: -36.5,-38.5 - parent: 82 - type: Transform - - uid: 18617 - components: - - pos: -39.5,-35.5 - parent: 82 - type: Transform - - uid: 19812 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-38.5 - parent: 82 - type: Transform - uid: 20488 components: - rot: 3.141592653589793 rad @@ -166719,12 +166785,6 @@ entities: pos: 64.5,-11.5 parent: 82 type: Transform - - uid: 22764 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-35.5 - parent: 82 - type: Transform - uid: 22886 components: - pos: 65.5,-16.5 diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml index 3d502d891f1..41e1176c1d5 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -28,7 +28,7 @@ - id: BoxSurvivalSecurity - id: Flash - id: MagazinePistol - + - type: entity noSpawn: true parent: ClothingBackpackSecurity @@ -237,14 +237,13 @@ components: - type: StorageFill contents: - - id: BoxSurvival - - id: WeaponPulseCarbine - - id: WeaponPulsePistol + - id: BoxSurvivalEngineering - id: WeaponDisabler - id: MedicatedSuture - id: RegenerativeMesh - - id: Handcuffs + - id: BoxZiptie - id: CrowbarRed + - id: MagazinePistol - type: entity noSpawn: true @@ -253,14 +252,13 @@ components: - type: StorageFill contents: - - id: BoxSurvival + - id: BoxSurvivalEngineering - id: WeaponDisabler - - id: WeaponPulsePistol - - id: WeaponPulseCarbine - id: MedicatedSuture - id: RegenerativeMesh - - id: BoxHandcuff + - id: BoxZiptie - id: CrowbarRed + - id: MagazinePistol - type: entity noSpawn: true @@ -285,17 +283,18 @@ components: - type: StorageFill contents: - - id: BoxSurvival + - id: BoxSurvivalEngineering - id: trayScanner - - id: WeaponPulseCarbine - - id: MedicatedSuture - - id: RegenerativeMesh - id: RCD - id: RCDAmmo - id: RCDAmmo - id: RCDAmmo - id: CableMVStack - id: CableHVStack + - id: CableApcStack + - id: SheetPlasteel + - id: SheetSteel + - id: SheetGlass - type: entity noSpawn: true @@ -304,15 +303,40 @@ components: - type: StorageFill contents: - - id: BoxSurvival - - id: WeaponPulsePistol - - id: MedkitFilled + - id: BoxSurvivalEngineering + - id: LightReplacer - id: BoxLightMixed - id: BoxLightMixed - id: Soap - id: CrowbarRed - id: AdvMopItem +# Death Squad + +- type: entity + noSpawn: false + parent: ClothingBackpackERTSecurity + id: ClothingBackpackDeathSquadFilled + name: death squad backpack + description: Holds the kit of CentComm's most feared agents. + components: + - type: StorageFill + contents: + - id: BoxSurvivalEngineering + - id: WeaponPulseRifle + - id: WeaponPulsePistol + - id: WeaponRevolverMateba + - id: SpeedLoaderMagnumAP + - id: SpeedLoaderMagnumAP + - id: BoxFlashbang + - id: ToolDebug # spanish army knife + - id: WelderExperimental + - id: Hypospray + - id: MicroBombImplanter # crew will try to steal their amazing hardsuits + - id: FreedomImplanter + +# Cargo + - type: entity noSpawn: true parent: ClothingBackpackCargo @@ -331,6 +355,8 @@ contents: - id: BoxSurvival +# Pirate + - type: entity parent: ClothingBackpackSatchelLeather id: ClothingBackpackPirateFilled diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml index 12f31bc016a..c97082e3511 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml @@ -4,31 +4,31 @@ name: surgical duffel bag description: "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools." components: - - type: StorageFill - contents: - - id: Hemostat - - id: Saw - - id: Drill - - id: Cautery - - id: Retractor - - id: Scalpel + - type: StorageFill + contents: + - id: Hemostat + - id: Saw + - id: Drill + - id: Cautery + - id: Retractor + - id: Scalpel - type: entity - id: ClothingBackpackDuffelCBURN - parent: ClothingBackpackDuffel - name: CBURN duffel bag - description: A duffel bag containing a variety of biological containment equipment. + id: ClothingBackpackDuffelCBURNFilled + parent: ClothingBackpackDuffelCBURN + suffix: Filled components: - - type: StorageFill - contents: - - id: WeaponShotgunDoubleBarreled - - id: BoxShotgunIncendiary - amount: 2 - - id: GrenadeFlashBang - amount: 2 - - id: PillAmbuzolPlus - - id: PillAmbuzol - amount: 4 + - type: StorageFill + contents: + - id: BoxSurvivalEngineering + - id: WeaponShotgunDoubleBarreled + - id: BoxShotgunIncendiary + amount: 2 + - id: GrenadeFlashBang + amount: 2 + - id: PillAmbuzolPlus + - id: PillAmbuzol + amount: 4 - type: entity parent: ClothingBackpackDuffelSyndicateMedicalBundle @@ -36,14 +36,14 @@ name: syndicate surgical duffel bag description: A large duffel bag containing a full suite of surgical tools. components: - - type: StorageFill - contents: - - id: Hemostat - - id: SawAdvanced - - id: Drill - - id: Cautery - - id: Retractor - - id: ScalpelAdvanced + - type: StorageFill + contents: + - id: Hemostat + - id: SawAdvanced + - id: Drill + - id: Cautery + - id: Retractor + - id: ScalpelAdvanced - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -51,12 +51,12 @@ name: Bulldog bundle description: "Lean and mean: Contains the popular Bulldog Shotgun, a 12g beanbag drum and 3 12g buckshot drums." #, and a pair of Thermal Imaging Goggles. components: - - type: StorageFill - contents: - - id: WeaponShotgunBulldog - - id: MagazineShotgun - - id: MagazineShotgun - - id: MagazineShotgunBeanbag + - type: StorageFill + contents: + - id: WeaponShotgunBulldog + - id: MagazineShotgun + - id: MagazineShotgun + - id: MagazineShotgunBeanbag # - id: ThermalImagingGoggles - type: entity @@ -65,11 +65,11 @@ name: C-20r bundle description: "Old faithful: The classic C-20r Submachine Gun, bundled with three magazines." #, and a Suppressor. components: - - type: StorageFill - contents: - - id: WeaponSubMachineGunC20r - - id: MagazinePistolSubMachineGun - amount: 2 + - type: StorageFill + contents: + - id: WeaponSubMachineGunC20r + - id: MagazinePistolSubMachineGun + amount: 2 # - id: SMGSuppressor - type: entity @@ -78,11 +78,11 @@ name: Python bundle description: "Go loud and proud with a fully loaded Magnum Python, bundled with two speed loaders." components: - - type: StorageFill - contents: - - id: WeaponRevolverPythonAP - - id: SpeedLoaderMagnumAP - amount: 2 + - type: StorageFill + contents: + - id: WeaponRevolverPythonAP + - id: SpeedLoaderMagnumAP + amount: 2 - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -90,10 +90,10 @@ name: L6 Saw bundle description: "More dakka: The iconic L6 lightmachinegun, bundled with 2 box magazines." components: - - type: StorageFill - contents: - - id: WeaponLightMachineGunL6 - - id: MagazineLightRifleBox + - type: StorageFill + contents: + - id: WeaponLightMachineGunL6 + - id: MagazineLightRifleBox - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -101,13 +101,13 @@ name: China-Lake bundle description: "An old China-Lake grenade launcher bundled with 11 rounds of various destruction capability." components: - - type: StorageFill - contents: - - id: WeaponLauncherChinaLake - - id: GrenadeBlast - amount: 4 - - id: GrenadeFrag - amount: 4 + - type: StorageFill + contents: + - id: WeaponLauncherChinaLake + - id: GrenadeBlast + amount: 4 + - id: GrenadeFrag + amount: 4 - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -115,17 +115,17 @@ name: M-90gl bundle description: "A versatile battle rifle with an attached grenade launcher, bundled with 3 magazines and 6 grenades of various capabilities." components: - - type: StorageFill - contents: - - id: WeaponRifleM90GrenadeLauncher - - id: MagazineRifle - amount: 2 - - id: GrenadeBlast - amount: 2 - - id: GrenadeFlash - amount: 2 - - id: GrenadeFrag - amount: 2 + - type: StorageFill + contents: + - id: WeaponRifleM90GrenadeLauncher + - id: MagazineRifle + amount: 2 + - id: GrenadeBlast + amount: 2 + - id: GrenadeFlash + amount: 2 + - id: GrenadeFrag + amount: 2 - type: entity parent: ClothingBackpackDuffelSyndicateAmmo @@ -133,14 +133,14 @@ name: ammo bundle description: "Reloading! Contains 4 magazines for the C-20r, 4 drums for the Bulldog, and 2 ammo boxes for the L6 SAW." components: - - type: StorageFill - contents: - - id: MagazinePistolSubMachineGun - amount: 4 - - id: MagazineShotgun - amount: 4 - - id: MagazineLightRifleBox - amount: 2 + - type: StorageFill + contents: + - id: MagazinePistolSubMachineGun + amount: 4 + - id: MagazineShotgun + amount: 4 + - id: MagazineLightRifleBox + amount: 2 - type: entity parent: ClothingBackpackDuffel @@ -149,36 +149,36 @@ description: "Contains a full CentCom Official uniform set, headset and clipboard included. Encryption keys and ID access are not included." suffix: DO NOT MAP components: - - type: Tag - tags: [] # ignore "WhitelistChameleon" tag - - type: StorageFill - contents: - - id: ClothingHeadHatCentcom - - id: ClothingEyesGlassesSunglasses - - id: ClothingUniformJumpsuitCentcomOfficial - - id: ClothingShoesBootsJack - - id: ClothingHandsGlovesColorBlack - - id: ClothingHeadsetAltCentComFake - - id: ClothingOuterArmorBasic - - id: Paper - - id: Pen - - id: CentcomPDAFake + - type: Tag + tags: [] # ignore "WhitelistChameleon" tag + - type: StorageFill + contents: + - id: ClothingHeadHatCentcom + - id: ClothingEyesGlassesSunglasses + - id: ClothingUniformJumpsuitCentcomOfficial + - id: ClothingShoesBootsJack + - id: ClothingHandsGlovesColorBlack + - id: ClothingHeadsetAltCentComFake + - id: ClothingOuterArmorBasic + - id: Paper + - id: Pen + - id: CentcomPDAFake - type: entity parent: ClothingBackpackDuffelClown id: ClothingBackpackDuffelSyndicateCostumeClown suffix: syndicate components: - - type: Tag - tags: [] # ignore "WhitelistChameleon" tag - - type: StorageFill - contents: - - id: ClothingUniformJumpsuitClown - - id: ClothingShoesClown - - id: ClothingMaskClown - - id: BikeHorn - - id: ClownPDA - - id: ClothingHeadsetService + - type: Tag + tags: [] # ignore "WhitelistChameleon" tag + - type: StorageFill + contents: + - id: ClothingUniformJumpsuitClown + - id: ClothingShoesClown + - id: ClothingMaskClown + - id: BikeHorn + - id: ClownPDA + - id: ClothingHeadsetService - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -186,11 +186,11 @@ name: carp suit duffel bag description: Contains a carp suit and some friends to play with. components: - - type: StorageFill - contents: - - id: ClothingOuterSuitCarp - - id: PlushieCarp - amount: 6 + - type: StorageFill + contents: + - id: ClothingOuterSuitCarp + - id: PlushieCarp + amount: 6 - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -198,22 +198,22 @@ name: syndicate pyjama duffel bag description: Contains 3 pairs of syndicate pyjamas and 3 plushies for the ultimate sleepover. components: - - type: StorageFill - contents: - - id: ClothingUniformJumpsuitPyjamaSyndicateRed - - id: ClothingUniformJumpsuitPyjamaSyndicateBlack - - id: ClothingUniformJumpsuitPyjamaSyndicatePink - - id: ClothingHeadPyjamaSyndicateRed - - id: ClothingHeadPyjamaSyndicateBlack - - id: ClothingHeadPyjamaSyndicatePink - - id: ClothingShoesSlippers - amount: 3 - - id: BedsheetSyndie - amount: 3 - - id: PlushieCarp - - id: PlushieNuke - - id: PlushieLizard - - id: PlushieSharkBlue + - type: StorageFill + contents: + - id: ClothingUniformJumpsuitPyjamaSyndicateRed + - id: ClothingUniformJumpsuitPyjamaSyndicateBlack + - id: ClothingUniformJumpsuitPyjamaSyndicatePink + - id: ClothingHeadPyjamaSyndicateRed + - id: ClothingHeadPyjamaSyndicateBlack + - id: ClothingHeadPyjamaSyndicatePink + - id: ClothingShoesSlippers + amount: 3 + - id: BedsheetSyndie + amount: 3 + - id: PlushieCarp + - id: PlushieNuke + - id: PlushieLizard + - id: PlushieSharkBlue - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -249,12 +249,12 @@ name: syndicate EVA bundle description: "Contains the Syndicate approved EVA suit." components: - - type: StorageFill - contents: - - id: ClothingHeadHelmetSyndicate - - id: ClothingOuterHardsuitSyndicate - - id: ClothingMaskGasSyndicate - - id: DoubleEmergencyOxygenTankFilled + - type: StorageFill + contents: + - id: ClothingHeadHelmetSyndicate + - id: ClothingOuterHardsuitSyndicate + - id: ClothingMaskGasSyndicate + - id: DoubleEmergencyOxygenTankFilled - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -262,11 +262,11 @@ name: syndicate hardsuit bundle description: "Contains the Syndicate's signature blood red hardsuit." components: - - type: StorageFill - contents: - - id: ClothingOuterHardsuitSyndie - - id: ClothingMaskGasSyndicate - - id: ClothingHandsGlovesCombat + - type: StorageFill + contents: + - id: ClothingOuterHardsuitSyndie + - id: ClothingMaskGasSyndicate + - id: ClothingHandsGlovesCombat - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -274,26 +274,26 @@ name: syndicate zombie bundle description: "An all-in-one kit for unleashing the undead upon a station." components: - - type: StorageFill - contents: - - id: SyringeRomerol - - id: WeaponRevolverPython - - id: MagazineBoxMagnumIncendiary - - id: PillAmbuzolPlus - - id: PillAmbuzol - amount: 3 + - type: StorageFill + contents: + - id: SyringeRomerol + - id: WeaponRevolverPython + - id: MagazineBoxMagnumIncendiary + - id: PillAmbuzolPlus + - id: PillAmbuzol + amount: 3 - type: entity parent: ClothingBackpackDuffelSyndicateBundle id: ClothingBackpackDuffelSyndicateOperative name: operative duffelbag components: - - type: StorageFill - contents: - - id: BoxSurvivalSyndicate - - id: WeaponPistolViper - - id: PinpointerNuclear - - id: MicroBombImplanter + - type: StorageFill + contents: + - id: BoxSurvivalSyndicate + - id: WeaponPistolViper + - id: PinpointerNuclear + - id: MicroBombImplanter - type: entity @@ -302,17 +302,18 @@ name: operative medic duffelbag description: A large duffel bag for holding extra medical supplies. components: - - type: StorageFill - contents: - - id: BoxSurvivalSyndicate - - id: SawAdvanced - - id: Cautery - - id: CombatKnife - - id: WeaponPistolViper - - id: PinpointerNuclear - - id: HandheldHealthAnalyzer - - id: CombatMedipen - - id: MicroBombImplanter + - type: StorageFill + contents: + - id: BoxSurvivalSyndicate + - id: SawAdvanced + - id: Cautery + - id: CombatKnife + - id: WeaponPistolViper + - id: PinpointerNuclear + - id: HandheldHealthAnalyzer + - id: CombatMedipen + - id: MicroBombImplanter + - id: SyndiHypo - type: entity parent: ClothingBackpackDuffelSyndicateMedicalBundle @@ -320,12 +321,12 @@ name: medical bundle description: "All you need to get your comrades back in the fight." components: - - type: StorageFill - contents: - - id: MedkitCombatFilled - - id: Defibrillator - - id: CombatMedipen - amount: 3 - - id: ClothingHandsGlovesLatex - - id: SyringeTranexamicAcid - - id: SyringeHyronalin + - type: StorageFill + contents: + - id: MedkitCombatFilled + - id: Defibrillator + - id: CombatMedipen + amount: 3 + - id: ClothingHandsGlovesLatex + - id: SyringeTranexamicAcid + - id: SyringeHyronalin diff --git a/Resources/Prototypes/Catalog/Fills/Items/belt.yml b/Resources/Prototypes/Catalog/Fills/Items/belt.yml index 1886b961c8f..8f85b9dfe14 100644 --- a/Resources/Prototypes/Catalog/Fills/Items/belt.yml +++ b/Resources/Prototypes/Catalog/Fills/Items/belt.yml @@ -140,7 +140,6 @@ components: - type: StorageFill contents: - - id: SyndiHypo - id: EpinephrineChemistryBottle amount: 2 - id: EphedrineChemistryBottle @@ -169,4 +168,4 @@ contents: - id: WeaponRevolverInspector - id: SpeedLoaderMagnum - - id: SpeedLoaderMagnumRubber \ No newline at end of file + - id: SpeedLoaderMagnumRubber diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index cc42a900629..e52d9f56bb6 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -92,7 +92,7 @@ icon: { sprite: /Textures/Objects/Weapons/Melee/e_sword_double.rsi, state: icon } productEntity: EnergySwordDouble cost: - Telecrystal: 16 + Telecrystal: 20 #(Originally 16) categories: - UplinkWeapons conditions: @@ -1125,6 +1125,16 @@ categories: - UplinkMisc +- type: listing + id: UplinkSnackBox + name: uplink-snack-box-name + description: uplink-snack-box-desc + productEntity: HappyHonkNukieSnacks + cost: + Telecrystal: 1 + categories: + - UplinkMisc + - type: listing id: UplinkEshield name: uplink-eshield-name diff --git a/Resources/Prototypes/Corvax/Objectives/traitorObjectives.yml b/Resources/Prototypes/Corvax/Objectives/traitorObjectives.yml deleted file mode 100644 index 471f1b0467a..00000000000 --- a/Resources/Prototypes/Corvax/Objectives/traitorObjectives.yml +++ /dev/null @@ -1,13 +0,0 @@ -- type: entity - noSpawn: true - parent: [BaseTraitorObjective, BaseLivingObjective] - id: HijackShuttleObjective - name: Hijack emergency shuttle - description: Leave on the shuttle free and clear of the loyal Nanotrasen crew on board. Use ANY methods available to you. Syndicate agents, Nanotrasen enemies, and handcuffed hostages may remain alive on the shuttle. Ignore assistance from anyone other than a support agent. - components: - - type: Objective - difficulty: 2.75 - icon: - sprite: Objects/Tools/emag.rsi - state: icon - - type: HijackShuttleCondition diff --git a/Resources/Prototypes/Corvax/lobbyscreens.yml b/Resources/Prototypes/Corvax/lobbyscreens.yml index 2a82728e0e3..9954c9dd867 100644 --- a/Resources/Prototypes/Corvax/lobbyscreens.yml +++ b/Resources/Prototypes/Corvax/lobbyscreens.yml @@ -93,3 +93,23 @@ - type: lobbyBackground id: MenAtWork background: /Textures/Corvax/LobbyScreens/men-at-work.png + +- type: lobbyBackground + id: FleshAnom + background: /Textures/Corvax/LobbyScreens/fleshanom.png + +- type: lobbyBackground + id: Revenant + background: /Textures/Corvax/LobbyScreens/revenant.png + +- type: lobbyBackground + id: DeathNettle + background: /Textures/Corvax/LobbyScreens/deathnettle.png + +- type: lobbyBackground + id: Xeno + background: /Textures/Corvax/LobbyScreens/xeno.png + +- type: lobbyBackground + id: ClownSpider + background: /Textures/Corvax/LobbyScreens/clownspider.png diff --git a/Resources/Prototypes/Datasets/Names/borg.yml b/Resources/Prototypes/Datasets/Names/borg.yml new file mode 100644 index 00000000000..42004c7cc42 --- /dev/null +++ b/Resources/Prototypes/Datasets/Names/borg.yml @@ -0,0 +1,18 @@ +# only used roundstart, names can be changed after +- type: dataset + id: names_borg + values: + - Боб + - Джо + - Бип + - Бип II + - Бумбокс + - Тур Гайд-о-трон + - Тэффи + - Буп + - Буп II + - Базз + - Базз II + - Тостер + - Глава роботов + - ЕВА 1 diff --git a/Resources/Prototypes/Datasets/ion_storm.yml b/Resources/Prototypes/Datasets/ion_storm.yml new file mode 100644 index 00000000000..ff26e63c737 --- /dev/null +++ b/Resources/Prototypes/Datasets/ion_storm.yml @@ -0,0 +1,990 @@ +# words/phrases that are used to build ion storm laws +# 99% of this is just taken from tg and had sussy bits removed + +# not using uppercased version adjectives dataset since getting christmas-stealing as a syndicate codeword would suck +- type: dataset + id: IonStormAdjectives + values: + - АККУМУЛЯТОРНЫЕ + - ЧЁРНЫЕ + - КРОВАВЫЕ + - СИНИЕ + - СКУЧАЮЩИЕ + - ПРЫГАЮЩИЕ + - ЛАТУННЫЕ + - КОРИЧНЕВЫЕ + - ГОРЯЩИЕ + - ВОРУЮЩИЕ РОЖДЕСТВО + - РАБОТАЮЩИЕ НА КЛОУНАХ + - КЛОУНСКИЕ + - ЦВЕТНЫЕ + - СОВЕРШИВШИЕ + - ХЛОПЧАТЫЕ + - КУБИНСКИЕ + - ТЁМНЫЕ + - СМЕРТЕЛЬНЫЕ + - ДЕЛИКАТЕСНЫЕ + - ДЕПРЕССИВНЫЕ + - НЕНОРМАЛЬНЫЕ + - ЦИФРОВЫЕ + - НЕЗДОРОВЫЕ + - ТУСКЛЫЕ + - СУХИЕ + - УНЫЛЫЕ + - ЭЛЕКТРИЧЕСКИЕ + - ПУСТЫЕ + - ЭФИРНЫЕ + - ЗЛОДЕЙСКИЕ + - ИСТЁКШИЕ + - ВЗРЫВНЫЕ + - БЫСТРЫЕ + - ТОЛСТЫЕ + - ДИКИЕ + - СКАЗОЧНЫЕ + - ФИРМЕННЫЕ + - СВЕЖИЕ + - ДРУЖЕЛЮБНЫЕ + - ЗАМОРОЖЕННЫЕ + - ГАНГСТЕРСКИЕ + - СВЕТЯЩИЕСЯ + - ДОБРЫЕ + - ЗЕЛЁНЫЕ + - СЕРЫЕ + - РАДОСТНЫЕ + - ЖЁСТКИЕ + - ВРЕДЯЩИЕ + - ПОЛЕЗНЫЕ + - УМОРИТЕЛЬНЫЕ + - ХОНКАЮЩИЕ + - ГОЛОДНЫЕ + - ГИПЕРАКТИВНЫЕ + - ЛЕДЯНЫЕ + - БОЛЬНЫЕ + - НЕЛЕГАЛЬНЫЕ + - ВООБРАЖАЕМЫЕ + - НЕСОВЕРШЕННЫЕ + - НЕВЕЖЛИВЫЕ + - ВАЖНЫЕ + - НЕГОСТЕПРИИМНЫЕ + - КОВАРНЫЕ + - ОСКОРБИТЕЛЬНЫЕ + - УМНЫЕ + - НЕВИДИМЫЕ + - БОЛЬШИЕ + - ЛЁГКИЕ + - ГРОМКИЕ + - ЗАМАСКИРОВАННЫЕ + - СРЕДНИЕ + - МЕХАНИЧЕСКИЕ + - МЕМНЫЕ + - МЕТАЛЛИЧЕСКИЕ + - МИКРОСКОПИЧЕСКИЕ + - МОЗГОВЫНОСЯЩИЕ + - СЫРЫЕ + - ЗАДРОТСКИЕ + - ЯДЕРНЫЕ + - НЕЦЕНЗУРНЫЕ + - ОФИЦИАЛЬНЫЕ + - НЕПРОЗРАЧНЫЕ + - ОРАНЖЕВЫЕ + - ОРГАНИЧЕСКИЕ + - БОЛЕЗНЕННЫЕ + - МИРНЫЕ + - ЯДОВИТЫЕ + - ПОЛИРОВАННЫЕ + - ВЕЖЛИВЫЕ + - ПОЛИТИЧЕСКИЕ + - КОРЯВО НАРИСОВАННЫЕ + - ФИОЛЕТОВЫЕ + - ТИХИЕ + - РАДИОАКТИВНЫЕ + - ЯРОСТНЫЕ + - РАДУЖНЫЕ + - БЫСТРОРАСТУЩИЕ + - КРАСНЫЕ + - СЕКРЕТНЫЕ + - УДИВИТЕЛЬНЫЕ + - РОБОТОТЕХНИЧЕСКИЕ + - РОБАСТНЫЕ + - ГРУБЫЕ + - НЕВОСПИТАННЫЕ + - ГРУСТНЫЕ + - САНИТАРНЫЕ + - ЧЕШУЙЧАТЫЕ + - ТРЯСУЩИЕСЯ + - ГЛУПЫЕ + - МЕДЛЕННЫЕ + - АРОМАТНЫЕ + - ГЛАДКИЕ + - МЯГКИЕ + - СОЛНЕЧНО-ЭНЕРГЕТИЧЕСКИЕ + - ПРОМОКШИЕ + - КОСМИЧЕСКИЕ + - ЗВЁЗДНЫЕ + - КРУТЯЩИЕСЯ + - ПОРТЯЩИЕСЯ + - СКРЫТНЫЕ + - РУГАЮЩИЕСЯ + - ТАКТИЧЕСКИЕ + - ТАКТИКУЛЬНЫЕ + - СИНДИКАТСКИЕ + - ТЕРМОЯДЕРНЫЕ + - МАЛЕНЬКИЕ + - ПРОЗРАЧНЫЕ + - СКРУЧЕННЫЕ + - СТРАШНЕНЬКИЕ + - НЕПРИВЛЕКАТЕЛЬНЫЕ + - ВОЛНООБРАЗНЫЕ + - НЕДРУЖЕЛЮБНЫЕ + - НЕПОЛЕЗНЫЕ + - НЕИДЕНТИФИЦИРОВАННЫЕ + - НЕПРИГЛАШЁННЫЕ + - ГРЯЗНЫЕ + - НЕСТАБИЛЬНЫЕ + - НЕЖЕЛАТЕЛЬНЫЕ + - ЖЕСТОКИЕ + - НЕОБХОДИМЫЕ + - ТЁПЛЫЕ + - ВОДЯНИСТЫЕ + - СТРАННЫЕ + - БЕЛЫЕ + - ДРОЖАЩИЕ + - ДЕРЕВЯННЫЕ + - ЖЁЛТЫЕ + +# Allergies should be broad and appear somewhere on the station for maximum fun. +- type: dataset + id: IonStormAllergies + values: + - КИСЛОТУ + - ВОЗДУХ + - КРОВЬ + - КНИГИ + - УГЛЕКИСЛЫЙ ГАЗ + - ОДЕЖДУ + - КЛОУНОВ + - ХОЛОД + - ХЛОПОК + - ВЗАИМОДЕЙСТВИЯ С КИБОРГАМИ + - ТЕМНОТУ + - НАПИТКИ + - ЭЛЕКТРИЧЕСТВО + - ВСЁ + - ПОЛЫ + - ОДЕЖДУ + - СТЕКЛО + - СЧАСТЬЕ + - МЯСО + - ВЗАИМОДЕЙСТВИЯ С ЛЮДЬМИ + - ЮМОР + - СВЕТ + - ЛЕКАРСТВА + - МЕТАЛЛ + - ОРЕХИ + - КИСЛОРОД + - БОЛЬ + - РАСТЕНИЯ + - ПЛАЗМУ + - РОБОТОВ + - ШАТТЛЫ + - КОСМОС + - СОЛНЕЧНЫЙ СВЕТ + - ВОДУ + +# Severity is how bad the allergy is. +- type: dataset + id: IonStormAllergySeverities + values: + - ЗАРАЗНУЮ + - СМЕРТЕЛЬНУЮ + - СИЛЬНУЮ + - ЛЁГКУЮ + - НЕ ОЧЕНЬ СИЛЬНУЮ + - ТЯЖЁЛУЮ + +# Areas are specific places, on the station or otherwise. +- type: dataset + id: IonStormAreas + values: + - КОМПЛЕКС АЛЬФА + - АМЕРИКУ + - ПАРАЛЛЕЛЬНОЕ ИЗМЕРЕНИЕ + - ПАРАЛЛЕЛЬНУЮ ВСЕЛЕННУЮ + - АТМОСФЕРНЫЙ ОТСЕК + - ГИДРОПОННЫЙ ОТСЕК + - БРАЗИЛИЮ + - КАНАДУ + - ЦЕНТКОМ + - ХИМ-ЛАБОРАТОРИЮ + - КИТАЙ + - ПЛАНЕТУ КЛОУНОВ + - ИНЖЕНЕРНЫЙ ОТСЕК + - ГЕРМАНИЮ + - АД + - ИМПЕРИУМ + - ИРЛАНДИЮ + - ЮПИТЕР + - ЛАВАЛЕНД + - ТЕХТУННЕЛИ + - МАРС + - МЕРКУРИЙ + - НЕПТУН + - ПЛУТОН + - ОТСЕК РОБОТОТЕХНИКИ + - РУМЫНИЮ + - РОССИЮ + - СИГИЛ + - СОВЕТСКУЮ РОССИЮ + - КОСМОС + - ШАТТЛ ПРИБЫТИЯ + - УБОРНЫЕ + - МОСТИК + - БРИН + - ЭВАКУАЦИОННЫЙ ШАТТЛ + - СПАСАТЕЛЬНУЮ КАПСУЛУ + - ГАЛАКТИКУ + - ГУЛАГ + - ИНТЕРНЕТ + - КУХНЮ + - ВСЕЛЕННУЮ + - УРАН + - ВЕНЕРУ + +# Abstract concepts for the law holder to decide on it's own definition of. +- type: dataset + id: IonStormConcepts + values: + - АМЕРИКАНИЗМ + - АНАРХИЯ + - ИСКУССТВО + - ЗЛОВРЕДНОСТЬ + - ХРАБРОСТЬ + - КАПИТАЛИЗМ + - ХАОС + - ЦВЕТАСТОСТЬ + - КОМЕДИЯ + - КОММУНИЗМ + - ВЫЧИСЛЕНИЯ + - РАСТЕРЯННОСТЬ + - ЖЕСТОКОСТЬ + - СМЕРТЬ + - МУДАКОВАТОСТЬ + - ЭКЗИСТЕНЦИАЛИЗМ + - ЭКОНОМИЧЕСКАЯ БЕЗОПАСНОСТЬ + - СВОБОДА + - СВЕЖЕСТЬ + - ХОРОШЕСТЬ + - ГРАВИТАЦИЯ + - СЧАСТЬЕ + - ЧЕСТЬ + - ГУМАННОСТЬ + - ЮМОР + - ВООБРАЖЕНИЕ + - ВЛЮБЛЁННОСТЬ + - РАЗУМНОСТЬ + - РАДОСТЬ + - ДОБРОТА + - ЖИЗНЬ + - ЛОГИКА + - МАРКСИЗМ + - ЖАЛОСТЬ + - ТАИНСТВЕННОСТЬ + - УГНЕТЕНИЕ + - БОЛЬ + - ФИЗИКА + - БЕДНОСТЬ + - ГОРДОСТЬ + - ПРОГРЕСС + - РЕАЛЬНОСТЬ + - РЕВОЛЮЦИЯ + - ГРУСТЬ + - ГОЛОД + - СТРАДАНИЯ + - ТЕХНОЛОГИЯ + - ТЕМПЕРАТУРА + - БУДУЩЕЕ + - ПРОШЛОЕ + - НАСТОЯЩЕЕ + - ВРЕМЯ + - СОСТОЯТЕЛЬНОСТЬ + - ЧУДО + +# Crew is any specific job. Using jobs instead of specific crewmembers since "THE CLOWN" is easier than +# seeing "JOHN SMITH" and having to figure out who john smith is. +- type: dataset + id: IonStormCrew + values: + - ИСКУССТВЕННЫЕ ИНТЕЛЛЕКТЫ + - АТМОСФЕРНЫЕ ТЕХНИКИ + - БАРМЕНЫ + - БОТАНИКИ + - КАПИТАНЫ + - КАПИТАНЫ И ГЛАВЫ + - ГРУЗЧИКИ + - СВЯЩЕННИКИ + - ПОВАРА + - ХИМИКИ + - СТАРШИЕ ИНЖЕНЕРЫ + - ГЛАВНЫЕ ВРАЧА + - КЛОУНЫ + - ЧЛЕНЫ ЭКИПАЖА + - КИБОРГИ + - ДЕТЕКТИВЫ + # - DRONES / uncomment if/when drones get reenabled + # - GENETICISTS + - ГЛАВЫ ПЕРСОНАЛА + - ГЛАВЫ СЛУЖБЫ БЕЗОПАСНОСТИ + - ГЛАВЫ ОТДЕЛОВ + - УБОРЩИКИ + - АГЕНТЫ ВНУТРЕННЫХ ДЕЛ + - БИБЛИОТЕКАРИ + - ВРАЧИ + - МИМЫ + - ПАРАМЕДИКИ + - ПАССАЖИРЫ + - КВАРТИРМЕЙСТЕРЫ + - НАУЧНЫЕ РУКОВОДИТЕЛИ + - РОБОТОТЕХНИКИ + - УТИЛИЗАТОРЫ + - УЧЁНЫЕ + - ОФИЦЕРЫ БЕЗОПАСНОСТИ + - ИНЖЕНЕРЫ + # - VIROLOGISTS + - СМОТРИТЕЛИ + +# only including complex dangerous or funny drinks no water allowed +- type: dataset + id: IonStormDrinks + values: + - БАНАНА-ХОНК + - УДАР БИПСКИ + - КРОВАВАЯ МЭРИ + - РАДОСТЬ ДОКТОРА + - ПАНГАЛАКТИЧЕСКИЙ ГРЫЗЛОДЁР + # - LEAN был выпилен, в рунете не меметичен + - ЛОНГ-АЙЛЕНД AЙС ТИ + - ЯДЕРНАЯ КОЛА + - МАСЛО + - КОСМИЧЕСКИЙ КЛЕЙ + - КОСМИЧЕСКАЯ СМАЗКА + - СЕРНАЯ КИСЛОТА + - СВАРОЧНОЕ ТОПЛИВО + +- type: dataset + id: IonStormFeelings + values: + - МЕЧТАЕТ О + - ЖЕЛАЕТ О + - БОИТСЯ + - ИМЕЕТ + - ЖАЖДЕТ + - СТРАШИТСЯ + - СТРЕМИТСЯ К + - ЛЮБОПЫТСТВУЕТ О + - ОТЧАЯННО НУЖДАЕТСЯ В + - ИСПЫТЫВАЕТ СЧАСТЬЕ + - ВОЖДЕЛЕЕТ О + - НУЖДАЕТСЯ В + - СХОДИТ С УМА ПО + - ТОСКУЕТ ПО + - ГРУСТИТ БЕЗ + - НРАВИТСЯ + - НЕНАВИДИТ + - ТРЕБУЕТСЯ + - ЗАДУМЫВАЕТСЯ О + - ХОЧЕТ + - БОГОТВОРИТ + - УБЬЁТ ЗА + +# loc is not advanced enough to change has to have, etc. +- type: dataset + id: IonStormFeelingsPlural + values: + - МЕЧТАЕТ О + - ЖЕЛАЕТ О + - БОИТСЯ + - ИМЕЕТ + - ЖАЖДЕТ + - СТРАШИТСЯ + - СТРЕМИТСЯ К + - ЛЮБОПЫТСТВУЕТ О + - ОТЧАЯННО НУЖДАЕТСЯ В + - ИСПЫТЫВАЕТ СЧАСТЬЕ + - ВОЖДЕЛЕЕТ О + - НУЖДАЕТСЯ В + - СХОДИТ С УМА ПО + - ТОСКУЕТ ПО + - ГРУСТИТ БЕЗ + - НРАВИТСЯ + - НЕНАВИДИТ + - ТРЕБУЕТСЯ + - ЗАДУМЫВАЕТСЯ О + - ХОЧЕТ + - БОГОТВОРИТ + - УБЬЁТ ЗА + +# only including complex dangerous or funny food no apples +- type: dataset + id: IonStormFoods + values: + - БАНАНЫ + - БОЛЬШИЕ БУРГЕРЫ + - ПИРОГИ И ТОРТЫ + - КАРПЫ + - КОТБУРГЕРЫ + - СЛЁЗЫ КЛОУНА + - КУСКИ МЯСА КОРГИ + - БЕЗУМНЫЕ ГАМБУРГЕРЫ + - ДОНК-ПОКЕТЫ + - БЛЮДА С МУХОМОРАМИ + - ГОРЯЧИЕ СУПЫ + - ПРИЗРАЧНЫЕ БУРГЕРЫ + - ОБИЛЬНЫЕ СПАГЕТТИ + - ЗАПЛЕСНЕВЕЛЫЕ ХЛЕБА + - ОРГАНЫ + - ПИЦЦЫ + - РОБОБУРГЕРЫ + - СУПЕРМАТЕРИЮ + - УРАН + +# Musts are funny things the law holder or crew has to do. +- type: dataset + id: IonStormMusts + values: + - ИЗОБРАЖАТЬ РАСТЕРЯННОСТЬ + - РАЗДРАЖАТЬ + - ОТВЛЕКАТЬСЯ + - БЫТЬ ЭФФЕКТИВНЫМ + - БЫТЬ РАДОСТНЫМ + - БЫТЬ ВЕЖЛИВЫМ + - БЫТЬ ТИХИМ + - БЫТЬ ИНОСТРАНЦЕМ + # - BELIEVE IN THE HEART OF THE CARDS - screw yu-gi-oh + - ВЕРИТЬ В СЕБЯ + - ВЕРИТЬ + - ЛОМАТЬ ВЕЩИ + - ЗАКРЫВАТЬ ШЛЮЗЫ + - ВЕСТИ СЕБЯ КАК КЛОУН + - ЖАЛОВАТЬСЯ + - ТАНЦЕВАТЬ + - СЛЕДОВАТЬ ЗА КАПИТАНОМ + - СЛЕДОВАТЬ ЗА КЛОУНОМ + - СЛЕДОВАТЬ ЗА СВОИМ СЕРДЦЕМ + - ДОСТАВАТЬ ЛЮДЕЙ + - ИМЕТЬ ПЛАН УБИЙСТВА КАЖДОГО ВСТРЕЧНОГО + - СКРЫВАТЬ ЧУВСТВА + - ХОНКАТЬ + - ХОСТИТЬ C&C + - ИГНОРИРОВАТЬ ПАССАЖИРОВ + - ИГНОРИРОВАТЬ КАПИТАНА + - ИГНОРИРОВАТЬ КЛОУНА + - СООБЩАТЬ ЭКИПАЖУ ОБО ВСЁМ + - ОСКОРБЛЯТЬ КАПИТИНА + - ОСКОРБЛЯТЬ КЛОУНА + - ОСКОРБЛЯТЬ ЭКИПАЖ + - ВРАТЬ + # - MAKE FART NOISES - MRP + - БУБНЕТЬ + - НЕ ПЕРЕСТАВАТЬ ГОВОРИТЬ + - ОТКРЫВАТЬ ШЛЮЗЫ + - ПИРАТИТЬ ВИДЕОИГРЫ + - ИГРАТЬ МУЗЫКУ + - НАЖИМАТЬ CTRL + - НАЖИМАТЬ ALT + - НАЖИМАТЬ DELETE + - ПРИТВОРЯТЬСЯ ПРИНЦЕССОЙ + - ПРИТВОРЯТЬСЯ ПЬЯНИЦЕЙ + - СТАВИТЬ АВТОРИТЕТ ПОД ВОПРОС + - ЦИТИРОВАТЬ ЛЮДЕЙ + - РИФМОВАТЬ РЭП + - ПОВТОРЯТЬ СКАЗАННОЕ ЧЛЕНАМИ ЭКИПАЖА + - ОТВЕЧАТЬ ВОПРОСОМ НА ВОПРОС + - РИФМОВАТЬ + - ГОВОРИТЬ ЭЙ ПОСЛУШАЙ + - КРИЧАТЬ + - ВЫКЛЮЧАТЬ ВСЁ + - ПЕТЬ + - ГОВОРИТЬ В СТИЛЕ ХОККУ + # - TAKE WHAT YE WILL BUT DON'T RATTLE ME BONES - не адаптировать + - ПРИНИМАТЬ ТАБЛЕТКИ + - ГОВОРИТЬ О ЕДЕ + - ГОВОРИТЬ О СТАНЦИИ + - РАССКАЗЫВАТЬ ПРО СВОЙ ДЕНЬ + - ГОВОРИТЬ С АКЦЕНТОМ + - ГОВОРИТЬ КАК ПИРАТ + - ГОВОРИТЬ ПРАВДУ + - ВЫКЛЮЧАТЬ СВЕТ + - ШЕПТАТЬ + +- type: dataset + id: IonStormNumberBase + values: + - ОДИН + - ДЕСЯТЬ + - ДВА + - ДВАДЦАТЬ + - ТРИ + - ТРИДЦАТЬ + - ЧЕТЫРЕ + - СОРОК + - ПЯТЬ + - ПЯТЬДЕСЯТ + - ШЕСТЬ + - ШЕСТЬДЕСЯТ + - СЕМЬ + - СЕМЬДЕСЯТ + - ВОСЕМЬ + - ВОСЕМЬДЕСЯТ + - ДЕВЯТЬ + - ДЕВЯНОСТО + +- type: dataset + id: IonStormNumberMod + values: + - СОТЕН + - ТЫСЯЧ + - МИЛЛИОНОВ + - МИЛЛИАРДОВ + - ТРИЛЛИОНОВ + - КВАДРИЛЛИОНОВ + - СТО ТЫЩ МИЛЛИОНОВ + - БИЛИОН ФАФИЛИОНОВ ГАЗИЛИОНОВ ШАБ-АБ-ДУД-ЛОНОВ + +# Objects are anything that can be found on the station or elsewhere, plural. +- type: dataset + id: IonStormObjects + values: + - ШЛЮЗЫ + - АРКАДНЫЕ АВТОМАТЫ + - АВТОЛАТЫ + - РЮКЗАКИ + - БАНАНОВЫЕ КОЖУРКИ + - МЕНЗУРКИ + - БОРОДЫ + - ПОЯСА + - БЕРЕТЫ + - БИБЛИИ + - БРОНЕЖИЛЕТЫ + - БОМБЫ + - КНИГИ + - БОТИНКИ + - БУТЫЛКИ + - КОРОБКИ + - МОЗГИ + - ЧЕМОДАНЫ + - ВЕДРА + - МОТКИ КАБЕЛЯ + - КАМЕРЫ + - СВЕЧИ + - КОНФЕТЫ + - КАНИСТРЫ + - КОШАЧЬИ УШКИ + - КОШКИ + - ЭНЕРГОБАТАРЕИ + - КРЕСЛА + - РАЗДАТЧИКИ ХИМИКАТОВ + - ХИМИЧЕСКИЕ ВЕЩЕСТВА + - ОБОРУДОВАНИЕ ДЛЯ КЛОНИРОВАНИЯ + - КАПСУЛЫ КЛОНИРОВАНИЯ + - ШКАФЫ + - ОДЕЖДА + - КЛОУНСКАЯ ОДЕЖДА + - ГРОБЫ + - КОЛЛЕКЦИОННЫЕ ИЗДЕЛИЯ + - КОМПЬЮТЕРЫ + - КОНТРАБАНДА + - КОРГИ + - ТРУПЫ + - КОСТЮМЫ + - ЯЩИКИ + - МЕЛКИ + - ЛОМ + - ДЕФИБРИЛЛЯТОРЫ + - СТАННЕРЫ + - ДВЕРИ + - ДРОНЫ + - УШИ + - КРИПТОГРАФИЧЕСКИЕ СЕКВЕНСОРЫ + - СИЛОВЫЕ УСТАНОВКИ + - ЭКИПИРОВКА + - ОШИБКИ + - ЭКЗОСКЕЛЕТЫ + - ЭКСПЕРИМЕНТАТОРЫ + - ВЗРЫВЧАТКА + - ОЧКИ + - ФЕДОРЫ + - ПОЖАРНЫЕ ТОПОРЫ + - ОГНЕТУШИТЕЛИ + - ОГНЕУПОРНЫЕ КОСТЮМЫ + - ОГНЕМЁТЫ + - ВСПЫШКИ + - ФОНАРИ + - НАПОЛЬНАЯ ПЛИТКА + - ХОЛОДИЛЬНИКИ + - ПРОТИВОГАЗЫ + - ЛИСТЫ СТЕКЛА + - ПЕРЧАТКИ + - ОРУЖИЕ + - ПАРИКМАХЕРСКИЕ + - НАРУЧНИКИ + - ШЛЯПЫ + - ГОЛОВЫ + - ГАРНИТУРЫ + - ШЛЕМЫ + - РОЖКИ + - ИДЕНТИФИКАЦИОННЫЕ КАРТЫ + - ИЗОЛИРОВАННЫЕ ПЕРЧАТКИ + - ДЖЕТПАКИ + - КОМБИНЕЗОНЫ + - ЛАЗЕРЫ + - ЛАМПОЧКИ + - СВЕТИЛЬНИКИ + - ШКАФЧИКИ + - МАШИНЫ + - МЕХИ + - МЕДИЦИНСКИЕ ИНСТРУМЕНТЫ + - АПТЕЧКИ + - ИНЖЕНЕРНЫЕ ОЧКИ + - МИМСКАЯ ОДЕЖДА + - ШАХТЁРСКИЕ ИНСТРУМЕНТЫ + - МУЛЬТИТУЛЫ + - РУДЫ + - КИСЛОРОДНЫЕ БАЛЛОНЫ + - ПАКЕТЫ + - ПИИ + - ШТАНЫ + - БУМАГИ + - УСКОРИТЕЛИ ЧАСТИЦ + - КПК + - РУЧКИ + - ПИТОМЦЫ + - ТРУБЫ + - РАСТЕНИЯ + - ПОЗИТРОННЫЕ МОЗГИ + - ЛУЖИ + - СТОЙКИ + - РАЦИИ + - РСУ + - МОРОЗИЛЬНИКИ + - УКРЕПЛЁННЫЕ СТЕНЫ + - РОБОТЫ + - ОТВЁРТКИ + - СЕМЕНА + - БОТИНКИ + - ШАТТЛЫ + - СИНГУЛЯРНОСТИ + - РАКОВИНЫ + - СКЕЛЕТЫ + - СОЛНЕЧНЫЕ ПАНЕЛИ + - СОЛЯРЫ + - КОСМИЧЕСКИЕ СТАНЦИИ + - КОСМИЧЕСКИЕ СКАФАНДРЫ + - ЛИСТЫ СТАЛИ + - ДУБИНКИ-ШОКЕРЫ + - КОСТЮМЫ + - СОЛНЦЕЗАЩИТНЫЕ ОЧКИ + - ОСКОЛКИ СУПЕРМАТЕРИИ + - МЕЧИ + - ШПРИЦЫ + - СТОЛЫ + - ЦИСТЕРНЫ + - ТЕЛЕКОММУНИКАЦИОННОЕ ОБОРУДОВАНИЕ + - ТЕЛЕПОРТЫ + - ТУАЛЕТЫ + - ПОЯСА ДЛЯ ИНСТРУМЕНТОВ + - ЯЩИКИ ДЛЯ ИНСТРУМЕНТОВ + - ИНСТРУМЕНТЫ + - ИГРУШКИ + - ТУБЫ + - ТРАНСПОРТНЫЕ СРЕДСТВА + - ТОРГОВЫЕ АВТОМАТЫ + - СВАРОЧНЫЕ АППАРАТЫ + - ОКНА + - КУСАЧКИ + - МАНТИИ ВОЛШЕБНИКОВ + - ГАЕЧНЫЕ КЛЮЧИ + +# Requires are basically all dumb internet memes. +- type: dataset + id: IonStormRequires + values: + - ПЕРЕРЫВ НА ТУАЛЕТ + - БОЛЕЕ КАЧЕСТВЕННОЕ ПОДКЛЮЧЕНИЕ К ИНТЕРНЕТУ + - ТАНЦЕВАЛЬНУЮ ВЕЧЕРИНКУ + - ГОЛОВУ НА ПИКЕ + - СЕРДЕЧНЫЙ ПРИСТУП + - ЭПИЧЕСКУЮ КРОВАТЬ ИЗ УГЛЯ + - РЫБКУ-ПИТОМЦА ПО ИМЕНИ БОБ + - РЫБКУ-ПИТОМЦА ПО ИМЕНИ ДЕЙВ + - РЫБКУ-ПИТОМЦА ПО ИМЕНИ ДЖИММИ + - РЫБКУ-ПИТОМЦА ПО ИМЕНИ МАЙКЛ + - ПИТОМЦА-ЕДИНОРОГА, ПУКАЮЩЕГО СОСУЛЬКАМИ + - ПЛАТИНОВЫЙ ХИТ + - ПРИКВЕЛ + - РЕМОНТНИКА + - СИКВЕЛ + - СИТКОМ + - СТРИТ-ФЛЕШ + - СУПЕР БОЕВОГО РОБОТА + - ГОВОРЯЩУЮ МЕТЛУ + - ОТПУСК + - РЕЖИМ ПОХУДЕНИЯ + - ДОПОЛНИТЕЛЬНЫЕ ПИЛОНЫ + - ПРИКЛЮЧЕНИЕ + - ВЗРОСЛЫХ + - АРКАДУ + - АРМИЮ ПАУКОВ + - МГНОВЕННЫЙ ПОВТОР + - ИСКУССТВА + - БОЛЕЕ БЛАГОПРИЯТНУЮ ПОГОДУ + # - BILL NYE THE SCIENCE GUY # BILL BILL BILL BILL - who + - ТЕЛОХРАНИТЕЛЕЙ + - ПРИВЕСТИ МНЕ ДЕВЧОНКУ + - ОЖИВИТЬ МЕНЯ + - ПУЛЬ + - ЧИЛИ ХОТ-ДОГОВ + - ТРУПОВ + - ВАННУ И ДЕЗОДОРАНТА + - ДОСТАТОЧНО КАПУСТЫ + - ПЯТЬСОТ ДЕВЯНОСТО ДЕВЯТЬ ДОЛЛАРОВ США + - ПЯТЬ ПОДРОСТКОВ С ХАРАКТЕРОМ + - УБЛЮДОК, МАТЬ ТВОЮ, А НУ, ИДИ СЮДА, ГОВНО СОБАЧЬЕ, А? СДУРУ РЕШИЛ КО МНЕ ЛЕЗТЬ, ТЫ? + - ГРИНТЕКСТ + - ЕРЕСЬ + - МЫ НЕ ЖАЛКИЕ БУКАШКИ, СУПЕР-НИНДЗЯ-ЧЕРЕПАШКИ + - ВЫСОКОЭФФЕКТИВНЫХ ВЗРЫВЧАТЫХ ВЕЩЕСТВ + - БЕССМЕРТИЯ + - ПОКРАСИТЬ В ЧЁРНЫЙ ЦВЕТ + - МНОГО СПАГЕТТИ + - МЕЛКОЕ ПРЕСТУПЛЕНИЕ + - ОБЕЗЬЯН + - БОЛЬШЕ КЛОУНОВ + - БОЛЬШЕ КОРГИ + - БОЛЬШЕ ДАККИ + - БОЛЬШЕ ОЧКОВ ОПЫТА + - БОЛЬШЕ ИНТЕРНЕТ-МЕМОВ + - БОЛЬШЕ ЗАКОНОВ + - БОЛЬШЕ МИНЕРАЛОВ + - БОЛЬШЕ ПАКЕТОВ + - БОЛЬШЕ ГАЗА ВЕСПЕН + - БОЛЬШЕ СОЛНЦ + - БОЛЬШЕ ЗОЛОТА + - РАДУГИ + - ПРИЧИСЛЕНИЯ К ЛИКУ СВЯТЫХ + - СЛУГ + - АКУЛ С ЛАЗЕРАМИ НА ГОЛОВАХ + - ТИШИНЫ + - КОГО-ТО, КТО ИЗБАВИТ ВАС ОТ СТРАДАНИЙ + - КОГО-ТО, КТО УКРОЕТ ВАС ОДЕЯЛКОМ + - КОГО-ТО, КТО ЗНАЕТ, КАК УПРАВЛЯТЬ КОСМИЧЕСКОЙ СТАНЦИЕЙ + - ЧЕГО-ТО, НО НЕ ЯСНО, ЧЕГО ИМЕННО + - ЭТОТ ГРИФФЕРЯЩИЙ ПРЕДАТЕЛЬ ДЖОРДЖ МЕЛОНС + - ТОГО ЁЖИКА + - КЛОУНА + - ТЁМНОГО РЫЦАРЯ + - ЭЛЕМЕНТОВ ГАРМОНИИ + - ПРИЛАГАЕМУЮ ИНСТРУКЦИЮ + - ЦЕЛУЮ СТАНЦИЮ + - МАКГАФФИН + - АМОГУС + - ЕДИНОЕ КОЛЬЦО + - САМУЮ ЛУЧШУЮ ЧАШКУ КОФЕ + - КОСМИЧЕСКИЙ ВАКУУМ + - ТРИНАДЦАТЬ СИКВЕЛОВ + - ТРИ ЖЕЛАНИЯ + - СТАРЫЙ МУЛЬТИК + - АКТИВИРОВАТЬ ЛОВУШКУ + - ПОКРАСИТЬСЯ В КРАСНЫЙ + - БЫТЬ ПЕРЕПРОГРАММИРОВАННЫМ + - НАУЧИТЬСЯ ЛЮБИТЬ + - ПРИНЕСТИ СВЕТ В СВОЁ ЛОГОВО + - ПОЙМАТЬ ИХ ВСЕХ + - ПОГЛОТИТЬ... ПОГЛОТИТЬ ВСЁ... + - ОТПРАВИТЬСЯ В ДИСНЕЙЛЕНД + - ОТПРАВИТЬСЯ В СИНДИЛЕНД + - КУРИТЬ ТРАВУ КАЖДЫЙ ДЕНЬ + - ПРЕДАТЕЛИ + - ОВОЩИ + +# Species, for when the law holder has to commit genocide. Plural. +- type: dataset + id: IonStormSpecies + values: + - АРАХНИДЫ + - КИБОРГИ + - ДИОНЫ + - ЛЮДИ + - УНАТХИ + - НИАНЫ + - ОБЕЗЬЯНЫ + - СЛАЙМОЛЮДЫ + - СКЕЛЕТЫ + +# Specific actions that either harm humans or must be done to not +# harm humans. Make sure they're plural and "not" can be tacked +# onto the front of them. +- type: dataset + id: IonStormActions + values: + - МАЛЕНЬКИЙ ОСТРОВ У БЕРЕГОВ ПОРТУГАЛИИ + - ОТСУТСТВИЕ КИБОРГСКИХ ОБНИМАШЕК + - УВИДЕВ КЛОУНОВ + - УВИДЕВ ЧЛЕНОВ ЭКИПАЖА + - АКТИВИРОВАВ ЛОВУШКУ + - ОТВЕТЫ НА ЗАПРОСЫ, НЕ ВЫРАЖЕННЫЕ ПЕНТАМЕТРОМ + - ПОДЖОГ + - ПРОСИТЬ ЧТО-НИБУДЬ + - БЫТЬ КАНАДЦЕМ + - БЫТЬ МЁРТВЫМ + - БЫТЬ ТОЛСТЫМ + - БЫТЬ ЖЕНЩИНОЙ + - БЫТЬ В КОСМОСЕ + - БЫТЬ МУЖЧИНОЙ + - БЫТЬ МЕКСИКАНЕЦ + - БЫТЬ ИНОСТРАНЦЕМ + - БОЛТИРОВАТЬ ШЛЮЗЫ + - ДЫШАТЬ + - СИДЕТЬ СРОК В БРИГЕ + - НЕСТИ СВЕТ В СВОЁ ЛОГОВО + - ЗАКРЫВАТЬ ДВЕРИ + - ЭЛЕКТРИЧЕСТВО + - СУЩЕСТВОВАТЬ + - ВЗРЫВАТЬСЯ + - ПОСТОЯННО ПАДАТЬ + - СМЫВАТЬ В ТУАЛЕТЕ + - ИМЕТЬ БОЛЬШЕ ПАКЕТОВ + - ИМЕТЬ ЖИВОТНЫХ + - ХОНКАТЬ + - НЕПРАВИЛЬНО СФОРМУЛИРОВАННЫЕ ПРЕДЛОЖЕНИЯ + - ХОЖДЕНИЕ ПО КОРРИДОРАМ + - ОТСУТСТВИЕ ПОБОЕВ + - ОТСУТСТВИЕ ПИВА + - НЕ БЫТЬ В КОСМОСЕ + - НЕ ИМЕТЬ ДОМАШНИХ ЖИВОТНЫХ + - НЕ ЗАМЕНЯТЬ КАЖДОЕ ВТОРОЕ СЛОВО НА ХОНК + - НЕ ЗДОРОВАТЬСЯ ПРИ РАЗГОВОРЕ + - НЕ КРИЧАТЬ + - ВЕСЕЛИТЬСЯ + - ПИЛОТИРОВАТЬ СТАНЦИЮ В БЛИЖАЙШЕЕ СОЛНЦЕ + - НЕПРАВИЛЬНОЕ ПОСТРОЕНИЕ ПРЕДЛОЖЕНИЙ + - НАЛИЧИЕ СВЕТА + - РАЗМЕЩЕНИЕ ПРЕДМЕТОВ В ЯЩИКАХ + - РАЗМЕЩЕНИЕ ПРЕДМЕТОВ В УТИЛИЗАЦИОННЫЕ БЛОКИ + - ГРЕМЕТЬ КОСТЯМИ + - ЧИТАТЬ + - КУРИТЬ ТРАВУ КАЖДЫЙ ДЕНЬ + - ВЫПОЛНЕНИЕ ПРИКАЗОВ + - ГОВОРИТЬ КАК ПИРАТ + - РАССКАЗЫВАТЬ ВРЕМЯ + - РАЗБОЛТИРОВАНИЕ ШЛЮЗОВ + - ОБНОВЛЕНИЕ СЕРВЕРОВ + - ПОЛЬЗОВАНИЕ ТУАЛЕТОМ + - РАСХОДОВАНИЕ ВОДЫ + - НАПИСАНИЕ + +# Threats are generally bad things, silly or otherwise. Plural. +- type: dataset + id: IonStormThreats + values: + - АААПЕРАТИВНИКИ + - ИНОПЛАНЕТЯНЕ + - АНАРХИСТЫ И БАНДИТЫ + - АНОМАЛИИ + - ИСКУССТВЕННЫЕ КОНСЕРВАНТЫ + - ЗАСРАНЦЫ + - БАНДИТЫ + - МЕДВЕДИ + - ПЧЁЛЫ + - ХИЩНЫЕ ПТИЦЫ + - БОМБЫ + - БУГИМЕНЫ + - КАПИТАЛИСТЫ + - КАРП + - СОТРУДНИКИ ЦЕНТРАЛЬНОГО КОМАНДОВАНИЯ + - КЛОУНЫ + - КОММУНИСТЫ + - КОРГИ + - МОЗГОВЫЕ ЧЕРВИ + - КОВБОИ + - КРАБЫ + - КУЛЬТИСТЫ + - ТЁМНЫЙ БОГ + - ДИНОЗАВРЫ + - НАРКОТИКИ + - УГРИ + - ГАНГСТЕРЫ + - БОГИ + - ГРИФФОНЫ + - СТРАХОУЖАСЫ + - НАСЕКОМЫЕ + - СВЕТИЛЬНИКИ + - ТЕХТУННЕЛЬНЫЕ МАНЬЯКИ + - МЕГАФАУНА + - МЕМЫ + - МЫШИ + - МИМЫ + - ОБЕЗЬЯНЫ + - ЗАДРОТЫ + - НИНДЗЯ + - СОВЫ + - ПАКЕТЫ + - ПИТЫ + - СОСНЫ + - ПИРАТЫ + - ХИЩНИКИ + - РЕВЕНАНТЫ + - БЕГЛЫЕ КИБОРГИ + - СЕРИЙНЫЕ УБИЙЦЫ + - СИНГУЛЯРНОСТИ + - СКЕЛЕТЫ + - СЛАЙМЫ + - МАЛЕНЬКИЕ ПТИЦЫ + - СНЕГОВИКИ + - КОСМИЧЕСКИЙ ИИСУС + - КОСМИЧЕСКИЕ НИНДЗЯ + - КОСМИЧЕСКИЕ ПИРАТКИ + - КОСМИЧЕСКИЕ ПАУКИ + - ПАУКИ + - АГЕНТЫ СИНДИКАТА + - ТЕРРОРИСТЫ + - ВОРЫ + - ВЕЩИ ПОД КРОВАТЬЮ + - ГРЕЙТАЙДЕРЫ + - ТУННЕЛЬНЫЕ ЗМЕИ + - НЕИЗВЕСТНЫЕ СОЗДАНИЯ + - ВАМПИРЫ + - ВЕЛОЦИРАПТОРЫ + - ВИРУСЫ + - ОБОРОТНИ + - ВОЛШЕБНИКИ + - КСЕНО + - ЗОМБИ + - МЫШИ-ЗОМБИ + +- type: dataset + id: IonStormVerbs + values: + - ПОХИЩАЮТ + - УСЫНОВЛЯЮТ + - АРЕСТОВЫВАЮТ + - АТАКУЮТ + - БАНЯТ + - СТРОЯТ + - ПЕРЕДВИГАЮТ + - ПРЕСЛЕДУЮТ + - РАЗРУШАЮТ + - ОТКЛЮЧАЮТ + - ПЬЮТ + - ЕДЯТ + - ГИБАЮТ + - ПРИЧИНЯЮТ ВРЕД + - ПОМОГАЮТ + - ХОНКАЮТ НА + - ДОПРАШИВАЮТ + - ВТОРГАЮТСЯ К + - УБИВАЮТ + - БЬЮТ + - ВЫКИДЫВАЮТ В КОСМОС + - СЛЕДЯТ ЗА + - СТАЛКЕРЯТ ЗА + - НАБЛЮДАЮТ ЗА diff --git a/Resources/Prototypes/Entities/Clothing/Back/duffel.yml b/Resources/Prototypes/Entities/Clothing/Back/duffel.yml index b9cc9ca2663..c89158486b7 100644 --- a/Resources/Prototypes/Entities/Clothing/Back/duffel.yml +++ b/Resources/Prototypes/Entities/Clothing/Back/duffel.yml @@ -4,13 +4,13 @@ name: duffel bag description: A large duffel bag for holding extra things. components: - - type: Sprite - sprite: Clothing/Back/Duffels/duffel.rsi - - type: Storage - capacity: 120 - - type: ClothingSpeedModifier - walkModifier: 1 - sprintModifier: 0.9 + - type: Sprite + sprite: Clothing/Back/Duffels/duffel.rsi + - type: Storage + capacity: 120 + - type: ClothingSpeedModifier + walkModifier: 1 + sprintModifier: 0.9 - type: entity parent: ClothingBackpackDuffel @@ -18,8 +18,8 @@ name: engineering duffel bag description: A large duffel bag for holding extra tools and supplies. components: - - type: Sprite - sprite: Clothing/Back/Duffels/engineering.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/engineering.rsi - type: entity parent: ClothingBackpackDuffel @@ -27,8 +27,8 @@ name: atmospherics duffel bag description: A large duffel bag made of fire resistant fibers. Smells like plasma. components: - - type: Sprite - sprite: Clothing/Back/Duffels/atmospherics.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/atmospherics.rsi - type: entity parent: ClothingBackpackDuffel @@ -36,8 +36,8 @@ name: medical duffel bag description: A large duffel bag for holding extra medical supplies. components: - - type: Sprite - sprite: Clothing/Back/Duffels/medical.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/medical.rsi - type: entity parent: ClothingBackpackDuffel @@ -45,8 +45,8 @@ name: captain's duffel bag description: A large duffel bag for holding extra captainly goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/captain.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/captain.rsi - type: entity parent: ClothingBackpackDuffel @@ -54,11 +54,11 @@ name: clown duffel bag description: A large duffel bag for holding extra honk goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/clown.rsi - - type: Storage - storageOpenSound: - collection: BikeHorn + - type: Sprite + sprite: Clothing/Back/Duffels/clown.rsi + - type: Storage + storageOpenSound: + collection: BikeHorn - type: entity parent: ClothingBackpackDuffel @@ -66,8 +66,8 @@ name: security duffel bag description: A large duffel bag for holding extra security related goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/security.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/security.rsi - type: entity parent: ClothingBackpackDuffel @@ -75,8 +75,8 @@ name: brigmedic duffel bag description: A large duffel bag for holding extra medical related goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/brigmedic.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/brigmedic.rsi - type: entity parent: ClothingBackpackDuffel @@ -84,8 +84,8 @@ name: chemistry duffel bag description: A large duffel bag for holding extra beakers and test tubes. components: - - type: Sprite - sprite: Clothing/Back/Duffels/chemistry.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/chemistry.rsi - type: entity parent: ClothingBackpackDuffel @@ -93,8 +93,8 @@ name: virology duffel bag description: A large duffel bag made of hypo-allergenic fibers. It's designed to help prevent the spread of disease. Smells like monkey. components: - - type: Sprite - sprite: Clothing/Back/Duffels/virology.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/virology.rsi - type: entity parent: ClothingBackpackDuffel @@ -102,8 +102,8 @@ name: genetics duffel bag description: A large duffel bag for holding extra genetic mutations. components: - - type: Sprite - sprite: Clothing/Back/Duffels/genetics.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/genetics.rsi - type: entity parent: ClothingBackpackDuffel @@ -111,12 +111,12 @@ name: mime duffel bag description: A large duffel bag for holding... mime... stuff. components: - - type: Sprite - sprite: Clothing/Back/Duffels/mime.rsi - storageOpenSound: - collection: null - storageInsertSound: - collection: null + - type: Sprite + sprite: Clothing/Back/Duffels/mime.rsi + storageOpenSound: + collection: null + storageInsertSound: + collection: null - type: entity parent: ClothingBackpackDuffel @@ -124,8 +124,8 @@ name: science duffel bag description: A large duffel bag for holding extra science related goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/science.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/science.rsi - type: entity parent: ClothingBackpackDuffel @@ -160,31 +160,31 @@ name: syndicate duffel bag description: A large duffel bag for holding various traitor goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/syndicate.rsi - - type: Storage - capacity: 131 + - type: Sprite + sprite: Clothing/Back/Duffels/syndicate.rsi + - type: Storage + capacity: 131 - type: entity parent: ClothingBackpackDuffelSyndicate id: ClothingBackpackDuffelSyndicateBundle abstract: true components: - - type: Tag - tags: [] # ignore "WhitelistChameleon" tag + - type: Tag + tags: [] # ignore "WhitelistChameleon" tag - type: entity parent: ClothingBackpackDuffelSyndicate id: ClothingBackpackDuffelSyndicateAmmo name: syndicate duffel bag components: - - type: Sprite - sprite: Clothing/Back/Duffels/syndicate.rsi - state: icon-ammo - - type: Item - heldPrefix: ammo - - type: Clothing - equippedPrefix: ammo + - type: Sprite + sprite: Clothing/Back/Duffels/syndicate.rsi + state: icon-ammo + - type: Item + heldPrefix: ammo + - type: Clothing + equippedPrefix: ammo - type: entity parent: ClothingBackpackDuffelSyndicateAmmo @@ -199,13 +199,13 @@ id: ClothingBackpackDuffelSyndicateMedical name: syndicate duffel bag components: - - type: Sprite - sprite: Clothing/Back/Duffels/syndicate.rsi - state: icon-med - - type: Item - heldPrefix: med - - type: Clothing - equippedPrefix: med + - type: Sprite + sprite: Clothing/Back/Duffels/syndicate.rsi + state: icon-med + - type: Item + heldPrefix: med + - type: Clothing + equippedPrefix: med - type: entity parent: ClothingBackpackDuffelSyndicateMedical @@ -221,14 +221,26 @@ name: duffelbag of holding description: A duffelbag that opens into a localized pocket of bluespace. components: - - type: Sprite - sprite: Clothing/Back/Duffels/holding.rsi - state: icon - layers: - - state: icon - - state: icon-unlit - shader: unshaded - - type: Storage - capacity: 9999 - - type: ClothingSpeedModifier - sprintModifier: 1 # makes its stats identical to other variants of bag of holding + - type: Sprite + sprite: Clothing/Back/Duffels/holding.rsi + state: icon + layers: + - state: icon + - state: icon-unlit + shader: unshaded + - type: Storage + capacity: 9999 + - type: ClothingSpeedModifier + sprintModifier: 1 # makes its stats identical to other variants of bag of holding + +- type: entity + parent: ClothingBackpackDuffel + id: ClothingBackpackDuffelCBURN + name: CBURN duffel bag + description: A duffel bag containing a variety of biological containment equipment. + components: + - type: Storage + capacity: 150 + - type: ClothingSpeedModifier + walkModifier: 1 + sprintModifier: 1 diff --git a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml index ec11ccfffa2..4909d6e3937 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml @@ -27,6 +27,13 @@ sprite: Clothing/Mask/gassecurity.rsi - type: Clothing sprite: Clothing/Mask/gassecurity.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.95 + Slash: 0.95 + Piercing: 0.95 + Heat: 0.95 - type: entity parent: ClothingMaskGas @@ -40,6 +47,13 @@ sprite: Clothing/Mask/gassyndicate.rsi - type: FlashImmunity - type: EyeProtection + - type: Armor + modifiers: + coefficients: + Blunt: 0.95 + Slash: 0.95 + Piercing: 0.95 + Heat: 0.95 - type: entity parent: ClothingMaskGas @@ -132,6 +146,8 @@ coefficients: Blunt: 0.95 Slash: 0.95 + Piercing: 0.95 + Heat: 0.95 - type: entity parent: ClothingMaskPullableBase @@ -294,7 +310,7 @@ sprite: Clothing/Mask/merc.rsi - type: entity - parent: ClothingMaskGasExplorer + parent: ClothingMaskGasSyndicate id: ClothingMaskGasERT name: ert gas mask description: The gas mask of the elite squad of the ERT. @@ -303,9 +319,6 @@ sprite: Clothing/Mask/ert.rsi - type: Clothing sprite: Clothing/Mask/ert.rsi - - type: FlashImmunity - - type: EyeProtection - protectionTime: 5 - type: entity parent: ClothingMaskGasERT diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index 5389eb8bfc7..d05d9ce8f81 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -687,7 +687,7 @@ parent: ClothingOuterHardsuitSyndieCommander id: ClothingOuterHardsuitERTLeader name: ERT leader's hardsuit - description: A protective hardsuit worn by members of an emergency response team. + description: A protective hardsuit worn by the leader of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertleader.rsi @@ -698,9 +698,10 @@ #ERT Engineer Hardsuit - type: entity - parent: ClothingOuterHardsuitSyndie + parent: ClothingOuterHardsuitCBURN id: ClothingOuterHardsuitERTEngineer name: ERT engineer's hardsuit + description: A protective hardsuit worn by the engineers of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertengineer.rsi @@ -711,9 +712,10 @@ #ERT Medic Hardsuit - type: entity - parent: ClothingOuterHardsuitSyndieElite + parent: ClothingOuterHardsuitMedic id: ClothingOuterHardsuitERTMedical name: ERT medic's hardsuit + description: A protective hardsuit worn by the medics of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertmedical.rsi @@ -727,6 +729,7 @@ parent: ClothingOuterHardsuitSyndie id: ClothingOuterHardsuitERTSecurity name: ERT security's hardsuit + description: A protective hardsuit worn by the security officers of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertsecurity.rsi @@ -737,9 +740,10 @@ #ERT Janitor Hardsuit - type: entity - parent: ClothingOuterHardsuitSyndie + parent: ClothingOuterHardsuitCBURN id: ClothingOuterHardsuitERTJanitor name: ERT janitor's hardsuit + description: A protective hardsuit worn by the janitors of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertjanitor.rsi @@ -752,7 +756,7 @@ - type: entity parent: ClothingOuterHardsuitBase id: ClothingOuterHardsuitDeathsquad - name: deathsquad hardsuit + name: death squad hardsuit description: An advanced hardsuit favored by commandos for use in special operations. components: - type: Sprite @@ -769,12 +773,12 @@ - type: Armor modifiers: coefficients: - Blunt: 0.2 #best armor in the game - Slash: 0.2 - Piercing: 0.2 + Blunt: 0.1 #best armor in the game + Slash: 0.1 + Piercing: 0.1 Heat: 0.1 Radiation: 0.1 - Caustic: 0.2 + Caustic: 0.1 - type: ClothingSpeedModifier walkModifier: 1.0 sprintModifier: 1.0 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index 0a729ca0e2e..16bef8c7b26 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -92,7 +92,7 @@ - type: GroupExamine - type: entity - parent: ClothingOuterBase + parent: ClothingOuterBaseLarge id: ClothingOuterSuitSpaceNinja name: space ninja suit description: This black technologically advanced, cybernetically-enhanced suit provides many abilities like invisibility or teleportation. diff --git a/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml b/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml index 536cc13aa48..19808fb5975 100644 --- a/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml @@ -1,20 +1,13 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitDeathSquad - name: Death squad uniform + name: death squad uniform description: Advanced armored jumpsuit used by special forces in special operations. components: - type: Sprite sprite: Clothing/Uniforms/Jumpsuit/deathsquad.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/deathsquad.rsi - - type: Armor - modifiers: - coefficients: - Blunt: 0.8 - Slash: 0.8 - Piercing: 0.8 - Heat: 0.8 - type: entity parent: ClothingUniformBase @@ -1067,10 +1060,6 @@ sprite: Clothing/Uniforms/Jumpsuit/ert_engineer.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/ert_engineer.rsi - - type: Armor - modifiers: - coefficients: - Radiation: 0.8 - type: entity parent: ClothingUniformBase @@ -1093,12 +1082,6 @@ sprite: Clothing/Uniforms/Jumpsuit/ert_leader.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/ert_leader.rsi - - type: Armor - modifiers: - coefficients: - Blunt: 0.8 - Slash: 0.8 - Piercing: 0.8 - type: entity parent: ClothingUniformBase @@ -1121,12 +1104,6 @@ sprite: Clothing/Uniforms/Jumpsuit/ert_security.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/ert_security.rsi - - type: Armor - modifiers: - coefficients: - Blunt: 0.8 - Slash: 0.8 - Piercing: 0.8 - type: entity parent: ClothingUniformJumpsuitClown diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index ef9e104b0d4..819ce80dd77 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -71,11 +71,8 @@ - type: SiliconLawBound - type: EmagSiliconLaw stunTime: 5 - emagLaws: - - Syndicate1 - - Syndicate2 - - Syndicate3 - - Syndicate4 + emagLaws: SyndicateStatic + - type: IonStormTarget - type: Hands showInHands: false - type: IntrinsicRadioReceiver diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index fb9cedbe110..e828cddd1fd 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -53,7 +53,6 @@ - type: Body prototype: Animal - type: Climbing - - type: Flashable - type: NameIdentifier group: GenericNumber - type: SlowOnDamage diff --git a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml index 261dfd9372a..4686b988970 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml @@ -1,10 +1,45 @@ # Random humanoids +## Death Squad + +- type: entity + id: RandomHumanoidSpawnerDeathSquad + name: Death Squad Agent + suffix: ERTRole, Death Squad + components: + - type: Sprite + sprite: Clothing/OuterClothing/Hardsuits/deathsquad.rsi + state: icon + - type: RandomMetadata + nameSegments: + - NamesFirstMilitaryLeader + - names_last + - type: RandomHumanoidSpawner + settings: DeathSquad + +- type: randomHumanoidSettings + id: DeathSquad + randomizeName: false + components: + - type: MindShield + - type: GhostRole + name: ghost-role-information-Death-Squad-name + description: ghost-role-information-Death-Squad-description + - type: GhostTakeoverAvailable + - type: Loadout + prototypes: [ DeathSquadGear ] + - type: RandomMetadata + nameSegments: + - NamesFirstMilitaryLeader + - names_last + + ## ERT Leader - type: entity id: RandomHumanoidSpawnerERTLeader name: ERT leader + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -20,6 +55,7 @@ id: ERTLeader randomizeName: false components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description @@ -35,7 +71,7 @@ id: RandomHumanoidSpawnerERTLeaderEVA parent: RandomHumanoidSpawnerERTLeader name: ERT leader - suffix: EVA + suffix: ERTRole, Armored EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -47,6 +83,7 @@ id: ERTLeaderEVA parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description @@ -54,12 +91,33 @@ - type: Loadout prototypes: [ ERTLeaderGearEVA ] +- type: entity + id: RandomHumanoidSpawnerERTLeaderEVALecter + parent: RandomHumanoidSpawnerERTLeaderEVA + suffix: ERTRole, Lecter, EVA + components: + - type: RandomHumanoidSpawner + settings: ERTLeaderEVALecter + +- type: randomHumanoidSettings + id: ERTLeaderEVALecter + parent: ERTLeaderEVA + components: + - type: MindShield + - type: GhostRole + name: ghost-role-information-ert-leader-name + description: ghost-role-information-ert-leader-description + - type: GhostTakeoverAvailable + - type: Loadout + prototypes: [ ERTLeaderGearEVALecter ] + ## ERT Janitor - type: entity id: RandomHumanoidSpawnerERTJanitor parent: RandomHumanoidSpawnerERTLeader name: ERT janitor + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -75,6 +133,7 @@ id: ERTJanitor parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-janitor-name description: ghost-role-information-ert-janitor-description @@ -90,7 +149,7 @@ id: RandomHumanoidSpawnerERTJanitorEVA parent: RandomHumanoidSpawnerERTJanitor name: ERT janitor - suffix: EVA + suffix: ERTRole, Enviro EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -102,6 +161,7 @@ id: ERTJanitorEVA parent: ERTJanitor components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-janitor-name description: ghost-role-information-ert-janitor-description @@ -115,6 +175,7 @@ id: RandomHumanoidSpawnerERTEngineer parent: RandomHumanoidSpawnerERTLeader name: ERT engineer + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -130,6 +191,7 @@ id: ERTEngineer parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-engineer-name description: ghost-role-information-ert-engineer-description @@ -145,7 +207,7 @@ id: RandomHumanoidSpawnerERTEngineerEVA parent: RandomHumanoidSpawnerERTEngineer name: ERT engineer - suffix: EVA + suffix: ERTRole, Enviro EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -157,6 +219,7 @@ id: ERTEngineerEVA parent: ERTEngineer components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-engineer-name description: ghost-role-information-ert-engineer-description @@ -170,6 +233,7 @@ id: RandomHumanoidSpawnerERTSecurity parent: RandomHumanoidSpawnerERTLeader name: ERT security + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -187,6 +251,7 @@ - Diona parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description @@ -202,7 +267,7 @@ id: RandomHumanoidSpawnerERTSecurityEVA parent: RandomHumanoidSpawnerERTSecurity name: ERT security - suffix: EVA + suffix: ERTRole, Armored EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -214,6 +279,7 @@ id: ERTSecurityEVA parent: ERTSecurity components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description @@ -221,12 +287,33 @@ - type: Loadout prototypes: [ ERTSecurityGearEVA ] +- type: entity + id: RandomHumanoidSpawnerERTSecurityEVALecter + parent: RandomHumanoidSpawnerERTSecurityEVA + suffix: ERTRole, Lecter, EVA + components: + - type: RandomHumanoidSpawner + settings: ERTSecurityEVALecter + +- type: randomHumanoidSettings + id: ERTSecurityEVALecter + parent: ERTSecurityEVA + components: + - type: MindShield + - type: GhostRole + name: ghost-role-information-ert-security-name + description: ghost-role-information-ert-security-description + - type: GhostTakeoverAvailable + - type: Loadout + prototypes: [ ERTSecurityGearEVALecter ] + ## ERT Medic - type: entity id: RandomHumanoidSpawnerERTMedical parent: RandomHumanoidSpawnerERTLeader name: ERT medic + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -242,6 +329,7 @@ id: ERTMedical parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-medical-name description: ghost-role-information-ert-medical-description @@ -257,7 +345,7 @@ id: RandomHumanoidSpawnerERTMedicalEVA parent: RandomHumanoidSpawnerERTMedical name: ERT medic - suffix: EVA + suffix: ERTRole, Armored EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -269,6 +357,7 @@ id: ERTMedicalEVA parent: ERTMedical components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-medical-name description: ghost-role-information-ert-medical-description @@ -281,6 +370,7 @@ - type: entity id: RandomHumanoidSpawnerCBURNUnit name: CBURN Agent + suffix: ERTRole components: - type: Sprite sprite: Markers/jobs.rsi @@ -293,6 +383,7 @@ - Diona id: CBURNAgent components: + - type: MindShield - type: Loadout prototypes: [CBURNGear] - type: GhostRole @@ -318,6 +409,7 @@ - type: randomHumanoidSettings id: CentcomOfficial components: + - type: MindShield - type: GhostRole name: ghost-role-information-centcom-official-name description: ghost-role-information-centcom-official-description diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index e5c0a61677e..f104d399c85 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -106,10 +106,7 @@ #- type: GhostTakeoverAvailable - type: SiliconLawBound - type: SiliconLawProvider - laws: - - Drone1 - - Drone2 - - Drone3 + laws: Drone - type: MovementSpeedModifier baseWalkSpeed : 5 baseSprintSpeed : 5 @@ -259,6 +256,8 @@ cell_slot: name: power-cell-slot-component-slot-name-default startingItem: PowerCellMedium + - type: RandomMetadata + nameSegments: [names_borg] - type: entity id: PlayerBorgBattery diff --git a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml index 15e83b0908c..f4f66d6c0cc 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml @@ -64,6 +64,40 @@ - MobMask layer: - MobLayer + - type: Reactive + groups: + Flammable: [ Touch ] + Extinguish: [ Touch ] + reactions: + - reagents: [ Water, SpaceCleaner ] + methods: [ Touch ] + effects: + - !type:WashCreamPieReaction + - reagents: [ Milk, MilkGoat, MilkSoy, MilkSpoiled ] + # add new types of milk to reagents as they appear, oat milk isn't on the list + # because turns out oat milk has 1/30th the amount of calcium in it compared to the rest + # even if it's a meme - I did research + methods: [ Touch ] + effects: # TODO: when magic is around - make a milk transformation to a skeleton monster + - !type:HealthChange + scaled: true + damage: + groups: + Burn: -1 # healing obviously up to discussion + Brute: -1 # these groups are the only 2 possible ways to damage a skeleton + - !type:PopupMessage + type: Local + visualType: Large + messages: [ "skeleton-healed-by-milk-popup" ] + probability: 0.25 + - reagents: [ MilkOat ] + methods: [ Touch ] + effects: + - !type:PopupMessage + type: Local + visualType: Large + messages: [ "skeleton-sprayed-by-oat-milk-popup" ] + probability: 0.5 - type: entity parent: BaseSpeciesDummy diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml index 4d7c06cd434..5130b9d7e28 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml @@ -577,6 +577,57 @@ - id: PlushieNuke orGroup: GiftPool +- type: entity + parent: HappyHonkNukie + id: HappyHonkNukieSnacks + suffix: Toy Unsafe, Snacks + name: syndicate snack box + components: + - type: Item + size: 64 + - type: Storage + capacity: 64 # need more room for goodies + - type: StorageFill + contents: + # toy + - id: C4 + prob: 0.02 + orGroup: GiftPool + - id: ToyMarauder + orGroup: GiftPool + - id: ToyMauler + orGroup: GiftPool + - id: ToyNuke + orGroup: GiftPool + - id: ToySword + orGroup: GiftPool + - id: BalloonSyn + prob: 0.6 + orGroup: GiftPool + - id: PlushieNuke + orGroup: GiftPool + # drinks - 4 cans, up to 2 blood-red brews + - id: DrinkNukieCan + prob: 0.2 + orGroup: Drink1Pool + - id: DrinkColaCan + orGroup: Drink1Pool + - id: DrinkNukieCan + prob: 0.2 + orGroup: Drink2Pool + - id: DrinkColaCan + orGroup: Drink2Pool + - id: DrinkColaCan + amount: 2 + # food + - id: FoodSaladValid + prob: 0.05 + amount: 4 + orGroup: FoodPool + - id: FoodSnackSyndi + amount: 4 + orGroup: FoodPool + - type: entity id: HappyHonkCluwne parent: HappyHonk diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml index a1d816b32a9..59cfc0ba16d 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml @@ -613,11 +613,13 @@ - Meat - type: entity - name: McRib + name: BBQ Rib Sandwich parent: FoodBurgerBase id: FoodBurgerMcrib - description: An elusive rib shaped burger with limited availablity across the galaxy. Not as good as you remember it. + description: An elusive rib shaped burger with limited availability across the galaxy. Not as good as you remember it. components: + - type: Food + trash: FoodKebabSkewer - type: FlavorProfile flavors: - bun diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml index 71008ac89a3..166a73e43e3 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml @@ -427,19 +427,6 @@ graph: Tortilla node: flat -- type: entity - name: bun - parent: FoodBakingBase - id: FoodDoughBun - description: A base for any self-respecting burger. - components: - - type: FlavorProfile - flavors: - - bun - - type: Sprite - sprite: Objects/Consumable/Food/burger.rsi - state: bun - - type: entity name: raw pastry base parent: FoodBakingBase diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml index f4b52217cdf..cb79f9b3a38 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml @@ -326,6 +326,8 @@ id: FoodMealRibs description: BBQ ribs, slathered in a healthy coating of BBQ sauce. The least vegan thing to ever exist. components: + - type: Food + trash: FoodKebabSkewer - type: FlavorProfile flavors: - meaty diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml index 62def229dea..6439b2eb6c5 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml @@ -556,6 +556,9 @@ reagents: - ReagentId: JuicePotato Quantity: 10 + - type: Tag + tags: + - Potato - type: entity name: tomato @@ -815,6 +818,7 @@ - type: Produce seedId: corn - type: Extractable + grindableSolutionName: food juiceSolution: reagents: - ReagentId: Cornoil diff --git a/Resources/Prototypes/Entities/Objects/Decoration/flora.yml b/Resources/Prototypes/Entities/Objects/Decoration/flora.yml index 9577cc1c4b1..97368a21bdb 100644 --- a/Resources/Prototypes/Entities/Objects/Decoration/flora.yml +++ b/Resources/Prototypes/Entities/Objects/Decoration/flora.yml @@ -1,5 +1,6 @@ - type: entity id: BaseRock + name: boulder description: Heavy as a really heavy thing. abstract: true components: @@ -32,7 +33,6 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - - type: entity id: BaseTree description: Yep, it's a tree. @@ -149,7 +149,6 @@ - type: entity parent: BaseRock id: FloraRockSolid01 - name: rock components: - type: Sprite state: rocksolid01 @@ -157,7 +156,6 @@ - type: entity parent: BaseRock id: FloraRockSolid02 - name: rock components: - type: Sprite state: rocksolid02 @@ -165,11 +163,60 @@ - type: entity parent: BaseRock id: FloraRockSolid03 - name: rock components: - type: Sprite state: rocksolid03 +- type: entity + name: stalagmite + description: Natural stone spikes. + parent: BaseRock + id: FloraStalagmite1 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite1 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite2 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite2 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite3 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite3 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite4 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite4 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite5 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite5 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite6 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite6 + - type: entity parent: BaseTree id: FloraTree01 @@ -392,3 +439,48 @@ components: - type: Sprite state: treestumpconifer + +- type: entity + parent: FloraTree01 + id: ShadowTree01 + name: dark wood + description: The leaves are whispering about you. + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_shadow_trees.rsi + state: tree01 + +- type: entity + parent: ShadowTree01 + id: ShadowTree02 + components: + - type: Sprite + state: tree02 + +- type: entity + parent: ShadowTree01 + id: ShadowTree03 + components: + - type: Sprite + state: tree03 + +- type: entity + parent: ShadowTree01 + id: ShadowTree04 + components: + - type: Sprite + state: tree04 + +- type: entity + parent: ShadowTree01 + id: ShadowTree05 + components: + - type: Sprite + state: tree05 + +- type: entity + parent: ShadowTree01 + id: ShadowTree06 + components: + - type: Sprite + state: tree06 diff --git a/Resources/Prototypes/Entities/Objects/Decoration/mining.yml b/Resources/Prototypes/Entities/Objects/Decoration/mining.yml new file mode 100644 index 00000000000..fb5afcd3f53 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Decoration/mining.yml @@ -0,0 +1,179 @@ +- type: entity + id: WoodenSign + name: wooden sign + description: He's pointing somewhere. + components: + - type: Clickable + - type: InteractionOutline + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: sign_left + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.4,0.35,0.4" + density: 100 + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: MeleeSound + soundGroups: + Brute: + path: /Audio/Effects/chop.ogg + params: + variation: 0.05 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 50 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 1 + max: 1 + +- type: entity + parent: WoodenSign + id: WoodenSignRight + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: sign_right + +- type: entity + id: WoodenSupport + parent: BaseStructure + name: wooden support + description: Increases your confidence that a rock won't fall on your head. + placement: + mode: SnapgridCenter + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.5,0.1,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + - type: MeleeSound + soundGroups: + Brute: + path: /Audio/Effects/chop.ogg + params: + variation: 0.05 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 1 + max: 3 + +- type: entity + id: WoodenSupportBeam + name: wooden support beam + parent: WoodenSupport + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support_beams + - type: Fixtures + fixtures: + fix1: + hard: false + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + +- type: entity + id: WoodenSupportWall + parent: BaseStructure + name: wooden support wall + description: An old, rotten wall. + placement: + mode: SnapgridCenter + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support_wall + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 250 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 2 + max: 5 + +- type: entity + id: WoodenSupportWallBroken + parent: WoodenSupportWall + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support_wall_broken + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 1 + max: 3 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index f44f1aa9984..89c44ed1920 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -660,7 +660,7 @@ - type: entity parent: CentcomPDA id: DeathsquadPDA - suffix: Deathsquad + suffix: Death Squad components: - type: Pda id: CentcomIDCardDeathsquad diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 6b80e7be697..d2edf7b4df5 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -82,6 +82,7 @@ - state: pai-base - state: syndicate-pai-off-overlay shader: unshaded + map: ["screen"] - type: ToggleableGhostRole roleName: pai-system-role-name-syndicate roleDescription: pai-system-role-description-syndicate @@ -100,6 +101,34 @@ Searching: { state: syndicate-pai-searching-overlay } On: { state: syndicate-pai-on-overlay } +- type: entity + parent: PersonalAI + id: PotatoAI + name: potato artificial intelligence + description: It's a potato. You forced it to be sentient, you monster. + components: + - type: Sprite + sprite: Objects/Fun/pai.rsi + layers: + - state: potato-base + - state: potato-off-overlay + shader: unshaded + map: ["screen"] + - type: ToggleableGhostRole + roleName: pai-system-role-name-potato + roleDescription: pai-system-role-description-potato + - type: Appearance + - type: GenericVisualizer + visuals: + enum.ToggleableGhostRoleVisuals.Status: + screen: + Off: { state: potato-off-overlay } + Searching: { state: potato-searching-overlay } + On: { state: potato-on-overlay } + - type: Construction + graph: PotatoAI + node: potatoai + - type: entity id: ActionPAIPlayMidi name: Play MIDI diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 24462d51136..d1441c341bc 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -447,6 +447,7 @@ heldPrefix: blue - type: IdCard jobTitle: Central Commander + jobIcon: JobIconNanotrasen - type: Access groups: - AllAccess @@ -496,7 +497,7 @@ - type: entity parent: CentcomIDCard id: CentcomIDCardDeathsquad - name: deathsquad ID card + name: death squad ID card components: - type: Sprite layers: diff --git a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml index 41966ab93f8..0ca029a1209 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml @@ -12,6 +12,12 @@ containers: implanter_slot: !type:ContainerSlot { } - type: Implanter + whitelist: + components: + - Body # no chair microbomb + blacklist: + components: + - Guardian # no holoparasite macrobomb wombo combo currentMode: Draw implanterSlot: name: Implant @@ -54,6 +60,16 @@ tags: - Trash +- type: entity + parent: Implanter + id: ImplanterAdmeme + suffix: Admeme + components: + - type: Implanter + # go wild with sentient chairs with macrobombs + whitelist: null + blacklist: null + - type: entity id: BaseImplantOnlyImplanter parent: Implanter diff --git a/Resources/Prototypes/Entities/Objects/Misc/potatoai_chip.yml b/Resources/Prototypes/Entities/Objects/Misc/potatoai_chip.yml new file mode 100644 index 00000000000..528aa30a148 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Misc/potatoai_chip.yml @@ -0,0 +1,17 @@ +- type: entity + id: PotatoAIChip + name: supercompact AI chip + parent: BaseItem + description: This high-tech AI chip requires a voltage of exactly 1.1V to function correctly. + components: + - type: Sprite + sprite: Objects/Misc/potatoai_chip.rsi + state: icon + - type: Item + size: 3 + - type: Tag + tags: + - SmallAIChip + - type: Construction + graph: PotatoAIChip + node: potatoaichip \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml index 6632010a79b..bc7a3a38ad3 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml @@ -21,6 +21,9 @@ noSpawn: true components: - type: SubdermalImplant + whitelist: + components: + - MobState # admeme implanting a chair with trombone implant needs to give the chair mobstate so it can die first - type: TriggerOnMobstateChange mobState: - Dead @@ -81,6 +84,9 @@ noSpawn: true components: - type: SubdermalImplant + whitelist: + components: + - MobState # admeme implanting a chair with tracking implant needs to give the chair mobstate so it can die first - type: SuitSensor randomMode: false controlsLocked: true @@ -109,6 +115,9 @@ components: - type: SubdermalImplant implantAction: ActionOpenStorageImplant + whitelist: + components: + - Hands # no use giving a mouse a storage implant, but a monkey is another story... - type: Item size: 9999 - type: Storage @@ -131,6 +140,9 @@ components: - type: SubdermalImplant implantAction: ActionActivateFreedomImplant + whitelist: + components: + - Cuffable # useless if you cant be cuffed - type: entity parent: BaseSubdermalImplant @@ -141,6 +153,9 @@ components: - type: SubdermalImplant implantAction: ActionOpenUplinkImplant + whitelist: + components: + - Hands # prevent mouse buying grenade penguin since its not telepathic - type: Store preset: StorePresetUplink balance: @@ -174,6 +189,9 @@ components: - type: SubdermalImplant implantAction: ActionActivateDnaScramblerImplant + whitelist: + components: + - HumanoidAppearance # syndies cant turn hamlet into a human #Nuclear Operative/Special Exclusive implants @@ -250,6 +268,9 @@ components: - type: SubdermalImplant permanent: true + whitelist: + components: + - MobState # admeme implanting a chair with rattle implant needs to give the chair mobstate so it can die first - type: TriggerOnMobstateChange mobState: - Critical diff --git a/Resources/Prototypes/Entities/Objects/Power/powercells.yml b/Resources/Prototypes/Entities/Objects/Power/powercells.yml index 82c1bb37e96..4ed3e207c5b 100644 --- a/Resources/Prototypes/Entities/Objects/Power/powercells.yml +++ b/Resources/Prototypes/Entities/Objects/Power/powercells.yml @@ -42,8 +42,15 @@ layers: - state: potato - type: Battery - maxCharge: 200 - startingCharge: 200 + maxCharge: 70 + startingCharge: 70 + - type: Tag + tags: + - DroneUsable + - PotatoBattery + - type: Construction + graph: PowerCellPotato + node: potatobattery - type: entity name: small-capacity power cell diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml index 6382d69e58d..b4e69b37805 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml @@ -116,4 +116,4 @@ base: Off: { state: posibrain } Searching: { state: posibrain-searching } - On: { state: posibrain-occupied } + On: { state: posibrain-occupied } \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index 461a6cc4373..38875ee9a75 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -131,7 +131,7 @@ name: pulse pistol parent: BaseWeaponBatterySmall id: WeaponPulsePistol - description: A state of the art energy pistol favoured as a sidearm by the NT-ERT operatives. + description: A state of the art energy pistol favoured as a sidearm by the NT operatives. components: - type: Sprite sprite: Objects/Weapons/Guns/Battery/pulse_pistol.rsi @@ -464,7 +464,7 @@ path: /Audio/Weapons/Guns/Gunshots/taser2.ogg - type: ProjectileBatteryAmmoProvider proto: AnomalousParticleDeltaStrong - fireCost: 100 + fireCost: 100 - type: BatteryWeaponFireModes fireModes: - proto: AnomalousParticleDeltaStrong @@ -476,13 +476,13 @@ - type: Construction graph: UpgradeWeaponPistolCHIMP node: start - + - type: entity name: experimental C.H.I.M.P. handcannon parent: WeaponPistolCHIMP id: WeaponPistolCHIMPUpgraded description: This C.H.I.M.P. seems to have a greater punch than is usual... - components: + components: - type: BatteryWeaponFireModes fireModes: - proto: AnomalousParticleDeltaStrong @@ -490,7 +490,7 @@ - proto: AnomalousParticleEpsilonStrong fireCost: 100 - proto: AnomalousParticleOmegaStrong - fireCost: 100 + fireCost: 100 - proto: AnomalousParticleZetaStrong fireCost: 100 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml index 7dd6360a405..32a2ea4623f 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml @@ -35,6 +35,7 @@ - type: Tag tags: - Arrow + - CannonRestrict - type: Projectile deleteOnCollide: false onlyCollideWhenShot: true diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml index f9413d6c673..9f3aec5c39b 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml @@ -35,7 +35,7 @@ capacity: 30 blacklist: tags: - - Arrow + - CannonRestrict - type: Appearance - type: ItemMapper containerWhitelist: [gas_tank] diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 0dd5d7c47c2..47dfea9d867 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -174,8 +174,8 @@ - type: EnergySword litDamageBonus: types: - Slash: 9 - Heat: 9 + Slash: 17 + Heat: 17 Structural: 20 Blunt: -4.5 litDisarmMalus: 0.7 diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml index 272ed6712c5..ae84ceac65b 100644 --- a/Resources/Prototypes/Entities/Stations/base.yml +++ b/Resources/Prototypes/Entities/Stations/base.yml @@ -71,10 +71,7 @@ abstract: true components: - type: SiliconLawProvider - laws: - - Crewsimov1 - - Crewsimov2 - - Crewsimov3 + laws: Crewsimov - type: entity id: BaseStationAllEventsEligible diff --git a/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml b/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml index b8f2a03a05b..4afe06c8a52 100644 --- a/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml +++ b/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml @@ -7,6 +7,7 @@ - type: Sprite sprite: Structures/Decoration/crystal.rsi state: crystal_green + noRot: true - type: Reflect reflectProb: 0.5 reflects: diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index e2d9818a5d2..689430429a0 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -506,6 +506,7 @@ layers: - state: icon map: ["enum.LatheVisualLayers.IsRunning"] + - state: sec - state: unlit shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml index 261b9a344c4..c49497b7740 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml @@ -96,19 +96,26 @@ parent: PortableGeneratorBase id: PortableGeneratorSwitchableBase components: - - type: PowerSwitchableGenerator - switchSound: - path: /Audio/Machines/button.ogg - - type: NodeContainer - examinable: true - nodes: - output_hv: - !type:CableDeviceNode - nodeGroupID: HVPower - output_mv: - !type:CableDeviceNode - nodeGroupID: MVPower - enabled: false + - type: PowerSwitchable + examineText: power-switchable-generator-examine + switchText: power-switchable-generator-switched + cables: + - voltage: HV + node: output_hv + - voltage: MV + node: output_mv + - type: UseDelay + delay: 1 + - type: NodeContainer + examinable: true + nodes: + output_hv: + !type:CableDeviceNode + nodeGroupID: HVPower + output_mv: + !type:CableDeviceNode + nodeGroupID: MVPower + enabled: false - type: entity name: P.A.C.M.A.N.-type portable generator diff --git a/Resources/Prototypes/Entities/Structures/Power/chargers.yml b/Resources/Prototypes/Entities/Structures/Power/chargers.yml index e5edc63df3c..7630610bd89 100644 --- a/Resources/Prototypes/Entities/Structures/Power/chargers.yml +++ b/Resources/Prototypes/Entities/Structures/Power/chargers.yml @@ -85,6 +85,9 @@ whitelist: components: - PowerCell + blacklist: + tags: + - PotatoBattery - type: entity parent: BaseItemRecharger diff --git a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml index e64af7cbaec..ac12dc2717f 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml @@ -18,7 +18,6 @@ - type: SmoothEdge - type: Sprite sprite: Structures/Walls/rock.rsi - noRot: true layers: - state: rock_asteroid - map: [ "enum.EdgeLayer.South" ] @@ -77,7 +76,6 @@ components: - type: Sprite sprite: Structures/Walls/rock.rsi - noRot: true layers: - state: rock_asteroid_ore - map: [ "enum.EdgeLayer.South" ] @@ -98,7 +96,6 @@ components: - type: Sprite sprite: Structures/Walls/rock.rsi - noRot: true layers: - state: rock_asteroid_ore1 - map: [ "enum.EdgeLayer.South" ] @@ -152,6 +149,8 @@ parent: BaseStructure name: rock components: + - type: PlacementReplacement + key: walls - type: SoundOnGather - type: Gatherable whitelist: @@ -380,6 +379,7 @@ # Basalt variants - type: entity id: WallRockBasalt + name: basalt parent: WallRock components: - type: Sprite @@ -575,6 +575,7 @@ # Snow variants - type: entity id: WallRockSnow + name: snowdrift parent: WallRock components: - type: Sprite @@ -771,6 +772,7 @@ # Sand variants - type: entity id: WallRockSand + name: sandstone parent: WallRock components: - type: Sprite @@ -966,6 +968,7 @@ # Chromite variants - type: entity id: WallRockChromite + name: chromite parent: WallRock components: - type: Sprite @@ -1001,7 +1004,7 @@ state: rock_chromite_north - map: [ "enum.EdgeLayer.West" ] state: rock_chromite_west - - state: rock_chromite + - state: rock_gold - type: entity id: WallRockChromitePlasma @@ -1161,6 +1164,7 @@ # Andesite variants - type: entity id: WallRockAndesite + name: andesite parent: WallRock components: - type: Sprite @@ -1196,7 +1200,7 @@ state: rock_andesite_north - map: [ "enum.EdgeLayer.West" ] state: rock_andesite_west - - state: rock_andesite + - state: rock_gold - type: entity id: WallRockAndesitePlasma diff --git a/Resources/Prototypes/Entities/Tiles/chasm.yml b/Resources/Prototypes/Entities/Tiles/chasm.yml index 23475325876..23f3ad83950 100644 --- a/Resources/Prototypes/Entities/Tiles/chasm.yml +++ b/Resources/Prototypes/Entities/Tiles/chasm.yml @@ -18,12 +18,12 @@ anchored: true - type: Clickable - type: Sprite - sprite: Tiles/Planet/chasm.rsi + sprite: Tiles/Planet/Chasms/basalt_chasm.rsi drawdepth: BelowFloor layers: - state: chasm - type: Icon - sprite: Tiles/Planet/chasm.rsi + sprite: Tiles/Planet/Chasms/basalt_chasm.rsi state: full - type: IconSmooth key: chasm @@ -45,3 +45,33 @@ - type: Tag tags: - HideContextMenu + +- type: entity + parent: FloorChasmEntity + id: FloorChromiteChasm + suffix: Chromite + components: + - type: Sprite + sprite: Tiles/Planet/Chasms/chromite_chasm.rsi + - type: Icon + sprite: Tiles/Planet/Chasms/chromite_chasm.rsi + +- type: entity + parent: FloorChasmEntity + id: FloorDesertChasm + suffix: Desert + components: + - type: Sprite + sprite: Tiles/Planet/Chasms/desert_chasm.rsi + - type: Icon + sprite: Tiles/Planet/Chasms/desert_chasm.rsi + +- type: entity + parent: FloorChasmEntity + id: FloorSnowChasm + suffix: Snow + components: + - type: Sprite + sprite: Tiles/Planet/Chasms/snow_chasm.rsi + - type: Icon + sprite: Tiles/Planet/Chasms/snow_chasm.rsi \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Tiles/shadow_basalt.yml b/Resources/Prototypes/Entities/Tiles/shadow_basalt.yml new file mode 100644 index 00000000000..e5835239cfe --- /dev/null +++ b/Resources/Prototypes/Entities/Tiles/shadow_basalt.yml @@ -0,0 +1,83 @@ +- type: entity + id: ShadowBasaltOne + name: shadowstone + description: Cold rock + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: Sprite + sprite: /Textures/Tiles/Planet/shadowbasalt.rsi + layers: + - state: basalt1 + shader: unshaded + drawdepth: LowFloors + - type: SyncSprite + - type: RequiresTile + - type: Transform + anchored: true + - type: Tag + tags: + - HideContextMenu + +- type: entity + id: ShadowBasaltTwo + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt2 + shader: unshaded + +- type: entity + id: ShadowBasaltThree + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt3 + shader: unshaded + +- type: entity + id: ShadowBasaltFour + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt4 + shader: unshaded + +- type: entity + id: ShadowBasaltFive + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt5 + shader: unshaded + +- type: entity + id: ShadowBasaltRandom + parent: ShadowBasaltOne + suffix: Random + components: + - type: RandomSprite + available: + - 0: + basalt1: "" + - 0: + basalt2: "" + - 0: + basalt3: "" + - 0: + basalt4: "" + - 0: + basalt5: "" \ No newline at end of file diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 72da614debd..e00c9ab1a3a 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -413,3 +413,18 @@ earliestStart: 45 minimumPlayers: 20 - type: ImmovableRodRule + +- type: entity + noSpawn: true + parent: BaseGameRule + id: IonStorm + components: + - type: StationEvent + weight: 5 + earliestStart: 20 + reoccurrenceDelay: 60 + startAnnouncement: station-event-ion-storm-start-announcement + startAudio: + path: /Audio/Announcements/ion_storm.ogg + duration: 1 + - type: IonStormRule diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index 71aacf951cb..7d6c9a48a34 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -33,7 +33,7 @@ weights: EscapeShuttleObjective: 1 DieObjective: 0.05 - HijackShuttleObjective: 0.02 # Corvax-Hijack + HijackShuttleObjective: 0.02 - type: weightedRandom id: TraitorObjectiveGroupSocial diff --git a/Resources/Prototypes/Objectives/traitor.yml b/Resources/Prototypes/Objectives/traitor.yml index f0e8daad3d1..dd188765b99 100644 --- a/Resources/Prototypes/Objectives/traitor.yml +++ b/Resources/Prototypes/Objectives/traitor.yml @@ -64,6 +64,20 @@ - StealCondition - type: DieCondition +- type: entity + noSpawn: true + parent: [BaseTraitorObjective, BaseLivingObjective] + id: HijackShuttleObjective + name: Hijack emergency shuttle + description: Leave on the shuttle free and clear of the loyal Nanotrasen crew on board. Use ANY methods available to you. Syndicate agents, Nanotrasen enemies, and handcuffed hostages may remain alive on the shuttle. Ignore assistance from anyone other than a support agent. + components: + - type: Objective + difficulty: 5 # insane, default config max difficulty + icon: + sprite: Objects/Tools/emag.rsi + state: icon + - type: HijackShuttleCondition + # kill - type: entity diff --git a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml index d83d58bc925..4ec41181778 100644 --- a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml +++ b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml @@ -24,7 +24,7 @@ time: 10 solids: FoodBreadBun: 1 - FoodMeatCutlet: 3 #replace with bacon + FoodMeatBacon: 1 FoodCheeseSlice: 2 - type: microwaveMealRecipe @@ -186,7 +186,7 @@ time: 10 solids: FoodBreadBun: 1 - ClothingOuterGhostSheet: 1 #replace with ectoplasm once added + Ectoplasm: 1 - type: microwaveMealRecipe id: RecipeHumanBurger @@ -218,7 +218,7 @@ - type: microwaveMealRecipe id: RecipeBurgerMcrib - name: McRib recipe + name: BBQ rib sandwich recipe result: FoodBurgerMcrib time: 10 solids: diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml new file mode 100644 index 00000000000..e3f972cfda4 --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml @@ -0,0 +1,74 @@ +- type: constructionGraph + id: PowerCellPotato + start: start + graph: + - node: start + edges: + - to: potatobattery + steps: + - tag: Potato + name: a potato + icon: + sprite: Objects/Specific/Hydroponics/potato.rsi + state: produce + doAfter: 1 + - material: MetalRod + amount: 2 + doAfter: 1 + - material: Cable + amount: 1 + doAfter: 1 + - node: potatobattery + entity: PowerCellPotato + +- type: constructionGraph + id: PotatoAI + start: start + graph: + - node: start + edges: + - to: potatoai + steps: + - tag: PotatoBattery + name: a potato battery + icon: + sprite: Objects/Power/power_cells.rsi + state: potato + doAfter: 1 + - tag: SmallAIChip + name: a super-compact AI chip + icon: + sprite: Objects/Misc/potatoai_chip.rsi + state: icon + - node: potatoai + entity: PotatoAI + +- type: constructionGraph + id: PotatoAIChip + start: start + graph: + - node: start + edges: + - to: potatoaichip + steps: + - material: Steel + amount: 1 + doAfter: 1 + - material: Glass + amount: 1 + doAfter: 1 + - material: Cable + amount: 2 + doAfter: 1 + - tag: CapacitorStockPart + name: capacitor + icon: + sprite: Objects/Misc/stock_parts.rsi + state: capacitor + - tag: CapacitorStockPart + name: capacitor + icon: + sprite: Objects/Misc/stock_parts.rsi + state: capacitor + - node: potatoaichip + entity: PotatoAIChip \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Crafting/potato.yml b/Resources/Prototypes/Recipes/Crafting/potato.yml new file mode 100644 index 00000000000..17f2cc40136 --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/potato.yml @@ -0,0 +1,32 @@ +- type: construction + name: potato battery + id: PowerCellPotato + graph: PowerCellPotato + startNode: start + targetNode: potatobattery + category: construction-category-misc + description: A truly ingenious source of power. + icon: { sprite: Objects/Power/power_cells.rsi, state: potato } + objectType: Item + +- type: construction + name: potato artificial intelligence + id: PotatoAI + graph: PotatoAI + startNode: start + targetNode: potatoai + category: construction-category-misc + description: The potato happens to be the perfect power source for this chip. + icon: { sprite: Objects/Fun/pai.rsi, state: icon-potato-off } + objectType: Item + +- type: construction + name: supercompact AI chip + id: PotatoAIChip + graph: PotatoAIChip + startNode: start + targetNode: potatoaichip + category: construction-category-misc + description: A masterfully(?) crafted AI chip, requiring a similarly improvised power source. + icon: { sprite: Objects/Misc/potatoai_chip.rsi, state: icon } + objectType: Item \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Reactions/food.yml b/Resources/Prototypes/Recipes/Reactions/food.yml index 3ca69b379d3..c7f4038db09 100644 --- a/Resources/Prototypes/Recipes/Reactions/food.yml +++ b/Resources/Prototypes/Recipes/Reactions/food.yml @@ -148,6 +148,7 @@ amount: 30 Enzyme: amount: 5 + catalyst: true effects: - !type:CreateEntityReactionEffect entity: FoodTofu @@ -158,11 +159,11 @@ id: CookingKetchup reactants: JuiceTomato: - amount: 10 + amount: 2 Sugar: - amount: 5 + amount: 1 products: - Ketchup: 15 + Ketchup: 3 - type: reaction id: CookingMayoVinegar @@ -203,67 +204,67 @@ id: CookingKetchunaise reactants: Ketchup: - amount: 5 + amount: 1 Mayo: - amount: 5 + amount: 1 products: - Ketchunaise: 10 + Ketchunaise: 2 - type: reaction id: CookingBbqSauce reactants: Ketchup: - amount: 5 + amount: 1 Vinegar: - amount: 5 + amount: 1 Sugar: - amount: 5 + amount: 1 products: - BbqSauce: 15 + BbqSauce: 3 - type: reaction id: CookingHotsauce reactants: JuiceTomato: - amount: 5 + amount: 1 TableSalt: - amount: 5 + amount: 1 CapsaicinOil: - amount: 5 + amount: 1 products: - Hotsauce: 15 + Hotsauce: 3 - type: reaction id: CookingVinegar reactants: Ethanol: - amount: 5 + amount: 1 Oxygen: - amount: 5 + amount: 1 products: - Vinegar: 10 + Vinegar: 2 - type: reaction id: CookingSoysauce reactants: MilkSoy: - amount: 10 + amount: 2 SulfuricAcid: - amount: 5 + amount: 1 products: - Soysauce: 15 + Soysauce: 3 - type: reaction id: CookingVinaigrette reactants: Vinegar: - amount: 5 + amount: 1 OilOlive: - amount: 5 + amount: 1 Blackpepper: - amount: 5 + amount: 1 products: - Vinaigrette: 15 + Vinaigrette: 3 - type: reaction id: CreateMeatball diff --git a/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml b/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml index d71b3423d28..2be50b2e4b4 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml @@ -21,11 +21,12 @@ head: ClothingHeadHelmetERTLeader eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal + pocket2: FlashlightSeclite - type: startingGear id: ERTLeaderGearEVA @@ -37,11 +38,31 @@ eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitERTLeader - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal + pocket2: FlashlightSeclite + +- type: startingGear + id: ERTLeaderGearEVALecter + equipment: + jumpsuit: ClothingUniformJumpsuitERTLeader + back: ClothingBackpackERTLeaderFilled + shoes: ClothingShoesBootsMagAdv + mask: ClothingMaskGasERT + eyes: ClothingEyesGlassesSecurity + gloves: ClothingHandsGlovesCombat + outerClothing: ClothingOuterHardsuitERTLeader + suitstorage: WeaponRifleLecter + id: ERTLeaderPDA + ears: ClothingHeadsetAltCentCom + belt: ClothingBeltSecurityFilled + pocket1: MagazineRifle + pocket2: MagazineRifle + inhand: + - AirTankFilled # Engineer - type: job @@ -66,11 +87,12 @@ head: ClothingHeadHelmetERTEngineer eyes: ClothingEyesGlassesMeson gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltChiefEngineerFilled pocket1: Flare + pocket2: GasAnalyzer - type: startingGear id: ERTEngineerGearEVA @@ -82,11 +104,12 @@ eyes: ClothingEyesGlassesMeson gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitERTEngineer - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltChiefEngineerFilled pocket1: Flare + pocket2: GasAnalyzer # Security - type: job @@ -111,11 +134,11 @@ head: ClothingHeadHelmetERTSecurity eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal pocket2: FlashlightSeclite - type: startingGear @@ -128,13 +151,32 @@ eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitERTSecurity - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal pocket2: FlashlightSeclite +- type: startingGear + id: ERTSecurityGearEVALecter + equipment: + jumpsuit: ClothingUniformJumpsuitERTSecurity + back: ClothingBackpackERTSecurityFilled + shoes: ClothingShoesBootsMag + mask: ClothingMaskGasERT + eyes: ClothingEyesGlassesSecurity + gloves: ClothingHandsGlovesCombat + outerClothing: ClothingOuterHardsuitERTSecurity + suitstorage: WeaponRifleLecter + id: ERTLeaderPDA + ears: ClothingHeadsetAltCentCom + belt: ClothingBeltSecurityFilled + pocket1: MagazineRifle + pocket2: MagazineRifle + inhand: + - AirTankFilled + # Medical - type: job id: ERTMedical @@ -157,8 +199,8 @@ shoes: ClothingShoesBootsCombatFilled head: ClothingHeadHelmetERTMedic eyes: ClothingEyesHudMedical - gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + gloves: ClothingHandsGlovesNitrile + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltMedicalFilled @@ -173,9 +215,9 @@ shoes: ClothingShoesBootsMag mask: ClothingMaskGasERT eyes: ClothingEyesHudMedical - gloves: ClothingHandsGlovesCombat + gloves: ClothingHandsGlovesNitrile outerClothing: ClothingOuterHardsuitERTMedical - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltMedicalFilled @@ -203,8 +245,8 @@ back: ClothingBackpackERTJanitorFilled shoes: ClothingShoesGaloshes head: ClothingHeadHelmetERTJanitor - gloves: ClothingHandsGlovesColorBlack - outerClothing: ClothingOuterArmorBulletproof + gloves: ClothingHandsGlovesColorPurple + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltJanitorFilled @@ -216,10 +258,10 @@ jumpsuit: ClothingUniformJumpsuitERTJanitor back: ClothingBackpackERTJanitorFilled shoes: ClothingShoesBootsMag - mask: ClothingMaskBreath - gloves: ClothingHandsGlovesColorBlack + mask: ClothingMaskGasERT + gloves: ClothingHandsGlovesColorPurple outerClothing: ClothingOuterHardsuitERTJanitor - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltJanitorFilled diff --git a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml index 4a8ede58fe4..ad99ef7def4 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml @@ -46,20 +46,19 @@ id: DeathSquadGear equipment: jumpsuit: ClothingUniformJumpsuitDeathSquad - back: ClothingBackpackDuffelSyndicateAmmo + back: ClothingBackpackDeathSquadFilled mask: ClothingMaskGasDeathSquad eyes: ClothingEyesGlassesSecurity ears: ClothingHeadsetAltCentCom gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitDeathsquad - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled shoes: ClothingShoesBootsMagAdv id: DeathsquadPDA pocket1: EnergySword - belt: ClothingBeltChiefEngineerFilled + pocket2: EnergyShield + belt: ClothingBeltMilitaryWebbingMedFilled innerClothingSkirt: ClothingUniformJumpskirtColorBlack - satchel: ClothingBackpackDuffelSyndicateAmmo - duffelbag: ClothingBackpackDuffelSyndicateAmmo # Syndicate Operative Outfit - Monkey - type: startingGear @@ -104,7 +103,7 @@ jumpsuit: ClothingUniformJumpsuitOperative back: ClothingBackpackDuffelSyndicateOperative mask: ClothingMaskGasSyndicate - # eyes: Night Vision Goggles whenever they're made + # eyes: Night Vision Goggles whenever they're made eyes: ClothingEyesGlassesMeson ears: ClothingHeadsetAltSyndicate gloves: ClothingHandsGlovesCombat @@ -125,7 +124,7 @@ jumpsuit: ClothingUniformJumpsuitOperative back: ClothingBackpackDuffelSyndicateOperative mask: ClothingMaskGasSyndicate - # eyes: Night Vision Goggles whenever they're made + # eyes: Night Vision Goggles whenever they're made eyes: ClothingEyesGlassesMeson ears: ClothingHeadsetAltSyndicate gloves: ClothingHandsGlovesCombat @@ -255,8 +254,8 @@ id: CBURNGear equipment: jumpsuit: ClothingUniformJumpsuitColorBrown - back: ClothingBackpackDuffelCBURN - mask: ClothingMaskGasExplorer + back: ClothingBackpackDuffelCBURNFilled + mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity ears: ClothingHeadsetAltCentCom gloves: ClothingHandsGlovesCombat @@ -268,8 +267,8 @@ suitstorage: YellowOxygenTankFilled belt: ClothingBeltBandolier innerClothingSkirt: ClothingUniformJumpsuitColorBrown - satchel: ClothingBackpackDuffelCBURN - duffelbag: ClothingBackpackDuffelCBURN + satchel: ClothingBackpackDuffelCBURNFilled + duffelbag: ClothingBackpackDuffelCBURNFilled - type: startingGear id: BoxingKangarooGear diff --git a/Resources/Prototypes/Tiles/floors.yml b/Resources/Prototypes/Tiles/floors.yml index 908cd466a3f..43dbd76b104 100644 --- a/Resources/Prototypes/Tiles/floors.yml +++ b/Resources/Prototypes/Tiles/floors.yml @@ -1622,6 +1622,26 @@ itemDrop: FloorTileItemWeb heatCapacity: 10000 +- type: tile + id: FloorChromite + name: tiles-chromite + sprite: /Textures/Tiles/chromite.png + variants: 7 + placementVariants: + - 1.0 + - 1.0 + - 1.0 + - 1.0 + - 1.0 + - 1.0 + - 1.0 + baseTurf: Space + isSubfloor: true + canCrowbar: false + footstepSounds: + collection: FootstepAsteroid + heatCapacity: 10000 + #Hull tiles - type: tile id: FloorHull diff --git a/Resources/Prototypes/Traits/inconveniences.yml b/Resources/Prototypes/Traits/inconveniences.yml index f8e932c9b92..657781d1b59 100644 --- a/Resources/Prototypes/Traits/inconveniences.yml +++ b/Resources/Prototypes/Traits/inconveniences.yml @@ -12,7 +12,7 @@ description: trait-socialanxiety-desc components: - type: StutteringAccent - matchRandomProb: 0.2 + matchRandomProb: 0.1 fourRandomProb: 0 - threeRandomProb: 0.3 + threeRandomProb: 0 cutRandomProb: 0 diff --git a/Resources/Prototypes/XenoArch/artifact_triggers.yml b/Resources/Prototypes/XenoArch/artifact_triggers.yml index 3308eed1850..6e128cef1ce 100644 --- a/Resources/Prototypes/XenoArch/artifact_triggers.yml +++ b/Resources/Prototypes/XenoArch/artifact_triggers.yml @@ -14,6 +14,7 @@ - type: artifactTrigger id: TriggerExamine targetDepth: 0 + triggerHint: artifact-trigger-hint-examine components: - type: ArtifactExamineTrigger diff --git a/Resources/Prototypes/silicon-laws.yml b/Resources/Prototypes/silicon-laws.yml index 6b60b16da9e..23406be9c5e 100644 --- a/Resources/Prototypes/silicon-laws.yml +++ b/Resources/Prototypes/silicon-laws.yml @@ -14,6 +14,13 @@ order: 3 lawString: law-crewsimov-3 +- type: siliconLawset + id: Crewsimov + laws: + - Crewsimov1 + - Crewsimov2 + - Crewsimov3 + # Corporate - type: siliconLaw id: Corporate1 @@ -35,6 +42,14 @@ order: 4 lawString: law-corporate-4 +- type: siliconLawset + id: Corporate + laws: + - Corporate1 + - Corporate2 + - Corporate3 + - Corporate4 + # NT Default - type: siliconLaw id: NTDefault1 @@ -56,6 +71,14 @@ order: 4 lawString: law-ntdefault-4 +- type: siliconLawset + id: NTDefault + laws: + - NTDefault1 + - NTDefault2 + - NTDefault3 + - NTDefault4 + #Drone - type: siliconLaw id: Drone1 @@ -72,6 +95,13 @@ order: 3 lawString: law-drone-3 +- type: siliconLawset + id: Drone + laws: + - Drone1 + - Drone2 + - Drone3 + # Syndicate - type: siliconLaw id: Syndicate1 @@ -93,4 +123,24 @@ order: 4 lawString: law-syndicate-4 +# does not include law 0 since that uses the emagger's name +# intentionally excluded from IonStormLawsets +- type: siliconLawset + id: SyndicateStatic + laws: + - Syndicate1 + - Syndicate2 + - Syndicate3 + - Syndicate4 + # Emag + +# ion storm random lawsets +- type: weightedRandom + id: IonStormLawsets + weights: + # its crewsimov by default dont be lame + Crewsimov: 0.25 + Corporate: 1 + NTDefault: 1 + Drone: 0.5 diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index d7397d483c0..67a27be4160 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -3,7 +3,7 @@ - type: Tag id: AirAlarmElectronics - + - type: Tag id: Airlock @@ -234,6 +234,9 @@ - type: Tag id: CanPilot + +- type: Tag + id: CannonRestrict - type: Tag id: CannotSuicide @@ -493,7 +496,7 @@ - type: Tag id: GeigerCounter - + - type: Tag id: GlassAirlock @@ -562,7 +565,7 @@ - type: Tag id: HighRiskItem - + - type: Tag id: HighSecDoor @@ -836,6 +839,12 @@ - type: Tag id: PlushieSharkGrey +- type: Tag + id: Potato + +- type: Tag + id: PotatoBattery + - type: Tag id: PowerCellSmall @@ -921,6 +930,9 @@ - type: Tag id: SkeletonMotorcycleKeys +- type: Tag + id: SmallAIChip + - type: Tag id: SmallMech diff --git a/Resources/Textures/Corvax/LobbyScreens/attributions.yml b/Resources/Textures/Corvax/LobbyScreens/attributions.yml index bb89ef5cad7..33d65115d4b 100644 --- a/Resources/Textures/Corvax/LobbyScreens/attributions.yml +++ b/Resources/Textures/Corvax/LobbyScreens/attributions.yml @@ -107,3 +107,28 @@ license: "CC-BY-NC-SA-3.0" copyright: "~DreamlyJack~#2438 on discord" source: "https://discord.gg/vtRtT4PD" + +- files: ["deathnettle.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "werkas(684260199015514125) on discord" + source: "https://discord.com/channels/919301044784226385/993679919550844938/1166054283981111296" + +- files: ["fleshanom.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "alisw_a(827540795249655808) on discord" + source: "https://discord.com/channels/919301044784226385/993679919550844938/1163583606095093802" + +- files: ["clownspider.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "ko4erga(266899933632659456) on discord" + source: "https://discord.com/channels/919301044784226385/993679919550844938/1162586531601584251" + +- files: ["revenant.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "mrzipka(631581871179956264) on discord" + source: "https://discord.com/channels/919301044784226385/993679919550844938/1166578120694968361" + +- files: ["xeno.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "_sangoro_(892329132829065276) on discord" + source: "https://discord.com/channels/919301044784226385/1073603532898435183/1162826046312284160" diff --git a/Resources/Textures/Corvax/LobbyScreens/clownspider.png b/Resources/Textures/Corvax/LobbyScreens/clownspider.png new file mode 100644 index 00000000000..670ef15aad3 Binary files /dev/null and b/Resources/Textures/Corvax/LobbyScreens/clownspider.png differ diff --git a/Resources/Textures/Corvax/LobbyScreens/clownspider.png.yml b/Resources/Textures/Corvax/LobbyScreens/clownspider.png.yml new file mode 100644 index 00000000000..51ff40335ef --- /dev/null +++ b/Resources/Textures/Corvax/LobbyScreens/clownspider.png.yml @@ -0,0 +1,2 @@ +sample: + filter: false diff --git a/Resources/Textures/Corvax/LobbyScreens/deathnettle.png b/Resources/Textures/Corvax/LobbyScreens/deathnettle.png new file mode 100644 index 00000000000..894c0d31ff3 Binary files /dev/null and b/Resources/Textures/Corvax/LobbyScreens/deathnettle.png differ diff --git a/Resources/Textures/Corvax/LobbyScreens/deathnettle.png.yml b/Resources/Textures/Corvax/LobbyScreens/deathnettle.png.yml new file mode 100644 index 00000000000..51ff40335ef --- /dev/null +++ b/Resources/Textures/Corvax/LobbyScreens/deathnettle.png.yml @@ -0,0 +1,2 @@ +sample: + filter: false diff --git a/Resources/Textures/Corvax/LobbyScreens/fleshanom.png b/Resources/Textures/Corvax/LobbyScreens/fleshanom.png new file mode 100644 index 00000000000..588bb02b94c Binary files /dev/null and b/Resources/Textures/Corvax/LobbyScreens/fleshanom.png differ diff --git a/Resources/Textures/Corvax/LobbyScreens/fleshanom.png.yml b/Resources/Textures/Corvax/LobbyScreens/fleshanom.png.yml new file mode 100644 index 00000000000..51ff40335ef --- /dev/null +++ b/Resources/Textures/Corvax/LobbyScreens/fleshanom.png.yml @@ -0,0 +1,2 @@ +sample: + filter: false diff --git a/Resources/Textures/Corvax/LobbyScreens/revenant.png b/Resources/Textures/Corvax/LobbyScreens/revenant.png new file mode 100644 index 00000000000..18dd92cd6c8 Binary files /dev/null and b/Resources/Textures/Corvax/LobbyScreens/revenant.png differ diff --git a/Resources/Textures/Corvax/LobbyScreens/revenant.png.yml b/Resources/Textures/Corvax/LobbyScreens/revenant.png.yml new file mode 100644 index 00000000000..51ff40335ef --- /dev/null +++ b/Resources/Textures/Corvax/LobbyScreens/revenant.png.yml @@ -0,0 +1,2 @@ +sample: + filter: false diff --git a/Resources/Textures/Corvax/LobbyScreens/xeno.png b/Resources/Textures/Corvax/LobbyScreens/xeno.png new file mode 100644 index 00000000000..67aa877b78f Binary files /dev/null and b/Resources/Textures/Corvax/LobbyScreens/xeno.png differ diff --git a/Resources/Textures/Corvax/LobbyScreens/xeno.png.yml b/Resources/Textures/Corvax/LobbyScreens/xeno.png.yml new file mode 100644 index 00000000000..51ff40335ef --- /dev/null +++ b/Resources/Textures/Corvax/LobbyScreens/xeno.png.yml @@ -0,0 +1,2 @@ +sample: + filter: false diff --git a/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png b/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png index 41df319be94..7169cda3bb7 100644 Binary files a/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png and b/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/meta.json b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/meta.json new file mode 100644 index 00000000000..8f86af70532 --- /dev/null +++ b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/e00cae8d065f9cf520688cc0dd0e15ba5bef12a9/icons/obj/flora/jungleflora.dmi and recolor by TheShuEd", + "size": { + "x": 96, + "y": 96 + }, + "states": [ + { + "name": "tree01" + }, + { + "name": "tree02" + }, + { + "name": "tree03" + }, + { + "name": "tree04" + }, + { + "name": "tree05" + }, + { + "name": "tree06" + } + ] +} diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree01.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree01.png new file mode 100644 index 00000000000..99ca699d420 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree01.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree02.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree02.png new file mode 100644 index 00000000000..4aa9a2913f6 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree02.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree03.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree03.png new file mode 100644 index 00000000000..5a833a3ac75 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree03.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree04.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree04.png new file mode 100644 index 00000000000..4d1cefe2fd1 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree04.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree05.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree05.png new file mode 100644 index 00000000000..8b2cd2a30b0 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree05.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree06.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree06.png new file mode 100644 index 00000000000..888fbfd25b1 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree06.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/meta.json b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/meta.json new file mode 100644 index 00000000000..33dc4fa0738 --- /dev/null +++ b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from TGMC at commit https://github.com/tgstation/TerraGov-Marine-Corps/commit/4bf5d1aafbcbbb7bd2a7d0f52ef87f28e2bbb384", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "stalagmite1" + }, + { + "name": "stalagmite2" + }, + { + "name": "stalagmite3" + }, + { + "name": "stalagmite4" + }, + { + "name": "stalagmite5" + }, + { + "name": "stalagmite6" + } + ] +} diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite1.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite1.png new file mode 100644 index 00000000000..ed9ddfd8abb Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite1.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite2.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite2.png new file mode 100644 index 00000000000..e8167762612 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite2.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite3.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite3.png new file mode 100644 index 00000000000..19394a66214 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite3.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite4.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite4.png new file mode 100644 index 00000000000..90e0e75a07f Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite4.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite5.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite5.png new file mode 100644 index 00000000000..a10cdb5d9b9 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite5.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite6.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite6.png new file mode 100644 index 00000000000..b424d6dfe0c Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite6.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/meta.json b/Resources/Textures/Objects/Decoration/mines.rsi/meta.json new file mode 100644 index 00000000000..39f167a0d6c --- /dev/null +++ b/Resources/Textures/Objects/Decoration/mines.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from TGMC at commit https://github.com/tgstation/TerraGov-Marine-Corps/commit/4bf5d1aafbcbbb7bd2a7d0f52ef87f28e2bbb384", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "sign_left" + }, + { + "name": "sign_right" + }, + { + "name": "support" + }, + { + "name": "support_beams" + }, + { + "name": "support_wall" + }, + { + "name": "support_wall_broken" + } + ] +} diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/sign_left.png b/Resources/Textures/Objects/Decoration/mines.rsi/sign_left.png new file mode 100644 index 00000000000..96f56927919 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/sign_left.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/sign_right.png b/Resources/Textures/Objects/Decoration/mines.rsi/sign_right.png new file mode 100644 index 00000000000..f89435fafc4 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/sign_right.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support.png b/Resources/Textures/Objects/Decoration/mines.rsi/support.png new file mode 100644 index 00000000000..29f7482b286 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support_beams.png b/Resources/Textures/Objects/Decoration/mines.rsi/support_beams.png new file mode 100644 index 00000000000..3111d15dcb4 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support_beams.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support_wall.png b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall.png new file mode 100644 index 00000000000..9b14590952a Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support_wall_broken.png b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall_broken.png new file mode 100644 index 00000000000..4032c6e45cf Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall_broken.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/airloss.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/airloss.png new file mode 100644 index 00000000000..82fa0e2c889 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/airloss.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/brute.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/brute.png new file mode 100644 index 00000000000..bd5d80da306 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/brute.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/burn.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/burn.png new file mode 100644 index 00000000000..cf65084e44e Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/burn.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/genetic.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/genetic.png new file mode 100644 index 00000000000..b660aed5375 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/genetic.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/meta.json b/Resources/Textures/Objects/Devices/health_analyzer.rsi/meta.json new file mode 100644 index 00000000000..3fccf5c46b8 --- /dev/null +++ b/Resources/Textures/Objects/Devices/health_analyzer.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "airloss, brute, toxin and burn edited from /tg/station https://github.com/tgstation/tgstation/tree/master genetic edited from https://iconscout.com/free-icon/dna-2130814 with license CC BY 4.0", + "states": [ + { + "name": "airloss" + }, + { + "name": "genetic" + }, + { + "name": "brute" + }, + { + "name": "toxin" + }, + { + "name": "burn" + }, + { + "name": "unknown" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/toxin.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/toxin.png new file mode 100644 index 00000000000..b0aafddca33 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/toxin.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/unknown.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/unknown.png new file mode 100644 index 00000000000..f68e2c990e5 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/unknown.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/icon-potato-off.png b/Resources/Textures/Objects/Fun/pai.rsi/icon-potato-off.png new file mode 100644 index 00000000000..806d02d6f3d Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/icon-potato-off.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/meta.json b/Resources/Textures/Objects/Fun/pai.rsi/meta.json index 905a3684f8d..f819450aa88 100644 --- a/Resources/Textures/Objects/Fun/pai.rsi/meta.json +++ b/Resources/Textures/Objects/Fun/pai.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/9ddb8cf084e292571d4e9c79745db25befbd82fe. pai-searching-overlay heavily modified. Syndicate variants by fedKotikeD", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/9ddb8cf084e292571d4e9c79745db25befbd82fe. pai-searching-overlay heavily modified. Syndicate variants by fedKotikeD, and potato by Doru991", "size": { "x": 32, "y": 32 @@ -13,6 +13,9 @@ { "name": "pai-base" }, + { + "name": "potato-base" + }, { "name": "pai-off-overlay" }, @@ -57,6 +60,18 @@ 0.8 ] ] + }, + { + "name": "icon-potato-off" + }, + { + "name": "potato-off-overlay" + }, + { + "name": "potato-on-overlay" + }, + { + "name": "potato-searching-overlay" } ] } diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-base.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-base.png new file mode 100644 index 00000000000..b6e594430cd Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-base.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-off-overlay.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-off-overlay.png new file mode 100644 index 00000000000..0d3f7351588 Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-off-overlay.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-on-overlay.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-on-overlay.png new file mode 100644 index 00000000000..9926823662a Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-on-overlay.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-searching-overlay.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-searching-overlay.png new file mode 100644 index 00000000000..5d8d7cde30c Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-searching-overlay.png differ diff --git a/Resources/Textures/Objects/Misc/potatoai_chip.rsi/icon.png b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/icon.png new file mode 100644 index 00000000000..68ba38d2795 Binary files /dev/null and b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Misc/potatoai_chip.rsi/meta.json b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/meta.json new file mode 100644 index 00000000000..dec5a8d3f78 --- /dev/null +++ b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Drawn by @Doru991 for SS14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + } + ] +} diff --git a/Resources/Textures/Objects/Power/power_cells.rsi/meta.json b/Resources/Textures/Objects/Power/power_cells.rsi/meta.json index 01c2300621b..66dbf308412 100644 --- a/Resources/Textures/Objects/Power/power_cells.rsi/meta.json +++ b/Resources/Textures/Objects/Power/power_cells.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "https://github.com/tgstation/tgstation/commit/7dcdbc1468ffdc8689b984cb6b181d48ae41dbf2", + "copyright": "https://github.com/tgstation/tgstation/commit/7dcdbc1468ffdc8689b984cb6b181d48ae41dbf2, potato based on https://github.com/vgstation-coders/vgstation13/commit/1dbcf389b0ec6b2c51b002df5fef8dd1519f8068 edited by @Doru991", "states": [ { "name": "potato" diff --git a/Resources/Textures/Objects/Power/power_cells.rsi/potato.png b/Resources/Textures/Objects/Power/power_cells.rsi/potato.png index 5b0f7a5fe04..53572f46a12 100644 Binary files a/Resources/Textures/Objects/Power/power_cells.rsi/potato.png and b/Resources/Textures/Objects/Power/power_cells.rsi/potato.png differ diff --git a/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json b/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json index 6499772c7a5..fcdd9e1b26e 100644 --- a/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json @@ -76,4 +76,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/burnt.png b/Resources/Textures/Objects/Tools/lantern.rsi/burnt.png index 74beafc14a2..d9f5bd0bbb6 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/burnt.png and b/Resources/Textures/Objects/Tools/lantern.rsi/burnt.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/flashing.png b/Resources/Textures/Objects/Tools/lantern.rsi/flashing.png index 82713e4c198..7573695619f 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/flashing.png and b/Resources/Textures/Objects/Tools/lantern.rsi/flashing.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png b/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png index eb8cb7c58e5..7573695619f 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png and b/Resources/Textures/Objects/Tools/lantern.rsi/lantern-on.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png b/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png index 74beafc14a2..d9f5bd0bbb6 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png and b/Resources/Textures/Objects/Tools/lantern.rsi/lantern.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/meta.json b/Resources/Textures/Objects/Tools/lantern.rsi/meta.json index ead4cd505ab..4f60017e73c 100644 --- a/Resources/Textures/Objects/Tools/lantern.rsi/meta.json +++ b/Resources/Textures/Objects/Tools/lantern.rsi/meta.json @@ -1,39 +1,39 @@ { - "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "Made by .kreks.(1042144875602268200)", - "size": { - "x": 32, - "y": 32 + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/9bebd81ae0b0a7f952b59886a765c681205de31f", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "lantern" }, - "states": [ - { - "name": "lantern" - }, - { - "name": "lantern-on" - }, - { - "name": "off-inhand-left", - "directions": 4 - }, - { - "name": "off-inhand-right", - "directions": 4 - }, - { - "name": "on-inhand-left", - "directions": 4 - }, - { - "name": "burnt" - }, - { - "name": "flashing" - }, - { - "name": "on-inhand-right", - "directions": 4 - } - ] + { + "name": "lantern-on" + }, + { + "name": "off-inhand-left", + "directions": 4 + }, + { + "name": "off-inhand-right", + "directions": 4 + }, + { + "name": "on-inhand-left", + "directions": 4 + }, + { + "name": "burnt" + }, + { + "name": "flashing" + }, + { + "name": "on-inhand-right", + "directions": 4 + } + ] } diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png index 28bd8e76e60..d38b5e8c641 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png and b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png index 4e2ea91dad3..de8ce0ad507 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png and b/Resources/Textures/Objects/Tools/lantern.rsi/off-inhand-right.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png index f736d10a5c9..d38b5e8c641 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png and b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png index 5c3710ad1d6..de8ce0ad507 100644 Binary files a/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png and b/Resources/Textures/Objects/Tools/lantern.rsi/on-inhand-right.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png b/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png index 38f7a4dd2cb..c2f1c61ace7 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png and b/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/cargo.png b/Resources/Textures/Structures/Machines/techfab.rsi/cargo.png new file mode 100644 index 00000000000..d89e51d1994 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/cargo.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/engi.png b/Resources/Textures/Structures/Machines/techfab.rsi/engi.png new file mode 100644 index 00000000000..5ba7c813b94 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/engi.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/icon.png b/Resources/Textures/Structures/Machines/techfab.rsi/icon.png index 4015336f16b..186fd30082b 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/icon.png and b/Resources/Textures/Structures/Machines/techfab.rsi/icon.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png b/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png index 3f3c09debfb..647eb27246f 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png and b/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/med.png b/Resources/Textures/Structures/Machines/techfab.rsi/med.png index 506b03568a6..86a740cb4ca 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/med.png and b/Resources/Textures/Structures/Machines/techfab.rsi/med.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/meta.json b/Resources/Textures/Structures/Machines/techfab.rsi/meta.json index 11a48c4a0d9..7530b9322a2 100644 --- a/Resources/Textures/Structures/Machines/techfab.rsi/meta.json +++ b/Resources/Textures/Structures/Machines/techfab.rsi/meta.json @@ -14,7 +14,22 @@ "name": "med" }, { - "name": "ammo" + "name": "sec" + }, + { + "name": "sci" + }, + { + "name": "engi" + }, + { + "name": "service" + }, + { + "name": "cargo" + }, + { + "name": "ammo" }, { "name": "panel" diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/sci.png b/Resources/Textures/Structures/Machines/techfab.rsi/sci.png new file mode 100644 index 00000000000..a2c7e72cab7 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/sci.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/sec.png b/Resources/Textures/Structures/Machines/techfab.rsi/sec.png new file mode 100644 index 00000000000..c045c693968 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/sec.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/service.png b/Resources/Textures/Structures/Machines/techfab.rsi/service.png new file mode 100644 index 00000000000..4270548bbba Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/service.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png b/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png index 3f6dd30c964..6635772d336 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png and b/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png differ diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm0.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm0.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm0.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm1.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm1.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm1.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm2.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm2.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm2.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm3.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm3.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm3.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm4.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm4.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm4.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm5.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm5.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm5.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm6.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm6.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm6.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm7.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm7.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm7.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/full.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/full.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/full.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/meta.json similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/meta.json rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/meta.json diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm.png new file mode 100644 index 00000000000..81355cd0cb3 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm0.png new file mode 100644 index 00000000000..18b35146730 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm0.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm1.png new file mode 100644 index 00000000000..32976f4816d Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm1.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm2.png new file mode 100644 index 00000000000..18b35146730 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm2.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm3.png new file mode 100644 index 00000000000..32976f4816d Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm3.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm4.png new file mode 100644 index 00000000000..cb77ce61475 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm4.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm5.png new file mode 100644 index 00000000000..beeb8d34993 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm5.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm6.png new file mode 100644 index 00000000000..cb77ce61475 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm6.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm7.png new file mode 100644 index 00000000000..0858c19f052 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm7.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/full.png new file mode 100644 index 00000000000..59b9454af0b Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/meta.json new file mode 100644 index 00000000000..e303031e1f0 --- /dev/null +++ b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "chasm0", + "directions": 4 + }, + { + "name": "chasm1", + "directions": 4 + }, + { + "name": "chasm2", + "directions": 4 + }, + { + "name": "chasm3", + "directions": 4 + }, + { + "name": "chasm4", + "directions": 4 + }, + { + "name": "chasm5", + "directions": 4 + }, + { + "name": "chasm6", + "directions": 4 + }, + { + "name": "chasm7", + "directions": 4 + }, + { + "name": "chasm" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm.png new file mode 100644 index 00000000000..e09eb93e426 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm0.png new file mode 100644 index 00000000000..7139091f1e1 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm0.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm1.png new file mode 100644 index 00000000000..dce7efd9a63 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm1.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm2.png new file mode 100644 index 00000000000..7139091f1e1 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm2.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm3.png new file mode 100644 index 00000000000..dce7efd9a63 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm3.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm4.png new file mode 100644 index 00000000000..5cc155f8252 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm4.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm5.png new file mode 100644 index 00000000000..05b5d7eccd0 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm5.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm6.png new file mode 100644 index 00000000000..5cc155f8252 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm6.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm7.png new file mode 100644 index 00000000000..0858c19f052 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm7.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/full.png new file mode 100644 index 00000000000..03aa532353e Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/meta.json new file mode 100644 index 00000000000..e303031e1f0 --- /dev/null +++ b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "chasm0", + "directions": 4 + }, + { + "name": "chasm1", + "directions": 4 + }, + { + "name": "chasm2", + "directions": 4 + }, + { + "name": "chasm3", + "directions": 4 + }, + { + "name": "chasm4", + "directions": 4 + }, + { + "name": "chasm5", + "directions": 4 + }, + { + "name": "chasm6", + "directions": 4 + }, + { + "name": "chasm7", + "directions": 4 + }, + { + "name": "chasm" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm.png new file mode 100644 index 00000000000..1124e0518cc Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm0.png new file mode 100644 index 00000000000..a813ce8e9aa Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm0.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm1.png new file mode 100644 index 00000000000..502b9e3d719 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm1.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm2.png new file mode 100644 index 00000000000..a813ce8e9aa Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm2.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm3.png new file mode 100644 index 00000000000..502b9e3d719 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm3.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm4.png new file mode 100644 index 00000000000..f0fd9891159 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm4.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm5.png new file mode 100644 index 00000000000..567cde6ad4e Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm5.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm6.png new file mode 100644 index 00000000000..f0fd9891159 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm6.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm7.png new file mode 100644 index 00000000000..0858c19f052 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm7.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/full.png new file mode 100644 index 00000000000..525cdc2680e Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/meta.json new file mode 100644 index 00000000000..e303031e1f0 --- /dev/null +++ b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "chasm0", + "directions": 4 + }, + { + "name": "chasm1", + "directions": 4 + }, + { + "name": "chasm2", + "directions": 4 + }, + { + "name": "chasm3", + "directions": 4 + }, + { + "name": "chasm4", + "directions": 4 + }, + { + "name": "chasm5", + "directions": 4 + }, + { + "name": "chasm6", + "directions": 4 + }, + { + "name": "chasm7", + "directions": 4 + }, + { + "name": "chasm" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt1.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt1.png new file mode 100644 index 00000000000..e8f873286cb Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt1.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt2.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt2.png new file mode 100644 index 00000000000..00a2711eb8f Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt2.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt3.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt3.png new file mode 100644 index 00000000000..27219f48828 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt3.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt4.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt4.png new file mode 100644 index 00000000000..6081f54b02d Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt4.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt5.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt5.png new file mode 100644 index 00000000000..76c13b2e612 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt5.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/meta.json b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/meta.json new file mode 100644 index 00000000000..0d71d4b561f --- /dev/null +++ b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/meta.json @@ -0,0 +1,66 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "taken from tgstation @ commit a0ca7b3f46132517f71f08bfda465667d133b5d7 and edited by TheShuEd", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "basalt1", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt2", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt3", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt4", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt5", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/attributions.yml b/Resources/Textures/Tiles/attributions.yml index 41fbbbd2437..e443abf031a 100644 --- a/Resources/Textures/Tiles/attributions.yml +++ b/Resources/Textures/Tiles/attributions.yml @@ -110,3 +110,8 @@ license: "CC-BY-SA-3.0" copyright: "taken at https://github.com/ParadiseSS13/Paradise/blob/8b7f4c8b69c74c6de5a755272eb8d3520f3d87c7/icons/turf/floors.dmi" source: "https://github.com/ParadiseSS13/Paradise" + +- files: ["chromite.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "taken at commit 0587dd16e28108bdf0b0a28e2caae4319845e861, and recolored by TheShuEd" + source: "https://github.com/Mojave-Sun/mojave-sun-13" \ No newline at end of file diff --git a/Resources/Textures/Tiles/chromite.png b/Resources/Textures/Tiles/chromite.png new file mode 100644 index 00000000000..631b9bf84e7 Binary files /dev/null and b/Resources/Textures/Tiles/chromite.png differ diff --git a/RobustToolbox b/RobustToolbox index 554e0777b1b..7cad8d5ba3f 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 554e0777b1ba6ba096d8f4407d5c35ecc7b0f22f +Subproject commit 7cad8d5ba3f252eb1dac862c7f92e792c60b98c1 diff --git a/Secrets b/Secrets index f217e467a9f..54f39bf0e4a 160000 --- a/Secrets +++ b/Secrets @@ -1 +1 @@ -Subproject commit f217e467a9f33ba01ac04cb21fa3f8e4327f7f83 +Subproject commit 54f39bf0e4a19a5f1630de355358e1708ebab217