Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
682 changes: 682 additions & 0 deletions Content.Common.Data/_Goobstation/CCVar/CCVars.Goob.cs

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions Content.Common.Data/_Goobstation/Chemistry/ChemistryEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
// SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

namespace Content.Goobstation.Common.Chemistry;

/// <summary>
/// This event is fired off when a solution reacts.
/// </summary>
[ByRefEvent]
public sealed partial class SolutionReactedEvent : EntityEventArgs;

/// <summary>
/// This event is fired off before a solution reacts.
/// </summary>
[ByRefEvent]
public sealed partial class BeforeSolutionReactEvent : CancellableEntityEventArgs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
// SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
// SPDX-FileCopyrightText: 2025 TheBorzoiMustConsume <197824988+TheBorzoiMustConsume@users.noreply.github.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

using Content.Client.DamageState;
using Content.Goobstation.Shared.Xenobiology;
using Content.Goobstation.Shared.Xenobiology.Components;
using Content.Shared.Mobs;
using Robust.Client.GameObjects;

namespace Content.Goobstation.Client.Xenobiology;

/// <summary>
/// This handles visual changes in mobs which can transition growth states.
/// </summary>
public sealed class MobGrowthVisualizerSystem : VisualizerSystem<MobGrowthComponent>
{
//I have a feeling this may need some protective functions.
protected override void OnAppearanceChange(EntityUid uid, MobGrowthComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null
|| !AppearanceSystem.TryGetData<string>(uid, GrowthStateVisuals.Sprite, out var rsi, args.Component))
return;

args.Sprite.LayerSetRSI(DamageStateVisualLayers.Base, rsi);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
// SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
// SPDX-FileCopyrightText: 2025 TheBorzoiMustConsume <197824988+TheBorzoiMustConsume@users.noreply.github.com>
// SPDX-FileCopyrightText: 2025 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

using System.Diagnostics;
using Content.Client.DamageState;
using Content.Goobstation.Shared.Xenobiology;
using Content.Goobstation.Shared.Xenobiology.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;

namespace Content.Goobstation.Client.Xenobiology;

/// <summary>
/// This handles visual changes in slimes between breeds.
/// </summary>
public sealed class XenoSlimeVisualizerSystem : VisualizerSystem<SlimeComponent>
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;

protected override void OnAppearanceChange(EntityUid uid, SlimeComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null || !AppearanceSystem.TryGetData<Color>(uid, XenoSlimeVisuals.Color, out var color, args.Component) || !TryComp<SpriteComponent>(uid, out var spriteComponent))
return;

foreach (var layer in args.Sprite.AllLayers)
layer.Color = color.WithAlpha(layer.Color.A);

if (!AppearanceSystem.TryGetData<string>(uid, XenoSlimeVisuals.Shader, out var shader, args.Component))
return;
var spriteComp = args.Sprite;
var newShader = _proto.Index<ShaderPrototype>(shader).InstanceUnique();

var layerExists = _sprite.LayerMapTryGet(uid, DamageStateVisualLayers.Base, out var layerKey, false);
if (!layerExists)
return;
spriteComp.LayerSetShader(layerKey, newShader);
spriteComp.GetScreenTexture = true;
spriteComp.RaiseShaderEvent = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
// SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

using Content.Goobstation.Shared.Xenobiology.XenobiologyBountyConsole;
using Content.Shared.Cargo.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;

namespace Content.Goobstation.Client.Xenobiology.XenobiologyBountyConsole;

[UsedImplicitly]
public sealed class XenobiologyBountyConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
[ViewVariables]
private XenobiologyBountyMenu? _menu;

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

_menu = this.CreateWindow<XenobiologyBountyMenu>();

_menu.OnFulfillButtonPressed += id =>
{
SendMessage(new BountyFulfillMessage(id));
};

_menu.OnSkipButtonPressed += id =>
{
SendMessage(new BountySkipMessage(id));
};
}

