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

Bluespace update #139

Merged
merged 11 commits into from
Dec 9, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
<Label Name="PowerUsageLabel" Text="0w"/>
<Label Text="{Loc 'bluespace-harvester-window-power-next'}" StyleClasses="StatusFieldTitle"/>
<Label Name="PowerUsageNextLabel" Text="0w"/>
<Label Text="{Loc 'bluespace-harvester-window-power-surplus'}" StyleClasses="StatusFieldTitle"/>
<Label Name="PowerSuppliertLabel" Text="0w"/>
</GridContainer>
<Control/>
<Label Text="{Loc 'bluespace-harvester-window-lable-output'}"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public void UpdateState(BluespaceHarvesterBoundUserInterfaceState state)

PowerUsageLabel.Text = Loc.GetString("power-monitoring-window-value", ("value", state.PowerUsage));
PowerUsageNextLabel.Text = Loc.GetString("power-monitoring-window-value", ("value", state.PowerUsageNext));
PowerSuppliertLabel.Text = Loc.GetString("power-monitoring-window-value", ("value", state.PowerSuppliert));

AvailablePointsLabel.Text = $"{state.Points}";
TotalPontsLabel.Text = $"{state.TotalPoints}";
Expand All @@ -48,7 +47,7 @@ public void UpdateState(BluespaceHarvesterBoundUserInterfaceState state)
{
var child = new BluespaceHarvesterCategory(category, state.Points >= category.Cost);

child.CategoryButton.OnButtonDown += (args) =>
child.CategoryButton.OnButtonDown += _ =>
{
_owner.SendBuy(category.Type);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ namespace Content.Server._CorvaxNext.BluespaceHarvester;
[RegisterComponent, Access(typeof(BluespaceHarvesterSystem))]
public sealed partial class BluespaceHarvesterComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan ResetTime;

/// <summary>
/// Responsible for forcibly turning off the harvester and blocking input level.
/// </summary>
[DataField]
public bool Reseted;
[ViewVariables(VVAccess.ReadWrite)]
public bool Reset;

/// <summary>
/// The current level at which the harvester is located is what other parameters are calculated from.
Expand Down Expand Up @@ -106,31 +109,34 @@ public sealed partial class BluespaceHarvesterComponent : Component
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float EmaggedRiftChance = 0.03f;

[ViewVariables(VVAccess.ReadWrite)]
public int Harvesters;

[DataField]
public List<BluespaceHarvesterCategoryInfo> Categories = new()
{
new BluespaceHarvesterCategoryInfo()
new BluespaceHarvesterCategoryInfo
{
PrototypeId = "RandomHarvesterBiologicalLoot",
Cost = 7_500,
Cost = 7500,
Type = BluespaceHarvesterCategory.Biological,
},
new BluespaceHarvesterCategoryInfo()
{
PrototypeId = "RandomHarvesterTechnologicalLoot",
Cost = 7_500,
Cost = 10000,
Type = BluespaceHarvesterCategory.Technological,
},
new BluespaceHarvesterCategoryInfo()
new BluespaceHarvesterCategoryInfo
{
PrototypeId = "RandomHarvesterIndustrialLoot",
Cost = 7_500,
Cost = 12500,
Type = BluespaceHarvesterCategory.Industrial,
},
new BluespaceHarvesterCategoryInfo()
{
PrototypeId = "RandomHarvesterDestructionLoot",
Cost = 7_500,
Cost = 15000,
Type = BluespaceHarvesterCategory.Destruction,
},
};
Expand All @@ -146,6 +152,12 @@ public sealed partial class BluespaceHarvesterComponent : Component

[DataField]
public SoundSpecifier SpawnSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg");

[ViewVariables]
public float ReceivedPower;

[ViewVariables]
public float DrawRate;
}

[Serializable]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,83 @@
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Server.Power.NodeGroups;
using Content.Shared.Audio;
using Content.Shared._CorvaxNext.BluespaceHarvester;
using Content.Shared.Destructible;
using Content.Shared.Emag.Components;
using Microsoft.CodeAnalysis;
using Robust.Server.GameObjects;
using Robust.Shared.Random;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Power.EntitySystems;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Timing;

namespace Content.Server._CorvaxNext.BluespaceHarvester;

public sealed class BluespaceHarvesterSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;

public List<BluespaceHarvesterTap> Taps = new List<BluespaceHarvesterTap>()
{
new BluespaceHarvesterTap() { Level = 0, Visual = BluespaceHarvesterVisuals.Tap0 },
new BluespaceHarvesterTap() { Level = 1, Visual = BluespaceHarvesterVisuals.Tap1 },
new BluespaceHarvesterTap() { Level = 5, Visual = BluespaceHarvesterVisuals.Tap2 },
new BluespaceHarvesterTap() { Level = 10, Visual = BluespaceHarvesterVisuals.Tap3 },
new BluespaceHarvesterTap() { Level = 15, Visual = BluespaceHarvesterVisuals.Tap4 },
new BluespaceHarvesterTap() { Level = 20, Visual = BluespaceHarvesterVisuals.Tap5 },
};
private readonly List<BluespaceHarvesterTap> _taps =
[
new() { Level = 0, Visual = BluespaceHarvesterVisuals.Tap0 },
new() { Level = 1, Visual = BluespaceHarvesterVisuals.Tap1 },
new() { Level = 5, Visual = BluespaceHarvesterVisuals.Tap2 },
new() { Level = 10, Visual = BluespaceHarvesterVisuals.Tap3 },
new() { Level = 15, Visual = BluespaceHarvesterVisuals.Tap4 },
new() { Level = 20, Visual = BluespaceHarvesterVisuals.Tap5 },
];

private float _updateTimer;
private const float UpdateTime = 1.0f;

private EntityQuery<BluespaceHarvesterComponent> _harvesterQuery;

public override void Initialize()
{
base.Initialize();

_harvesterQuery = GetEntityQuery<BluespaceHarvesterComponent>();

SubscribeLocalEvent<BluespaceHarvesterComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<BluespaceHarvesterComponent, ComponentRemove>(OnRemove);

SubscribeLocalEvent<BluespaceHarvesterComponent, PowerConsumerReceivedChanged>(ReceivedChanged);
SubscribeLocalEvent<BluespaceHarvesterComponent, BluespaceHarvesterTargetLevelMessage>(OnTargetLevel);
SubscribeLocalEvent<BluespaceHarvesterComponent, BluespaceHarvesterBuyMessage>(OnBuy);
SubscribeLocalEvent<BluespaceHarvesterComponent, DestructionEventArgs>(OnDestruction);
}

private void OnStartup(Entity<BluespaceHarvesterComponent> ent, ref ComponentStartup args)
{
var query = EntityQueryEnumerator<BluespaceHarvesterComponent>();
while (query.MoveNext(out _, out var harvester))
{
harvester.Harvesters++;
}
}

Tornado-Technology marked this conversation as resolved.
Show resolved Hide resolved
private void OnRemove(Entity<BluespaceHarvesterComponent> ent, ref ComponentRemove args)
{
var query = EntityQueryEnumerator<BluespaceHarvesterComponent>();
while (query.MoveNext(out _, out var harvester))
{
harvester.Harvesters--;
}
}

private void ReceivedChanged(Entity<BluespaceHarvesterComponent> ent, ref PowerConsumerReceivedChanged args)
{
ent.Comp.ReceivedPower = args.ReceivedPower;
ent.Comp.DrawRate = args.DrawRate;
}

public override void Update(float frameTime)
{
base.Update(frameTime);
Expand All @@ -63,25 +92,22 @@ public override void Update(float frameTime)
var query = EntityQueryEnumerator<BluespaceHarvesterComponent, PowerConsumerComponent>();
while (query.MoveNext(out var uid, out var harvester, out var consumer))
{
var ent = (uid, harvester);

// We start only after manual switching on.
if (harvester is { Reseted: false, CurrentLevel: 0 })
harvester.Reseted = true;
if (harvester is { Reset: false, CurrentLevel: 0 })
harvester.Reset = true;

// The HV wires cannot transmit a lot of electricity so quickly,
// which is why it will not start.
// So this is simply using the amount of free electricity in the network.
var supplier = GetPowerSupplier(uid, harvester);
if (supplier < GetUsagePower(harvester.CurrentLevel) && harvester.CurrentLevel != 0)
if (harvester.ReceivedPower < harvester.DrawRate && harvester.CurrentLevel != 0)
{
// If there is insufficient production,
// it will reset itself (turn off) and you will need to start it again,
// this will not allow you to set it to maximum and enjoy life
Reset(uid, harvester);
}

if (harvester.Reseted)
if (harvester.Reset)
{
if (harvester.CurrentLevel < harvester.TargetLevel)
harvester.CurrentLevel++;
Expand Down Expand Up @@ -110,7 +136,7 @@ public override void Update(float frameTime)
}

if (TryComp<AmbientSoundComponent>(uid, out var ambient))
_ambientSound.SetAmbience(uid, harvester.Reseted, ambient); // Bzhzh, bzhzh
_ambientSound.SetAmbience(uid, harvester.Reset, ambient); // Bzhzh, bzhzh

UpdateAppearance(uid, harvester);
UpdateUI(uid, harvester);
Expand All @@ -125,17 +151,16 @@ private void OnDestruction(Entity<BluespaceHarvesterComponent> harvester, ref De
private void OnTargetLevel(Entity<BluespaceHarvesterComponent> harvester, ref BluespaceHarvesterTargetLevelMessage args)
{
// If we switch off, we don't need to be switched on.
if (!harvester.Comp.Reseted && harvester.Comp.CurrentLevel != 0)
if (!harvester.Comp.Reset)
return;

harvester.Comp.TargetLevel = args.TargetLevel;
harvester.Comp.Reseted = true; // We start only after manual switching on.
UpdateUI(harvester.Owner, harvester.Comp);
}

private void OnBuy(Entity<BluespaceHarvesterComponent> harvester, ref BluespaceHarvesterBuyMessage args)
{
if (!harvester.Comp.Reseted)
if (!harvester.Comp.Reset)
return;

if (!TryGetCategory(harvester.Owner, args.Category, out var info, harvester.Comp))
Expand All @@ -158,7 +183,7 @@ private void UpdateAppearance(EntityUid uid, BluespaceHarvesterComponent? harves
var level = harvester.CurrentLevel;
BluespaceHarvesterTap? max = null;

foreach (var tap in Taps)
foreach (var tap in _taps)
{
if (tap.Level > level)
continue;
Expand All @@ -184,13 +209,14 @@ private void UpdateUI(EntityUid uid, BluespaceHarvesterComponent? harvester = nu
if (!Resolve(uid, ref harvester))
return;

_ui.SetUiState(uid, BluespaceHarvesterUiKey.Key, new BluespaceHarvesterBoundUserInterfaceState(
_ui.SetUiState(uid,
BluespaceHarvesterUiKey.Key,
new BluespaceHarvesterBoundUserInterfaceState(
harvester.TargetLevel,
harvester.CurrentLevel,
harvester.MaxLevel,
GetUsagePower(harvester.CurrentLevel),
GetUsageNextPower(harvester.CurrentLevel),
GetPowerSupplier(uid, harvester),
harvester.Points,
harvester.TotalPoints,
GetPointGeneration(uid, harvester),
Expand Down Expand Up @@ -265,7 +291,7 @@ private int GetPointGeneration(EntityUid uid, BluespaceHarvesterComponent? harve
if (!Resolve(uid, ref harvester))
return 0;

return harvester.CurrentLevel * 4 * (Emagged(uid) ? 2 : 1);
return harvester.CurrentLevel * 4 * (Emagged(uid) ? 2 : 1) * (harvester.ResetTime == TimeSpan.Zero ? 1 : 0);
}

private int GetDangerPointGeneration(EntityUid uid, BluespaceHarvesterComponent? harvester = null)
Expand All @@ -274,7 +300,6 @@ private int GetDangerPointGeneration(EntityUid uid, BluespaceHarvesterComponent?
return 0;

var stable = GetStableLevel(uid, harvester);

if (harvester.CurrentLevel < stable && harvester.CurrentLevel != 0)
return -1;

Expand All @@ -297,52 +322,10 @@ private int GetStableLevel(EntityUid uid, BluespaceHarvesterComponent? harvester
if (!Resolve(uid, ref harvester))
return 0;

return Emagged(uid) ? harvester.EmaggedStableLevel : harvester.StableLevel;
}

/// <summary>
/// Receives information about all consumers and generators, subtracts and returns the amount of excess energy in the network.
/// </summary>
private float GetPowerSupplier(EntityUid uid, BluespaceHarvesterComponent? harvester = null, NodeContainerComponent? nodeComp = null)
{
if (!Resolve(uid, ref harvester, ref nodeComp))
return 0;

if (!_nodeContainer.TryGetNode<Node>(nodeComp, "input", out var node))
return 0;

if (node.NodeGroup is not PowerNet netQ)
if (harvester.Harvesters > 1)
return 0;

var totalSources = 0.0f;
foreach (var psc in netQ.Suppliers)
{
totalSources += psc.Enabled ? psc.MaxSupply : 0f;
}

foreach (var pcc in netQ.Dischargers)
{
if (!TryComp(pcc.Owner, out PowerNetworkBatteryComponent? batteryComp))
continue;

totalSources += batteryComp.NetworkBattery.CurrentSupply;
}

var totalConsumer = 0.0f;
foreach (var pcc in netQ.Consumers)
{
totalConsumer += pcc.DrawRate;
}

foreach (var pcc in netQ.Chargers)
{
if (!TryComp(pcc.Owner, out PowerNetworkBatteryComponent? batteryComp))
continue;

totalConsumer += batteryComp.NetworkBattery.CurrentReceiving;
}

return totalSources - totalConsumer;
return Emagged(uid) ? harvester.EmaggedStableLevel : harvester.StableLevel;
}

private bool TryGetCategory(EntityUid uid, BluespaceHarvesterCategory target, [NotNullWhen(true)] out BluespaceHarvesterCategoryInfo? info, BluespaceHarvesterComponent? harvester = null)
Expand All @@ -369,7 +352,7 @@ private void Reset(EntityUid uid, BluespaceHarvesterComponent? harvester = null)
return;

harvester.Danger += harvester.DangerFromReset;
harvester.Reseted = true;
harvester.Reset = false;
harvester.TargetLevel = 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,21 @@ public sealed class BluespaceHarvesterBoundUserInterfaceState : BoundUserInterfa

public readonly uint PowerUsage;
public readonly uint PowerUsageNext;
public readonly float PowerSuppliert;

public readonly int Points;
public readonly int TotalPoints;
public readonly int PointsGen;

public readonly List<BluespaceHarvesterCategoryInfo> Categories;

public BluespaceHarvesterBoundUserInterfaceState(int targetLevel, int currentLevel, int maxLevel, uint powerUsage, uint powerUsageNext, float powerSuppliert, int points, int totalPoints, int pointsGen, List<BluespaceHarvesterCategoryInfo> categories)
public BluespaceHarvesterBoundUserInterfaceState(int targetLevel, int currentLevel, int maxLevel, uint powerUsage, uint powerUsageNext, int points, int totalPoints, int pointsGen, List<BluespaceHarvesterCategoryInfo> categories)
{
TargetLevel = targetLevel;
CurrentLevel = currentLevel;
MaxLevel = maxLevel;

PowerUsage = powerUsage;
PowerUsageNext = powerUsageNext;
PowerSuppliert = powerSuppliert;

Points = points;
TotalPoints = totalPoints;
Expand Down
1 change: 1 addition & 0 deletions Resources/Locale/en-US/_corvaxnext/bluespace_harvester.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ bluespace-harvester-category-Industrial = Industrial
bluespace-harvester-category-Technological = Technological
bluespace-harvester-category-Biological = Biological
bluespace-harvester-category-Destruction = Destruction
research-technology-bluespace = Bluespace
research-technology-bluespace-mining = Bluespace Mining
1 change: 1 addition & 0 deletions Resources/Locale/ru-RU/_corvaxnext/bluespace_harvester.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ bluespace-harvester-category-Industrial = Промышленная
bluespace-harvester-category-Technological = Технологическая
bluespace-harvester-category-Biological = Биологическая
bluespace-harvester-category-Destruction = Разрушительная
research-technology-bluespace = Блюспейс
research-technology-bluespace-mining = Блюспейс Добыча
Loading
Loading