Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MODsuits (Port From Goob #1242) #1640

Merged
merged 52 commits into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
eefdf2f
What have I chosen to do here? What is the end goal?
Erisfiregamer1 Jan 23, 2025
2c2d5e5
Merge branch 'master' into modsuits
Erisfiregamer1 Jan 23, 2025
7c5e0bb
A
Erisfiregamer1 Jan 23, 2025
e433036
Merge branch 'modsuits' of https://github.com/Erisfiregamer1/Einstein…
Erisfiregamer1 Jan 23, 2025
f975bad
Porting
Erisfiregamer1 Jan 23, 2025
bf5642e
guh
Erisfiregamer1 Jan 23, 2025
d4cc0bb
Hell
Erisfiregamer1 Jan 23, 2025
a65dd57
MORE FIXES!!!
Erisfiregamer1 Jan 23, 2025
09bbdaa
fix
Erisfiregamer1 Jan 23, 2025
154c4e1
Robbery of Goobcode
Erisfiregamer1 Jan 23, 2025
81f38c2
Fix 1
Erisfiregamer1 Jan 23, 2025
904267e
MORE FIX
Erisfiregamer1 Jan 23, 2025
57e026e
I feel like this'll breka shit
Erisfiregamer1 Jan 23, 2025
5dbafaa
I am losing my grip on reality, AGAIN
Erisfiregamer1 Jan 23, 2025
3e260e2
Cleanup (Mostly just hitting tests with lots of BRICKS)
Erisfiregamer1 Jan 23, 2025
d636dbf
i am slowly losing my grip on reality
Erisfiregamer1 Jan 23, 2025
41b04d1
Fixes!!
Erisfiregamer1 Jan 23, 2025
1e4b4cc
MORE FIXES!!!
Erisfiregamer1 Jan 23, 2025
46c51a3
I will make these damn suits work if it is the LAST thing I do
Erisfiregamer1 Jan 23, 2025
f5be2a6
I think I'm having a minor stroke, but that should be all the NECCESA…
Erisfiregamer1 Jan 23, 2025
a5af3a9
Fixes
Erisfiregamer1 Jan 23, 2025
28bf089
screaming into the void
Erisfiregamer1 Jan 23, 2025
8702381
PATC HES
Erisfiregamer1 Jan 23, 2025
a729157
That *Should!!* be everything
Erisfiregamer1 Jan 23, 2025
314eceb
Nitpicks
Erisfiregamer1 Jan 23, 2025
1f76e17
Merge branch 'master' into modsuits
Erisfiregamer1 Jan 23, 2025
9cddea8
Finishing touches (and a logger in Barotrauma in case it breaks again…
Erisfiregamer1 Jan 23, 2025
9e13bdf
Merge branch 'modsuits' of https://github.com/Erisfiregamer1/Einstein…
Erisfiregamer1 Jan 23, 2025
b4066a9
Oop
Erisfiregamer1 Jan 23, 2025
4955a5c
J
Erisfiregamer1 Jan 23, 2025
f024c58
GET ME OUT OF THIS GODFORSAKEN REVIEW
Erisfiregamer1 Jan 24, 2025
7446237
please let me OUT!!! of hell (i did nothing wrong)
Erisfiregamer1 Jan 24, 2025
a860ffe
Update Content.Shared/_Goobstation/Clothing/Systems/SharedSealableClo…
Erisfiregamer1 Jan 24, 2025
17f73c3
i still cant sleep i have to fix more shit this is BADDD
Erisfiregamer1 Jan 24, 2025
13d35cf
Oops, Another Build Failure!
Erisfiregamer1 Jan 24, 2025
4b8773b
BUILD REPAIR.
Erisfiregamer1 Jan 24, 2025
938e0a7
Buildfix 2
Erisfiregamer1 Jan 24, 2025
0c00728
Death fix
Erisfiregamer1 Jan 24, 2025
5f36a6c
More dathfixes
Erisfiregamer1 Jan 24, 2025
540cde7
THIS ISNT FUCKING LUA WHY IS THIS VALID SYNTAX. HELLO?
Erisfiregamer1 Jan 24, 2025
8b6992a
patc
Erisfiregamer1 Jan 24, 2025
4984829
Patches !!!
Erisfiregamer1 Jan 24, 2025
59c3369
Merge branch 'master' into modsuits
Erisfiregamer1 Jan 24, 2025
32f68dc
Help.
Erisfiregamer1 Jan 25, 2025
7ee91cc
Merge branch 'modsuits' of https://github.com/Erisfiregamer1/Einstein…
Erisfiregamer1 Jan 25, 2025
53d0845
Merge branch 'master' into modsuits
Erisfiregamer1 Jan 25, 2025
6da4071
Update Content.Server/Body/Systems/LungSystem.cs
Erisfiregamer1 Jan 25, 2025
b9ecc76
Update Content.Server/Body/Systems/LungSystem.cs
Erisfiregamer1 Jan 25, 2025
442be7c
Update Content.Client/_Goobstation/Clothing/ToggleableClothingRadialM…
Erisfiregamer1 Jan 25, 2025
7f5d1e4
GRAHHHHH
Erisfiregamer1 Jan 25, 2025
87f84a5
Update Resources/Prototypes/_Goobstation/Research/experimental.yml
Erisfiregamer1 Jan 25, 2025
d89185d
WHY.
Erisfiregamer1 Jan 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Content.Client/DoAfter/DoAfterOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ protected override void Draw(in OverlayDrawArgs args)
var alpha = 1f;
if (doAfter.Args.Hidden)
{
if (uid != localEnt)
// Goobstation - Show doAfter progress bar to another entity
if (uid != localEnt && localEnt != doAfter.Args.ShowTo)
continue;

// Hints to the local player that this do-after is not visible to other players.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Content.Client._Goobstation.Clothing.Components;

[RegisterComponent]
public sealed partial class SealableClothingVisualsComponent : Component
{
[DataField]
public string SpriteLayer = "sealed";

[DataField]
public Dictionary<string, List<PrototypeLayerData>> VisualLayers = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Content.Shared._Goobstation.Clothing.Systems;

namespace Content.Client._Goobstation.Clothing.EntitySystems;

public sealed class PoweredSealableClothingSystem : SharedPoweredSealableClothingSystem
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Content.Shared._Goobstation.Clothing.Systems;

namespace Content.Client._Goobstation.Clothing.EntitySystems;

public sealed partial class SealableClothingSystem : SharedSealableClothingSystem
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Content.Client._Goobstation.Clothing.Components;
using Content.Client.Clothing;
using Content.Shared._Goobstation.Clothing;
using Content.Shared.Clothing;
using Content.Shared.Item;
using Robust.Client.GameObjects;
using System.Linq;

namespace Content.Client._Goobstation.Clothing.EntitySystems;

public sealed class SealableClothingVisualizerSystem : VisualizerSystem<SealableClothingVisualsComponent>
{
[Dependency] private readonly SharedItemSystem _itemSystem = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SealableClothingVisualsComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals, after: new[] { typeof(ClientClothingSystem) });
}

protected override void OnAppearanceChange(EntityUid uid, SealableClothingVisualsComponent component, ref AppearanceChangeEvent args)
{
if (!AppearanceSystem.TryGetData<bool>(uid, SealableClothingVisuals.Sealed, out var isSealed, args.Component))
return;

if (args.Sprite != null && component.SpriteLayer != null && args.Sprite.LayerMapTryGet(component.SpriteLayer, out var layer))
args.Sprite.LayerSetVisible(layer, isSealed);

_itemSystem.VisualsChanged(uid);
}

private void OnGetEquipmentVisuals(Entity<SealableClothingVisualsComponent> sealable, ref GetEquipmentVisualsEvent args)
{
var (uid, comp) = sealable;

if (!TryComp(uid, out AppearanceComponent? appearance)
|| !AppearanceSystem.TryGetData<bool>(uid, SealableClothingVisuals.Sealed, out var isSealed, appearance)
|| !isSealed)
return;

if (!comp.VisualLayers.TryGetValue(args.Slot, out var layers))
return;

var i = 0;
foreach (var layer in layers)
{
var key = layer.MapKeys?.FirstOrDefault();
if (key == null)
{
key = i == 0 ? $"{args.Slot}-sealed" : $"{args.Slot}-sealed-{i}";
i++;
}

args.Layers.Add((key, layer));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared.Clothing.Components;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;

namespace Content.Client._Goobstation.Clothing;

public sealed class ToggleableClothingBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IClyde _displayManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;

private IEntityManager _entityManager;
private ToggleableClothingRadialMenu? _menu;

public ToggleableClothingBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
IoCManager.InjectDependencies(this);
_entityManager = IoCManager.Resolve<IEntityManager>();
}

protected override void Open()
{
base.Open();

_menu = this.CreateWindow<ToggleableClothingRadialMenu>();
_menu.SetEntity(Owner);
_menu.SendToggleClothingMessageAction += SendToggleableClothingMessage;

var vpSize = _displayManager.ScreenSize;
_menu.OpenCenteredAt(_inputManager.MouseScreenPosition.Position / vpSize);
}

private void SendToggleableClothingMessage(EntityUid uid)
{
var message = new ToggleableClothingUiMessage(_entityManager.GetNetEntity(uid));
SendPredictedMessage(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<ui:RadialMenu xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
BackButtonStyleClass="RadialMenuBackButton" CloseButtonStyleClass="RadialMenuCloseButton"
VerticalExpand="True" HorizontalExpand="True" MinSize="450 450">
<ui:RadialContainer Name="Main" VerticalExpand="True" HorizontalExpand="True" Radius="64" ReserveSpaceForHiddenChildren="False" />
</ui:RadialMenu>
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.Clothing.Components;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using System.Numerics;

namespace Content.Client._Goobstation.Clothing;

public sealed partial class ToggleableClothingRadialMenu : RadialMenu
{
[Dependency] private readonly EntityManager _entityManager = default!;

public event Action<EntityUid>? SendToggleClothingMessageAction;

public EntityUid Entity { get; set; }

public ToggleableClothingRadialMenu()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
}

public void SetEntity(EntityUid uid)
{
Entity = uid;
RefreshUI();
}

public void RefreshUI()
{
// Even EmotesMenu has to call this, I'm assuming it's essential.
var main = FindControl<RadialContainer>("Main");
Erisfiregamer1 marked this conversation as resolved.
Show resolved Hide resolved

if (!_entityManager.TryGetComponent<ToggleableClothingComponent>(Entity, out var clothing)
|| clothing.Container is not { } clothingContainer)
return;

foreach (var attached in clothing.ClothingUids)
{
// Change tooltip text if attached clothing is toggle/untoggled
var tooltipText = Loc.GetString(clothing.UnattachTooltip);

if (clothingContainer.Contains(attached.Key))
tooltipText = Loc.GetString(clothing.AttachTooltip);

var button = new ToggleableClothingRadialMenuButton()
{
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64, 64),
ToolTip = tooltipText,
AttachedClothingId = attached.Key
};

var spriteView = new SpriteView()
{
SetSize = new Vector2(48, 48),
VerticalAlignment = VAlignment.Center,
HorizontalAlignment = HAlignment.Center,
Stretch = SpriteView.StretchMode.Fill
};

spriteView.SetEntity(attached.Key);

button.AddChild(spriteView);
main.AddChild(button);
Erisfiregamer1 marked this conversation as resolved.
Show resolved Hide resolved
}

AddToggleableClothingMenuButtonOnClickAction(main);
}

private void AddToggleableClothingMenuButtonOnClickAction(Control control)
{
if (control is not RadialContainer mainControl)
return;

foreach (var child in mainControl.Children)
{
if (child is not ToggleableClothingRadialMenuButton castChild)
continue;

castChild.OnButtonDown += _ =>
{
SendToggleClothingMessageAction?.Invoke(castChild.AttachedClothingId);
mainControl.DisposeAllChildren();
RefreshUI();
};
}
}
}

public sealed class ToggleableClothingRadialMenuButton : RadialMenuTextureButton
{
public EntityUid AttachedClothingId { get; set; }
}
33 changes: 30 additions & 3 deletions Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,27 @@ public sealed class BarotraumaSystem : EntitySystem
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger= default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;

[Dependency] private readonly ILogManager _logManager = default!;

private const float UpdateTimer = 1f;

private ISawmill _sawmill = default!;
private float _timer;

public override void Initialize()
{
SubscribeLocalEvent<PressureProtectionComponent, GotEquippedEvent>(OnPressureProtectionEquipped);
SubscribeLocalEvent<PressureProtectionComponent, GotUnequippedEvent>(OnPressureProtectionUnequipped);
SubscribeLocalEvent<PressureProtectionComponent, ComponentInit>(OnUpdateResistance);
SubscribeLocalEvent<PressureProtectionComponent, ComponentRemove>(OnUpdateResistance);
SubscribeLocalEvent<PressureProtectionComponent, ComponentInit>(OnPressureProtectionChanged); // Goobstation - Update component state on toggle
SubscribeLocalEvent<PressureProtectionComponent, ComponentRemove>(OnPressureProtectionChanged); // Goobstation - Update component state on toggle

SubscribeLocalEvent<PressureImmunityComponent, ComponentInit>(OnPressureImmuneInit);
SubscribeLocalEvent<PressureImmunityComponent, ComponentRemove>(OnPressureImmuneRemove);

// _sawmill = _logManager.GetSawmill("barotrauma");
}

private void OnPressureImmuneInit(EntityUid uid, PressureImmunityComponent pressureImmunity, ComponentInit args)
Expand All @@ -51,6 +57,27 @@ private void OnPressureImmuneRemove(EntityUid uid, PressureImmunityComponent pre
}
}

// Goobstation - Modsuits - Update component state on toggle
private void OnPressureProtectionChanged(EntityUid uid, PressureProtectionComponent pressureProtection, EntityEventArgs args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reminds me that I would LOVE to eventually have a system that makes it so that taking enough damage while wearing space gear makes it lose its pressure protection(Or "Degrade" its pressure protection). That is until the suit is repaired, which is a process that requires you first take the suit off, and either sew back up the kevlar seals if it's a vacsuit, or otherwise weld the holes back shut. That was actually the intended way to differentiate Vacsuits > Hardsuits > Tacsuits > Modsuits

Vacsuits: Cheap as fuck, extremely common. ANY amount of physical damage ruins the protection. You are NOT fighting in these.

Hardsuits: Has extremely significant "Pressure sealing" against anything other than Piercing damage. You can get hit by a rock in space, and the suit will probably still work. Gunfire however will fuck it up. Don't wear one to a gunfight.

Tacsuits: Trades the "Blunt Object Sealing" for "Gunfire Sealing". Can take a burst of machine gun fire and still be able to keep the void of space from boiling off your eyeballs. Don't wear one to a meteor shower.

Modsuits: The tradeoff between Hardsuit & Tacsuit's style of protection is essentially an "Operator's Choice" slider depending on how its configured. I imagine it almost like the comparison between Clan Omnimechs and Inner Sphere Battlemechs. The former's a mech where you basically throw your whole bank account into a furnace to gain the ability to hotswap mech configurations within an hour instead of weeks/months. The latter being cheap industrial quantity manufactured workhorses that are made to do just one thing and be good at only that one thing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't consider this comment to be a requirement by the way, just musings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be awesome and I agree. Maybe in PR 2 (general touch-ups)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't, I have an idea for it already

{
var protectionTarget = uid;
string? slotTarget = null;

if (_inventorySystem.TryGetContainingEntity(uid, out var entity) && _inventorySystem.TryGetContainingSlot(uid, out var slot))
{
protectionTarget = entity.Value;
slotTarget = slot.Name;
}

if (!TryComp<BarotraumaComponent>(protectionTarget, out var barotrauma))
return;

if (slotTarget != null && !barotrauma.ProtectionSlots.Contains(slotTarget))
return;

UpdateCachedResistances(protectionTarget, barotrauma);
}

/// <summary>
/// Generic method for updating resistance on component Lifestage events
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions Content.Server/Body/Components/LungComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,10 @@ public sealed partial class LungComponent : Component
/// </summary>
[DataField]
public ProtoId<AlertPrototype> Alert = "LowOxygen";

[DataField]
public float MaxVolume = 100f;

[DataField]
public bool CanReact = false; // No Dexalin lungs... right?
}
42 changes: 34 additions & 8 deletions Content.Server/Body/Systems/LungSystem.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Chemistry.Components;
using Content.Shared.Clothing;
using Content.Shared.Inventory.Events;
using Content.Shared.Inventory;
using Content.Server.Power.EntitySystems;
using Robust.Server.Containers;

namespace Content.Server.Body.Systems;

public sealed class LungSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmos = default!;
[Dependency] private readonly InternalsSystem _internals = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly InternalsSystem _internals = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly InventorySystem _inventory = default!; // Goobstation



public static string LungSolutionName = "Lung";

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LungComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<BreathToolComponent, ComponentInit>(OnBreathToolInit); // Goobstation - Modsuits - Update on component toggle
SubscribeLocalEvent<BreathToolComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<BreathToolComponent, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<BreathToolComponent, ItemMaskToggledEvent>(OnMaskToggled);
Expand Down Expand Up @@ -50,16 +56,36 @@ private void OnGotEquipped(Entity<BreathToolComponent> ent, ref GotEquippedEvent

private void OnComponentInit(Entity<LungComponent> entity, ref ComponentInit args)
{
var solution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName);
solution.MaxVolume = 100.0f;
solution.CanReact = false; // No dexalin lungs
if (_solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName, out var solution))
{
solution.MaxVolume = entity.Comp.MaxVolume;
solution.CanReact = entity.Comp.CanReact;
}
}

// Goobstation - Update component state on component toggle
private void OnBreathToolInit(Entity<BreathToolComponent> ent, ref ComponentInit args)
{
var comp = ent.Comp;

comp.IsFunctional = true;

if (!_inventory.TryGetContainingEntity(ent.Owner, out var parent)
|| !_inventory.TryGetContainingSlot(ent.Owner, out var slot)
|| (slot.SlotFlags & comp.AllowedSlots) == 0
|| !TryComp(parent, out InternalsComponent? internals))
return;

ent.Comp.ConnectedInternalsEntity = parent;
_internals.ConnectBreathTool((parent.Value, internals), ent);
}


private void OnMaskToggled(Entity<BreathToolComponent> ent, ref ItemMaskToggledEvent args)
{
if (args.IsToggled || args.IsEquip)
{
_atmos.DisconnectInternals(ent.Comp);
_atmosphereSystem.DisconnectInternals(ent);
}
else
{
Expand Down
Loading
Loading