Merge remote-tracking branch 'space-wizards/master'
# Conflicts: # Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs # Content.Server/Explosion/EntitySystems/ExplosionSystem.cs # Resources/Maps/_Sunrise/Station/marathon.yml # Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml # Resources/Prototypes/Entities/Mobs/Player/silicon.yml # Resources/Prototypes/GameRules/events.yml # Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json
|
|
@ -15,6 +15,7 @@ namespace Content.Client.Administration.Managers
|
|||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
||||
[Dependency] private readonly IClientConGroupController _conGroup = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _host = default!;
|
||||
[Dependency] private readonly IResourceManager _res = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
|
||||
|
|
@ -86,12 +87,12 @@ namespace Content.Client.Administration.Managers
|
|||
private void UpdateMessageRx(MsgUpdateAdminStatus message)
|
||||
{
|
||||
_availableCommands.Clear();
|
||||
var host = IoCManager.Resolve<IClientConsoleHost>();
|
||||
|
||||
// Anything marked as Any we'll just add even if the server doesn't know about it.
|
||||
foreach (var (command, instance) in host.AvailableCommands)
|
||||
foreach (var (command, instance) in _host.AvailableCommands)
|
||||
{
|
||||
if (Attribute.GetCustomAttribute(instance.GetType(), typeof(AnyCommandAttribute)) == null) continue;
|
||||
if (Attribute.GetCustomAttribute(instance.GetType(), typeof(AnyCommandAttribute)) == null)
|
||||
continue;
|
||||
_availableCommands.Add(command);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,17 +3,13 @@ using Content.Shared.CCVar;
|
|||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Audio.Effects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
|
|
@ -31,6 +27,7 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem
|
|||
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
|
|
@ -65,18 +62,19 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem
|
|||
get => _overlayEnabled;
|
||||
set
|
||||
{
|
||||
if (_overlayEnabled == value) return;
|
||||
if (_overlayEnabled == value)
|
||||
return;
|
||||
|
||||
_overlayEnabled = value;
|
||||
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||
|
||||
if (_overlayEnabled)
|
||||
{
|
||||
_overlay = new AmbientSoundOverlay(EntityManager, this, EntityManager.System<EntityLookupSystem>());
|
||||
overlayManager.AddOverlay(_overlay);
|
||||
_overlayManager.AddOverlay(_overlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayManager.RemoveOverlay(_overlay!);
|
||||
_overlayManager.RemoveOverlay(_overlay!);
|
||||
_overlay = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,8 @@ using Content.Client.Gameplay;
|
|||
using Content.Shared.Audio;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Random;
|
||||
using Content.Shared.Random.Rules;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.State;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Components;
|
||||
|
|
@ -25,6 +22,7 @@ public sealed partial class ContentAudioSystem
|
|||
{
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
|
@ -61,7 +59,7 @@ public sealed partial class ContentAudioSystem
|
|||
private void InitializeAmbientMusic()
|
||||
{
|
||||
Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChanged, true);
|
||||
_sawmill = IoCManager.Resolve<ILogManager>().GetSawmill("audio.ambience");
|
||||
_sawmill = _logManager.GetSawmill("audio.ambience");
|
||||
|
||||
// Reset audio
|
||||
_nextAudio = TimeSpan.MaxValue;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
using Content.Shared.Changeling.Components;
|
||||
using Content.Shared.Changeling.Systems;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Changeling.Systems;
|
||||
|
||||
public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem
|
||||
{
|
||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
|
||||
}
|
||||
|
||||
private void OnAfterAutoHandleState(Entity<ChangelingIdentityComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
UpdateUi(ent);
|
||||
}
|
||||
|
||||
public void UpdateUi(EntityUid uid)
|
||||
{
|
||||
if (_ui.TryGetOpenUi(uid, ChangelingTransformUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Changeling.Transform;
|
||||
namespace Content.Client.Changeling.UI;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||
|
|
@ -16,16 +16,16 @@ public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owne
|
|||
_window = this.CreateWindow<ChangelingTransformMenu>();
|
||||
|
||||
_window.OnIdentitySelect += SendIdentitySelect;
|
||||
|
||||
_window.Update(Owner);
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
public override void Update()
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (state is not ChangelingTransformBoundUserInterfaceState current)
|
||||
if (_window == null)
|
||||
return;
|
||||
|
||||
_window?.UpdateState(current);
|
||||
_window.Update(Owner);
|
||||
}
|
||||
|
||||
public void SendIdentitySelect(NetEntity identityId)
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Changeling.Systems;
|
||||
using Content.Shared.Changeling.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Changeling.Transform;
|
||||
namespace Content.Client.Changeling.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ChangelingTransformMenu : RadialMenu
|
||||
|
|
@ -19,13 +19,15 @@ public sealed partial class ChangelingTransformMenu : RadialMenu
|
|||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
public void UpdateState(ChangelingTransformBoundUserInterfaceState state)
|
||||
public void Update(EntityUid uid)
|
||||
{
|
||||
Main.DisposeAllChildren();
|
||||
foreach (var identity in state.Identites)
|
||||
{
|
||||
var identityUid = _entity.GetEntity(identity);
|
||||
|
||||
if (!_entity.TryGetComponent<ChangelingIdentityComponent>(uid, out var identityComp))
|
||||
return;
|
||||
|
||||
foreach (var identityUid in identityComp.ConsumedIdentities)
|
||||
{
|
||||
if (!_entity.TryGetComponent<MetaDataComponent>(identityUid, out var metadata))
|
||||
continue;
|
||||
|
||||
|
|
@ -48,7 +50,7 @@ public sealed partial class ChangelingTransformMenu : RadialMenu
|
|||
entView.SetEntity(identityUid);
|
||||
button.OnButtonUp += _ =>
|
||||
{
|
||||
OnIdentitySelect?.Invoke(identity);
|
||||
OnIdentitySelect?.Invoke(_entity.GetNetEntity(identityUid));
|
||||
Close();
|
||||
};
|
||||
button.AddChild(entView);
|
||||
|
|
@ -30,6 +30,10 @@ namespace Content.Client.Lathe.UI
|
|||
{
|
||||
SendMessage(new LatheQueueRecipeMessage(recipe, amount));
|
||||
};
|
||||
_menu.QueueDeleteAction += index => SendMessage(new LatheDeleteRequestMessage(index));
|
||||
_menu.QueueMoveUpAction += index => SendMessage(new LatheMoveRequestMessage(index, -1));
|
||||
_menu.QueueMoveDownAction += index => SendMessage(new LatheMoveRequestMessage(index, 1));
|
||||
_menu.DeleteFabricatingAction += () => SendMessage(new LatheAbortFabricationMessage());
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<DefaultWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:ui="clr-namespace:Content.Client.Materials.UI"
|
||||
Title="{Loc 'lathe-menu-title'}"
|
||||
MinSize="550 450"
|
||||
|
|
@ -110,6 +111,18 @@
|
|||
HorizontalAlignment="Left"
|
||||
Margin="130 0 0 0">
|
||||
</Label>
|
||||
<Button
|
||||
Name="DeleteFabricating"
|
||||
Margin="0"
|
||||
Text="✖"
|
||||
SetSize="38 32"
|
||||
HorizontalAlignment="Right"
|
||||
ToolTip="{Loc 'lathe-menu-delete-fabricating-tooltip'}">
|
||||
<Button.StyleClasses>
|
||||
<system:String>Caution</system:String>
|
||||
<system:String>OpenLeft</system:String>
|
||||
</Button.StyleClasses>
|
||||
</Button>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||
|
||||
public event Action<BaseButton.ButtonEventArgs>? OnServerListButtonPressed;
|
||||
public event Action<string, int>? RecipeQueueAction;
|
||||
public event Action<int>? QueueDeleteAction;
|
||||
public event Action<int>? QueueMoveUpAction;
|
||||
public event Action<int>? QueueMoveDownAction;
|
||||
public event Action? DeleteFabricatingAction;
|
||||
|
||||
public List<ProtoId<LatheRecipePrototype>> Recipes = new();
|
||||
|
||||
|
|
@ -50,12 +54,21 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||
};
|
||||
AmountLineEdit.OnTextChanged += _ =>
|
||||
{
|
||||
if (int.TryParse(AmountLineEdit.Text, out var amount))
|
||||
{
|
||||
if (amount > LatheSystem.MaxItemsPerRequest)
|
||||
AmountLineEdit.Text = LatheSystem.MaxItemsPerRequest.ToString();
|
||||
else if (amount < 0)
|
||||
AmountLineEdit.Text = "0";
|
||||
}
|
||||
|
||||
PopulateRecipes();
|
||||
};
|
||||
|
||||
FilterOption.OnItemSelected += OnItemSelected;
|
||||
|
||||
ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
|
||||
DeleteFabricating.OnPressed += _ => DeleteFabricatingAction?.Invoke();
|
||||
}
|
||||
|
||||
public void SetEntity(EntityUid uid)
|
||||
|
|
@ -223,22 +236,27 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||
/// Populates the build queue list with all queued items
|
||||
/// </summary>
|
||||
/// <param name="queue"></param>
|
||||
public void PopulateQueueList(IReadOnlyCollection<ProtoId<LatheRecipePrototype>> queue)
|
||||
public void PopulateQueueList(IReadOnlyCollection<LatheRecipeBatch> queue)
|
||||
{
|
||||
QueueList.DisposeAllChildren();
|
||||
|
||||
var idx = 1;
|
||||
foreach (var recipeProto in queue)
|
||||
foreach (var batch in queue)
|
||||
{
|
||||
var recipe = _prototypeManager.Index(recipeProto);
|
||||
var queuedRecipeBox = new BoxContainer();
|
||||
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;
|
||||
var recipe = _prototypeManager.Index(batch.Recipe);
|
||||
|
||||
queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe));
|
||||
var itemName = _lathe.GetRecipeName(batch.Recipe);
|
||||
string displayText;
|
||||
if (batch.ItemsRequested > 1)
|
||||
displayText = Loc.GetString("lathe-menu-item-batch", ("index", idx), ("name", itemName), ("printed", batch.ItemsPrinted), ("total", batch.ItemsRequested));
|
||||
else
|
||||
displayText = Loc.GetString("lathe-menu-item-single", ("index", idx), ("name", itemName));
|
||||
|
||||
var queuedRecipeBox = new QueuedRecipeControl(displayText, idx - 1, GetRecipeDisplayControl(recipe));
|
||||
queuedRecipeBox.OnDeletePressed += s => QueueDeleteAction?.Invoke(s);
|
||||
queuedRecipeBox.OnMoveUpPressed += s => QueueMoveUpAction?.Invoke(s);
|
||||
queuedRecipeBox.OnMoveDownPressed += s => QueueMoveDownAction?.Invoke(s);
|
||||
|
||||
var queuedRecipeLabel = new Label();
|
||||
queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}";
|
||||
queuedRecipeBox.AddChild(queuedRecipeLabel);
|
||||
QueueList.AddChild(queuedRecipeBox);
|
||||
idx++;
|
||||
}
|
||||
|
|
|
|||
35
Content.Client/Lathe/UI/QueuedRecipeControl.xaml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<Control xmlns="https://spacestation14.io"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<BoxContainer
|
||||
Name="RecipeDisplayContainer"
|
||||
Margin="0 0 4 0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
MinSize="32 32"
|
||||
/>
|
||||
<Label Name="RecipeName" HorizontalExpand="True" />
|
||||
<Button
|
||||
Name="MoveUp"
|
||||
Margin="0"
|
||||
Text="⏶"
|
||||
StyleClasses="OpenRight"
|
||||
ToolTip="{Loc 'lathe-menu-move-up-tooltip'}"/>
|
||||
<Button
|
||||
Name="MoveDown"
|
||||
Margin="0"
|
||||
Text="⏷"
|
||||
StyleClasses="OpenBoth"
|
||||
ToolTip="{Loc 'lathe-menu-move-down-tooltip'}"/>
|
||||
<Button
|
||||
Name="Delete"
|
||||
Margin="0"
|
||||
Text="✖"
|
||||
ToolTip="{Loc 'lathe-menu-delete-item-tooltip'}">
|
||||
<Button.StyleClasses>
|
||||
<system:String>Caution</system:String>
|
||||
<system:String>OpenLeft</system:String>
|
||||
</Button.StyleClasses>
|
||||
</Button>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
36
Content.Client/Lathe/UI/QueuedRecipeControl.xaml.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Lathe.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class QueuedRecipeControl : Control
|
||||
{
|
||||
public Action<int>? OnDeletePressed;
|
||||
public Action<int>? OnMoveUpPressed;
|
||||
public Action<int>? OnMoveDownPressed;
|
||||
|
||||
public QueuedRecipeControl(string displayText, int index, Control displayControl)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
RecipeName.Text = displayText;
|
||||
RecipeDisplayContainer.AddChild(displayControl);
|
||||
|
||||
MoveUp.OnPressed += (_) =>
|
||||
{
|
||||
OnMoveUpPressed?.Invoke(index);
|
||||
};
|
||||
|
||||
MoveDown.OnPressed += (_) =>
|
||||
{
|
||||
OnMoveDownPressed?.Invoke(index);
|
||||
};
|
||||
|
||||
Delete.OnPressed += (_) =>
|
||||
{
|
||||
OnDeletePressed?.Invoke(index);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ namespace Content.Client.NPC
|
|||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly IResourceCache _cache = default!;
|
||||
[Dependency] private readonly NPCSteeringSystem _steering = default!;
|
||||
[Dependency] private readonly MapSystem _mapSystem = default!;
|
||||
|
|
@ -30,17 +31,15 @@ namespace Content.Client.NPC
|
|||
get => _modes;
|
||||
set
|
||||
{
|
||||
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||
|
||||
if (value == PathfindingDebugMode.None)
|
||||
{
|
||||
Breadcrumbs.Clear();
|
||||
Polys.Clear();
|
||||
overlayManager.RemoveOverlay<PathfindingOverlay>();
|
||||
_overlayManager.RemoveOverlay<PathfindingOverlay>();
|
||||
}
|
||||
else if (!overlayManager.HasOverlay<PathfindingOverlay>())
|
||||
else if (!_overlayManager.HasOverlay<PathfindingOverlay>())
|
||||
{
|
||||
overlayManager.AddOverlay(new PathfindingOverlay(EntityManager, _eyeManager, _inputManager, _mapManager, _cache, this, _mapSystem, _transformSystem));
|
||||
_overlayManager.AddOverlay(new PathfindingOverlay(EntityManager, _eyeManager, _inputManager, _mapManager, _cache, this, _mapSystem, _transformSystem));
|
||||
}
|
||||
|
||||
if ((value & PathfindingDebugMode.Steering) != 0x0)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ namespace Content.Client.Radiation.Overlays;
|
|||
public sealed class RadiationDebugOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IResourceCache _cache = default!;
|
||||
|
||||
private readonly SharedMapSystem _mapSystem;
|
||||
private readonly RadiationSystem _radiation;
|
||||
|
||||
|
|
@ -24,8 +26,7 @@ public sealed class RadiationDebugOverlay : Overlay
|
|||
_radiation = _entityManager.System<RadiationSystem>();
|
||||
_mapSystem = _entityManager.System<SharedMapSystem>();
|
||||
|
||||
var cache = IoCManager.Resolve<IResourceCache>();
|
||||
_font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8);
|
||||
_font = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8);
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
|
|
|
|||
|
|
@ -16,20 +16,20 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
|
|||
get => _enableShuttlePosition;
|
||||
set
|
||||
{
|
||||
if (_enableShuttlePosition == value) return;
|
||||
if (_enableShuttlePosition == value)
|
||||
return;
|
||||
|
||||
_enableShuttlePosition = value;
|
||||
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||
|
||||
if (_enableShuttlePosition)
|
||||
{
|
||||
_overlay = new EmergencyShuttleOverlay(EntityManager.TransformQuery, XformSystem);
|
||||
overlayManager.AddOverlay(_overlay);
|
||||
_overlays.AddOverlay(_overlay);
|
||||
RaiseNetworkEvent(new EmergencyShuttleRequestPositionMessage());
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayManager.RemoveOverlay(_overlay!);
|
||||
_overlays.RemoveOverlay(_overlay!);
|
||||
_overlay = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||
[Dependency] private readonly IComponentFactory _factory = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IStateManager _state = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
|
@ -75,11 +76,10 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||
return;
|
||||
|
||||
_spreadOverlay = value;
|
||||
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||
|
||||
if (_spreadOverlay)
|
||||
{
|
||||
overlayManager.AddOverlay(new GunSpreadOverlay(
|
||||
_overlayManager.AddOverlay(new GunSpreadOverlay(
|
||||
EntityManager,
|
||||
_eyeManager,
|
||||
Timing,
|
||||
|
|
@ -90,7 +90,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||
}
|
||||
else
|
||||
{
|
||||
overlayManager.RemoveOverlay<GunSpreadOverlay>();
|
||||
_overlayManager.RemoveOverlay<GunSpreadOverlay>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
using Content.IntegrationTests.Tests.Interaction;
|
||||
using Content.Shared.Engineering.Systems;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Engineering;
|
||||
|
||||
[TestFixture]
|
||||
[TestOf(typeof(InflatableSafeDisassemblySystem))]
|
||||
public sealed class InflatablesDeflateTest : InteractionTest
|
||||
{
|
||||
[Test]
|
||||
public async Task Test()
|
||||
{
|
||||
await SpawnTarget(InflatableWall);
|
||||
|
||||
await InteractUsing(Needle);
|
||||
|
||||
AssertDeleted();
|
||||
await AssertEntityLookup(new EntitySpecifier(InflatableWallStack.Id, 1));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Interaction;
|
||||
|
||||
// This partial class contains various constant prototype IDs common to interaction tests.
|
||||
|
|
@ -32,4 +35,9 @@ public abstract partial class InteractionTest
|
|||
protected const string Manipulator1 = "MicroManipulatorStockPart";
|
||||
protected const string Battery1 = "PowerCellSmall";
|
||||
protected const string Battery4 = "PowerCellHyper";
|
||||
|
||||
// Inflatables & Needle used to pop them
|
||||
protected static readonly EntProtoId InflatableWall = "InflatableWall";
|
||||
protected static readonly EntProtoId Needle = "WeaponMeleeNeedle";
|
||||
protected static readonly ProtoId<StackPrototype> InflatableWallStack = "InflatableWall";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using Content.Server.Atmos.Components;
|
|||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Clothing.Systems;
|
||||
using Content.Server.Electrocution;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.GhostKick;
|
||||
|
|
@ -22,6 +21,7 @@ using Content.Server.Tabletop.Components;
|
|||
using Content.Server.Terminator.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Components;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Clumsy;
|
||||
|
|
@ -47,7 +47,6 @@ using Content.Shared.Nutrition.Components;
|
|||
using Content.Shared.Popups;
|
||||
using Content.Shared.Slippery;
|
||||
using Content.Shared.Storage.Components;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Tabletop.Components;
|
||||
using Content.Shared.Tools.Systems;
|
||||
using Content.Shared.Verbs;
|
||||
|
|
@ -57,7 +56,6 @@ using Robust.Shared.Physics.Components;
|
|||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Effects.Components;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.Anomaly.Effects;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared.Changeling.Systems;
|
||||
|
||||
namespace Content.Server.Changeling.Systems;
|
||||
|
||||
public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem;
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
|
|
@ -22,6 +21,7 @@ using Content.Server.Temperature.Systems;
|
|||
using Content.Server.Traits.Assorted;
|
||||
using Content.Server.Zombies;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.EntityEffects.EffectConditions;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using Content.Server.Atmos.Components;
|
|||
using Content.Server.NodeContainer.EntitySystems;
|
||||
using Content.Server.NPC.Pathfinding;
|
||||
using Content.Shared._RMC14.Explosion;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Camera;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Damage;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ namespace Content.Server.Lathe
|
|||
|
||||
SubscribeLocalEvent<LatheComponent, LatheQueueRecipeMessage>(OnLatheQueueRecipeMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheSyncRequestMessage>(OnLatheSyncRequestMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheDeleteRequestMessage>(OnLatheDeleteRequestMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheMoveRequestMessage>(OnLatheMoveRequestMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheAbortFabricationMessage>(OnLatheAbortFabricationMessage);
|
||||
|
||||
SubscribeLocalEvent<LatheComponent, BeforeActivatableUIOpenEvent>((u, c, _) => UpdateUserInterfaceState(u, c));
|
||||
SubscribeLocalEvent<LatheComponent, MaterialAmountChangedEvent>(OnMaterialAmountChanged);
|
||||
|
|
@ -168,23 +171,32 @@ namespace Content.Server.Lathe
|
|||
return ev.Recipes.ToList();
|
||||
}
|
||||
|
||||
public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, LatheComponent? component = null)
|
||||
public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, int quantity, LatheComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
if (!CanProduce(uid, recipe, 1, component))
|
||||
if (quantity <= 0)
|
||||
return false;
|
||||
quantity = int.Min(quantity, MaxItemsPerRequest);
|
||||
|
||||
if (!CanProduce(uid, recipe, quantity, component))
|
||||
return false;
|
||||
|
||||
foreach (var (mat, amount) in recipe.Materials)
|
||||
{
|
||||
var adjustedAmount = recipe.ApplyMaterialDiscount
|
||||
? (int) (-amount * component.MaterialUseMultiplier)
|
||||
? (int)(-amount * component.MaterialUseMultiplier)
|
||||
: -amount;
|
||||
adjustedAmount *= quantity;
|
||||
|
||||
_materialStorage.TryChangeMaterialAmount(uid, mat, adjustedAmount);
|
||||
}
|
||||
component.Queue.Enqueue(recipe);
|
||||
|
||||
if (component.Queue.Last is { } node && node.ValueRef.Recipe == recipe.ID)
|
||||
node.ValueRef.ItemsRequested += quantity;
|
||||
else
|
||||
component.Queue.AddLast(new LatheRecipeBatch(recipe.ID, 0, quantity));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -196,8 +208,11 @@ namespace Content.Server.Lathe
|
|||
if (component.CurrentRecipe != null || component.Queue.Count <= 0 || !this.IsPowered(uid, EntityManager))
|
||||
return false;
|
||||
|
||||
var recipeProto = component.Queue.Dequeue();
|
||||
var recipe = _proto.Index(recipeProto);
|
||||
var batch = component.Queue.First();
|
||||
batch.ItemsPrinted++;
|
||||
if (batch.ItemsPrinted >= batch.ItemsRequested || batch.ItemsPrinted < 0) // Rollover sanity check
|
||||
component.Queue.RemoveFirst();
|
||||
var recipe = _proto.Index(batch.Recipe);
|
||||
|
||||
var time = _reagentSpeed.ApplySpeed(uid, recipe.CompleteTime) * component.TimeMultiplier;
|
||||
|
||||
|
|
@ -273,8 +288,8 @@ namespace Content.Server.Lathe
|
|||
return;
|
||||
|
||||
var producing = component.CurrentRecipe;
|
||||
if (producing == null && component.Queue.TryPeek(out var next))
|
||||
producing = next;
|
||||
if (producing == null && component.Queue.First is { } node)
|
||||
producing = node.Value.Recipe;
|
||||
|
||||
var state = new LatheUpdateState(GetAvailableRecipes(uid, component), component.Queue.ToArray(), producing);
|
||||
_uiSys.SetUiState(uid, LatheUiKey.Key, state);
|
||||
|
|
@ -351,12 +366,10 @@ namespace Content.Server.Lathe
|
|||
{
|
||||
if (!args.Powered)
|
||||
{
|
||||
RemComp<LatheProducingComponent>(uid);
|
||||
UpdateRunningAppearance(uid, false);
|
||||
AbortProduction(uid);
|
||||
}
|
||||
else if (component.CurrentRecipe != null)
|
||||
else
|
||||
{
|
||||
EnsureComp<LatheProducingComponent>(uid);
|
||||
TryStartProducing(uid, component);
|
||||
}
|
||||
}
|
||||
|
|
@ -420,25 +433,46 @@ namespace Content.Server.Lathe
|
|||
return GetAvailableRecipes(uid, component).Contains(recipe.ID);
|
||||
}
|
||||
|
||||
public void AbortProduction(EntityUid uid, LatheComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (component.CurrentRecipe != null)
|
||||
{
|
||||
if (component.Queue.Count > 0)
|
||||
{
|
||||
// Batch abandoned while printing last item, need to create a one-item batch
|
||||
var batch = component.Queue.First();
|
||||
if (batch.Recipe != component.CurrentRecipe)
|
||||
{
|
||||
var newBatch = new LatheRecipeBatch(component.CurrentRecipe.Value, 0, 1);
|
||||
component.Queue.AddFirst(newBatch);
|
||||
}
|
||||
else if (batch.ItemsPrinted > 0)
|
||||
{
|
||||
batch.ItemsPrinted--;
|
||||
}
|
||||
}
|
||||
|
||||
component.CurrentRecipe = null;
|
||||
}
|
||||
RemCompDeferred<LatheProducingComponent>(uid);
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
UpdateRunningAppearance(uid, false);
|
||||
}
|
||||
|
||||
#region UI Messages
|
||||
|
||||
private void OnLatheQueueRecipeMessage(EntityUid uid, LatheComponent component, LatheQueueRecipeMessage args)
|
||||
{
|
||||
if (_proto.TryIndex(args.ID, out LatheRecipePrototype? recipe))
|
||||
{
|
||||
var count = 0;
|
||||
for (var i = 0; i < args.Quantity; i++)
|
||||
{
|
||||
if (TryAddToQueue(uid, recipe, component))
|
||||
count++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (count > 0)
|
||||
if (TryAddToQueue(uid, recipe, args.Quantity, component))
|
||||
{
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(args.Actor):player} queued {count} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}");
|
||||
$"{ToPrettyString(args.Actor):player} queued {args.Quantity} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}");
|
||||
}
|
||||
}
|
||||
TryStartProducing(uid, component);
|
||||
|
|
@ -449,6 +483,92 @@ namespace Content.Server.Lathe
|
|||
{
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a batch from the batch queue by index.
|
||||
/// If the index given does not exist or is outside of the bounds of the lathe's batch queue, nothing happens.
|
||||
/// </summary>
|
||||
/// <param name="uid">The lathe whose queue is being altered.</param>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="args"></param>
|
||||
public void OnLatheDeleteRequestMessage(EntityUid uid, LatheComponent component, ref LatheDeleteRequestMessage args)
|
||||
{
|
||||
if (args.Index < 0 || args.Index >= component.Queue.Count)
|
||||
return;
|
||||
|
||||
var node = component.Queue.First;
|
||||
for (int i = 0; i < args.Index; i++)
|
||||
node = node?.Next;
|
||||
|
||||
if (node == null) // Shouldn't happen with checks above.
|
||||
return;
|
||||
|
||||
var batch = node.Value;
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(args.Actor):player} deleted a lathe job for ({batch.ItemsPrinted}/{batch.ItemsRequested}) {GetRecipeName(batch.Recipe)} at {ToPrettyString(uid):lathe}");
|
||||
|
||||
component.Queue.Remove(node);
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
}
|
||||
|
||||
public void OnLatheMoveRequestMessage(EntityUid uid, LatheComponent component, ref LatheMoveRequestMessage args)
|
||||
{
|
||||
if (args.Change == 0 || args.Index < 0 || args.Index >= component.Queue.Count)
|
||||
return;
|
||||
|
||||
// New index must be within the bounds of the batch.
|
||||
var newIndex = args.Index + args.Change;
|
||||
if (newIndex < 0 || newIndex >= component.Queue.Count)
|
||||
return;
|
||||
|
||||
var node = component.Queue.First;
|
||||
for (int i = 0; i < args.Index; i++)
|
||||
node = node?.Next;
|
||||
|
||||
if (node == null) // Something went wrong.
|
||||
return;
|
||||
|
||||
if (args.Change > 0)
|
||||
{
|
||||
var newRelativeNode = node.Next;
|
||||
for (int i = 1; i < args.Change; i++) // 1-indexed: starting from Next
|
||||
newRelativeNode = newRelativeNode?.Next;
|
||||
|
||||
if (newRelativeNode == null) // Something went wrong.
|
||||
return;
|
||||
|
||||
component.Queue.Remove(node);
|
||||
component.Queue.AddAfter(newRelativeNode, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newRelativeNode = node.Previous;
|
||||
for (int i = 1; i < -args.Change; i++) // 1-indexed: starting from Previous
|
||||
newRelativeNode = newRelativeNode?.Previous;
|
||||
|
||||
if (newRelativeNode == null) // Something went wrong.
|
||||
return;
|
||||
|
||||
component.Queue.Remove(node);
|
||||
component.Queue.AddBefore(newRelativeNode, node);
|
||||
}
|
||||
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
}
|
||||
|
||||
public void OnLatheAbortFabricationMessage(EntityUid uid, LatheComponent component, ref LatheAbortFabricationMessage args)
|
||||
{
|
||||
if (component.CurrentRecipe == null)
|
||||
return;
|
||||
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(args.Actor):player} aborted printing {GetRecipeName(component.CurrentRecipe.Value)} at {ToPrettyString(uid):lathe}");
|
||||
|
||||
component.CurrentRecipe = null;
|
||||
FinishProducing(uid, component);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.NPC.Queries;
|
||||
|
|
@ -6,13 +5,11 @@ using Content.Server.NPC.Queries.Considerations;
|
|||
using Content.Server.NPC.Queries.Curves;
|
||||
using Content.Server.NPC.Queries.Queries;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
|
|
@ -31,6 +28,7 @@ using Microsoft.Extensions.ObjectPool;
|
|||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.NPC.Systems;
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ public sealed partial class PolymorphSystem : EntitySystem
|
|||
|
||||
if (configuration.TransferHumanoidAppearance)
|
||||
{
|
||||
_humanoid.CloneAppearance(uid, child);
|
||||
_humanoid.CloneAppearance(child, uid);
|
||||
}
|
||||
|
||||
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||
|
|
|
|||
44
Content.Server/Trigger/Systems/GameRuleTriggerSystem.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Trigger;
|
||||
using Content.Shared.Trigger.Components.Effects;
|
||||
|
||||
namespace Content.Server.Trigger.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// Trigger system for game rules.
|
||||
/// </summary>
|
||||
public sealed class GameRuleTriggerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<AddGameRuleOnTriggerComponent, TriggerEvent>(AddRuleOnTrigger);
|
||||
}
|
||||
|
||||
private void AddRuleOnTrigger(Entity<AddGameRuleOnTriggerComponent> ent, ref TriggerEvent args)
|
||||
{
|
||||
if (args.Key != null && !ent.Comp.KeysIn.Contains(args.Key))
|
||||
return;
|
||||
|
||||
var rule = _ticker.AddGameRule(ent.Comp.GameRule);
|
||||
|
||||
_adminLogger.Add(LogType.EventStarted,
|
||||
$"{ToPrettyString(args.User):entity} added a game rule [{ent.Comp.GameRule}]" +
|
||||
$" via a trigger on {ToPrettyString(ent.Owner):entity}.");
|
||||
|
||||
if (ent.Comp.StartRule && _ticker.RunLevel == GameRunLevel.InRound)
|
||||
{
|
||||
_ticker.StartGameRule(rule);
|
||||
_adminLogger.Add(LogType.EventStarted, $"{ToPrettyString(args.User):entity} started game rule [{ent.Comp.GameRule}].");
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using Content.Shared.Popups;
|
|||
using Content.Shared.Tag;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Weapons.Melee.Balloon;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Server.Weapons.Melee.Balloon;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Xenoarchaeology.Artifact.XAE.Components;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Xenoarchaeology.Artifact;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.XAE;
|
||||
using Robust.Shared.Random;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
using Content.Shared.Alert;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Atmos.Components
|
||||
namespace Content.Shared.Atmos.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class FlammableComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
|
|
@ -8,7 +8,7 @@ namespace Content.Shared.Changeling.Components;
|
|||
/// The storage component for Changelings, it handles the link between a changeling and its consumed identities
|
||||
/// that exist on a paused map.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true)]
|
||||
public sealed partial class ChangelingIdentityComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public sealed class ChangelingDevourSystem : EntitySystem
|
|||
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly ChangelingIdentitySystem _changelingIdentitySystem = default!;
|
||||
[Dependency] private readonly SharedChangelingIdentitySystem _changelingIdentitySystem = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
|
|
|
|||
|
|
@ -14,20 +14,8 @@ public sealed class ChangelingTransformIdentitySelectMessage(NetEntity targetIde
|
|||
public readonly NetEntity TargetIdentity = targetIdentity;
|
||||
}
|
||||
|
||||
// TODO: Replace with component states.
|
||||
// We are already networking the ChangelingIdentityComponent, which contains all this information,
|
||||
// so we can just read it from them from the component and update the UI in an AfterAuotHandleState subscription.
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChangelingTransformBoundUserInterfaceState(List<NetEntity> identities) : BoundUserInterfaceState
|
||||
{
|
||||
/// <summary>
|
||||
/// The uids of the cloned identities.
|
||||
/// </summary>
|
||||
public readonly List<NetEntity> Identites = identities;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum TransformUI : byte
|
||||
public enum ChangelingTransformUiKey : byte
|
||||
{
|
||||
Key,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
_actionsSystem.AddAction(ent, ref ent.Comp.ChangelingTransformActionEntity, ent.Comp.ChangelingTransformAction);
|
||||
|
||||
var userInterfaceComp = EnsureComp<UserInterfaceComponent>(ent);
|
||||
_uiSystem.SetUi((ent, userInterfaceComp), TransformUI.Key, new InterfaceData(ChangelingBuiXmlGeneratedName));
|
||||
_uiSystem.SetUi((ent, userInterfaceComp), ChangelingTransformUiKey.Key, new InterfaceData(ChangelingBuiXmlGeneratedName));
|
||||
}
|
||||
|
||||
private void OnShutdown(Entity<ChangelingTransformComponent> ent, ref ComponentShutdown args)
|
||||
|
|
@ -64,18 +64,9 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
if (!TryComp<ChangelingIdentityComponent>(ent, out var userIdentity))
|
||||
return;
|
||||
|
||||
if (!_uiSystem.IsUiOpen((ent, userInterfaceComp), TransformUI.Key, args.Performer))
|
||||
if (!_uiSystem.IsUiOpen((ent, userInterfaceComp), ChangelingTransformUiKey.Key, args.Performer))
|
||||
{
|
||||
_uiSystem.OpenUi((ent, userInterfaceComp), TransformUI.Key, args.Performer);
|
||||
|
||||
var identityData = new List<NetEntity>();
|
||||
|
||||
foreach (var consumedIdentity in userIdentity.ConsumedIdentities)
|
||||
{
|
||||
identityData.Add(GetNetEntity(consumedIdentity));
|
||||
}
|
||||
|
||||
_uiSystem.SetUiState((ent, userInterfaceComp), TransformUI.Key, new ChangelingTransformBoundUserInterfaceState(identityData));
|
||||
_uiSystem.OpenUi((ent, userInterfaceComp), ChangelingTransformUiKey.Key, args.Performer);
|
||||
} //TODO: Can add a Else here with TransformInto and CloseUI to make a quick switch,
|
||||
// issue right now is that Radials cover the Action buttons so clicking the action closes the UI (due to clicking off a radial causing it to close, even with UI)
|
||||
// but pressing the number does.
|
||||
|
|
@ -108,7 +99,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
else
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(ent.Owner):player} begun an attempt to transform into \"{Name(targetIdentity)}\"");
|
||||
|
||||
var result = _doAfterSystem.TryStartDoAfter(new DoAfterArgs(
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(
|
||||
EntityManager,
|
||||
ent,
|
||||
ent.Comp.TransformWindup,
|
||||
|
|
@ -127,7 +118,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
private void OnTransformSelected(Entity<ChangelingTransformComponent> ent,
|
||||
ref ChangelingTransformIdentitySelectMessage args)
|
||||
{
|
||||
_uiSystem.CloseUi(ent.Owner, TransformUI.Key, ent);
|
||||
_uiSystem.CloseUi(ent.Owner, ChangelingTransformUiKey.Key, ent);
|
||||
|
||||
if (!TryGetEntity(args.TargetIdentity, out var targetIdentity))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
using Content.Shared.Changeling.Components;
|
||||
using Content.Shared.Cloning;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.NameModifier.EntitySystems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
|
|
@ -12,7 +11,7 @@ using Robust.Shared.Prototypes;
|
|||
|
||||
namespace Content.Shared.Changeling.Systems;
|
||||
|
||||
public sealed class ChangelingIdentitySystem : EntitySystem
|
||||
public abstract class SharedChangelingIdentitySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
|
@ -32,22 +31,19 @@ public sealed class ChangelingIdentitySystem : EntitySystem
|
|||
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, MindAddedMessage>(OnMindAdded);
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, MindRemovedMessage>(OnMindRemoved);
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, PlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<ChangelingIdentityComponent, PlayerDetachedEvent>(OnPlayerDetached);
|
||||
SubscribeLocalEvent<ChangelingStoredIdentityComponent, ComponentRemove>(OnStoredRemove);
|
||||
}
|
||||
|
||||
private void OnMindAdded(Entity<ChangelingIdentityComponent> ent, ref MindAddedMessage args)
|
||||
private void OnPlayerAttached(Entity<ChangelingIdentityComponent> ent, ref PlayerAttachedEvent args)
|
||||
{
|
||||
if (!TryComp<ActorComponent>(args.Container.Owner, out var actor))
|
||||
return;
|
||||
|
||||
HandOverPvsOverride(actor.PlayerSession, ent.Comp);
|
||||
HandOverPvsOverride(ent, args.Player);
|
||||
}
|
||||
|
||||
private void OnMindRemoved(Entity<ChangelingIdentityComponent> ent, ref MindRemovedMessage args)
|
||||
private void OnPlayerDetached(Entity<ChangelingIdentityComponent> ent, ref PlayerDetachedEvent args)
|
||||
{
|
||||
CleanupPvsOverride(ent, args.Container.Owner);
|
||||
CleanupPvsOverride(ent, args.Player);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<ChangelingIdentityComponent> ent, ref MapInitEvent args)
|
||||
|
|
@ -59,7 +55,8 @@ public sealed class ChangelingIdentitySystem : EntitySystem
|
|||
|
||||
private void OnShutdown(Entity<ChangelingIdentityComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
CleanupPvsOverride(ent, ent.Owner);
|
||||
if (TryComp<ActorComponent>(ent, out var actor))
|
||||
CleanupPvsOverride(ent, actor.PlayerSession);
|
||||
CleanupChangelingNullspaceIdentities(ent);
|
||||
}
|
||||
|
||||
|
|
@ -107,66 +104,63 @@ public sealed class ChangelingIdentitySystem : EntitySystem
|
|||
// Movercontrollers and mob collisions are currently being calculated even for paused entities.
|
||||
// Spawning all of them in the same spot causes severe performance problems.
|
||||
// Cryopods and Polymorph have the same problem.
|
||||
var mob = Spawn(speciesPrototype.Prototype, new MapCoordinates(new Vector2(2 * _numberOfStoredIdentities++, 0), PausedMapId!.Value));
|
||||
var clone = Spawn(speciesPrototype.Prototype, new MapCoordinates(new Vector2(2 * _numberOfStoredIdentities++, 0), PausedMapId!.Value));
|
||||
|
||||
var storedIdentity = EnsureComp<ChangelingStoredIdentityComponent>(mob);
|
||||
var storedIdentity = EnsureComp<ChangelingStoredIdentityComponent>(clone);
|
||||
storedIdentity.OriginalEntity = target; // TODO: network this once we have WeakEntityReference or the autonetworking source gen is fixed
|
||||
|
||||
if (TryComp<ActorComponent>(target, out var actor))
|
||||
storedIdentity.OriginalSession = actor.PlayerSession;
|
||||
|
||||
_humanoidSystem.CloneAppearance(target, mob);
|
||||
_cloningSystem.CloneComponents(target, mob, settings);
|
||||
_humanoidSystem.CloneAppearance(target, clone);
|
||||
_cloningSystem.CloneComponents(target, clone, settings);
|
||||
|
||||
var targetName = _nameMod.GetBaseName(target);
|
||||
_metaSystem.SetEntityName(mob, targetName);
|
||||
ent.Comp.ConsumedIdentities.Add(mob);
|
||||
_metaSystem.SetEntityName(clone, targetName);
|
||||
ent.Comp.ConsumedIdentities.Add(clone);
|
||||
|
||||
Dirty(ent);
|
||||
HandlePvsOverride(ent, mob);
|
||||
HandlePvsOverride(ent, clone);
|
||||
|
||||
return mob;
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple helper to add a PVS override to a Nullspace Identity
|
||||
/// Simple helper to add a PVS override to a nullspace identity.
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="target"></param>
|
||||
private void HandlePvsOverride(EntityUid uid, EntityUid target)
|
||||
/// <param name="uid">The actor that should get the override.</param>
|
||||
/// <param name="identity">The identity stored in nullspace.</param>
|
||||
private void HandlePvsOverride(EntityUid uid, EntityUid identity)
|
||||
{
|
||||
if (!TryComp<ActorComponent>(uid, out var actor))
|
||||
return;
|
||||
|
||||
_pvsOverrideSystem.AddSessionOverride(target, actor.PlayerSession);
|
||||
_pvsOverrideSystem.AddSessionOverride(identity, actor.PlayerSession);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup all Pvs Overrides for the owner of the ChangelingIdentity
|
||||
/// Cleanup all PVS overrides for the owner of the ChangelingIdentity
|
||||
/// </summary>
|
||||
/// <param name="ent">the Changeling itself</param>
|
||||
/// <param name="entityUid">Who specifically to cleanup from, usually just the same owner, but in the case of a mindswap we want to clean up the victim</param>
|
||||
private void CleanupPvsOverride(Entity<ChangelingIdentityComponent> ent, EntityUid entityUid)
|
||||
/// <param name="ent">The changeling storing the identities.</param>
|
||||
/// <param name="entityUid"The session you wish to remove the overrides from.</param>
|
||||
private void CleanupPvsOverride(Entity<ChangelingIdentityComponent> ent, ICommonSession session)
|
||||
{
|
||||
if (!TryComp<ActorComponent>(entityUid, out var actor))
|
||||
return;
|
||||
|
||||
foreach (var identity in ent.Comp.ConsumedIdentities)
|
||||
{
|
||||
_pvsOverrideSystem.RemoveSessionOverride(identity, actor.PlayerSession);
|
||||
_pvsOverrideSystem.RemoveSessionOverride(identity, session);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inform another Session of the entities stored for Transformation
|
||||
/// Inform another session of the entities stored for transformation.
|
||||
/// </summary>
|
||||
/// <param name="session">The Session you wish to inform</param>
|
||||
/// <param name="comp">The Target storage of identities</param>
|
||||
public void HandOverPvsOverride(ICommonSession session, ChangelingIdentityComponent comp)
|
||||
/// <param name="ent">The changeling storing the identities.</param>
|
||||
/// <param name="session">The session you wish to inform.</param>
|
||||
public void HandOverPvsOverride(Entity<ChangelingIdentityComponent> ent, ICommonSession session)
|
||||
{
|
||||
foreach (var entity in comp.ConsumedIdentities)
|
||||
foreach (var identity in ent.Comp.ConsumedIdentities)
|
||||
{
|
||||
_pvsOverrideSystem.AddSessionOverride(entity, session);
|
||||
_pvsOverrideSystem.AddSessionOverride(identity, session);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using Content.Shared.Engineering.Systems;
|
||||
using Content.Shared.Weapons.Melee.Balloon;
|
||||
|
||||
namespace Content.Shared.Engineering.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Implements logic to allow inflatable objects to be safely deflated by <see cref="BalloonPopperComponent"/> items.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The owning entity must have <see cref="DisassembleOnAltVerbComponent"/> to implement the logic.
|
||||
/// </remarks>
|
||||
/// <seealso cref="InflatableSafeDisassemblySystem"/>
|
||||
[RegisterComponent]
|
||||
public sealed partial class InflatableSafeDisassemblyComponent : Component;
|
||||
|
|
@ -19,14 +19,12 @@ public sealed partial class DisassembleOnAltVerbSystem : EntitySystem
|
|||
SubscribeLocalEvent<DisassembleOnAltVerbComponent, GetVerbsEvent<AlternativeVerb>>(AddDisassembleVerb);
|
||||
SubscribeLocalEvent<DisassembleOnAltVerbComponent, DisassembleDoAfterEvent>(OnDisassembleDoAfter);
|
||||
}
|
||||
private void AddDisassembleVerb(Entity<DisassembleOnAltVerbComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanInteract || !args.CanAccess || args.Hands == null)
|
||||
return;
|
||||
|
||||
public void StartDisassembly(Entity<DisassembleOnAltVerbComponent> entity, EntityUid user)
|
||||
{
|
||||
// Doafter setup
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager,
|
||||
args.User,
|
||||
user,
|
||||
entity.Comp.DisassembleTime,
|
||||
new DisassembleDoAfterEvent(),
|
||||
entity,
|
||||
|
|
@ -35,12 +33,22 @@ public sealed partial class DisassembleOnAltVerbSystem : EntitySystem
|
|||
BreakOnMove = true,
|
||||
};
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
}
|
||||
|
||||
private void AddDisassembleVerb(Entity<DisassembleOnAltVerbComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanInteract || !args.CanAccess || args.Hands == null)
|
||||
return;
|
||||
|
||||
var user = args.User;
|
||||
|
||||
// Actual verb stuff
|
||||
AlternativeVerb verb = new()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
StartDisassembly(entity, user);
|
||||
},
|
||||
Text = Loc.GetString("disassemble-system-verb-disassemble"),
|
||||
Priority = 2
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
using Content.Shared.Engineering.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Weapons.Melee.Balloon;
|
||||
|
||||
namespace Content.Shared.Engineering.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="InflatableSafeDisassemblyComponent"/>
|
||||
/// </summary>
|
||||
public sealed class InflatableSafeDisassemblySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DisassembleOnAltVerbSystem _disassembleOnAltVerbSystem = null!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = null!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<InflatableSafeDisassemblyComponent, InteractUsingEvent>(InteractHandler);
|
||||
}
|
||||
|
||||
private void InteractHandler(Entity<InflatableSafeDisassemblyComponent> ent, ref InteractUsingEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (!HasComp<BalloonPopperComponent>(args.Used))
|
||||
return;
|
||||
|
||||
_popupSystem.PopupPredicted(
|
||||
Loc.GetString("inflatable-safe-disassembly", ("item", args.Used), ("target", ent.Owner)),
|
||||
ent,
|
||||
args.User);
|
||||
|
||||
_disassembleOnAltVerbSystem.StartDisassembly((ent, Comp<DisassembleOnAltVerbComponent>(ent)), args.User);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,10 +26,14 @@ namespace Content.Shared.Lathe
|
|||
// Otherwise the material arbitrage test and/or LatheSystem.GetAllBaseRecipes needs to be updated
|
||||
|
||||
/// <summary>
|
||||
/// The lathe's construction queue
|
||||
/// The lathe's construction queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a LinkedList to allow for constant time insertion/deletion (vs a List), and more efficient
|
||||
/// moves (vs a Queue).
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public Queue<ProtoId<LatheRecipePrototype>> Queue = new();
|
||||
public LinkedList<LatheRecipeBatch> Queue = new();
|
||||
|
||||
/// <summary>
|
||||
/// The sound that plays when the lathe is producing an item, if any
|
||||
|
|
@ -97,6 +101,21 @@ namespace Content.Shared.Lathe
|
|||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed partial class LatheRecipeBatch
|
||||
{
|
||||
public ProtoId<LatheRecipePrototype> Recipe;
|
||||
public int ItemsPrinted;
|
||||
public int ItemsRequested;
|
||||
|
||||
public LatheRecipeBatch(ProtoId<LatheRecipePrototype> recipe, int itemsPrinted, int itemsRequested)
|
||||
{
|
||||
Recipe = recipe;
|
||||
ItemsPrinted = itemsPrinted;
|
||||
ItemsRequested = itemsRequested;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised on a lathe when it starts producing a recipe.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ public sealed class LatheUpdateState : BoundUserInterfaceState
|
|||
{
|
||||
public List<ProtoId<LatheRecipePrototype>> Recipes;
|
||||
|
||||
public ProtoId<LatheRecipePrototype>[] Queue;
|
||||
public LatheRecipeBatch[] Queue;
|
||||
|
||||
public ProtoId<LatheRecipePrototype>? CurrentlyProducing;
|
||||
|
||||
public LatheUpdateState(List<ProtoId<LatheRecipePrototype>> recipes, ProtoId<LatheRecipePrototype>[] queue, ProtoId<LatheRecipePrototype>? currentlyProducing = null)
|
||||
public LatheUpdateState(List<ProtoId<LatheRecipePrototype>> recipes, LatheRecipeBatch[] queue, ProtoId<LatheRecipePrototype>? currentlyProducing = null)
|
||||
{
|
||||
Recipes = recipes;
|
||||
Queue = queue;
|
||||
|
|
@ -46,6 +46,33 @@ public sealed class LatheQueueRecipeMessage : BoundUserInterfaceMessage
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to remove a batch from the queue.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LatheDeleteRequestMessage(int index) : BoundUserInterfaceMessage
|
||||
{
|
||||
public int Index = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to move the position of a batch in the queue.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LatheMoveRequestMessage(int index, int change) : BoundUserInterfaceMessage
|
||||
{
|
||||
public int Index = index;
|
||||
public int Change = change;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to stop producing the current item.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LatheAbortFabricationMessage() : BoundUserInterfaceMessage
|
||||
{
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public enum LatheUiKey
|
||||
{
|
||||
|
|
|
|||
81
Content.Shared/Lathe/PrototypeIdLinkedListSerializer.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Sequence;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
|
||||
|
||||
namespace Content.Shared.Lathe;
|
||||
|
||||
/// <summary>
|
||||
/// Handles reading, writing, and validation for linked lists of prototypes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of prototype this linked list represents</typeparam>
|
||||
/// <remarks>
|
||||
/// This is in the Content.Shared.Lathe namespace as there are no other LinkedList ProtoId instances.
|
||||
/// </remarks>
|
||||
[TypeSerializer]
|
||||
public sealed class LinkedListSerializer<T> : ITypeSerializer<LinkedList<T>, SequenceDataNode>, ITypeCopier<LinkedList<T>> where T : class
|
||||
{
|
||||
public ValidationNode Validate(ISerializationManager serializationManager, SequenceDataNode node,
|
||||
IDependencyCollection dependencies, ISerializationContext? context = null)
|
||||
{
|
||||
var list = new List<ValidationNode>();
|
||||
|
||||
foreach (var elem in node.Sequence)
|
||||
{
|
||||
list.Add(serializationManager.ValidateNode<T>(elem, context));
|
||||
}
|
||||
|
||||
return new ValidatedSequenceNode(list);
|
||||
}
|
||||
|
||||
public DataNode Write(ISerializationManager serializationManager, LinkedList<T> value,
|
||||
IDependencyCollection dependencies,
|
||||
bool alwaysWrite = false,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
var sequence = new SequenceDataNode();
|
||||
|
||||
foreach (var elem in value)
|
||||
{
|
||||
sequence.Add(serializationManager.WriteValue(elem, alwaysWrite, context));
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
LinkedList<T> ITypeReader<LinkedList<T>, SequenceDataNode>.Read(ISerializationManager serializationManager,
|
||||
SequenceDataNode node,
|
||||
IDependencyCollection dependencies,
|
||||
SerializationHookContext hookCtx,
|
||||
ISerializationContext? context, ISerializationManager.InstantiationDelegate<LinkedList<T>>? instanceProvider)
|
||||
{
|
||||
var list = instanceProvider != null ? instanceProvider() : new LinkedList<T>();
|
||||
|
||||
foreach (var dataNode in node.Sequence)
|
||||
{
|
||||
list.AddLast(serializationManager.Read<T>(dataNode, hookCtx, context));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void CopyTo(
|
||||
ISerializationManager serializationManager,
|
||||
LinkedList<T> source,
|
||||
ref LinkedList<T> target,
|
||||
IDependencyCollection dependencies,
|
||||
SerializationHookContext hookCtx,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
target.Clear();
|
||||
using var enumerator = source.GetEnumerator();
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var current = enumerator.Current;
|
||||
target.AddLast(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ public abstract class SharedLatheSystem : EntitySystem
|
|||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
|
||||
public readonly Dictionary<string, List<LatheRecipePrototype>> InverseRecipes = new();
|
||||
public const int MaxItemsPerRequest = 10_000;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
|
@ -86,6 +87,8 @@ public abstract class SharedLatheSystem : EntitySystem
|
|||
return false;
|
||||
if (!HasRecipe(uid, recipe, component))
|
||||
return false;
|
||||
if (amount <= 0)
|
||||
return false;
|
||||
|
||||
foreach (var (material, needed) in recipe.Materials)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
using Content.Shared.GameTicking.Components;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Trigger.Components.Effects;
|
||||
|
||||
/// <summary>
|
||||
/// Adds and starts a new game rule on a trigger.
|
||||
/// The user is always logged alongside the game rule and this entity.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class AddGameRuleOnTriggerComponent : BaseXOnTriggerComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The game rule that will be added. Entity requires <see cref="GameRuleComponent"/>.
|
||||
/// </summary>
|
||||
[DataField(required: true), AutoNetworkedField]
|
||||
public EntProtoId<GameRuleComponent> GameRule;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to also start the game rule when adding it.
|
||||
/// You almost always want this to be true.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool StartRule = true;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Weapons.Melee.Balloon;
|
||||
namespace Content.Shared.Weapons.Melee.Balloon;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for weapons that pop balloons on attack.
|
||||
|
|
@ -9,7 +9,6 @@ using Content.Shared.CombatMode;
|
|||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Gravity;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Hands.Components;
|
||||
|
|
@ -34,7 +33,6 @@ using Robust.Shared.Containers;
|
|||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
|
|
@ -65,7 +63,6 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
||||
[Dependency] private readonly SharedCombatModeSystem _combatMode = default!;
|
||||
[Dependency] protected readonly SharedContainerSystem Containers = default!;
|
||||
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
||||
[Dependency] protected readonly SharedPointLightSystem Lights = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem PopupSystem = default!;
|
||||
[Dependency] protected readonly SharedPhysicsSystem Physics = default!;
|
||||
|
|
|
|||
|
|
@ -1,27 +1,4 @@
|
|||
Entries:
|
||||
- author: metalgearsloth
|
||||
changes:
|
||||
- message: Tweak mob collision values in line with RMC14.
|
||||
type: Tweak
|
||||
id: 8367
|
||||
time: '2025-04-27T14:47:18.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/36851
|
||||
- author: Fildrance
|
||||
changes:
|
||||
- message: node scanner now dislplays live artifact info (while in range) after
|
||||
linking to artifact
|
||||
type: Tweak
|
||||
id: 8368
|
||||
time: '2025-04-27T15:11:13.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/36635
|
||||
- author: ArtisticRoomba
|
||||
changes:
|
||||
- message: A new Mapping changelog has been added. You can find it in a different
|
||||
"Mapping" tab under the changelog menu.
|
||||
type: Add
|
||||
id: 8369
|
||||
time: '2025-04-27T20:15:17.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/34848
|
||||
- author: ScarKy0
|
||||
changes:
|
||||
- message: Deliveries can now spawn as fragile-type! Deliver them intact to earn
|
||||
|
|
@ -3948,3 +3925,26 @@
|
|||
id: 8879
|
||||
time: '2025-08-22T22:26:48.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/39834
|
||||
- author: _miket, RedBookcase
|
||||
changes:
|
||||
- message: Added new Derelict Cyborg ghost roles, including the Derelict Engineer,
|
||||
Janitor, Salvage, Medical, and Assault Cyborg!
|
||||
type: Add
|
||||
id: 8880
|
||||
time: '2025-08-23T20:32:15.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/38159
|
||||
- author: FungiFellow
|
||||
changes:
|
||||
- message: Added the Inflatable Module for borgs.
|
||||
type: Add
|
||||
id: 8881
|
||||
time: '2025-08-23T22:15:28.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/35100
|
||||
- author: whatston3
|
||||
changes:
|
||||
- message: Lathes now batch items into jobs, which can be moved around in priority
|
||||
or deleted.
|
||||
type: Add
|
||||
id: 8882
|
||||
time: '2025-08-24T15:02:47.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/38624
|
||||
|
|
|
|||
|
|
@ -551,4 +551,11 @@
|
|||
id: 67
|
||||
time: '2025-08-18T18:22:15.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/39091
|
||||
- author: M4rchy-S
|
||||
changes:
|
||||
- message: On Marathon, fixed the reagent grinder in perma not having power.
|
||||
type: Fix
|
||||
id: 68
|
||||
time: '2025-08-23T22:48:39.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/39801
|
||||
Order: 1
|
||||
|
|
|
|||
|
|
@ -251,9 +251,24 @@ ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg
|
|||
ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg
|
||||
ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them.
|
||||
|
||||
ghost-role-information-derelict-cyborg-name = Derelict Cyborg
|
||||
ghost-role-information-derelict-engineering-cyborg-name = Derelict Engineer Cyborg
|
||||
ghost-role-information-derelict-engineering-cyborg-description = You are an engineer cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
|
||||
|
||||
ghost-role-information-derelict-cyborg-name = Derelict Generic Cyborg
|
||||
ghost-role-information-derelict-cyborg-description = You are a regular cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
|
||||
|
||||
ghost-role-information-derelict-janitor-cyborg-name = Derelict Janitor Cyborg
|
||||
ghost-role-information-derelict-janitor-cyborg-description = You are a janitor cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
|
||||
|
||||
ghost-role-information-derelict-medical-cyborg-name = Derelict Medical Cyborg
|
||||
ghost-role-information-derelict-medical-cyborg-description = You are a medical cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
|
||||
|
||||
ghost-role-information-derelict-mining-cyborg-name = Derelict Salvage Cyborg
|
||||
ghost-role-information-derelict-mining-cyborg-description = You are a salvage cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
|
||||
|
||||
ghost-role-information-derelict-syndicate-assault-cyborg-name = Derelict Syndicate Assault Cyborg
|
||||
ghost-role-information-derelict-syndicate-assault-cyborg-description = You are an early model syndicate assault cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
|
||||
|
||||
ghost-role-information-security-name = Security
|
||||
ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation...
|
||||
|
||||
|
|
|
|||
|
|
@ -29,3 +29,9 @@ lathe-menu-silo-linked-message = Silo Linked
|
|||
lathe-menu-fabricating-message = Fabricating...
|
||||
lathe-menu-materials-title = Materials
|
||||
lathe-menu-queue-title = Build Queue
|
||||
lathe-menu-delete-fabricating-tooltip = Cancel printing the current item.
|
||||
lathe-menu-delete-item-tooltip = Cancel printing this batch.
|
||||
lathe-menu-move-up-tooltip = Move this batch ahead in the queue.
|
||||
lathe-menu-move-down-tooltip = Move this batch back in the queue.
|
||||
lathe-menu-item-single = {$index}. {$name}
|
||||
lathe-menu-item-batch = {$index}. {$name} ({$printed}/{$total})
|
||||
|
|
|
|||
|
|
@ -10,3 +10,5 @@ borg-slot-documents-empty = Books and papers
|
|||
borg-slot-soap-empty = Soap
|
||||
borg-slot-instruments-empty = Instruments
|
||||
borg-slot-beakers-empty = Beakers
|
||||
borg-slot-inflatable-door-empty = Inflatable Door
|
||||
borg-slot-inflatable-wall-empty = Inflatable Wall
|
||||
|
|
|
|||
1
Resources/Locale/en-US/engineering/inflatables.ftl
Normal file
|
|
@ -0,0 +1 @@
|
|||
inflatable-safe-disassembly = You expertly use { THE($item) } to open the valve on { THE($target) }, and start deflating { OBJECT($target) } without causing damage.
|
||||
|
|
@ -248,6 +248,18 @@
|
|||
- sprite: Mobs/Aliens/paradox_clone.rsi
|
||||
state: preview
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: SpawnPointGhostDerelictCyborg
|
||||
id: SpawnPointGhostDerelictEngineeringCyborg
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-engineering-cyborg-name
|
||||
description: ghost-role-information-derelict-engineering-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: BaseAntagSpawner
|
||||
|
|
@ -266,6 +278,54 @@
|
|||
- sprite: Mobs/Silicon/chassis.rsi
|
||||
state: derelict_icon
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: SpawnPointGhostDerelictCyborg
|
||||
id: SpawnPointGhostDerelictJanitorCyborg
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-janitor-cyborg-name
|
||||
description: ghost-role-information-derelict-janitor-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: SpawnPointGhostDerelictCyborg
|
||||
id: SpawnPointGhostDerelictMedicalCyborg
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-medical-cyborg-name
|
||||
description: ghost-role-information-derelict-medical-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: SpawnPointGhostDerelictCyborg
|
||||
id: SpawnPointGhostDerelictMiningCyborg
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-mining-cyborg-name
|
||||
description: ghost-role-information-derelict-mining-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: SpawnPointGhostDerelictCyborg
|
||||
id: SpawnPointGhostDerelictSyndicateAssaultCyborg
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-syndicate-assault-cyborg-name
|
||||
description: ghost-role-information-derelict-syndicate-assault-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu, Spawner ]
|
||||
parent: BaseAntagSpawner
|
||||
|
|
|
|||
|
|
@ -413,6 +413,7 @@
|
|||
- Syndicate
|
||||
- type: ActiveRadio
|
||||
channels:
|
||||
- Binary
|
||||
- Syndicate
|
||||
- type: ShowSyndicateIcons
|
||||
- type: MovementAlwaysTouching
|
||||
|
|
@ -460,6 +461,19 @@
|
|||
chance: 1
|
||||
- type: ShowJobIcons
|
||||
|
||||
- type: entity
|
||||
id: BaseBorgChassisSyndicateDerelict #For assault borg and maybe others in time
|
||||
parent: BaseBorgChassisSyndicate
|
||||
abstract: true
|
||||
components:
|
||||
- type: SiliconLawProvider
|
||||
laws: SyndicateStatic #Non-subverted version so they can still be changed
|
||||
- type: StartIonStormed
|
||||
ionStormAmount: 3
|
||||
- type: IonStormTarget
|
||||
chance: 1
|
||||
- type: ShowJobIcons
|
||||
|
||||
- type: entity
|
||||
parent: BaseBorgChassisNotIonStormable
|
||||
id: BaseXenoborgChassis
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@
|
|||
map: ["light"]
|
||||
visible: false
|
||||
- type: BorgChassis
|
||||
maxModules: 5 # the sixth one broke lol
|
||||
maxModules: 5 # One less module slot than the regular module to reflect this being a "broken" cyborg.
|
||||
moduleWhitelist:
|
||||
tags:
|
||||
- BorgModuleGeneric
|
||||
|
|
@ -267,3 +267,164 @@
|
|||
interactFailureString: petting-failure-derelict-cyborg
|
||||
interactSuccessSound:
|
||||
path: /Audio/Ambience/Objects/periodic_beep.ogg
|
||||
|
||||
- type: entity
|
||||
parent: BaseBorgChassisDerelict
|
||||
id: EngineeringBorgChassisDerelict
|
||||
name: derelict engineer cyborg
|
||||
description: A man-machine hybrid that assists the engineering department. This one seems to have chunks of strange crystals pockmarking its surface.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: engineer_derelict
|
||||
- state: engineer_e_r
|
||||
map: ["enum.BorgVisualLayers.Light"]
|
||||
shader: unshaded
|
||||
visible: false
|
||||
- state: engineer_derelict_crystal #This layer and the layer below are duplicated in order to create a more mellow unshaded layer. See https://github.com/space-wizards/space-station-14/pull/37869 for more info on the method.
|
||||
shader: unshaded
|
||||
- state: engineer_derelict_crystal
|
||||
shader: shaded
|
||||
- state: engineer_l
|
||||
shader: unshaded
|
||||
map: ["light"]
|
||||
visible: false
|
||||
- type: BorgChassis
|
||||
maxModules: 5 # One less module slot than the regular module to reflect this being a "broken" cyborg.
|
||||
moduleWhitelist:
|
||||
tags:
|
||||
- BorgModuleGeneric
|
||||
- BorgModuleEngineering
|
||||
hasMindState: engineer_e
|
||||
noMindState: engineer_e_r
|
||||
|
||||
- type: entity
|
||||
parent: BaseBorgChassisDerelict
|
||||
id: JanitorBorgChassisDerelict
|
||||
name: derelict janitor cyborg
|
||||
description: A man-machine hybrid that assists the service department. It's a bigger mess than anything it can clean up.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: janitor_derelict
|
||||
map: ["movement"]
|
||||
- state: janitor_e_r
|
||||
map: ["enum.BorgVisualLayers.Light"]
|
||||
shader: unshaded
|
||||
visible: false
|
||||
- state: janitor_l
|
||||
shader: unshaded
|
||||
map: ["light"]
|
||||
visible: false
|
||||
- type: SpriteMovement
|
||||
movementLayers:
|
||||
movement:
|
||||
state: janitor_moving_derelict
|
||||
noMovementLayers:
|
||||
movement:
|
||||
state: janitor_derelict
|
||||
- type: BorgChassis
|
||||
maxModules: 5 # One less module slot than the regular module to reflect this being a "broken" cyborg.
|
||||
moduleWhitelist:
|
||||
tags:
|
||||
- BorgModuleGeneric
|
||||
- BorgModuleJanitor
|
||||
hasMindState: janitor_e
|
||||
noMindState: janitor_e_r
|
||||
|
||||
- type: entity
|
||||
parent: BaseBorgChassisDerelict
|
||||
id: MedicalBorgChassisDerelict
|
||||
name: derelict medical cyborg
|
||||
description: A man-machine hybrid that assists the medical department. This one's needles don't look very sanitary.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: medical_derelict
|
||||
map: ["movement"]
|
||||
- state: medical_e_r
|
||||
map: ["enum.BorgVisualLayers.Light"]
|
||||
shader: unshaded
|
||||
visible: false
|
||||
- state: medical_l
|
||||
shader: unshaded
|
||||
map: ["light"]
|
||||
visible: false
|
||||
- type: SpriteMovement
|
||||
movementLayers:
|
||||
movement:
|
||||
state: medical_moving_derelict
|
||||
noMovementLayers:
|
||||
movement:
|
||||
state: medical_derelict
|
||||
- type: BorgChassis
|
||||
maxModules: 6 # One less module slot than the regular module to reflect this being a "broken" cyborg.
|
||||
moduleWhitelist:
|
||||
tags:
|
||||
- BorgModuleGeneric
|
||||
- BorgModuleMedical
|
||||
hasMindState: medical_e
|
||||
noMindState: medical_e_r
|
||||
|
||||
- type: entity
|
||||
parent: BaseBorgChassisDerelict
|
||||
id: MiningBorgChassisDerelict
|
||||
name: derelict salvage cyborg
|
||||
description: A man-machine hybrid that assists the cargo department. This one has seen the wrong side of a gibtonite chunk.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: miner_derelict
|
||||
map: ["movement"]
|
||||
- state: miner_e_r
|
||||
map: ["enum.BorgVisualLayers.Light"]
|
||||
shader: unshaded
|
||||
visible: false
|
||||
- state: miner_l
|
||||
shader: unshaded
|
||||
map: ["light"]
|
||||
visible: false
|
||||
- type: SpriteMovement
|
||||
movementLayers:
|
||||
movement:
|
||||
state: miner_moving_derelict
|
||||
noMovementLayers:
|
||||
movement:
|
||||
state: miner_derelict
|
||||
- type: BorgChassis
|
||||
maxModules: 6 # One less module slot than the regular module to reflect this being a "broken" cyborg.
|
||||
moduleWhitelist:
|
||||
tags:
|
||||
- BorgModuleGeneric
|
||||
- BorgModuleCargo
|
||||
hasMindState: miner_e
|
||||
noMindState: miner_e_r
|
||||
|
||||
- type: entity
|
||||
parent: BaseBorgChassisSyndicateDerelict
|
||||
id: SyndicateAssaultBorgChassisDerelict
|
||||
name: derelict syndicate assault cyborg
|
||||
description: A lean, mean killing machine with access to a variety of deadly modules. This one is more rust-orange than blood-red.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: synd_sec_derelict
|
||||
- state: synd_sec_e
|
||||
map: ["enum.BorgVisualLayers.Light"]
|
||||
shader: unshaded
|
||||
visible: false
|
||||
- state: synd_sec_l
|
||||
shader: unshaded
|
||||
map: ["light"]
|
||||
visible: false
|
||||
- type: BorgChassis
|
||||
maxModules: 3
|
||||
moduleWhitelist: # Note - the Derelict Assault Borg does not have a traversal module. This is intentional as Assault Borgs have space traversal with their c20 and free space movement, and they can navigate to the station using the pinpointer.
|
||||
tags:
|
||||
- BorgModuleGeneric
|
||||
- BorgModuleSyndicate
|
||||
- BorgModuleSyndicateAssault
|
||||
hasMindState: synd_sec_derelict_e
|
||||
noMindState: synd_sec_derelict
|
||||
- type: Construction
|
||||
node: derelictcyborg
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@
|
|||
# borg_module:
|
||||
# - BorgModuleOperative
|
||||
# - BorgModuleL6C
|
||||
# - BorgModuleEsword
|
||||
# - BorgModuleDoubleEsword
|
||||
# - type: ItemSlots
|
||||
# slots:
|
||||
# cell_slot:
|
||||
|
|
@ -471,8 +471,44 @@
|
|||
- PlayerBorgSyndicateSaboteurGhostRole
|
||||
|
||||
- type: entity
|
||||
id: PlayerBorgDerelict
|
||||
parent: EngineeringBorgChassisDerelict
|
||||
id: PlayerEngineeringBorgDerelict
|
||||
suffix: Battery, Module
|
||||
components:
|
||||
- type: ContainerFill
|
||||
containers:
|
||||
borg_brain:
|
||||
- PositronicBrain
|
||||
borg_module:
|
||||
- BorgModuleTool
|
||||
- BorgModuleFireExtinguisher
|
||||
- BorgModuleConstruction
|
||||
- BorgModuleRCD
|
||||
- BorgModuleCable
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cell_slot:
|
||||
name: power-cell-slot-component-slot-name-default
|
||||
startingItem: PowerCellHigh
|
||||
- type: RandomMetadata
|
||||
nameSegments: [NamesBorg]
|
||||
|
||||
- type: entity
|
||||
parent: PlayerEngineeringBorgDerelict
|
||||
id: PlayerEngineeringBorgDerelictGhostRole
|
||||
suffix: Ghost role
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-engineering-cyborg-name
|
||||
description: ghost-role-information-derelict-engineering-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
|
||||
- type: entity
|
||||
parent: BorgChassisDerelict
|
||||
id: PlayerBorgDerelict
|
||||
suffix: Battery, Module
|
||||
components:
|
||||
- type: ContainerFill
|
||||
|
|
@ -491,8 +527,8 @@
|
|||
nameSegments: [NamesBorg]
|
||||
|
||||
- type: entity
|
||||
id: PlayerBorgDerelictGhostRole
|
||||
parent: PlayerBorgDerelict
|
||||
id: PlayerBorgDerelictGhostRole
|
||||
suffix: Ghost role
|
||||
components:
|
||||
- type: GhostRole
|
||||
|
|
@ -502,3 +538,143 @@
|
|||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
|
||||
- type: entity
|
||||
parent: JanitorBorgChassisDerelict
|
||||
id: PlayerJanitorBorgDerelict
|
||||
suffix: Battery, Module
|
||||
components:
|
||||
- type: ContainerFill
|
||||
containers:
|
||||
borg_brain:
|
||||
- PositronicBrain
|
||||
borg_module:
|
||||
- BorgModuleTool
|
||||
- BorgModuleFireExtinguisher
|
||||
- BorgModuleCleaning
|
||||
- BorgModuleCustodial
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cell_slot:
|
||||
name: power-cell-slot-component-slot-name-default
|
||||
startingItem: PowerCellHigh
|
||||
- type: RandomMetadata
|
||||
nameSegments: [NamesBorg]
|
||||
|
||||
- type: entity
|
||||
parent: PlayerJanitorBorgDerelict
|
||||
id: PlayerJanitorBorgDerelictGhostRole
|
||||
suffix: Ghost role
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-janitor-cyborg-name
|
||||
description: ghost-role-information-derelict-janitor-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
|
||||
- type: entity
|
||||
parent: MedicalBorgChassisDerelict
|
||||
id: PlayerMedicalBorgDerelict
|
||||
suffix: Battery, Module
|
||||
components:
|
||||
- type: ContainerFill
|
||||
containers:
|
||||
borg_brain:
|
||||
- PositronicBrain
|
||||
borg_module:
|
||||
- BorgModuleTool
|
||||
- BorgModuleFireExtinguisher
|
||||
- BorgModuleChemical
|
||||
- BorgModuleTopicals
|
||||
- BorgModuleRescue
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cell_slot:
|
||||
name: power-cell-slot-component-slot-name-default
|
||||
startingItem: PowerCellHigh
|
||||
- type: RandomMetadata
|
||||
nameSegments: [NamesBorg]
|
||||
|
||||
- type: entity
|
||||
parent: PlayerMedicalBorgDerelict
|
||||
id: PlayerMedicalBorgDerelictGhostRole
|
||||
suffix: Ghost role
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-medical-cyborg-name
|
||||
description: ghost-role-information-derelict-medical-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
|
||||
- type: entity
|
||||
parent: MiningBorgChassisDerelict
|
||||
id: PlayerMiningBorgDerelict
|
||||
suffix: Battery, Module
|
||||
components:
|
||||
- type: ContainerFill
|
||||
containers:
|
||||
borg_brain:
|
||||
- PositronicBrain
|
||||
borg_module:
|
||||
- BorgModuleTool #No fire extinguisher, traversal is better
|
||||
- BorgModuleMining
|
||||
- BorgModuleTraversal
|
||||
- BorgModuleAppraisal
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cell_slot:
|
||||
name: power-cell-slot-component-slot-name-default
|
||||
startingItem: PowerCellHigh
|
||||
- type: RandomMetadata
|
||||
nameSegments: [NamesBorg]
|
||||
|
||||
- type: entity
|
||||
parent: PlayerMiningBorgDerelict
|
||||
id: PlayerMiningBorgDerelictGhostRole
|
||||
suffix: Ghost role
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-mining-cyborg-name
|
||||
description: ghost-role-information-derelict-mining-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
|
||||
- type: entity
|
||||
parent: SyndicateAssaultBorgChassisDerelict
|
||||
id: PlayerSyndicateAssaultBorgDerelict
|
||||
suffix: Battery, Module
|
||||
components:
|
||||
- type: ContainerFill
|
||||
containers:
|
||||
borg_brain:
|
||||
- PositronicBrain
|
||||
borg_module:
|
||||
- BorgModuleOperative
|
||||
- BorgModuleC20r
|
||||
- BorgModuleEsword
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cell_slot:
|
||||
name: power-cell-slot-component-slot-name-default
|
||||
startingItem: PowerCellHyper
|
||||
- type: RandomMetadata
|
||||
nameSegments: [NamesDeathCommando]
|
||||
|
||||
- type: entity
|
||||
parent: PlayerSyndicateAssaultBorgDerelict
|
||||
id: PlayerBorgSyndicateDerelictGhostRole
|
||||
suffix: Ghost role
|
||||
components:
|
||||
- type: GhostRole
|
||||
name: ghost-role-information-derelict-syndicate-assault-cyborg-name
|
||||
description: ghost-role-information-derelict-syndicate-assault-cyborg-description
|
||||
rules: ghost-role-information-silicon-rules
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
- type: DisassembleOnAltVerb
|
||||
prototypeToSpawn: InflatableWallStack1
|
||||
disassembleTime: 3
|
||||
- type: InflatableSafeDisassembly
|
||||
- type: Airtight
|
||||
- type: Transform
|
||||
anchored: true
|
||||
|
|
@ -81,5 +82,6 @@
|
|||
- type: DisassembleOnAltVerb
|
||||
prototypeToSpawn: InflatableDoorStack1
|
||||
disassembleTime: 3
|
||||
- type: InflatableSafeDisassembly
|
||||
- type: Occluder
|
||||
enabled: false
|
||||
|
|
|
|||
|
|
@ -489,6 +489,36 @@
|
|||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: tool-module }
|
||||
|
||||
- type: entity
|
||||
id: BorgModuleInflatable
|
||||
parent: [ BaseBorgModule, BaseProviderBorgModule ]
|
||||
name: inflatable cyborg module
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: generic
|
||||
- state: icon-inflatable
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: InflatableDoorStack
|
||||
hand:
|
||||
emptyRepresentative: InflatableDoorStack
|
||||
emptyLabel: borg-slot-inflatable-door-empty
|
||||
whitelist:
|
||||
tags:
|
||||
- Inflatable
|
||||
- item: InflatableWallStack
|
||||
hand:
|
||||
emptyRepresentative: InflatableWallStack
|
||||
emptyLabel: borg-slot-inflatable-wall-empty
|
||||
whitelist:
|
||||
tags:
|
||||
- Inflatable
|
||||
- item: BoxInflatable
|
||||
- item: WeaponMeleeNeedle
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: inflatable-module }
|
||||
|
||||
# cargo modules
|
||||
- type: entity
|
||||
id: BorgModuleAppraisal
|
||||
|
|
@ -1135,8 +1165,8 @@
|
|||
|
||||
#syndicate modules
|
||||
- type: entity
|
||||
id: BorgModuleSyndicateWeapon
|
||||
parent: [ BaseBorgModule, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
id: BorgModuleSyndicateWeapon
|
||||
name: weapon cyborg module
|
||||
components:
|
||||
- type: Sprite
|
||||
|
|
@ -1171,8 +1201,8 @@
|
|||
price: 2500
|
||||
|
||||
- type: entity
|
||||
id: BorgModuleOperative
|
||||
parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
id: BorgModuleOperative
|
||||
name: operative cyborg module
|
||||
description: A module that comes with a crowbar, an Access Breaker and a syndicate pinpointer.
|
||||
components:
|
||||
|
|
@ -1190,42 +1220,76 @@
|
|||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-operative-module }
|
||||
|
||||
- type: entity
|
||||
id: BorgModuleEsword
|
||||
parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
id: BorgModuleEsword
|
||||
name: energy sword cyborg module
|
||||
description: A module that comes with a double energy sword.
|
||||
description: A weapons module that comes with an energy sword.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: syndicate
|
||||
- state: icon-syndicate
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: CyborgEnergySwordDouble
|
||||
- item: PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-esword-module }
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: syndicate
|
||||
- state: icon-syndicate
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: CyborgEnergySword
|
||||
- item: PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-esword-module }
|
||||
|
||||
- type: entity
|
||||
id: BorgModuleDoubleEsword
|
||||
parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
name: double energy sword cyborg module
|
||||
description: A weapons module that comes with a double energy sword.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: syndicate
|
||||
- state: icon-syndicate
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: CyborgEnergySwordDouble
|
||||
- item: PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-desword-module }
|
||||
|
||||
- type: entity
|
||||
id: BorgModuleL6C
|
||||
parent: [ BaseBorgModuleSyndicateAssault, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
id: BorgModuleL6C
|
||||
name: L6C ROW cyborg module
|
||||
description: A module that comes with a L6C.
|
||||
description: A weapons module that comes with a L6C.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: syndicate
|
||||
- state: icon-syndicate
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: WeaponLightMachineGunL6C
|
||||
- item: PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-l6c-module }
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: syndicate
|
||||
- state: icon-syndicate
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: WeaponLightMachineGunL6C
|
||||
- item: PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-l6c-module }
|
||||
|
||||
- type: entity
|
||||
parent: [ BaseBorgModuleSyndicateAssault, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
id: BorgModuleC20r
|
||||
name: C20-r ROW cyborg module
|
||||
description: A weapons module that comes with a burst-fire C-20r.
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: syndicate
|
||||
- state: icon-syndicate
|
||||
- type: ItemBorgModule
|
||||
hands:
|
||||
- item: WeaponSubMachineGunC20rROW
|
||||
- item: PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-c20r-module }
|
||||
|
||||
- type: entity
|
||||
id: BorgModuleMartyr
|
||||
parent: [ BaseBorgModule, BaseProviderBorgModule, BaseSyndicateContraband ]
|
||||
id: BorgModuleMartyr
|
||||
name: martyr cyborg module
|
||||
description: "A module that comes with an explosive you probably don't want to handle yourself."
|
||||
components:
|
||||
|
|
|
|||
|
|
@ -5,21 +5,24 @@
|
|||
description: A folded membrane which rapidly expands into a large cubical shape on activation.
|
||||
suffix: Full
|
||||
components:
|
||||
- type: Stack
|
||||
stackType: InflatableWall
|
||||
count: 10
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/inflatable_wall.rsi
|
||||
state: item_wall
|
||||
- type: Item
|
||||
sprite: Objects/Misc/inflatable_wall.rsi
|
||||
size: Small
|
||||
- type: SpawnAfterInteract
|
||||
prototype: InflatableWall
|
||||
doAfter: 1
|
||||
removeOnInteract: true
|
||||
- type: Clickable
|
||||
- type: PhysicalComposition
|
||||
- type: Stack
|
||||
stackType: InflatableWall
|
||||
count: 10
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/inflatable_wall.rsi
|
||||
state: item_wall
|
||||
- type: Item
|
||||
sprite: Objects/Misc/inflatable_wall.rsi
|
||||
size: Small
|
||||
- type: SpawnAfterInteract
|
||||
prototype: InflatableWall
|
||||
doAfter: 1
|
||||
removeOnInteract: true
|
||||
- type: Clickable
|
||||
- type: PhysicalComposition
|
||||
- type: Tag
|
||||
tags:
|
||||
- Inflatable
|
||||
# TODO: Add stack sprites + visuals.
|
||||
|
||||
- type: entity
|
||||
|
|
@ -29,21 +32,24 @@
|
|||
description: A folded membrane which rapidly expands into a large cubical shape on activation.
|
||||
suffix: Full
|
||||
components:
|
||||
- type: Stack
|
||||
stackType: InflatableDoor
|
||||
count: 4
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/inflatable_door.rsi
|
||||
state: item_door
|
||||
- type: Item
|
||||
sprite: Objects/Misc/inflatable_door.rsi
|
||||
size: Small
|
||||
- type: SpawnAfterInteract
|
||||
prototype: InflatableDoor
|
||||
doAfter: 1
|
||||
removeOnInteract: true
|
||||
- type: Clickable
|
||||
- type: PhysicalComposition
|
||||
- type: Stack
|
||||
stackType: InflatableDoor
|
||||
count: 4
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/inflatable_door.rsi
|
||||
state: item_door
|
||||
- type: Item
|
||||
sprite: Objects/Misc/inflatable_door.rsi
|
||||
size: Small
|
||||
- type: SpawnAfterInteract
|
||||
prototype: InflatableDoor
|
||||
doAfter: 1
|
||||
removeOnInteract: true
|
||||
- type: Clickable
|
||||
- type: PhysicalComposition
|
||||
- type: Tag
|
||||
tags:
|
||||
- Inflatable
|
||||
# TODO: Add stack sprites + visuals.
|
||||
|
||||
- type: entity
|
||||
|
|
@ -51,27 +57,27 @@
|
|||
id: InflatableWallStack5
|
||||
suffix: 5
|
||||
components:
|
||||
- type: Sprite
|
||||
state: item_wall
|
||||
- type: Stack
|
||||
count: 5
|
||||
- type: Sprite
|
||||
state: item_wall
|
||||
- type: Stack
|
||||
count: 5
|
||||
|
||||
- type: entity
|
||||
parent: InflatableWallStack
|
||||
id: InflatableWallStack1
|
||||
suffix: 1
|
||||
components:
|
||||
- type: Sprite
|
||||
state: item_wall
|
||||
- type: Stack
|
||||
count: 1
|
||||
- type: Sprite
|
||||
state: item_wall
|
||||
- type: Stack
|
||||
count: 1
|
||||
|
||||
- type: entity
|
||||
parent: InflatableDoorStack
|
||||
id: InflatableDoorStack1
|
||||
suffix: 1
|
||||
components:
|
||||
- type: Sprite
|
||||
state: item_door
|
||||
- type: Stack
|
||||
count: 1
|
||||
- type: Sprite
|
||||
state: item_door
|
||||
- type: Stack
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -143,6 +143,47 @@
|
|||
- type: StaticPrice
|
||||
price: 5000
|
||||
|
||||
- type: entity
|
||||
name: C-20r ROW #I think ROW stands for Recharging Onboard Weapon so i'm following the L6C's example
|
||||
id: WeaponSubMachineGunC20rROW
|
||||
parent: BaseItem
|
||||
description: A burst-fire C-20r submachine gun for use by cyborgs. Creates .35 caliber ammo on the fly from an internal ammo fabricator, which slowly self-charges.
|
||||
components:
|
||||
- type: Gun
|
||||
minAngle: 2
|
||||
maxAngle: 16
|
||||
angleIncrease: 4
|
||||
angleDecay: 16
|
||||
fireRate: 8
|
||||
burstFireRate: 8
|
||||
selectedMode: Burst
|
||||
availableModes:
|
||||
- Burst
|
||||
soundGunshot:
|
||||
path: /Audio/Weapons/Guns/Gunshots/c-20r.ogg
|
||||
- type: Sprite
|
||||
sprite: Objects/Weapons/Guns/SMGs/c20r.rsi
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-5
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: Item
|
||||
size: Huge
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
ballistic-ammo: !type:Container
|
||||
- type: ProjectileBatteryAmmoProvider
|
||||
proto: CartridgePistol
|
||||
fireCost: 100
|
||||
- type: Battery
|
||||
maxCharge: 3000
|
||||
startingCharge: 3000
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 25
|
||||
- type: AmmoCounter
|
||||
|
||||
- type: entity
|
||||
name: Drozd
|
||||
parent: [BaseWeaponSubMachineGun, BaseSecurityContraband]
|
||||
|
|
|
|||
|
|
@ -444,10 +444,17 @@
|
|||
spread: 75
|
||||
|
||||
# Borgs
|
||||
|
||||
- type: entity
|
||||
parent: EnergySword
|
||||
id: CyborgEnergySword
|
||||
suffix: For Borgs
|
||||
description: A very loud & dangerous sword with a beam made of pure, concentrated plasma. Specially designed for syndicate cyborgs.
|
||||
|
||||
- type: entity
|
||||
suffix: One-Handed, For Borgs
|
||||
parent: EnergySwordDouble
|
||||
id: CyborgEnergySwordDouble # why is this invalid if ID is BorgEnergySwordDouble
|
||||
suffix: One-Handed, For Borgs
|
||||
description: Syndicate Command Interns thought that having one blade on the energy sword was not enough. Specially designed for syndicate cyborgs.
|
||||
components: # could add energy-draining like the L6C
|
||||
- type: Wieldable
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
- id: ClosetSkeleton
|
||||
- id: KingRatMigration
|
||||
- id: RevenantSpawn
|
||||
- id: DerelictCyborgSpawn
|
||||
- !type:NestedSelector
|
||||
tableId: DerelictBorgEventTable
|
||||
|
||||
- type: entityTable
|
||||
id: ModerateAntagEventsTable
|
||||
|
|
@ -48,6 +49,25 @@
|
|||
- id: LoneOpsSpawn
|
||||
- id: WizardSpawn
|
||||
- id: AbductorsSpawn # Sunrise-Edit
|
||||
- !type:NestedSelector
|
||||
tableId: DerelictBorgEventTable
|
||||
|
||||
- type: entityTable
|
||||
id: DerelictBorgEventTable #For Derelict Borg spawns
|
||||
table: !type:GroupSelector
|
||||
children:
|
||||
- !type:GroupSelector # Standard NT Borgs
|
||||
weight: 85
|
||||
children:
|
||||
- id: DerelictEngineerCyborgSpawn
|
||||
- id: DerelictGenericCyborgSpawn
|
||||
- id: DerelictJanitorCyborgSpawn
|
||||
- id: DerelictMedicalCyborgSpawn
|
||||
- id: DerelictMiningCyborgSpawn
|
||||
- !type:GroupSelector # Other Borgs
|
||||
weight: 15
|
||||
children:
|
||||
- id: DerelictSyndicateAssaultCyborgSpawn
|
||||
|
||||
- type: entity
|
||||
id: BaseStationEvent
|
||||
|
|
@ -556,7 +576,7 @@
|
|||
earliestStart: 35
|
||||
weight: 5.5
|
||||
minimumPlayers: 20
|
||||
duration: null # LoneOpsSpawn needs an infinite duration so that it inherits the NukeOpsRule things of an actually appropriate end scrreen (not always "Neutral outcome!") and... ending the game if the station is nuked.
|
||||
duration: null # LoneOpsSpawn needs an infinite duration so that it inherits the NukeOpsRule things of an actually appropriate end screen (not always "Neutral outcome!") and... ending the game if the station is nuked.
|
||||
- type: RuleGrids
|
||||
- type: LoadMapRule
|
||||
gridPath: /Maps/Shuttles/ShuttleEvent/striker.yml
|
||||
|
|
@ -697,10 +717,10 @@
|
|||
|
||||
- type: entity
|
||||
parent: BaseGameRule
|
||||
id: DerelictCyborgSpawn
|
||||
id: DerelictEngineerCyborgSpawn
|
||||
components:
|
||||
- type: StationEvent
|
||||
weight: 5
|
||||
weight: 2.5
|
||||
earliestStart: 15
|
||||
reoccurrenceDelay: 20
|
||||
minimumPlayers: 4
|
||||
|
|
@ -708,10 +728,115 @@
|
|||
- type: SpaceSpawnRule
|
||||
spawnDistance: 0
|
||||
- type: AntagSpawner
|
||||
prototype: PlayerBorgDerelict
|
||||
prototype: PlayerEngineeringBorgDerelictGhostRole
|
||||
- type: AntagSelection
|
||||
definitions:
|
||||
- spawnerPrototype: SpawnPointGhostDerelictEngineeringCyborg
|
||||
min: 1
|
||||
max: 1
|
||||
pickPlayer: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseGameRule
|
||||
id: DerelictGenericCyborgSpawn
|
||||
components:
|
||||
- type: StationEvent
|
||||
weight: 2.5
|
||||
earliestStart: 15
|
||||
reoccurrenceDelay: 20
|
||||
minimumPlayers: 4
|
||||
duration: null
|
||||
- type: SpaceSpawnRule
|
||||
spawnDistance: 0
|
||||
- type: AntagSpawner
|
||||
prototype: PlayerBorgDerelictGhostRole
|
||||
- type: AntagSelection
|
||||
definitions:
|
||||
- spawnerPrototype: SpawnPointGhostDerelictCyborg
|
||||
min: 1
|
||||
max: 1
|
||||
pickPlayer: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseGameRule
|
||||
id: DerelictJanitorCyborgSpawn
|
||||
components:
|
||||
- type: StationEvent
|
||||
weight: 2.5
|
||||
earliestStart: 15
|
||||
reoccurrenceDelay: 20
|
||||
minimumPlayers: 4
|
||||
duration: null
|
||||
- type: SpaceSpawnRule
|
||||
spawnDistance: 0
|
||||
- type: AntagSpawner
|
||||
prototype: PlayerJanitorBorgDerelictGhostRole
|
||||
- type: AntagSelection
|
||||
definitions:
|
||||
- spawnerPrototype: SpawnPointGhostDerelictJanitorCyborg
|
||||
min: 1
|
||||
max: 1
|
||||
pickPlayer: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseGameRule
|
||||
id: DerelictMedicalCyborgSpawn
|
||||
components:
|
||||
- type: StationEvent
|
||||
weight: 2.5
|
||||
earliestStart: 15
|
||||
reoccurrenceDelay: 20
|
||||
minimumPlayers: 4
|
||||
duration: null
|
||||
- type: SpaceSpawnRule
|
||||
spawnDistance: 0
|
||||
- type: AntagSpawner
|
||||
prototype: PlayerMedicalBorgDerelictGhostRole
|
||||
- type: AntagSelection
|
||||
definitions:
|
||||
- spawnerPrototype: SpawnPointGhostDerelictMedicalCyborg
|
||||
min: 1
|
||||
max: 1
|
||||
pickPlayer: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseGameRule
|
||||
id: DerelictMiningCyborgSpawn
|
||||
components:
|
||||
- type: StationEvent
|
||||
weight: 2.5
|
||||
earliestStart: 15
|
||||
reoccurrenceDelay: 20
|
||||
minimumPlayers: 4
|
||||
duration: null
|
||||
- type: SpaceSpawnRule
|
||||
spawnDistance: 0
|
||||
- type: AntagSpawner
|
||||
prototype: PlayerMiningBorgDerelictGhostRole
|
||||
- type: AntagSelection
|
||||
definitions:
|
||||
- spawnerPrototype: SpawnPointGhostDerelictMiningCyborg
|
||||
min: 1
|
||||
max: 1
|
||||
pickPlayer: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseGameRule
|
||||
id: DerelictSyndicateAssaultCyborgSpawn
|
||||
components:
|
||||
- type: StationEvent
|
||||
weight: 2.5
|
||||
earliestStart: 25
|
||||
reoccurrenceDelay: 20
|
||||
minimumPlayers: 15
|
||||
duration: null
|
||||
- type: SpaceSpawnRule
|
||||
spawnDistance: 0
|
||||
- type: AntagSpawner
|
||||
prototype: PlayerBorgSyndicateDerelictGhostRole
|
||||
- type: AntagSelection
|
||||
definitions:
|
||||
- spawnerPrototype: SpawnPointGhostDerelictSyndicateAssaultCyborg
|
||||
min: 1
|
||||
max: 1
|
||||
pickPlayer: false
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
- BorgModuleTool
|
||||
- BorgModuleCable
|
||||
- BorgModuleFireExtinguisher
|
||||
- BorgModuleInflatable
|
||||
|
||||
- type: latheRecipePack
|
||||
id: BorgLimbsStatic
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@
|
|||
id: BorgModuleFireExtinguisher
|
||||
result: BorgModuleFireExtinguisher
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseBorgModuleRecipe
|
||||
id: BorgModuleInflatable
|
||||
result: BorgModuleInflatable
|
||||
|
||||
# Cargo Modules
|
||||
|
||||
- type: latheRecipe
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
defaultModules:
|
||||
- BorgModuleTool
|
||||
- BorgModuleInflatable
|
||||
- BorgModuleArtifact
|
||||
- BorgModuleAnomaly
|
||||
|
||||
|
|
|
|||
|
|
@ -804,6 +804,9 @@
|
|||
- type: Tag
|
||||
id: Ingot
|
||||
|
||||
- type: Tag
|
||||
id: Inflatable
|
||||
|
||||
- type: Tag
|
||||
id: InstantDoAfters
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 5.4 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA",
|
||||
"copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, inflatable module by FungiFellow (GitHub), Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA. c20r and esword by RedBookcase on Github.",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
|
|
@ -31,6 +31,9 @@
|
|||
{
|
||||
"name":"geiger-module"
|
||||
},
|
||||
{
|
||||
"name":"inflatable-module"
|
||||
},
|
||||
{
|
||||
"name":"rcd-module"
|
||||
},
|
||||
|
|
@ -109,12 +112,18 @@
|
|||
{
|
||||
"name":"syndicate-operative-module"
|
||||
},
|
||||
{
|
||||
"name":"syndicate-desword-module"
|
||||
},
|
||||
{
|
||||
"name":"syndicate-esword-module"
|
||||
},
|
||||
{
|
||||
"name":"syndicate-l6c-module"
|
||||
},
|
||||
{
|
||||
"name":"syndicate-c20r-module"
|
||||
},
|
||||
{
|
||||
"name":"syndicate-martyr-module"
|
||||
},
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 675 B |
|
After Width: | Height: | Size: 782 B |
|
Before Width: | Height: | Size: 782 B After Width: | Height: | Size: 560 B |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_derelict.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
BIN
Resources/Textures/Mobs/Silicon/chassis.rsi/medical_derelict.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
BIN
Resources/Textures/Mobs/Silicon/chassis.rsi/miner_derelict.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 824 B |
|
After Width: | Height: | Size: 924 B |
|
|
@ -1,9 +1,7 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from cev-eris at https://github.com/discordia-space/CEV-Eris/commit/740ff31a81313086cf16761f3677cf1e2ab46c93 and Taken from tgstation at https://github.com/tgstation/tgstation/blob/623290915c2292b56da11048deb62d758e1e3fb4/icons/obj/bloodpack.dmi, Blood pack redone by Ubaser",
|
||||
"copyright": "Taken from https://github.com/tgstation/tgstation/blob/a3568da5634e756d0849480104afda402c6f1c3c/icons/obj/medical/stack_medical.dmi",
|
||||
"copyright": "Tourniquet Sprite by PoorMansDreams, in-hand sprites of tourniquet, gauze, and bloodpack made by SeamLesss (github)",
|
||||
"copyright": "Taken from cev-eris at https://github.com/discordia-space/CEV-Eris/commit/740ff31a81313086cf16761f3677cf1e2ab46c93 and Taken from tgstation at https://github.com/tgstation/tgstation/blob/623290915c2292b56da11048deb62d758e1e3fb4/icons/obj/bloodpack.dmi, Blood pack redone by Ubaser. Taken from https://github.com/tgstation/tgstation/blob/a3568da5634e756d0849480104afda402c6f1c3c/icons/obj/medical/stack_medical.dmi. Tourniquet Sprite by PoorMansDreams, in-hand sprites of tourniquet, gauze, and bloodpack made by SeamLesss (github).",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 4.5 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC0-1.0",
|
||||
"copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). layered inhands by mubururu_ (github), icon-chem.png & icon-mining-adv.png created by mubururu_ (github), Xenoborg modules sprites by Samuka-C (github)",
|
||||
"copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). icon-chem.png & icon-mining-adv.png created by mubururu_ (github) icon-inflatable.png made by FungiFellow (GitHub), Xenoborg modules sprites by Samuka-C (github)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
|
|
@ -28,6 +28,9 @@
|
|||
{
|
||||
"name": "icon-cables"
|
||||
},
|
||||
{
|
||||
"name": "icon-inflatable"
|
||||
},
|
||||
{
|
||||
"name": "icon-chemist"
|
||||
},
|
||||
|
|
@ -244,4 +247,5 @@
|
|||
"name": "NT"
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
|
|
|
|||