Merge remote-tracking branch 'refs/remotes/wizards/master'
This commit is contained in:
commit
461f70ab28
35 changed files with 395 additions and 228 deletions
10
Content.Client/Atmos/EntitySystems/GasMinerSystem.cs
Normal file
10
Content.Client/Atmos/EntitySystems/GasMinerSystem.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Content.Shared.Atmos.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class GasMinerSystem : SharedGasMinerSystem
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
|
|||
/// </summary>
|
||||
private bool _isReplaying;
|
||||
|
||||
private float _deadzone;
|
||||
public float Deadzone;
|
||||
|
||||
private DragState _state = DragState.NotDragging;
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
|
|||
|
||||
private void SetDeadZone(float deadZone)
|
||||
{
|
||||
_deadzone = deadZone;
|
||||
Deadzone = deadZone;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
|
|
@ -212,7 +212,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
|
|||
|
||||
_draggedEntity = entity;
|
||||
_state = DragState.MouseDown;
|
||||
_mouseDownScreenPos = _inputManager.MouseScreenPosition;
|
||||
_mouseDownScreenPos = args.ScreenCoordinates;
|
||||
_mouseDownTime = 0;
|
||||
|
||||
// don't want anything else to process the click,
|
||||
|
|
@ -240,8 +240,13 @@ public sealed class DragDropSystem : SharedDragDropSystem
|
|||
|
||||
if (TryComp<SpriteComponent>(_draggedEntity, out var draggedSprite))
|
||||
{
|
||||
var screenPos = _inputManager.MouseScreenPosition;
|
||||
// No _draggedEntity in null window (Happens in tests)
|
||||
if (!screenPos.IsValid)
|
||||
return;
|
||||
|
||||
// pop up drag shadow under mouse
|
||||
var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition);
|
||||
var mousePos = _eyeManager.PixelToMap(screenPos);
|
||||
_dragShadow = EntityManager.SpawnEntity("dragshadow", mousePos);
|
||||
var dragSprite = Comp<SpriteComponent>(_dragShadow.Value);
|
||||
dragSprite.CopyFrom(draggedSprite);
|
||||
|
|
@ -534,7 +539,7 @@ public sealed class DragDropSystem : SharedDragDropSystem
|
|||
case DragState.MouseDown:
|
||||
{
|
||||
var screenPos = _inputManager.MouseScreenPosition;
|
||||
if ((_mouseDownScreenPos!.Value.Position - screenPos.Position).Length() > _deadzone)
|
||||
if ((_mouseDownScreenPos!.Value.Position - screenPos.Position).Length() > Deadzone)
|
||||
{
|
||||
StartDrag();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1207,11 +1207,12 @@ public abstract partial class InteractionTest
|
|||
BoundKeyFunction key,
|
||||
BoundKeyState state,
|
||||
NetCoordinates? coordinates = null,
|
||||
NetEntity? cursorEntity = null)
|
||||
NetEntity? cursorEntity = null,
|
||||
ScreenCoordinates? screenCoordinates = null)
|
||||
{
|
||||
var coords = coordinates ?? TargetCoords;
|
||||
var target = cursorEntity ?? Target ?? default;
|
||||
ScreenCoordinates screen = default;
|
||||
var screen = screenCoordinates ?? default;
|
||||
|
||||
var funcId = InputManager.NetworkBindMap.KeyFunctionID(key);
|
||||
var message = new ClientFullInputCmdMessage(CTiming.CurTick, CTiming.TickFraction, funcId)
|
||||
|
|
|
|||
46
Content.IntegrationTests/Tests/Strip/StrippableTest.cs
Normal file
46
Content.IntegrationTests/Tests/Strip/StrippableTest.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
using Content.Client.Interaction;
|
||||
using Content.IntegrationTests.Tests.Interaction;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Strip;
|
||||
|
||||
public sealed class StrippableTest : InteractionTest
|
||||
{
|
||||
protected override string PlayerPrototype => "MobHuman";
|
||||
|
||||
[Test]
|
||||
public async Task DragDropOpensStrip()
|
||||
{
|
||||
// Spawn one tile away
|
||||
TargetCoords = SEntMan.GetNetCoordinates(new EntityCoordinates(MapData.MapUid, 1, 0));
|
||||
await SpawnTarget("MobHuman");
|
||||
|
||||
var userInterface = Comp<UserInterfaceComponent>(Target);
|
||||
Assert.That(userInterface.Actors.Count == 0);
|
||||
|
||||
// screenCoordinates diff needs to be larger than DragDropSystem._deadzone
|
||||
var screenX = CEntMan.System<DragDropSystem>().Deadzone + 1f;
|
||||
|
||||
// Start drag
|
||||
await SetKey(EngineKeyFunctions.Use,
|
||||
BoundKeyState.Down,
|
||||
TargetCoords,
|
||||
Target,
|
||||
screenCoordinates: new ScreenCoordinates(screenX, 0f, WindowId.Main));
|
||||
|
||||
await RunTicks(5);
|
||||
|
||||
// End drag
|
||||
await SetKey(EngineKeyFunctions.Use,
|
||||
BoundKeyState.Up,
|
||||
PlayerCoords,
|
||||
Player,
|
||||
screenCoordinates: new ScreenCoordinates(0f, 0f, WindowId.Main));
|
||||
|
||||
await RunTicks(5);
|
||||
|
||||
Assert.That(userInterface.Actors.Count > 0);
|
||||
}
|
||||
}
|
||||
90
Content.Server/Atmos/EntitySystems/GasMinerSystem.cs
Normal file
90
Content.Server/Atmos/EntitySystems/GasMinerSystem.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Atmos.Piping.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.Atmos.EntitySystems;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class GasMinerSystem : SharedGasMinerSystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GasMinerComponent, AtmosDeviceUpdateEvent>(OnMinerUpdated);
|
||||
}
|
||||
|
||||
private void OnMinerUpdated(Entity<GasMinerComponent> ent, ref AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
var miner = ent.Comp;
|
||||
var oldState = miner.MinerState;
|
||||
float toSpawn;
|
||||
|
||||
if (!GetValidEnvironment(ent, out var environment) || !Transform(ent).Anchored)
|
||||
{
|
||||
miner.MinerState = GasMinerState.Disabled;
|
||||
}
|
||||
// SpawnAmount is declared in mol/s so to get the amount of gas we hope to mine, we have to multiply this by
|
||||
// how long we have been waiting to spawn it and further cap the number according to the miner's state.
|
||||
else if ((toSpawn = CapSpawnAmount(ent, miner.SpawnAmount * args.dt, environment)) == 0)
|
||||
{
|
||||
miner.MinerState = GasMinerState.Idle;
|
||||
}
|
||||
else
|
||||
{
|
||||
miner.MinerState = GasMinerState.Working;
|
||||
|
||||
// Time to mine some gas.
|
||||
var merger = new GasMixture(1) { Temperature = miner.SpawnTemperature };
|
||||
merger.SetMoles(miner.SpawnGas, toSpawn);
|
||||
_atmosphereSystem.Merge(environment, merger);
|
||||
}
|
||||
|
||||
if (miner.MinerState != oldState)
|
||||
{
|
||||
Dirty(ent);
|
||||
}
|
||||
}
|
||||
|
||||
private bool GetValidEnvironment(Entity<GasMinerComponent> ent, [NotNullWhen(true)] out GasMixture? environment)
|
||||
{
|
||||
var (uid, miner) = ent;
|
||||
var transform = Transform(uid);
|
||||
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||
|
||||
// Treat space as an invalid environment
|
||||
if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position))
|
||||
{
|
||||
environment = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
|
||||
return environment != null;
|
||||
}
|
||||
|
||||
private float CapSpawnAmount(Entity<GasMinerComponent> ent, float toSpawnTarget, GasMixture environment)
|
||||
{
|
||||
var (uid, miner) = ent;
|
||||
|
||||
// How many moles could we theoretically spawn. Cap by pressure and amount.
|
||||
var allowableMoles = Math.Min(
|
||||
(miner.MaxExternalPressure - environment.Pressure) * environment.Volume / (miner.SpawnTemperature * Atmospherics.R),
|
||||
miner.MaxExternalAmount - environment.TotalMoles);
|
||||
|
||||
var toSpawnReal = Math.Clamp(allowableMoles, 0f, toSpawnTarget);
|
||||
|
||||
if (toSpawnReal < Atmospherics.GasMinMoles) {
|
||||
return 0f;
|
||||
}
|
||||
|
||||
return toSpawnReal;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
using Content.Shared.Atmos;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Other.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class GasMinerComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public bool Idle { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// If the number of moles in the external environment exceeds this number, no gas will be mined.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("maxExternalAmount")]
|
||||
public float MaxExternalAmount { get; set; } = float.PositiveInfinity;
|
||||
|
||||
/// <summary>
|
||||
/// If the pressure (in kPA) of the external environment exceeds this number, no gas will be mined.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("maxExternalPressure")]
|
||||
public float MaxExternalPressure { get; set; } = Atmospherics.GasMinerDefaultMaxExternalPressure;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("spawnGas")]
|
||||
public Gas? SpawnGas { get; set; } = null;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("spawnTemperature")]
|
||||
public float SpawnTemperature { get; set; } = Atmospherics.T20C;
|
||||
|
||||
/// <summary>
|
||||
/// Number of moles created per second when the miner is working.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("spawnAmount")]
|
||||
public float SpawnAmount { get; set; } = Atmospherics.MolesCellStandard * 20f;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Atmos.Piping.Components;
|
||||
using Content.Server.Atmos.Piping.Other.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Other.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class GasMinerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GasMinerComponent, AtmosDeviceUpdateEvent>(OnMinerUpdated);
|
||||
}
|
||||
|
||||
private void OnMinerUpdated(Entity<GasMinerComponent> ent, ref AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
var miner = ent.Comp;
|
||||
|
||||
if (!GetValidEnvironment(ent, out var environment))
|
||||
{
|
||||
miner.Idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// SpawnAmount is declared in mol/s so to get the amount of gas we hope to mine, we have to multiply this by
|
||||
// how long we have been waiting to spawn it and further cap the number according to the miner's state.
|
||||
var toSpawn = CapSpawnAmount(ent, miner.SpawnAmount * args.dt, environment);
|
||||
miner.Idle = toSpawn == 0;
|
||||
if (miner.Idle || !miner.Enabled || !miner.SpawnGas.HasValue)
|
||||
return;
|
||||
|
||||
// Time to mine some gas.
|
||||
|
||||
var merger = new GasMixture(1) { Temperature = miner.SpawnTemperature };
|
||||
merger.SetMoles(miner.SpawnGas.Value, toSpawn);
|
||||
|
||||
_atmosphereSystem.Merge(environment, merger);
|
||||
}
|
||||
|
||||
private bool GetValidEnvironment(Entity<GasMinerComponent> ent, [NotNullWhen(true)] out GasMixture? environment)
|
||||
{
|
||||
var (uid, miner) = ent;
|
||||
var transform = Transform(uid);
|
||||
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||
|
||||
// Treat space as an invalid environment
|
||||
if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position))
|
||||
{
|
||||
environment = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
|
||||
return environment != null;
|
||||
}
|
||||
|
||||
private float CapSpawnAmount(Entity<GasMinerComponent> ent, float toSpawnTarget, GasMixture environment)
|
||||
{
|
||||
var (uid, miner) = ent;
|
||||
|
||||
// How many moles could we theoretically spawn. Cap by pressure and amount.
|
||||
var allowableMoles = Math.Min(
|
||||
(miner.MaxExternalPressure - environment.Pressure) * environment.Volume / (miner.SpawnTemperature * Atmospherics.R),
|
||||
miner.MaxExternalAmount - environment.TotalMoles);
|
||||
|
||||
var toSpawnReal = Math.Clamp(allowableMoles, 0f, toSpawnTarget);
|
||||
|
||||
if (toSpawnReal < Atmospherics.GasMinMoles) {
|
||||
return 0f;
|
||||
}
|
||||
|
||||
return toSpawnReal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,13 +30,12 @@ public sealed class TwoStageTriggerSystem : EntitySystem
|
|||
{
|
||||
foreach (var (name, entry) in component.SecondStageComponents)
|
||||
{
|
||||
var comp = (Component) _factory.GetComponent(name);
|
||||
var temp = (object) comp;
|
||||
var comp = (Component)_factory.GetComponent(name);
|
||||
var temp = (object)comp;
|
||||
|
||||
if (EntityManager.TryGetComponent(uid, entry.Component.GetType(), out var c))
|
||||
RemComp(uid, c);
|
||||
|
||||
comp.Owner = uid;
|
||||
_serializationManager.CopyTo(entry.Component, ref temp);
|
||||
EntityManager.AddComponent(uid, comp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ public sealed class RandomHumanoidSystem : EntitySystem
|
|||
{
|
||||
foreach (var entry in prototype.Components.Values)
|
||||
{
|
||||
var comp = (Component) _serialization.CreateCopy(entry.Component, notNullableOverride: true);
|
||||
comp.Owner = humanoid; // This .owner must survive for now.
|
||||
var comp = (Component)_serialization.CreateCopy(entry.Component, notNullableOverride: true);
|
||||
EntityManager.RemoveComponent(humanoid, comp.GetType());
|
||||
EntityManager.AddComponent(humanoid, comp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,11 @@ namespace Content.Server.Jobs
|
|||
foreach (var (name, data) in Components)
|
||||
{
|
||||
var component = (Component) factory.GetComponent(name);
|
||||
component.Owner = mob;
|
||||
|
||||
var temp = (object) component;
|
||||
var temp = (object)component;
|
||||
serializationManager.CopyTo(data.Component, ref temp);
|
||||
entityManager.RemoveComponent(mob, temp!.GetType());
|
||||
entityManager.AddComponent(mob, (Component) temp);
|
||||
entityManager.AddComponent(mob, (Component)temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Content.Server.Speech
|
|||
{
|
||||
public sealed class AccentSystem : EntitySystem
|
||||
{
|
||||
public static readonly Regex SentenceRegex = new(@"(?<=[\.!\?])", RegexOptions.Compiled);
|
||||
public static readonly Regex SentenceRegex = new(@"(?<=[\.!\?‽])(?![\.!\?‽])", RegexOptions.Compiled);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,5 +7,4 @@ namespace Content.Server.Speech.Components;
|
|||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[Access(typeof(FrenchAccentSystem))]
|
||||
public sealed partial class FrenchAccentComponent : Component
|
||||
{ }
|
||||
public sealed partial class FrenchAccentComponent : Component {}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
namespace Content.Server.Speech.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class SpanishAccentComponent : Component
|
||||
{
|
||||
}
|
||||
}
|
||||
namespace Content.Server.Speech.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class SpanishAccentComponent : Component {}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ public sealed class FrenchAccentSystem : EntitySystem
|
|||
|
||||
msg = _replacement.ApplyReplacements(msg, "french");
|
||||
|
||||
// replaces th with dz
|
||||
// replaces th with z
|
||||
msg = RegexTh.Replace(msg, "'z");
|
||||
|
||||
// removes the letter h from the start of words.
|
||||
// replaces h with ' at the start of words.
|
||||
msg = RegexStartH.Replace(msg, "'");
|
||||
|
||||
// spaces out ! ? : and ;.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Text;
|
||||
using Content.Server.Speech.Components;
|
||||
|
||||
namespace Content.Server.Speech.EntitySystems
|
||||
|
|
@ -14,7 +15,7 @@ namespace Content.Server.Speech.EntitySystems
|
|||
// Insert E before every S
|
||||
message = InsertS(message);
|
||||
// If a sentence ends with ?, insert a reverse ? at the beginning of the sentence
|
||||
message = ReplaceQuestionMark(message);
|
||||
message = ReplacePunctuation(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
|
@ -36,24 +37,32 @@ namespace Content.Server.Speech.EntitySystems
|
|||
return msg;
|
||||
}
|
||||
|
||||
private string ReplaceQuestionMark(string message)
|
||||
private string ReplacePunctuation(string message)
|
||||
{
|
||||
var sentences = AccentSystem.SentenceRegex.Split(message);
|
||||
var msg = "";
|
||||
var msg = new StringBuilder();
|
||||
foreach (var s in sentences)
|
||||
{
|
||||
if (s.EndsWith("?", StringComparison.Ordinal)) // We've got a question => add ¿ to the beginning
|
||||
var toInsert = new StringBuilder();
|
||||
for (var i = s.Length - 1; i >= 0 && "?!‽".Contains(s[i]); i--)
|
||||
{
|
||||
// Because we don't split by whitespace, we may have some spaces in front of the sentence.
|
||||
// So we add the symbol before the first non space char
|
||||
msg += s.Insert(s.Length - s.TrimStart().Length, "¿");
|
||||
toInsert.Append(s[i] switch
|
||||
{
|
||||
'?' => '¿',
|
||||
'!' => '¡',
|
||||
'‽' => '⸘',
|
||||
_ => ' '
|
||||
});
|
||||
}
|
||||
else
|
||||
if (toInsert.Length == 0)
|
||||
{
|
||||
msg += s;
|
||||
msg.Append(s);
|
||||
} else
|
||||
{
|
||||
msg.Append(s.Insert(s.Length - s.TrimStart().Length, toInsert.ToString()));
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
return msg.ToString();
|
||||
}
|
||||
|
||||
private void OnAccent(EntityUid uid, SpanishAccentComponent component, AccentGetEvent args)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ public sealed partial class BiomePrototype : IPrototype, IInheritingPrototype
|
|||
foreach (var data in ChunkComponents.Values)
|
||||
{
|
||||
var comp = (Component) serialization.CreateCopy(data.Component, notNullableOverride: true);
|
||||
comp.Owner = target; // look im sorry ok this .owner has to live until engine api exists
|
||||
entityManager.AddComponent(target, comp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ public sealed partial class WorldgenConfigPrototype : IPrototype
|
|||
foreach (var data in Components.Values)
|
||||
{
|
||||
var comp = (Component) serialization.CreateCopy(data.Component, notNullableOverride: true);
|
||||
comp.Owner = target; // look im sorry ok this .owner has to live until engine api exists
|
||||
entityManager.AddComponent(target, comp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,13 +182,12 @@ public sealed partial class ArtifactSystem
|
|||
EntityManager.RemoveComponent(uid, reg.Type);
|
||||
}
|
||||
|
||||
var comp = (Component) _componentFactory.GetComponent(reg);
|
||||
comp.Owner = uid;
|
||||
var comp = (Component)_componentFactory.GetComponent(reg);
|
||||
|
||||
var temp = (object) comp;
|
||||
var temp = (object)comp;
|
||||
_serialization.CopyTo(entry.Component, ref temp);
|
||||
EntityManager.RemoveComponent(uid, temp!.GetType());
|
||||
EntityManager.AddComponent(uid, (Component) temp!);
|
||||
EntityManager.AddComponent(uid, (Component)temp!);
|
||||
}
|
||||
|
||||
node.Discovered = true;
|
||||
|
|
@ -218,12 +217,11 @@ public sealed partial class ArtifactSystem
|
|||
// if the entity prototype contained the component originally
|
||||
if (entityPrototype?.Components.TryGetComponent(name, out var entry) ?? false)
|
||||
{
|
||||
var comp = (Component) _componentFactory.GetComponent(name);
|
||||
comp.Owner = uid;
|
||||
var temp = (object) comp;
|
||||
var comp = (Component)_componentFactory.GetComponent(name);
|
||||
var temp = (object)comp;
|
||||
_serialization.CopyTo(entry, ref temp);
|
||||
EntityManager.RemoveComponent(uid, temp!.GetType());
|
||||
EntityManager.AddComponent(uid, (Component) temp);
|
||||
EntityManager.AddComponent(uid, (Component)temp);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
60
Content.Shared/Atmos/Components/GasMinerComponent.cs
Normal file
60
Content.Shared/Atmos/Components/GasMinerComponent.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Atmos.Components;
|
||||
|
||||
[NetworkedComponent]
|
||||
[AutoGenerateComponentState]
|
||||
[RegisterComponent]
|
||||
public sealed partial class GasMinerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Operational state of the miner.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public GasMinerState MinerState = GasMinerState.Disabled;
|
||||
|
||||
/// <summary>
|
||||
/// If the number of moles in the external environment exceeds this number, no gas will be mined.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public float MaxExternalAmount = float.PositiveInfinity;
|
||||
|
||||
/// <summary>
|
||||
/// If the pressure (in kPA) of the external environment exceeds this number, no gas will be mined.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public float MaxExternalPressure = Atmospherics.GasMinerDefaultMaxExternalPressure;
|
||||
|
||||
/// <summary>
|
||||
/// Gas to spawn.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField(required: true)]
|
||||
public Gas SpawnGas;
|
||||
|
||||
/// <summary>
|
||||
/// Temperature in Kelvin.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public float SpawnTemperature = Atmospherics.T20C;
|
||||
|
||||
/// <summary>
|
||||
/// Number of moles created per second when the miner is working.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public float SpawnAmount = Atmospherics.MolesCellStandard * 20f;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum GasMinerState : byte
|
||||
{
|
||||
Disabled,
|
||||
Idle,
|
||||
Working,
|
||||
}
|
||||
55
Content.Shared/Atmos/EntitySystems/SharedGasMinerSystem.cs
Normal file
55
Content.Shared/Atmos/EntitySystems/SharedGasMinerSystem.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Temperature;
|
||||
|
||||
namespace Content.Shared.Atmos.EntitySystems;
|
||||
|
||||
public abstract class SharedGasMinerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAtmosphereSystem _sharedAtmosphereSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasMinerComponent, ExaminedEvent>(OnExamine);
|
||||
}
|
||||
|
||||
private void OnExamine(Entity<GasMinerComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
var component = ent.Comp;
|
||||
|
||||
using (args.PushGroup(nameof(GasMinerComponent)))
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("gas-miner-mines-text",
|
||||
("gas", Loc.GetString(_sharedAtmosphereSystem.GetGas(component.SpawnGas).Name))));
|
||||
|
||||
args.PushText(Loc.GetString("gas-miner-amount-text",
|
||||
("moles", $"{component.SpawnAmount:0.#}")));
|
||||
|
||||
args.PushText(Loc.GetString("gas-miner-temperature-text",
|
||||
("tempK", $"{component.SpawnTemperature:0.#}"),
|
||||
("tempC", $"{TemperatureHelpers.KelvinToCelsius(component.SpawnTemperature):0.#}")));
|
||||
|
||||
if (component.MaxExternalAmount < float.PositiveInfinity)
|
||||
{
|
||||
args.PushText(Loc.GetString("gas-miner-moles-cutoff-text",
|
||||
("moles", $"{component.MaxExternalAmount:0.#}")));
|
||||
}
|
||||
|
||||
if (component.MaxExternalPressure < float.PositiveInfinity)
|
||||
{
|
||||
args.PushText(Loc.GetString("gas-miner-pressure-cutoff-text",
|
||||
("pressure", $"{component.MaxExternalPressure:0.#}")));
|
||||
}
|
||||
|
||||
args.AddMarkup(component.MinerState switch
|
||||
{
|
||||
GasMinerState.Disabled => Loc.GetString("gas-miner-state-disabled-text"),
|
||||
GasMinerState.Idle => Loc.GetString("gas-miner-state-idle-text"),
|
||||
GasMinerState.Working => Loc.GetString("gas-miner-state-working-text"),
|
||||
// C# pattern matching is not exhaustive for enums
|
||||
_ => throw new IndexOutOfRangeException(nameof(component.MinerState)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -369,11 +369,10 @@ public abstract class SharedMagicSystem : EntitySystem
|
|||
if (HasComp(ev.Target, data.Component.GetType()))
|
||||
continue;
|
||||
|
||||
var component = (Component) _compFact.GetComponent(name);
|
||||
component.Owner = ev.Target;
|
||||
var temp = (object) component;
|
||||
var component = (Component)_compFact.GetComponent(name);
|
||||
var temp = (object)component;
|
||||
_seriMan.CopyTo(data.Component, ref temp);
|
||||
EntityManager.AddComponent(ev.Target, (Component) temp!);
|
||||
EntityManager.AddComponent(ev.Target, (Component)temp!);
|
||||
}
|
||||
}
|
||||
// End Change Component Spells
|
||||
|
|
|
|||
|
|
@ -80,11 +80,6 @@ public partial class MobStateSystem
|
|||
case MobState.Dead:
|
||||
RemComp<CollisionWakeComponent>(target);
|
||||
_standing.Stand(target);
|
||||
if (!_standing.IsDown(target) && TryComp<PhysicsComponent>(target, out var physics))
|
||||
{
|
||||
_physics.SetCanCollide(target, true, body: physics);
|
||||
}
|
||||
|
||||
break;
|
||||
case MobState.Invalid:
|
||||
//unused
|
||||
|
|
@ -115,12 +110,6 @@ public partial class MobStateSystem
|
|||
case MobState.Dead:
|
||||
EnsureComp<CollisionWakeComponent>(target);
|
||||
_standing.Down(target);
|
||||
|
||||
if (_standing.IsDown(target) && TryComp<PhysicsComponent>(target, out var physics))
|
||||
{
|
||||
_physics.SetCanCollide(target, false, body: physics);
|
||||
}
|
||||
|
||||
_appearance.SetData(target, MobStateVisuals.State, MobState.Dead);
|
||||
break;
|
||||
case MobState.Invalid:
|
||||
|
|
|
|||
|
|
@ -1,28 +1,4 @@
|
|||
Entries:
|
||||
- author: Plykiya
|
||||
changes:
|
||||
- message: The ninja's katana dash is now more reliable.
|
||||
type: Fix
|
||||
id: 6556
|
||||
time: '2024-05-08T10:21:59.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27793
|
||||
- author: K-Dynamic
|
||||
changes:
|
||||
- message: Bike Horns, Suspenders and the Clown Recorder are now available from
|
||||
the Theatrical Performances Crate
|
||||
type: Tweak
|
||||
id: 6557
|
||||
time: '2024-05-08T12:30:43.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27668
|
||||
- author: Riolume
|
||||
changes:
|
||||
- message: Added ability to drink from spray bottles
|
||||
type: Add
|
||||
- message: Can now see the amount of liquid in spray bottles
|
||||
type: Add
|
||||
id: 6558
|
||||
time: '2024-05-09T05:56:13.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27815
|
||||
- author: Blackern5000
|
||||
changes:
|
||||
- message: Atmos metal pipes now deal blunt damage.
|
||||
|
|
@ -3784,3 +3760,24 @@
|
|||
id: 7055
|
||||
time: '2024-08-07T09:26:40.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29746
|
||||
- author: IProduceWidgets
|
||||
changes:
|
||||
- message: butter is slippery
|
||||
type: Tweak
|
||||
id: 7056
|
||||
time: '2024-08-07T21:47:03.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/29772
|
||||
- author: Mervill
|
||||
changes:
|
||||
- message: Gas Miners now have detailed examine text
|
||||
type: Tweak
|
||||
id: 7057
|
||||
time: '2024-08-08T02:14:31.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/30480
|
||||
- author: BackeTako
|
||||
changes:
|
||||
- message: "!, \u203D and multiple punctuations now work for Spanish."
|
||||
type: Tweak
|
||||
id: 7058
|
||||
time: '2024-08-08T03:08:28.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/30551
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
advertisement-atmosdrobe-1 = Get your inflammable clothing right here!!!
|
||||
advertisement-atmosdrobe-2 = Protects you against plasma fires!
|
||||
advertisement-atmosdrobe-3 = Enjoy your off-brand engineering clothing!
|
||||
advertisement-atmosdrobe-3 = Enjoy your off-brand engineering clothing!
|
||||
advertisement-atmosdrobe-4 = Always under control of your atmosphere!
|
||||
advertisement-atmosdrobe-5 = Providing comfort in every breath!
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
advertisement-chefdrobe-1 = Our clothes are guaranteed to protect you from food splatters!
|
||||
advertisement-chefdrobe-1 = Our clothes are guaranteed to protect you from food splatters!
|
||||
advertisement-chefdrobe-2 = Perfectly white, so everyone knows about the murder in the kitchen!
|
||||
advertisement-chefdrobe-3 = Easy to clean, easy to see!
|
||||
advertisement-chefdrobe-4 = Cook like a pro, look like a maestro!
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
advertisement-chemdrobe-1 = Our clothes are 0.5% more resistant to acid spills! Get yours now!
|
||||
advertisement-chemdrobe-2 = Professional laboratory clothing, designed by NanoTrasen!
|
||||
advertisement-chemdrobe-3 = I'm pretty sure these will protect you against acid spills!
|
||||
advertisement-chemdrobe-3 = I'm pretty sure these will protect you against acid spills!
|
||||
advertisement-chemdrobe-4 = The best fashion formula!
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ advertisement-donut-2 = Hope you're hunger!
|
|||
advertisement-donut-3 = Over 1 million donuts sold!
|
||||
advertisement-donut-4 = We pride ourselves in the consistency of our products!
|
||||
advertisement-donut-5 = Sweet, sugary and delicious!
|
||||
advertisement-donut-6 = Donut worry, be happy!
|
||||
thankyou-donut-1 = Enjoy your donut!
|
||||
thankyou-donut-2 = Another donut sold!
|
||||
thankyou-donut-3 = Have a nice day, officer!
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
advertisement-hydrobe-1 = Do you love soil? Then buy our clothes!
|
||||
advertisement-hydrobe-2 = Get outfits to match your green thumb here!
|
||||
advertisement-hydrobe-3 = Here to give you an outfit perfect for handling plants!
|
||||
advertisement-hydrobe-4 = Perfect outfits for tree huggers... or just literal trees!
|
||||
advertisement-hydrobe-4 = Perfect outfits for tree huggers... or just literal trees!
|
||||
advertisement-hydrobe-5 = Wear green and grow!
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
advertisement-janidrobe-1 = Come and get your janitorial clothing, now endorsed by lizard janitors everywhere!
|
||||
advertisement-janidrobe-2 = Here to keep you clean as you clean up non-clean things!
|
||||
advertisement-janidrobe-3 = Stylishly yellow!
|
||||
|
||||
advertisement-janidrobe-4 = Polish your appearance with JaniDrobe!
|
||||
advertisement-janidrobe-5 = Shine like a shiny floor!
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ advertisement-lawdrobe-5 = No one is above the law!
|
|||
advertisement-lawdrobe-6 = No officer, I do not consent to a search!
|
||||
advertisement-lawdrobe-7 = Injecting space drugs leaves no evidence!
|
||||
advertisement-lawdrobe-8 = You or a loved one hurt by Nanotrasen? Too bad!
|
||||
advertisement-lawdrobe-9 = Case closed! Defendant has too much drip!
|
||||
thankyou-lawdrobe-1 = You can win any case in that outfit!
|
||||
thankyou-lawdrobe-2 = Get one for your client as well!
|
||||
thankyou-lawdrobe-3 = Win or lose, you get paid either way!
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
advertisement-medidrobe-1 = Make those blood stains look fashionable!!
|
||||
advertisement-medidrobe-2 = Clean and hygienic! Don't get too many bloodstains on yourself!
|
||||
advertisement-medidrobe-3 = With these outfits, you'll look like a professional doctor now!
|
||||
advertisement-medidrobe-4 = Jumpsuit, check. Coat, check. Someone who will wear this? Check!
|
||||
|
|
|
|||
11
Resources/Locale/en-US/atmos/gas-miner-component.ftl
Normal file
11
Resources/Locale/en-US/atmos/gas-miner-component.ftl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
gas-miner-mines-text = It mines [color=lightgray]{$gas}[/color] when active.
|
||||
|
||||
gas-miner-amount-text = It mines {$moles} moles of gas a second when active.
|
||||
gas-miner-temperature-text = Mined gas temp: {$tempK}K ({$tempC}°C).
|
||||
|
||||
gas-miner-moles-cutoff-text = Surrounding moles cutoff: {$moles} moles.
|
||||
gas-miner-pressure-cutoff-text = Surrounding pressure cutoff: {$pressure} kPA.
|
||||
|
||||
gas-miner-state-working-text = The miner is [color=green]active[/color] and mining gas.
|
||||
gas-miner-state-idle-text = The miner is [color=yellow]idle[/color] and not mining gas.
|
||||
gas-miner-state-disabled-text = The miner is [color=red]disabled[/color] and not mining gas.
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
id: AtmosDrobeAds
|
||||
values:
|
||||
prefix: advertisement-atmosdrobe-
|
||||
count: 3
|
||||
count: 5
|
||||
|
||||
- type: localizedDataset
|
||||
id: BarDrobeAds
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
id: ChefDrobeAds
|
||||
values:
|
||||
prefix: advertisement-chefdrobe-
|
||||
count: 3
|
||||
count: 4
|
||||
|
||||
- type: localizedDataset
|
||||
id: ChefvendAds
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
id: ChemDrobeAds
|
||||
values:
|
||||
prefix: advertisement-chemdrobe-
|
||||
count: 3
|
||||
count: 4
|
||||
|
||||
- type: localizedDataset
|
||||
id: CigaretteMachineAds
|
||||
|
|
@ -110,7 +110,7 @@
|
|||
id: DonutAds
|
||||
values:
|
||||
prefix: advertisement-donut-
|
||||
count: 5
|
||||
count: 6
|
||||
|
||||
- type: localizedDataset
|
||||
id: EngiDrobeAds
|
||||
|
|
@ -146,19 +146,19 @@
|
|||
id: HyDrobeAds
|
||||
values:
|
||||
prefix: advertisement-hydrobe-
|
||||
count: 4
|
||||
count: 5
|
||||
|
||||
- type: localizedDataset
|
||||
id: JaniDrobeAds
|
||||
values:
|
||||
prefix: advertisement-janidrobe-
|
||||
count: 3
|
||||
count: 5
|
||||
|
||||
- type: localizedDataset
|
||||
id: LawDrobeAds
|
||||
values:
|
||||
prefix: advertisement-lawdrobe-
|
||||
count: 8
|
||||
count: 9
|
||||
|
||||
- type: localizedDataset
|
||||
id: MagiVendAds
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
id: MediDrobeAds
|
||||
values:
|
||||
prefix: advertisement-medidrobe-
|
||||
count: 3
|
||||
count: 4
|
||||
|
||||
- type: localizedDataset
|
||||
id: MegaSeedAds
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Lots of misc stuff in here, hard to parent it.
|
||||
# ^ Yeah, this stuff should probably get split into different files but not my fight today.
|
||||
|
||||
# Powder (For when you throw stuff like flour and it explodes)
|
||||
|
||||
|
|
@ -481,10 +482,33 @@
|
|||
components:
|
||||
- type: Sprite
|
||||
state: butter
|
||||
- type: Slippery
|
||||
- type: StepTrigger
|
||||
intersectRatio: 0.2
|
||||
- type: CollisionWake
|
||||
enabled: false
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
slips:
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.3,-0.2,0.3,0.2"
|
||||
layer:
|
||||
- SlipLayer
|
||||
hard: false
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.3,-0.2,0.3,0.2"
|
||||
density: 10
|
||||
mask:
|
||||
- ItemMask
|
||||
|
||||
- type: entity
|
||||
name: stick of cannabis butter
|
||||
parent: FoodBakingBase
|
||||
parent: FoodButter
|
||||
id: FoodCannabisButter
|
||||
description: Add this to your favorite baked goods for an irie time.
|
||||
components:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5c0ce43e6c3c22a939fad8a9f9848e489b135651
|
||||
Subproject commit 49c831b48d1449e90a65acdb0c276d2deea4ce2c
|
||||
Loading…
Add table
Reference in a new issue