Merge branch 'master' into offmed-staging
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
using Content.Shared.PAI;
|
|
||||||
|
|
||||||
namespace Content.Client.PAI
|
|
||||||
{
|
|
||||||
public sealed class PAISystem : SharedPAISystem
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Shared.Body.Systems;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared;
|
using Robust.Shared;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Helpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component that is used by <see cref="TestListenerSystem{TEvent}"/> to store any information about received events.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class TestListenerComponent : Component
|
||||||
|
{
|
||||||
|
public Dictionary<Type, List<object>> Events = new();
|
||||||
|
}
|
||||||
45
Content.IntegrationTests/Tests/Helpers/TestListenerSystem.cs
Normal file
45
Content.IntegrationTests/Tests/Helpers/TestListenerSystem.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Helpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generic system that listens for and records any received events of a given type.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class TestListenerSystem<TEvent> : EntitySystem where TEvent : notnull
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// supporting broadcast events requires cleanup on test finish, which will probably require changes to the
|
||||||
|
// test pair/pool manager and would conflict with #36797
|
||||||
|
SubscribeLocalEvent<TestListenerComponent, TEvent>(OnDirectedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDirectedEvent(Entity<TestListenerComponent> ent, ref TEvent args)
|
||||||
|
{
|
||||||
|
ent.Comp.Events.GetOrNew(args.GetType()).Add(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count(EntityUid uid, Func<TEvent, bool>? predicate = null)
|
||||||
|
{
|
||||||
|
return GetEvents(uid, predicate).Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(EntityUid uid)
|
||||||
|
{
|
||||||
|
CompOrNull<TestListenerComponent>(uid)?.Events.Remove(typeof(TEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TEvent> GetEvents(EntityUid uid, Func<TEvent, bool>? predicate = null)
|
||||||
|
{
|
||||||
|
var events = CompOrNull<TestListenerComponent>(uid)?.Events.GetValueOrDefault(typeof(TEvent));
|
||||||
|
if (events == null)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
return events.Cast<TEvent>().Where(e => predicate?.Invoke(e) ?? true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Content.Client.Construction;
|
using Content.Client.Construction;
|
||||||
|
using Content.IntegrationTests.Tests.Helpers;
|
||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Construction.Components;
|
using Content.Server.Construction.Components;
|
||||||
using Content.Server.Gravity;
|
using Content.Server.Gravity;
|
||||||
@@ -22,6 +23,8 @@ using Robust.Shared.Input;
|
|||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Reflection;
|
||||||
|
using Robust.UnitTesting;
|
||||||
using ItemToggleComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleComponent;
|
using ItemToggleComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleComponent;
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.Interaction;
|
namespace Content.IntegrationTests.Tests.Interaction;
|
||||||
@@ -29,6 +32,8 @@ namespace Content.IntegrationTests.Tests.Interaction;
|
|||||||
// This partial class defines various methods that are useful for performing & validating interactions
|
// This partial class defines various methods that are useful for performing & validating interactions
|
||||||
public abstract partial class InteractionTest
|
public abstract partial class InteractionTest
|
||||||
{
|
{
|
||||||
|
private Dictionary<Type, EntitySystem> _listenerCache = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Begin constructing an entity.
|
/// Begin constructing an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -758,6 +763,139 @@ public abstract partial class InteractionTest
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region EventListener
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asserts that running the given action causes an event to be fired directed at the specified entity (defaults to <see cref="Target"/>).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This currently only checks server-side events.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uid">The entity at which the events are supposed to be directed</param>
|
||||||
|
/// <param name="count">How many new events are expected</param>
|
||||||
|
/// <param name="clear">Whether to clear all previously recorded events before invoking the delegate</param>
|
||||||
|
protected async Task AssertFiresEvent<TEvent>(Func<Task> act, EntityUid? uid = null, int count = 1, bool clear = true)
|
||||||
|
where TEvent : notnull
|
||||||
|
{
|
||||||
|
var sys = GetListenerSystem<TEvent>();
|
||||||
|
|
||||||
|
uid ??= STarget;
|
||||||
|
if (uid == null)
|
||||||
|
{
|
||||||
|
Assert.Fail("No target specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear)
|
||||||
|
sys.Clear(uid.Value);
|
||||||
|
else
|
||||||
|
count += sys.Count(uid.Value);
|
||||||
|
|
||||||
|
await Server.WaitPost(() => SEntMan.EnsureComponent<TestListenerComponent>(uid.Value));
|
||||||
|
await act();
|
||||||
|
AssertEvent<TEvent>(uid, count: count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a variant of <see cref="AssertFiresEvent{TEvent}"/> that passes the delegate to <see cref="RobustIntegrationTest.ServerIntegrationInstance.WaitPost"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This currently only checks for server-side events.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uid">The entity at which the events are supposed to be directed</param>
|
||||||
|
/// <param name="count">How many new events are expected</param>
|
||||||
|
/// <param name="clear">Whether to clear all previously recorded events before invoking the delegate</param>
|
||||||
|
protected async Task AssertPostFiresEvent<TEvent>(Action act, EntityUid? uid = null, int count = 1, bool clear = true)
|
||||||
|
where TEvent : notnull
|
||||||
|
{
|
||||||
|
await AssertFiresEvent<TEvent>(async () => await Server.WaitPost(act), uid, count, clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a variant of <see cref="AssertFiresEvent{TEvent}"/> that passes the delegate to <see cref="RobustIntegrationTest.ServerIntegrationInstance.WaitAssertion"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This currently only checks for server-side events.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uid">The entity at which the events are supposed to be directed</param>
|
||||||
|
/// <param name="count">How many new events are expected</param>
|
||||||
|
/// <param name="clear">Whether to clear all previously recorded events before invoking the delegate</param>
|
||||||
|
protected async Task AssertAssertionFiresEvent<TEvent>(Action act,
|
||||||
|
EntityUid? uid = null,
|
||||||
|
int count = 1,
|
||||||
|
bool clear = true)
|
||||||
|
where TEvent : notnull
|
||||||
|
{
|
||||||
|
await AssertFiresEvent<TEvent>(async () => await Server.WaitAssertion(act), uid, count, clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asserts that the specified event has been fired some number of times at the given entity (defaults to <see cref="Target"/>).
|
||||||
|
/// For this to work, this requires that the entity has been given a <see cref="TestListenerComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This currently only checks server-side events.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uid">The entity at which the events were directed</param>
|
||||||
|
/// <param name="count">How many new events are expected</param>
|
||||||
|
/// <param name="predicate">A predicate that can be used to filter the recorded events</param>
|
||||||
|
protected void AssertEvent<TEvent>(EntityUid? uid = null, int count = 1, Func<TEvent,bool>? predicate = null)
|
||||||
|
where TEvent : notnull
|
||||||
|
{
|
||||||
|
Assert.That(GetEvents(uid, predicate).Count, Is.EqualTo(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all the events of the specified type that have been fired at the given entity (defaults to <see cref="Target"/>).
|
||||||
|
/// For this to work, this requires that the entity has been given a <see cref="TestListenerComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This currently only gets for server-side events.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uid">The entity at which the events were directed</param>
|
||||||
|
/// <param name="predicate">A predicate that can be used to filter the returned events</param>
|
||||||
|
protected IEnumerable<TEvent> GetEvents<TEvent>(EntityUid? uid = null, Func<TEvent, bool>? predicate = null)
|
||||||
|
where TEvent : notnull
|
||||||
|
{
|
||||||
|
uid ??= STarget;
|
||||||
|
if (uid == null)
|
||||||
|
{
|
||||||
|
Assert.Fail("No target specified");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.That(SEntMan.HasComponent<TestListenerComponent>(uid), $"Entity must have {nameof(TestListenerComponent)}");
|
||||||
|
return GetListenerSystem<TEvent>().GetEvents(uid.Value, predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TestListenerSystem<TEvent> GetListenerSystem<TEvent>()
|
||||||
|
where TEvent : notnull
|
||||||
|
{
|
||||||
|
if (_listenerCache.TryGetValue(typeof(TEvent), out var listener))
|
||||||
|
return (TestListenerSystem<TEvent>) listener;
|
||||||
|
|
||||||
|
var type = Server.Resolve<IReflectionManager>().GetAllChildren<TestListenerSystem<TEvent>>().Single();
|
||||||
|
if (!SEntMan.EntitySysManager.TryGetEntitySystem(type, out var systemObj))
|
||||||
|
{
|
||||||
|
// There has to be a listener system that is manually defined. Event subscriptions are locked once
|
||||||
|
// finalized, so we can't really easily create new subscriptions on the fly.
|
||||||
|
// TODO find a better solution
|
||||||
|
throw new InvalidOperationException($"Event {typeof(TEvent).Name} has no associated listener system!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var system = (TestListenerSystem<TEvent>)systemObj;
|
||||||
|
_listenerCache[typeof(TEvent)] = system;
|
||||||
|
return system;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all recorded events of the given type.
|
||||||
|
/// </summary>
|
||||||
|
protected void ClearEvents<TEvent>(EntityUid uid) where TEvent : notnull
|
||||||
|
=> GetListenerSystem<TEvent>().Clear(uid);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Entity lookups
|
#region Entity lookups
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Collections.Generic;
|
using Content.IntegrationTests.Tests.Helpers;
|
||||||
using Content.IntegrationTests.Tests.Interaction;
|
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Slippery;
|
using Content.Shared.Slippery;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Input;
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
@@ -12,44 +10,32 @@ namespace Content.IntegrationTests.Tests.Movement;
|
|||||||
|
|
||||||
public sealed class SlippingTest : MovementTest
|
public sealed class SlippingTest : MovementTest
|
||||||
{
|
{
|
||||||
public sealed class SlipTestSystem : EntitySystem
|
public sealed class SlipTestSystem : TestListenerSystem<SlipEvent>;
|
||||||
{
|
|
||||||
public HashSet<EntityUid> Slipped = new();
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
SubscribeLocalEvent<SlipperyComponent, SlipEvent>(OnSlip);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlip(EntityUid uid, SlipperyComponent component, ref SlipEvent args)
|
|
||||||
{
|
|
||||||
Slipped.Add(args.Slipped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task BananaSlipTest()
|
public async Task BananaSlipTest()
|
||||||
{
|
{
|
||||||
var sys = SEntMan.System<SlipTestSystem>();
|
|
||||||
await SpawnTarget("TrashBananaPeel");
|
await SpawnTarget("TrashBananaPeel");
|
||||||
|
|
||||||
var modifier = Comp<MovementSpeedModifierComponent>(Player).SprintSpeedModifier;
|
var modifier = Comp<MovementSpeedModifierComponent>(Player).SprintSpeedModifier;
|
||||||
Assert.That(modifier, Is.EqualTo(1), "Player is not moving at full speed.");
|
Assert.That(modifier, Is.EqualTo(1), "Player is not moving at full speed.");
|
||||||
|
|
||||||
// Player is to the left of the banana peel and has not slipped.
|
// Player is to the left of the banana peel.
|
||||||
Assert.That(Delta(), Is.GreaterThan(0.5f));
|
Assert.That(Delta(), Is.GreaterThan(0.5f));
|
||||||
Assert.That(sys.Slipped, Does.Not.Contain(SEntMan.GetEntity(Player)));
|
|
||||||
|
|
||||||
// Walking over the banana slowly does not trigger a slip.
|
// Walking over the banana slowly does not trigger a slip.
|
||||||
await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Down);
|
await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Down);
|
||||||
await Move(DirectionFlag.East, 1f);
|
await AssertFiresEvent<SlipEvent>(async () => await Move(DirectionFlag.East, 1f), count: 0);
|
||||||
|
|
||||||
Assert.That(Delta(), Is.LessThan(0.5f));
|
Assert.That(Delta(), Is.LessThan(0.5f));
|
||||||
Assert.That(sys.Slipped, Does.Not.Contain(SEntMan.GetEntity(Player)));
|
|
||||||
AssertComp<KnockedDownComponent>(false, Player);
|
AssertComp<KnockedDownComponent>(false, Player);
|
||||||
|
|
||||||
// Moving at normal speeds does trigger a slip.
|
// Moving at normal speeds does trigger a slip.
|
||||||
await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Up);
|
await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Up);
|
||||||
await Move(DirectionFlag.West, 1f);
|
await AssertFiresEvent<SlipEvent>(async () => await Move(DirectionFlag.West, 1f));
|
||||||
Assert.That(sys.Slipped, Does.Contain(SEntMan.GetEntity(Player)));
|
|
||||||
|
// And the person that slipped was the player
|
||||||
|
AssertEvent<SlipEvent>(predicate: @event => @event.Slipped == SPlayer);
|
||||||
AssertComp<KnockedDownComponent>(true, Player);
|
AssertComp<KnockedDownComponent>(true, Player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float[] GasSpecificHeats => _gasSpecificHeats;
|
public float[] GasSpecificHeats => _gasSpecificHeats;
|
||||||
|
|
||||||
public string?[] GasReagents = new string[Atmospherics.TotalNumberOfGases];
|
|
||||||
|
|
||||||
private void InitializeGases()
|
private void InitializeGases()
|
||||||
{
|
{
|
||||||
_gasReactions = _protoMan.EnumeratePrototypes<GasReactionPrototype>().ToArray();
|
_gasReactions = _protoMan.EnumeratePrototypes<GasReactionPrototype>().ToArray();
|
||||||
@@ -37,7 +35,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
for (var i = 0; i < GasPrototypes.Length; i++)
|
for (var i = 0; i < GasPrototypes.Length; i++)
|
||||||
{
|
{
|
||||||
_gasSpecificHeats[i] = GasPrototypes[i].SpecificHeat / HeatScale;
|
_gasSpecificHeats[i] = GasPrototypes[i].SpecificHeat / HeatScale;
|
||||||
GasReagents[i] = GasPrototypes[i].Reagent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Content.Server.Atmos.EntitySystems;
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.EntityEffects;
|
using Content.Server.EntityEffects;
|
||||||
|
using Content.Shared.Body.Systems;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
|
|||||||
@@ -2,27 +2,22 @@ using Content.Server.Ghost.Roles;
|
|||||||
using Content.Server.Ghost.Roles.Components;
|
using Content.Server.Ghost.Roles.Components;
|
||||||
using Content.Server.Instruments;
|
using Content.Server.Instruments;
|
||||||
using Content.Server.Kitchen.Components;
|
using Content.Server.Kitchen.Components;
|
||||||
using Content.Server.Store.Systems;
|
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Mind.Components;
|
using Content.Shared.Mind.Components;
|
||||||
using Content.Shared.PAI;
|
using Content.Shared.PAI;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Store;
|
|
||||||
using Content.Shared.Store.Components;
|
|
||||||
using Content.Shared.Instruments;
|
using Content.Shared.Instruments;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Content.Server.PAI;
|
namespace Content.Server.PAI;
|
||||||
|
|
||||||
public sealed class PAISystem : SharedPAISystem
|
public sealed class PAISystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly InstrumentSystem _instrumentSystem = default!;
|
[Dependency] private readonly InstrumentSystem _instrumentSystem = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
[Dependency] private readonly StoreSystem _store = default!;
|
|
||||||
[Dependency] private readonly ToggleableGhostRoleSystem _toggleableGhostRole = default!;
|
[Dependency] private readonly ToggleableGhostRoleSystem _toggleableGhostRole = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,8 +33,6 @@ public sealed class PAISystem : SharedPAISystem
|
|||||||
SubscribeLocalEvent<PAIComponent, MindAddedMessage>(OnMindAdded);
|
SubscribeLocalEvent<PAIComponent, MindAddedMessage>(OnMindAdded);
|
||||||
SubscribeLocalEvent<PAIComponent, MindRemovedMessage>(OnMindRemoved);
|
SubscribeLocalEvent<PAIComponent, MindRemovedMessage>(OnMindRemoved);
|
||||||
SubscribeLocalEvent<PAIComponent, BeingMicrowavedEvent>(OnMicrowaved);
|
SubscribeLocalEvent<PAIComponent, BeingMicrowavedEvent>(OnMicrowaved);
|
||||||
|
|
||||||
SubscribeLocalEvent<PAIComponent, PAIShopActionEvent>(OnShop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUseInHand(EntityUid uid, PAIComponent component, UseInHandEvent args)
|
private void OnUseInHand(EntityUid uid, PAIComponent component, UseInHandEvent args)
|
||||||
@@ -106,15 +99,6 @@ public sealed class PAISystem : SharedPAISystem
|
|||||||
var val = Loc.GetString("pai-system-pai-name-raw", ("name", name.ToString()));
|
var val = Loc.GetString("pai-system-pai-name-raw", ("name", name.ToString()));
|
||||||
_metaData.SetEntityName(uid, val);
|
_metaData.SetEntityName(uid, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnShop(Entity<PAIComponent> ent, ref PAIShopActionEvent args)
|
|
||||||
{
|
|
||||||
if (!TryComp<StoreComponent>(ent, out var store))
|
|
||||||
return;
|
|
||||||
|
|
||||||
_store.ToggleUi(args.Performer, ent, store);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PAITurningOff(EntityUid uid)
|
public void PAITurningOff(EntityUid uid)
|
||||||
{
|
{
|
||||||
// Close the instrument interface if it was open
|
// Close the instrument interface if it was open
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Content.Server.Actions;
|
using Content.Server.Actions;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Store.Components;
|
|
||||||
using Content.Server.Store.Systems;
|
using Content.Server.Store.Systems;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
@@ -21,7 +20,6 @@ using Content.Shared.Store.Components;
|
|||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Revenant.EntitySystems;
|
namespace Content.Server.Revenant.EntitySystems;
|
||||||
@@ -46,17 +44,12 @@ public sealed partial class RevenantSystem : EntitySystem
|
|||||||
[Dependency] private readonly TagSystem _tag = default!;
|
[Dependency] private readonly TagSystem _tag = default!;
|
||||||
[Dependency] private readonly VisibilitySystem _visibility = default!;
|
[Dependency] private readonly VisibilitySystem _visibility = default!;
|
||||||
[Dependency] private readonly TurfSystem _turf = default!;
|
[Dependency] private readonly TurfSystem _turf = default!;
|
||||||
|
|
||||||
private static readonly EntProtoId RevenantShopId = "ActionRevenantShop";
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<RevenantComponent, ComponentStartup>(OnStartup);
|
SubscribeLocalEvent<RevenantComponent, ComponentStartup>(OnStartup);
|
||||||
SubscribeLocalEvent<RevenantComponent, MapInitEvent>(OnMapInit);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<RevenantComponent, RevenantShopActionEvent>(OnShop);
|
|
||||||
SubscribeLocalEvent<RevenantComponent, DamageChangedEvent>(OnDamage);
|
SubscribeLocalEvent<RevenantComponent, DamageChangedEvent>(OnDamage);
|
||||||
SubscribeLocalEvent<RevenantComponent, ExaminedEvent>(OnExamine);
|
SubscribeLocalEvent<RevenantComponent, ExaminedEvent>(OnExamine);
|
||||||
SubscribeLocalEvent<RevenantComponent, StatusEffectAddedEvent>(OnStatusAdded);
|
SubscribeLocalEvent<RevenantComponent, StatusEffectAddedEvent>(OnStatusAdded);
|
||||||
@@ -94,11 +87,6 @@ public sealed partial class RevenantSystem : EntitySystem
|
|||||||
_eye.RefreshVisibilityMask(uid);
|
_eye.RefreshVisibilityMask(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, RevenantComponent component, MapInitEvent args)
|
|
||||||
{
|
|
||||||
_action.AddAction(uid, ref component.Action, RevenantShopId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnStatusAdded(EntityUid uid, RevenantComponent component, StatusEffectAddedEvent args)
|
private void OnStatusAdded(EntityUid uid, RevenantComponent component, StatusEffectAddedEvent args)
|
||||||
{
|
{
|
||||||
if (args.Key == "Stun")
|
if (args.Key == "Stun")
|
||||||
@@ -182,13 +170,6 @@ public sealed partial class RevenantSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnShop(EntityUid uid, RevenantComponent component, RevenantShopActionEvent args)
|
|
||||||
{
|
|
||||||
if (!TryComp<StoreComponent>(uid, out var store))
|
|
||||||
return;
|
|
||||||
_store.ToggleUi(uid, uid, store);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MakeVisible(bool visible)
|
public void MakeVisible(bool visible)
|
||||||
{
|
{
|
||||||
var query = EntityQueryEnumerator<RevenantComponent, VisibilityComponent>();
|
var query = EntityQueryEnumerator<RevenantComponent, VisibilityComponent>();
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
|
using System.Linq;
|
||||||
using Content.Server.Store.Components;
|
using Content.Server.Store.Components;
|
||||||
using Content.Shared.UserInterface;
|
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Implants.Components;
|
using Content.Shared.Implants.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Stacks;
|
using Content.Shared.Stacks;
|
||||||
using Content.Shared.Store.Components;
|
using Content.Shared.Store.Components;
|
||||||
using JetBrains.Annotations;
|
using Content.Shared.Store.Events;
|
||||||
|
using Content.Shared.UserInterface;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using System.Linq;
|
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Content.Shared.Mind;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Store.Systems;
|
namespace Content.Server.Store.Systems;
|
||||||
|
|
||||||
@@ -37,6 +36,7 @@ public sealed partial class StoreSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<StoreComponent, ComponentStartup>(OnStartup);
|
SubscribeLocalEvent<StoreComponent, ComponentStartup>(OnStartup);
|
||||||
SubscribeLocalEvent<StoreComponent, ComponentShutdown>(OnShutdown);
|
SubscribeLocalEvent<StoreComponent, ComponentShutdown>(OnShutdown);
|
||||||
SubscribeLocalEvent<StoreComponent, OpenUplinkImplantEvent>(OnImplantActivate);
|
SubscribeLocalEvent<StoreComponent, OpenUplinkImplantEvent>(OnImplantActivate);
|
||||||
|
SubscribeLocalEvent<StoreComponent, IntrinsicStoreActionEvent>(OnIntrinsicStoreAction);
|
||||||
|
|
||||||
InitializeUi();
|
InitializeUi();
|
||||||
InitializeCommand();
|
InitializeCommand();
|
||||||
@@ -187,6 +187,12 @@ public sealed partial class StoreSystem : EntitySystem
|
|||||||
UpdateUserInterface(null, uid, store);
|
UpdateUserInterface(null, uid, store);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnIntrinsicStoreAction(Entity<StoreComponent> ent, ref IntrinsicStoreActionEvent args)
|
||||||
|
{
|
||||||
|
ToggleUi(args.Performer, ent.Owner, ent.Comp);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CurrencyInsertAttemptEvent : CancellableEntityEventArgs
|
public sealed class CurrencyInsertAttemptEvent : CancellableEntityEventArgs
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Damage;
|
using Content.Shared.Clothing.Components;
|
||||||
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Silicons.Borgs;
|
using Content.Shared.Silicons.Borgs;
|
||||||
@@ -32,6 +33,9 @@ public abstract class SharedArmorSystem : EntitySystem
|
|||||||
/// <param name="args">The event, contains the running count of armor percentage as a coefficient</param>
|
/// <param name="args">The event, contains the running count of armor percentage as a coefficient</param>
|
||||||
private void OnCoefficientQuery(Entity<ArmorComponent> ent, ref InventoryRelayedEvent<CoefficientQueryEvent> args)
|
private void OnCoefficientQuery(Entity<ArmorComponent> ent, ref InventoryRelayedEvent<CoefficientQueryEvent> args)
|
||||||
{
|
{
|
||||||
|
if (TryComp<MaskComponent>(ent, out var mask) && mask.IsToggled)
|
||||||
|
return;
|
||||||
|
|
||||||
foreach (var armorCoefficient in ent.Comp.Modifiers.Coefficients)
|
foreach (var armorCoefficient in ent.Comp.Modifiers.Coefficients)
|
||||||
{
|
{
|
||||||
args.Args.DamageModifiers.Coefficients[armorCoefficient.Key] = args.Args.DamageModifiers.Coefficients.TryGetValue(armorCoefficient.Key, out var coefficient) ? coefficient * armorCoefficient.Value : armorCoefficient.Value;
|
args.Args.DamageModifiers.Coefficients[armorCoefficient.Key] = args.Args.DamageModifiers.Coefficients.TryGetValue(armorCoefficient.Key, out var coefficient) ? coefficient * armorCoefficient.Value : armorCoefficient.Value;
|
||||||
@@ -40,12 +44,18 @@ public abstract class SharedArmorSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnDamageModify(EntityUid uid, ArmorComponent component, InventoryRelayedEvent<DamageModifyEvent> args)
|
private void OnDamageModify(EntityUid uid, ArmorComponent component, InventoryRelayedEvent<DamageModifyEvent> args)
|
||||||
{
|
{
|
||||||
|
if (TryComp<MaskComponent>(uid, out var mask) && mask.IsToggled)
|
||||||
|
return;
|
||||||
|
|
||||||
args.Args.Damage = DamageSpecifier.ApplyModifierSet(args.Args.Damage, component.Modifiers);
|
args.Args.Damage = DamageSpecifier.ApplyModifierSet(args.Args.Damage, component.Modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBorgDamageModify(EntityUid uid, ArmorComponent component,
|
private void OnBorgDamageModify(EntityUid uid, ArmorComponent component,
|
||||||
ref BorgModuleRelayedEvent<DamageModifyEvent> args)
|
ref BorgModuleRelayedEvent<DamageModifyEvent> args)
|
||||||
{
|
{
|
||||||
|
if (TryComp<MaskComponent>(uid, out var mask) && mask.IsToggled)
|
||||||
|
return;
|
||||||
|
|
||||||
args.Args.Damage = DamageSpecifier.ApplyModifierSet(args.Args.Damage, component.Modifiers);
|
args.Args.Damage = DamageSpecifier.ApplyModifierSet(args.Args.Damage, component.Modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ namespace Content.Shared.Atmos.EntitySystems
|
|||||||
|
|
||||||
private EntityQuery<InternalsComponent> _internalsQuery;
|
private EntityQuery<InternalsComponent> _internalsQuery;
|
||||||
|
|
||||||
|
public string?[] GasReagents = new string[Atmospherics.TotalNumberOfGases];
|
||||||
|
|
||||||
protected readonly GasPrototype[] GasPrototypes = new GasPrototype[Atmospherics.TotalNumberOfGases];
|
protected readonly GasPrototype[] GasPrototypes = new GasPrototype[Atmospherics.TotalNumberOfGases];
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -26,6 +28,7 @@ namespace Content.Shared.Atmos.EntitySystems
|
|||||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||||
{
|
{
|
||||||
GasPrototypes[i] = _prototypeManager.Index<GasPrototype>(i.ToString());
|
GasPrototypes[i] = _prototypeManager.Index<GasPrototype>(i.ToString());
|
||||||
|
GasReagents[i] = GasPrototypes[i].Reagent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SleepingComponent, EntityZombifiedEvent>(OnZombified);
|
SubscribeLocalEvent<SleepingComponent, EntityZombifiedEvent>(OnZombified);
|
||||||
SubscribeLocalEvent<SleepingComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<SleepingComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
SubscribeLocalEvent<SleepingComponent, ComponentInit>(OnCompInit);
|
SubscribeLocalEvent<SleepingComponent, ComponentInit>(OnCompInit);
|
||||||
|
SubscribeLocalEvent<SleepingComponent, ComponentRemove>(OnComponentRemoved);
|
||||||
|
SubscribeLocalEvent<SleepingComponent, RejuvenateEvent>(OnRejuvenate);
|
||||||
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
|
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, CanSeeAttemptEvent>(OnSeeAttempt);
|
SubscribeLocalEvent<SleepingComponent, CanSeeAttemptEvent>(OnSeeAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, PointAttemptEvent>(OnPointAttempt);
|
SubscribeLocalEvent<SleepingComponent, PointAttemptEvent>(OnPointAttempt);
|
||||||
@@ -69,7 +71,6 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
||||||
SubscribeLocalEvent<SleepingComponent, StunEndAttemptEvent>(OnStunEndAttempt);
|
SubscribeLocalEvent<SleepingComponent, StunEndAttemptEvent>(OnStunEndAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, StandUpAttemptEvent>(OnStandUpAttempt);
|
SubscribeLocalEvent<SleepingComponent, StandUpAttemptEvent>(OnStandUpAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, RejuvenateEvent>(OnRejuvenate);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
||||||
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
||||||
@@ -102,6 +103,12 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
TrySleeping((ent, ent.Comp));
|
TrySleeping((ent, ent.Comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRejuvenate(Entity<SleepingComponent> ent, ref RejuvenateEvent args)
|
||||||
|
{
|
||||||
|
// WAKE UP!!!
|
||||||
|
RemComp<SleepingComponent>(ent);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// when sleeping component is added or removed, we do some stuff with other components.
|
/// when sleeping component is added or removed, we do some stuff with other components.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -143,6 +150,16 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
_actionsSystem.AddAction(ent, ref ent.Comp.WakeAction, WakeActionId, ent);
|
_actionsSystem.AddAction(ent, ref ent.Comp.WakeAction, WakeActionId, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnComponentRemoved(Entity<SleepingComponent> ent, ref ComponentRemove args)
|
||||||
|
{
|
||||||
|
_actionsSystem.RemoveAction(ent.Owner, ent.Comp.WakeAction);
|
||||||
|
|
||||||
|
var ev = new SleepStateChangedEvent(false);
|
||||||
|
RaiseLocalEvent(ent, ref ev);
|
||||||
|
|
||||||
|
_blindableSystem.UpdateIsBlind(ent.Owner);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnSpeakAttempt(Entity<SleepingComponent> ent, ref SpeakAttemptEvent args)
|
private void OnSpeakAttempt(Entity<SleepingComponent> ent, ref SpeakAttemptEvent args)
|
||||||
{
|
{
|
||||||
// TODO reduce duplication of this behavior with MobStateSystem somehow
|
// TODO reduce duplication of this behavior with MobStateSystem somehow
|
||||||
@@ -187,11 +204,6 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRejuvenate(Entity<SleepingComponent> ent, ref RejuvenateEvent args)
|
|
||||||
{
|
|
||||||
TryWaking((ent.Owner, ent.Comp), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnExamined(Entity<SleepingComponent> ent, ref ExaminedEvent args)
|
private void OnExamined(Entity<SleepingComponent> ent, ref ExaminedEvent args)
|
||||||
{
|
{
|
||||||
if (args.IsInDetailsRange)
|
if (args.IsInDetailsRange)
|
||||||
@@ -275,17 +287,6 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
TrySleeping(args.Target);
|
TrySleeping(args.Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Wake(Entity<SleepingComponent> ent)
|
|
||||||
{
|
|
||||||
RemComp<SleepingComponent>(ent);
|
|
||||||
_actionsSystem.RemoveAction(ent.Owner, ent.Comp.WakeAction);
|
|
||||||
|
|
||||||
var ev = new SleepStateChangedEvent(false);
|
|
||||||
RaiseLocalEvent(ent, ref ev);
|
|
||||||
|
|
||||||
_blindableSystem.UpdateIsBlind(ent.Owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try sleeping. Only mobs can sleep.
|
/// Try sleeping. Only mobs can sleep.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -345,8 +346,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
_popupSystem.PopupClient(Loc.GetString("wake-other-success", ("target", Identity.Entity(ent, EntityManager))), ent, user);
|
_popupSystem.PopupClient(Loc.GetString("wake-other-success", ("target", Identity.Entity(ent, EntityManager))), ent, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wake((ent, ent.Comp));
|
return RemComp<SleepingComponent>(ent);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Shared.Body.Systems;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.Body.Components;
|
namespace Content.Shared.Body.Components;
|
||||||
|
|
||||||
[RegisterComponent, Access(typeof(LungSystem))]
|
[RegisterComponent, NetworkedComponent, Access(typeof(LungSystem))]
|
||||||
public sealed partial class LungComponent : Component
|
public sealed partial class LungComponent : Component
|
||||||
{
|
{
|
||||||
[DataField]
|
[DataField]
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Shared.Atmos.Components;
|
||||||
using Content.Server.Body.Components;
|
using Content.Shared.Atmos.EntitySystems;
|
||||||
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Chemistry.EntitySystems;
|
using Content.Shared.Chemistry.EntitySystems;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Clothing;
|
using Content.Shared.Clothing;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using BreathToolComponent = Content.Shared.Atmos.Components.BreathToolComponent;
|
|
||||||
using InternalsComponent = Content.Shared.Body.Components.InternalsComponent;
|
|
||||||
|
|
||||||
namespace Content.Server.Body.Systems;
|
namespace Content.Shared.Body.Systems;
|
||||||
|
|
||||||
public sealed class LungSystem : EntitySystem
|
public sealed class LungSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
[Dependency] private readonly SharedAtmosphereSystem _atmos = default!;
|
||||||
[Dependency] private readonly InternalsSystem _internals = default!;
|
[Dependency] private readonly SharedInternalsSystem _internals = default!;
|
||||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
|
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
|
|
||||||
public static string LungSolutionName = "Lung";
|
public static string LungSolutionName = "Lung";
|
||||||
@@ -3,6 +3,7 @@ using Content.Shared.Inventory;
|
|||||||
using Content.Shared.Eye.Blinding.Components;
|
using Content.Shared.Eye.Blinding.Components;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
using Content.Shared.Item.ItemToggle.Components;
|
using Content.Shared.Item.ItemToggle.Components;
|
||||||
|
using Content.Shared.Clothing.Components;
|
||||||
|
|
||||||
namespace Content.Shared.Eye.Blinding.Systems
|
namespace Content.Shared.Eye.Blinding.Systems
|
||||||
{
|
{
|
||||||
@@ -29,6 +30,9 @@ namespace Content.Shared.Eye.Blinding.Systems
|
|||||||
|
|
||||||
private void OnGetProtection(EntityUid uid, EyeProtectionComponent component, GetEyeProtectionEvent args)
|
private void OnGetProtection(EntityUid uid, EyeProtectionComponent component, GetEyeProtectionEvent args)
|
||||||
{
|
{
|
||||||
|
if (TryComp<MaskComponent>(uid, out var mask) && mask.IsToggled)
|
||||||
|
return;
|
||||||
|
|
||||||
args.Protection += component.ProtectionTime;
|
args.Protection += component.ProtectionTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ using Robust.Shared.Timing;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Random.Helpers;
|
using Content.Shared.Random.Helpers;
|
||||||
|
using Content.Shared.Clothing.Components;
|
||||||
|
|
||||||
namespace Content.Shared.Flash;
|
namespace Content.Shared.Flash;
|
||||||
|
|
||||||
@@ -258,6 +259,9 @@ public abstract class SharedFlashSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnFlashImmunityFlashAttempt(Entity<FlashImmunityComponent> ent, ref FlashAttemptEvent args)
|
private void OnFlashImmunityFlashAttempt(Entity<FlashImmunityComponent> ent, ref FlashAttemptEvent args)
|
||||||
{
|
{
|
||||||
|
if (TryComp<MaskComponent>(ent, out var mask) && mask.IsToggled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ent.Comp.Enabled)
|
if (ent.Comp.Enabled)
|
||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using Content.Shared.FixedPoint;
|
|
||||||
using Content.Shared.Store;
|
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Shared.PAI;
|
namespace Content.Shared.PAI;
|
||||||
|
|
||||||
@@ -16,7 +12,7 @@ namespace Content.Shared.PAI;
|
|||||||
/// and there's not always enough players and ghost roles to justify it.
|
/// and there's not always enough players and ghost roles to justify it.
|
||||||
/// All logic in PAISystem.
|
/// All logic in PAISystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed partial class PAIComponent : Component
|
public sealed partial class PAIComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,12 +22,6 @@ public sealed partial class PAIComponent : Component
|
|||||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public EntityUid? LastUser;
|
public EntityUid? LastUser;
|
||||||
|
|
||||||
[DataField]
|
|
||||||
public EntProtoId ShopActionId = "ActionPAIOpenShop";
|
|
||||||
|
|
||||||
[DataField, AutoNetworkedField]
|
|
||||||
public EntityUid? ShopAction;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When microwaved there is this chance to brick the pai, kicking out its player and preventing it from being used again.
|
/// When microwaved there is this chance to brick the pai, kicking out its player and preventing it from being used again.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
using Content.Shared.Actions;
|
|
||||||
|
|
||||||
namespace Content.Shared.PAI;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// pAIs, or Personal AIs, are essentially portable ghost role generators.
|
|
||||||
/// In their current implementation, they create a ghost role anyone can access,
|
|
||||||
/// and that a player can also "wipe" (reset/kick out player).
|
|
||||||
/// Theoretically speaking pAIs are supposed to use a dedicated "offer and select" system,
|
|
||||||
/// with the player holding the pAI being able to choose one of the ghosts in the round.
|
|
||||||
/// This seems too complicated for an initial implementation, though,
|
|
||||||
/// and there's not always enough players and ghost roles to justify it.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class SharedPAISystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<PAIComponent, MapInitEvent>(OnMapInit);
|
|
||||||
SubscribeLocalEvent<PAIComponent, ComponentShutdown>(OnShutdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMapInit(Entity<PAIComponent> ent, ref MapInitEvent args)
|
|
||||||
{
|
|
||||||
_actions.AddAction(ent, ent.Comp.ShopActionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnShutdown(Entity<PAIComponent> ent, ref ComponentShutdown args)
|
|
||||||
{
|
|
||||||
_actions.RemoveAction(ent.Owner, ent.Comp.ShopAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public sealed partial class PAIShopActionEvent : InstantActionEvent
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -51,7 +51,6 @@ public sealed partial class ParcelWrappingSystem : EntitySystem
|
|||||||
wrapper.Owner != target &&
|
wrapper.Owner != target &&
|
||||||
// Wrapper should never be empty, but may as well make sure.
|
// Wrapper should never be empty, but may as well make sure.
|
||||||
!_charges.IsEmpty(wrapper.Owner) &&
|
!_charges.IsEmpty(wrapper.Owner) &&
|
||||||
_whitelist.IsWhitelistPass(wrapper.Comp.Whitelist, target) &&
|
_whitelist.CheckBoth(target, wrapper.Comp.Blacklist, wrapper.Comp.Whitelist);
|
||||||
_whitelist.IsBlacklistFail(wrapper.Comp.Blacklist, target);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,8 +215,6 @@ public sealed partial class RevenantComponent : Component
|
|||||||
public string HarvestingState = "harvesting";
|
public string HarvestingState = "harvesting";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[DataField] public EntityUid? Action;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Offbrand - how much cold damage to deal on harvest
|
/// Offbrand - how much cold damage to deal on harvest
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -42,10 +42,6 @@ public sealed class HarvestDoAfterCancelled : EntityEventArgs
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed partial class RevenantShopActionEvent : InstantActionEvent
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed partial class RevenantDefileActionEvent : InstantActionEvent
|
public sealed partial class RevenantDefileActionEvent : InstantActionEvent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
11
Content.Shared/Store/Events/IntrinsicStoreActionEvent.cs
Normal file
11
Content.Shared/Store/Events/IntrinsicStoreActionEvent.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
|
||||||
|
namespace Content.Shared.Store.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens a store specified by <see cref="StoreComponent"/>
|
||||||
|
/// Used for entities with a store built into themselves like Revenant or PAI
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class IntrinsicStoreActionEvent : InstantActionEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
using Content.Shared.Eye.Blinding.Components;
|
using Content.Shared.Eye.Blinding.Components;
|
||||||
using Content.Shared.Eye.Blinding.Systems;
|
using Content.Shared.Eye.Blinding.Systems;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Robust.Shared.Network;
|
|
||||||
|
|
||||||
namespace Content.Shared.Traits.Assorted;
|
namespace Content.Shared.Traits.Assorted;
|
||||||
|
|
||||||
@@ -38,6 +37,11 @@ public sealed class PermanentBlindnessSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
_blinding.SetMinDamage((blindness.Owner, blindable), 0);
|
_blinding.SetMinDamage((blindness.Owner, blindable), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Heal all eye damage when the component is removed.
|
||||||
|
// Otherwise you would still be blind, but not *permanently* blind, meaning you have to heal the eye damage with oculine.
|
||||||
|
// This is needed for changelings that transform from a blind player to a non-blind one.
|
||||||
|
_blinding.AdjustEyeDamage((blindness.Owner, blindable), -blindable.EyeDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(Entity<PermanentBlindnessComponent> blindness, ref MapInitEvent args)
|
private void OnMapInit(Entity<PermanentBlindnessComponent> blindness, ref MapInitEvent args)
|
||||||
|
|||||||
@@ -1,29 +1,4 @@
|
|||||||
Entries:
|
Entries:
|
||||||
- author: EmoGarbage404
|
|
||||||
changes:
|
|
||||||
- message: Added cargo orders for gold and silver ingots.
|
|
||||||
type: Add
|
|
||||||
- message: Reduced prices of cardboard and paper material crate.
|
|
||||||
type: Tweak
|
|
||||||
id: 8557
|
|
||||||
time: '2025-05-22T08:42:20.0000000+00:00'
|
|
||||||
url: https://github.com/space-wizards/space-station-14/pull/37713
|
|
||||||
- author: ArtisticRoomba
|
|
||||||
changes:
|
|
||||||
- message: The volume of large gas canisters have been increased to 1500L to encourage
|
|
||||||
their usage in resolving pressure problems in spaced rooms. The gas that starts
|
|
||||||
inside of the tanks and the price of them has increased to compensate.
|
|
||||||
type: Tweak
|
|
||||||
id: 8558
|
|
||||||
time: '2025-05-22T18:12:25.0000000+00:00'
|
|
||||||
url: https://github.com/space-wizards/space-station-14/pull/37564
|
|
||||||
- author: Hitlinemoss
|
|
||||||
changes:
|
|
||||||
- message: Liquid soap is now slippery.
|
|
||||||
type: Fix
|
|
||||||
id: 8559
|
|
||||||
time: '2025-05-23T21:57:06.0000000+00:00'
|
|
||||||
url: https://github.com/space-wizards/space-station-14/pull/37747
|
|
||||||
- author: CoconutThunder
|
- author: CoconutThunder
|
||||||
changes:
|
changes:
|
||||||
- message: The Chief Medical Officer should now appear with the correct precedence
|
- message: The Chief Medical Officer should now appear with the correct precedence
|
||||||
@@ -3952,3 +3927,25 @@
|
|||||||
id: 9059
|
id: 9059
|
||||||
time: '2025-10-08T23:45:56.0000000+00:00'
|
time: '2025-10-08T23:45:56.0000000+00:00'
|
||||||
url: https://github.com/space-wizards/space-station-14/pull/40786
|
url: https://github.com/space-wizards/space-station-14/pull/40786
|
||||||
|
- author: SlamBamActionman
|
||||||
|
changes:
|
||||||
|
- message: Nocturine now slows the target down, with a longer duration and shorter
|
||||||
|
delay before activating.
|
||||||
|
type: Tweak
|
||||||
|
id: 9060
|
||||||
|
time: '2025-10-09T13:32:34.0000000+00:00'
|
||||||
|
url: https://github.com/space-wizards/space-station-14/pull/40797
|
||||||
|
- author: Princess-Cheeseballs
|
||||||
|
changes:
|
||||||
|
- message: Dying while asleep shouldn't permanently blind you anymore.
|
||||||
|
type: Fix
|
||||||
|
id: 9061
|
||||||
|
time: '2025-10-09T13:46:20.0000000+00:00'
|
||||||
|
url: https://github.com/space-wizards/space-station-14/pull/40366
|
||||||
|
- author: kontakt
|
||||||
|
changes:
|
||||||
|
- message: Bulldog magazines are now only accessible through emagged fabricators.
|
||||||
|
type: Tweak
|
||||||
|
id: 9062
|
||||||
|
time: '2025-10-09T14:00:07.0000000+00:00'
|
||||||
|
url: https://github.com/space-wizards/space-station-14/pull/40790
|
||||||
|
|||||||
@@ -764,4 +764,11 @@
|
|||||||
id: 92
|
id: 92
|
||||||
time: '2025-10-08T20:41:46.0000000+00:00'
|
time: '2025-10-08T20:41:46.0000000+00:00'
|
||||||
url: https://github.com/space-wizards/space-station-14/pull/40785
|
url: https://github.com/space-wizards/space-station-14/pull/40785
|
||||||
|
- author: ToastEnjoyer
|
||||||
|
changes:
|
||||||
|
- message: On Plasma, added more nitrogen canisters to the maintenance hallways
|
||||||
|
type: Add
|
||||||
|
id: 93
|
||||||
|
time: '2025-10-10T01:11:33.0000000+00:00'
|
||||||
|
url: https://github.com/space-wizards/space-station-14/pull/40794
|
||||||
Order: 1
|
Order: 1
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ materials-glass = glass
|
|||||||
materials-reinforced-glass = reinforced glass
|
materials-reinforced-glass = reinforced glass
|
||||||
materials-plasma-glass = plasma glass
|
materials-plasma-glass = plasma glass
|
||||||
materials-reinforced-plasma-glass = reinforced plasma glass
|
materials-reinforced-plasma-glass = reinforced plasma glass
|
||||||
|
materials-uranium-glass = uranium glass
|
||||||
|
materials-reinforced-uranium-glass = reinforced uranium glass
|
||||||
|
|
||||||
# Metals
|
# Metals
|
||||||
materials-steel = steel
|
materials-steel = steel
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ uplink-pistol-magazine-name = Pistol Magazine (.35 auto)
|
|||||||
uplink-pistol-magazine-desc = Pistol magazine with 10 cartridges. Compatible with the Viper.
|
uplink-pistol-magazine-desc = Pistol magazine with 10 cartridges. Compatible with the Viper.
|
||||||
|
|
||||||
uplink-pistol-magazine-c20r-name = SMG magazine (.35 auto)
|
uplink-pistol-magazine-c20r-name = SMG magazine (.35 auto)
|
||||||
uplink-pistol-magazine-c20r-desc = Rifle magazine with 30 cartridges. Compatible with C-20r.
|
uplink-pistol-magazine-c20r-desc = SMG magazine with 30 cartridges. Compatible with C-20r.
|
||||||
|
|
||||||
uplink-magazine-bulldog-pellet-name = Drum magazine (.50 pellet)
|
uplink-magazine-bulldog-pellet-name = Drum magazine (.50 pellet)
|
||||||
uplink-magazine-bulldog-pellet-desc = Shotgun magazine with 8 shells filled with buckshot. Compatible with the Bulldog.
|
uplink-magazine-bulldog-pellet-desc = Shotgun magazine with 8 shells filled with buckshot. Compatible with the Bulldog.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,8 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseAction
|
parent: ActionIntrinsicStore
|
||||||
id: ActionRevenantShop
|
id: ActionRevenantShop
|
||||||
name: Shop
|
name: Shop
|
||||||
description: Opens the ability shop.
|
description: Opens the ability shop.
|
||||||
components:
|
|
||||||
- type: Action
|
|
||||||
icon: Interface/Actions/shop.png
|
|
||||||
- type: InstantAction
|
|
||||||
event: !type:RevenantShopActionEvent
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseAction
|
parent: BaseAction
|
||||||
|
|||||||
@@ -466,3 +466,14 @@
|
|||||||
itemIconStyle: BigAction
|
itemIconStyle: BigAction
|
||||||
- type: InstantAction
|
- type: InstantAction
|
||||||
event: !type:ChameleonControllerOpenMenuEvent
|
event: !type:ChameleonControllerOpenMenuEvent
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMentalAction
|
||||||
|
id: ActionIntrinsicStore
|
||||||
|
name: Store
|
||||||
|
description: Opens the store
|
||||||
|
components:
|
||||||
|
- type: Action
|
||||||
|
icon: Interface/Actions/shop.png
|
||||||
|
- type: InstantAction
|
||||||
|
event: !type:IntrinsicStoreActionEvent
|
||||||
|
|||||||
@@ -329,6 +329,7 @@
|
|||||||
weight: 95
|
weight: 95
|
||||||
children:
|
children:
|
||||||
- id: Machete
|
- id: Machete
|
||||||
|
- id: Claymore
|
||||||
- id: BaseBallBat
|
- id: BaseBallBat
|
||||||
- id: CombatKnife
|
- id: CombatKnife
|
||||||
- id: Spear
|
- id: Spear
|
||||||
|
|||||||
@@ -66,6 +66,9 @@
|
|||||||
type: StoreBoundUserInterface
|
type: StoreBoundUserInterface
|
||||||
- type: Visibility
|
- type: Visibility
|
||||||
layer: 2 #ghost vis layer
|
layer: 2 #ghost vis layer
|
||||||
|
- type: ActionGrant
|
||||||
|
actions:
|
||||||
|
- ActionRevenantShop
|
||||||
- type: Store
|
- type: Store
|
||||||
categories:
|
categories:
|
||||||
- RevenantAbilities
|
- RevenantAbilities
|
||||||
|
|||||||
@@ -105,6 +105,8 @@
|
|||||||
- id: Ointment
|
- id: Ointment
|
||||||
- id: Gauze
|
- id: Gauze
|
||||||
- id: ChemistryBottleParacetamol # Offbrand
|
- id: ChemistryBottleParacetamol # Offbrand
|
||||||
|
- id: SyndicateBusinessCard
|
||||||
|
weight: 0.5
|
||||||
|
|
||||||
# Packages
|
# Packages
|
||||||
# TODO: Currently mostly maints loot, should be updated in the future.
|
# TODO: Currently mostly maints loot, should be updated in the future.
|
||||||
@@ -138,6 +140,9 @@
|
|||||||
weight: 0.2
|
weight: 0.2
|
||||||
rolls: !type:RangeNumberSelector
|
rolls: !type:RangeNumberSelector
|
||||||
range: 2, 3
|
range: 2, 3
|
||||||
|
- !type:NestedSelector
|
||||||
|
tableId: InsulsTable #Uncommon since it's weighted towards budget/fingerless
|
||||||
|
weight: 0.2
|
||||||
|
|
||||||
- type: entityTable # TODO: Add more variety!
|
- type: entityTable # TODO: Add more variety!
|
||||||
id: PackageRareEntityTable
|
id: PackageRareEntityTable
|
||||||
@@ -157,3 +162,4 @@
|
|||||||
- !type:NestedSelector
|
- !type:NestedSelector
|
||||||
tableId: SyndieMaintLoot
|
tableId: SyndieMaintLoot
|
||||||
weight: 0.5
|
weight: 0.5
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,9 @@
|
|||||||
- Common
|
- Common
|
||||||
- type: DoAfter
|
- type: DoAfter
|
||||||
- type: Actions
|
- type: Actions
|
||||||
|
- type: ActionGrant
|
||||||
|
actions:
|
||||||
|
- ActionPAIOpenShop
|
||||||
- type: Store
|
- type: Store
|
||||||
categories:
|
categories:
|
||||||
- PAIAbilities
|
- PAIAbilities
|
||||||
@@ -188,15 +191,10 @@
|
|||||||
node: potatoai
|
node: potatoai
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseMentalAction
|
parent: ActionIntrinsicStore
|
||||||
id: ActionPAIOpenShop
|
id: ActionPAIOpenShop
|
||||||
name: Software Catalog
|
name: Software Catalog
|
||||||
description: Install new software to assist your owner.
|
description: Install new software to assist your owner.
|
||||||
components:
|
|
||||||
- type: Action
|
|
||||||
icon: Interface/Actions/shop.png
|
|
||||||
- type: InstantAction
|
|
||||||
event: !type:PAIShopActionEvent
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseMentalAction
|
parent: BaseMentalAction
|
||||||
|
|||||||
@@ -28,6 +28,17 @@
|
|||||||
- type: LimitedCharges
|
- type: LimitedCharges
|
||||||
maxCharges: 30
|
maxCharges: 30
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ParcelWrap
|
||||||
|
id: ParcelWrapAdmeme
|
||||||
|
name: bluespace wrap
|
||||||
|
suffix: Admeme
|
||||||
|
description: Paper used contain items for transport. This one seems to be able to store an unusual amount of space within it.
|
||||||
|
components:
|
||||||
|
- type: ParcelWrap
|
||||||
|
whitelist: null
|
||||||
|
blacklist: null
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
id: WrappedParcel
|
id: WrappedParcel
|
||||||
|
|||||||
@@ -136,6 +136,7 @@
|
|||||||
- type: EmagLatheRecipes
|
- type: EmagLatheRecipes
|
||||||
emagStaticPacks:
|
emagStaticPacks:
|
||||||
- SecurityAmmoStatic
|
- SecurityAmmoStatic
|
||||||
|
- SyndicateAmmoStatic
|
||||||
- type: BlueprintReceiver
|
- type: BlueprintReceiver
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
@@ -408,6 +409,9 @@
|
|||||||
- SecurityAmmo
|
- SecurityAmmo
|
||||||
- SecurityWeapons
|
- SecurityWeapons
|
||||||
- SecurityDisablers
|
- SecurityDisablers
|
||||||
|
- type: EmagLatheRecipes
|
||||||
|
emagStaticPacks:
|
||||||
|
- SyndicateAmmoStatic
|
||||||
- type: MaterialStorage
|
- type: MaterialStorage
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
@@ -444,6 +448,9 @@
|
|||||||
runningState: icon
|
runningState: icon
|
||||||
staticPacks:
|
staticPacks:
|
||||||
- SecurityAmmoStatic
|
- SecurityAmmoStatic
|
||||||
|
- type: EmagLatheRecipes
|
||||||
|
emagStaticPacks:
|
||||||
|
- SyndicateAmmoStatic
|
||||||
- type: MaterialStorage
|
- type: MaterialStorage
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
@@ -306,16 +306,19 @@
|
|||||||
Narcotic:
|
Narcotic:
|
||||||
statusEffects: # Offbrand
|
statusEffects: # Offbrand
|
||||||
- statusEffect: StatusEffectPainSuppressionNocturine
|
- statusEffect: StatusEffectPainSuppressionNocturine
|
||||||
effects:
|
effects: # It would be nice to have speech slurred or mumbly, but accents are a bit iffy atm. Same for distortion effects.
|
||||||
|
- !type:MovespeedModifier
|
||||||
|
walkSpeedModifier: 0.65
|
||||||
|
sprintSpeedModifier: 0.65
|
||||||
- !type:ModifyStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
conditions:
|
conditions:
|
||||||
- !type:ReagentThreshold
|
- !type:ReagentThreshold
|
||||||
reagent: Nocturine
|
reagent: Nocturine
|
||||||
min: 8
|
min: 8
|
||||||
effectProto: StatusEffectForcedSleeping
|
effectProto: StatusEffectForcedSleeping
|
||||||
time: 3
|
time: 6
|
||||||
delay: 6
|
delay: 5
|
||||||
type: Add
|
type: Update
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
id: MuteToxin
|
id: MuteToxin
|
||||||
|
|||||||
@@ -49,9 +49,6 @@
|
|||||||
- MagazinePistolSubMachineGunTopMountedEmpty
|
- MagazinePistolSubMachineGunTopMountedEmpty
|
||||||
- MagazineRifle
|
- MagazineRifle
|
||||||
- MagazineRifleEmpty
|
- MagazineRifleEmpty
|
||||||
- MagazineShotgun
|
|
||||||
- MagazineShotgunEmpty
|
|
||||||
- MagazineShotgunSlug
|
|
||||||
- SpeedLoaderMagnum
|
- SpeedLoaderMagnum
|
||||||
- SpeedLoaderMagnumEmpty
|
- SpeedLoaderMagnumEmpty
|
||||||
|
|
||||||
|
|||||||
9
Resources/Prototypes/Recipes/Lathes/Packs/syndicate.yml
Normal file
9
Resources/Prototypes/Recipes/Lathes/Packs/syndicate.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
## Static recipes
|
||||||
|
|
||||||
|
# Added to emagged autolathe
|
||||||
|
- type: latheRecipePack
|
||||||
|
id: SyndicateAmmoStatic
|
||||||
|
recipes:
|
||||||
|
- MagazineShotgun
|
||||||
|
- MagazineShotgunEmpty
|
||||||
|
- MagazineShotgunSlug
|
||||||
Reference in New Issue
Block a user