protected override void UpdateState(BoundUserInterfaceState message)
{
base.UpdateState(message);

if (message is not XenobiologyBountyConsoleState state)
return;

_menu?.UpdateEntries(state.Bounties, state.History, state.UntilNextSkip, state.UntilNextGlobalRefresh);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Content.Goobstation.Client.Xenobiology.XenobiologyBountyConsole.XenobiologyBountyEntry"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls;assembly=Content.Client"
Margin="10 10 10 0"
HorizontalExpand="True"
Visible="True">
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
<BoxContainer Orientation="Vertical"
HorizontalExpand="True">
<BoxContainer Orientation="Horizontal">
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<RichTextLabel Name="RewardLabel"/>
<RichTextLabel Name="ManifestLabel"/>
</BoxContainer>
<Control MinWidth="10"/>
<BoxContainer Orientation="Vertical" MinWidth="120">
<BoxContainer Orientation="Horizontal" MinWidth="120">
<Button Name="FulfillButton"
Text="{Loc 'xenobiology-console-fulfill-button-text'}"
HorizontalExpand="False"
HorizontalAlignment="Right"
StyleClasses="OpenRight"/>
<Button Name="SkipButton"
Text="{Loc 'bounty-console-skip-button-text'}"
HorizontalExpand="False"
HorizontalAlignment="Right"
StyleClasses="OpenLeft"/>
</BoxContainer>
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
</BoxContainer>
</BoxContainer>
<customControls:HSeparator Margin="5 10 5 10"/>
</BoxContainer>
</PanelContainer>
</BoxContainer>

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
// SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

using System.Linq;
using Content.Client.Message;
using Content.Goobstation.Shared.Xenobiology.XenobiologyBountyConsole;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

namespace Content.Goobstation.Client.Xenobiology.XenobiologyBountyConsole;

[GenerateTypedNameReferences]
public sealed partial class XenobiologyBountyEntry : BoxContainer
{
[Dependency] private readonly IPrototypeManager _prototype = default!;

public Action? OnFulfillButtonPressed;
public Action? OnSkipButtonPressed;

private TimeSpan _untilNextSkip;

public XenobiologyBountyEntry(XenobiologyBountyData bounty, TimeSpan untilNextSkip)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);

_untilNextSkip = untilNextSkip;

if (!_prototype.TryIndex(bounty.Bounty, out var bountyPrototype))
return;

double absNumber = Math.Abs(bountyPrototype.PointsAwarded);
var exponent = Math.Floor(Math.Log10(absNumber));
var baseValue = 0.25 * Math.Pow(10, exponent);
var roundedAbs = Math.Round(absNumber / baseValue, MidpointRounding.AwayFromZero) * baseValue;
var points = (int) roundedAbs;

var items = bountyPrototype.Entries
.Select(entry => Loc.GetString("bounty-console-manifest-entry",
("amount", entry.Amount),
("item", Loc.GetString(entry.Name))))
.ToList();

ManifestLabel.SetMarkup(Loc.GetString("bounty-console-manifest-label", ("item", string.Join(", ", items))));
RewardLabel.SetMarkup(Loc.GetString("xenobiology-console-reward-label", ("reward", points)));
IdLabel.SetMarkup(Loc.GetString("bounty-console-id-label", ("id", bounty.Id)));

FulfillButton.OnPressed += _ => OnFulfillButtonPressed?.Invoke();
SkipButton.OnPressed += _ => OnSkipButtonPressed?.Invoke();
}

private void UpdateSkipButton(float deltaSeconds)
{
_untilNextSkip -= TimeSpan.FromSeconds(deltaSeconds);
if (_untilNextSkip > TimeSpan.Zero)
{
SkipButton.Label.Text = _untilNextSkip.ToString("mm\\:ss");
SkipButton.Disabled = true;
return;
}

SkipButton.Label.Text = Loc.GetString("bounty-console-skip-button-text");
SkipButton.Disabled = false;
}

protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateSkipButton(args.DeltaSeconds);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Content.Goobstation.Client.Xenobiology.XenobiologyBountyConsole.XenobiologyBountyHistoryEntry"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls;assembly=Content.Client"
Margin="10 10 10 0"
HorizontalExpand="True">
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
<BoxContainer Orientation="Vertical"
HorizontalExpand="True">
<BoxContainer Orientation="Horizontal">
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<RichTextLabel Name="RewardLabel"/>
<RichTextLabel Name="ManifestLabel"/>
</BoxContainer>
<BoxContainer Orientation="Vertical" MinWidth="120" Margin="0 0 10 0">
<RichTextLabel Name="TimestampLabel" HorizontalAlignment="Right" />
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" />
</BoxContainer>
</BoxContainer>
<customControls:HSeparator Margin="5 10 5 10"/>
<RichTextLabel Name="NoticeLabel" />
</BoxContainer>
</PanelContainer>
</BoxContainer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
// SPDX-FileCopyrightText: 2025 BarryNorfolk <barrynorfolkman@protonmail.com>
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
// SPDX-FileCopyrightText: 2025 SX-7 <sn1.test.preria.2002@gmail.com>
// SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

using System.Linq;
using Content.Client.Message;
using Content.Goobstation.Shared.Xenobiology.XenobiologyBountyConsole;
using Content.Shared.Cargo;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;

namespace Content.Goobstation.Client.Xenobiology.XenobiologyBountyConsole;

[GenerateTypedNameReferences]
public sealed partial class XenobiologyBountyHistoryEntry : BoxContainer
{
[Dependency] private readonly IPrototypeManager _prototype = default!;

public XenobiologyBountyHistoryEntry(XenobiologyBountyHistoryData bounty)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);

if (!_prototype.TryIndex(bounty.Bounty, out var bountyPrototype))
return;

var items = bountyPrototype.Entries
.Select(entry => Loc.GetString("bounty-console-manifest-entry",
("amount", entry.Amount),
("item", Loc.GetString(entry.Name))))
.ToList();

ManifestLabel.SetMarkup(Loc.GetString("bounty-console-manifest-label", ("item", string.Join(", ", items))));
RewardLabel.SetMarkup(Loc.GetString("xenobiology-console-reward-label", ("reward", bountyPrototype.PointsAwarded)));
IdLabel.SetMarkup(Loc.GetString("bounty-console-id-label", ("id", bounty.Id)));

TimestampLabel.SetMarkup(bounty.Timestamp.ToString(@"hh\:mm\:ss"));

if (bounty.Result == CargoBountyHistoryData.BountyResult.Completed)
{
NoticeLabel.SetMarkup(Loc.GetString("bounty-console-history-notice-completed-label"));
}
else
{
NoticeLabel.SetMarkup(Loc.GetString("bounty-console-history-notice-skipped-label",
("id", bounty.ActorName ?? "")));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Content.Goobstation.Client.Xenobiology.XenobiologyBountyConsole.XenobiologyBountyMenu"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls;assembly=Content.Client"
Title="{Loc 'xenobiology-console-menu-title'}"
SetSize="550 420"
MinSize="400 350">
<BoxContainer Orientation="Vertical"
VerticalExpand="True"
HorizontalExpand="True">
<RichTextLabel Name="GlobalRefreshTimer"/>
<PanelContainer VerticalExpand="True" HorizontalExpand="True" Margin="10">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
</PanelContainer.PanelOverride>
<TabContainer Name="MasterTabContainer" VerticalExpand="True" HorizontalExpand="True">
<ScrollContainer HScrollEnabled="False"
HorizontalExpand="True"
VerticalExpand="True">
<BoxContainer Name="BountyEntriesContainer"
Orientation="Vertical"
VerticalExpand="True"
HorizontalExpand="True" />
</ScrollContainer>
<ScrollContainer HScrollEnabled="False"
HorizontalExpand="True"
VerticalExpand="True">
<Label Name="NoHistoryLabel"
Text="{Loc 'bounty-console-history-empty-label'}"
Visible="False"
Align="Center" />
<BoxContainer Name="BountyHistoryContainer"
Orientation="Vertical"
VerticalExpand="True"
HorizontalExpand="True" />
</ScrollContainer>
</TabContainer>
</PanelContainer>
<!-- Footer -->
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'xenobiology-console-flavor-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'xenobiology-console-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>


Loading
Loading