Singularity, Particle Accelerator & Radiation Collectors (#2169)

* basic radiation generator

* might need this

* thonk

* big thonk

* oop

* e

* werks

* sprite

* oopsy woopsy

* radiation

* clean up file

* makes it work, probably

* minor fixes

* resources

* progress on component

* this will no longer be necessary

* radiation go brrrr

* finally fix container issues

* out var

Co-authored-by: Remie Richards <remierichards@gmail.com>

* second out fix

* another out fix

Co-authored-by: Remie Richards <remierichards@gmail.com>

* switch case

* fix switch

* sound and improvements

* nullable

* basic containment field system

* ensure alignment

* fix beam placement logic

* field generation fully working

* fix potential crash

* working containment functionality

* extremely basic emitter functionality

* fix radiation panel naming

* emitter stuff

* oopsies

* fixes

* some fixes

* cleanup

* small fix and move emitter file

* add sprite resources for PA

* slight rework of the singulo
adds rads

* pushing for smugleaf :)

* added radiationpanels

* some fixes for the singulo

* containmentfield

* pa wip

* progress

* pa working

* emitter fix

* works :)

* ui works

* some work on ui & pa

* progress

* ui work & misc fixes

* GREYSCALE

* pa ui polish
containmentfieldgen rework

* singulo rework
added snapgrid

* getcomponent get out

* singulo rework
added collisiongroups underplating & passable

* yaml work:
- collision boxes
- singulo now unshaded

* no unlit

* misc changes

* pa wires

* add usability check

* nullable enable

* minor fix

* power need added

* reenables containment field energy drain
menu close button
singularity collider fix

* sprite replacement

* finished singulo pulling

* pjb fixes

* fixing sprites & minor adjustments

* decrease containmentfield power

* some yml adjustments

* unlit layers
singulogenerator

* singulogen

* everything works just not the powergetting on the pa
i wanna die

* Adds PA construction graphs, PA construction works

* Snap to grid parts when completing construction

* updated to newest master

* inb4 i work on power

* fixes upstream merge
adds power need to particleaccelerator

* properly implements power & apc power

* Emitters are now fancy.

* I have actually no idea how this happened.

* Give PA a wiring LayoutId

* PA is an acronym

* indicators
fixes hacking

* Singulo is a word you blasphemous IDE.

* Rewrite the PA.

* Fancy names for PA parts.

* Wiring fixes, strength wire cutting.

* fixes projectile & ignores components

* nullability errors

* fixes integration tests

Co-authored-by: unusualcrow <unusualcrow@protonmail.com>
Co-authored-by: L.E.D <10257081+unusualcrow@users.noreply.github.com>
Co-authored-by: Remie Richards <remierichards@gmail.com>
Co-authored-by: Víctor Aguilera Puerto <zddm@outlook.es>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
This commit is contained in:
Paul Ritter
2020-10-28 19:19:47 +01:00
committed by GitHub
parent 74fe2609f5
commit 6a0aa9b72f
171 changed files with 4357 additions and 42 deletions

View File

@@ -0,0 +1,545 @@
using System;
using Content.Client.Animations;
using Content.Client.UserInterface;
using Content.Client.UserInterface.Stylesheets;
using Content.Client.Utility;
using Content.Shared.GameObjects.Components;
using Robust.Client.Animations;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Noise;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.ParticleAccelerator
{
public sealed class ParticleAcceleratorControlMenu : BaseWindow
{
private ShaderInstance _greyScaleShader;
private readonly ParticleAcceleratorBoundUserInterface Owner;
private readonly Label _drawLabel;
private readonly NoiseGenerator _drawNoiseGenerator;
private readonly Button _onButton;
private readonly Button _offButton;
private readonly Button _scanButton;
private readonly Label _statusLabel;
private readonly SpinBox _stateSpinBox;
private readonly VBoxContainer _alarmControl;
private readonly Animation _alarmControlAnimation;
private readonly PASegmentControl _endCapTexture;
private readonly PASegmentControl _fuelChamberTexture;
private readonly PASegmentControl _controlBoxTexture;
private readonly PASegmentControl _powerBoxTexture;
private readonly PASegmentControl _emitterCenterTexture;
private readonly PASegmentControl _emitterRightTexture;
private readonly PASegmentControl _emitterLeftTexture;
private float _time;
private int _lastDraw;
private int _lastReceive;
private bool _blockSpinBox;
private bool _assembled;
private bool _shouldContinueAnimating;
public ParticleAcceleratorControlMenu(ParticleAcceleratorBoundUserInterface owner)
{
_greyScaleShader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("Greyscale").Instance();
Owner = owner;
_drawNoiseGenerator = new NoiseGenerator(NoiseGenerator.NoiseType.Fbm);
_drawNoiseGenerator.SetFrequency(0.5f);
var resourceCache = IoCManager.Resolve<IResourceCache>();
var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
MouseFilter = MouseFilterMode.Stop;
_alarmControlAnimation = new Animation
{
Length = TimeSpan.FromSeconds(1),
AnimationTracks =
{
new AnimationTrackControlProperty
{
Property = nameof(Control.Visible),
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(true, 0),
new AnimationTrackProperty.KeyFrame(false, 0.75f),
}
}
}
};
var back = new StyleBoxTexture
{
Texture = panelTex,
Modulate = Color.FromHex("#25252A"),
};
back.SetPatchMargin(StyleBox.Margin.All, 10);
var back2 = new StyleBoxTexture(back)
{
Modulate = Color.FromHex("#202023")
};
AddChild(new PanelContainer
{
PanelOverride = back,
MouseFilter = MouseFilterMode.Pass
});
_stateSpinBox = new SpinBox
{
Value = 0,
};
_stateSpinBox.IsValid = StrengthSpinBoxValid;
_stateSpinBox.InitDefaultButtons();
_stateSpinBox.ValueChanged += PowerStateChanged;
_stateSpinBox.LineEditDisabled = true;
_offButton = new Button
{
ToggleMode = false,
Text = "Off",
StyleClasses = {StyleBase.ButtonOpenRight},
};
_offButton.OnPressed += args => owner.SendEnableMessage(false);
_onButton = new Button
{
ToggleMode = false,
Text = "On",
StyleClasses = {StyleBase.ButtonOpenLeft},
};
_onButton.OnPressed += args => owner.SendEnableMessage(true);
var closeButton = new TextureButton
{
StyleClasses = {"windowCloseButton"},
SizeFlagsHorizontal = SizeFlags.ShrinkEnd
};
closeButton.OnPressed += args => Close();
var serviceManual = new Label
{
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
StyleClasses = {StyleBase.StyleClassLabelSubText},
Text = Loc.GetString("Refer to p.132 of service manual")
};
_drawLabel = new Label();
var imgSize = new Vector2(32, 32);
AddChild(new VBoxContainer
{
Children =
{
new MarginContainer
{
MarginLeftOverride = 2,
MarginTopOverride = 2,
Children =
{
new Label
{
Text = Loc.GetString("Mark 2 Particle Accelerator"),
FontOverride = font,
FontColorOverride = StyleNano.NanoGold,
},
new MarginContainer
{
MarginRightOverride = 8,
Children =
{
closeButton
}
}
}
},
new PanelContainer
{
PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold},
CustomMinimumSize = (0, 2),
},
new Control
{
CustomMinimumSize = (0, 4)
},
new HBoxContainer
{
SizeFlagsVertical = SizeFlags.FillExpand,
Children =
{
new MarginContainer
{
MarginLeftOverride = 4,
Children =
{
new VBoxContainer
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
Children =
{
new HBoxContainer
{
Children =
{
new Label
{
Text = Loc.GetString("Power: "),
SizeFlagsHorizontal = SizeFlags.Expand
},
_offButton,
_onButton
}
},
new HBoxContainer
{
Children =
{
new Label
{
Text = Loc.GetString("Strength: "),
SizeFlagsHorizontal = SizeFlags.Expand
},
_stateSpinBox
}
},
new Control
{
CustomMinimumSize = (0, 10),
},
_drawLabel,
new Control
{
SizeFlagsVertical = SizeFlags.Expand
},
(_alarmControl = new VBoxContainer
{
Children =
{
new Label
{
Text = Loc.GetString("PARTICLE STRENGTH\nLIMITER FAILURE"),
FontColorOverride = Color.Red,
Align = Label.AlignMode.Center
},
serviceManual
}
}),
}
}
}
},
new VBoxContainer
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
Children =
{
(_statusLabel = new Label
{
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
}),
new Control
{
CustomMinimumSize = (0, 20)
},
new PanelContainer
{
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
PanelOverride = back2,
Children =
{
new GridContainer
{
Columns = 3,
VSeparationOverride = 0,
HSeparationOverride = 0,
Children =
{
new Control {CustomMinimumSize = imgSize},
(_endCapTexture = Segment("end_cap")),
new Control {CustomMinimumSize = imgSize},
(_controlBoxTexture = Segment("control_box")),
(_fuelChamberTexture = Segment("fuel_chamber")),
new Control {CustomMinimumSize = imgSize},
new Control {CustomMinimumSize = imgSize},
(_powerBoxTexture = Segment("power_box")),
new Control {CustomMinimumSize = imgSize},
(_emitterLeftTexture = Segment("emitter_left")),
(_emitterCenterTexture = Segment("emitter_center")),
(_emitterRightTexture = Segment("emitter_right")),
}
}
}
},
(_scanButton = new Button
{
Text = Loc.GetString("Scan Parts"),
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
})
}
}
}
},
new StripeBack
{
Children =
{
new MarginContainer
{
MarginLeftOverride = 4,
MarginTopOverride = 4,
MarginBottomOverride = 4,
Children =
{
new Label
{
Text = Loc.GetString("Ensure containment field is active before operation"),
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
StyleClasses = {StyleBase.StyleClassLabelSubText},
}
}
}
}
},
new MarginContainer
{
MarginLeftOverride = 12,
Children =
{
new HBoxContainer
{
Children =
{
new Label
{
Text = "FOO-BAR-BAZ",
StyleClasses = {StyleBase.StyleClassLabelSubText}
}
}
}
}
},
}
});
_scanButton.OnPressed += args => Owner.SendScanPartsMessage();
_alarmControl.AnimationCompleted += s =>
{
if (_shouldContinueAnimating)
{
_alarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
}
else
{
_alarmControl.Visible = false;
}
};
PASegmentControl Segment(string name)
{
return new PASegmentControl(this, resourceCache, name);
}
}
private bool StrengthSpinBoxValid(int n)
{
return (n >= 0 && n <= 4 && !_blockSpinBox);
}
private void PowerStateChanged(object sender, ValueChangedEventArgs e)
{
ParticleAcceleratorPowerState newState;
switch (e.Value)
{
case 0:
newState = ParticleAcceleratorPowerState.Standby;
break;
case 1:
newState = ParticleAcceleratorPowerState.Level0;
break;
case 2:
newState = ParticleAcceleratorPowerState.Level1;
break;
case 3:
newState = ParticleAcceleratorPowerState.Level2;
break;
case 4:
newState = ParticleAcceleratorPowerState.Level3;
break;
default:
return;
}
Owner.SendPowerStateMessage(newState);
}
protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
{
return DragMode.Move;
}
protected override Vector2 CalculateMinimumSize()
{
return (400, 300);
}
public void DataUpdate(ParticleAcceleratorUIState uiState)
{
_assembled = uiState.Assembled;
UpdateUI(uiState.Assembled, uiState.InterfaceBlock, uiState.Enabled,
uiState.WirePowerBlock);
_statusLabel.Text = Loc.GetString($"Status: {(uiState.Assembled ? "Operational" : "Incomplete")}");
UpdatePowerState(uiState.State, uiState.Enabled, uiState.Assembled,
uiState.MaxLevel);
UpdatePreview(uiState);
_lastDraw = uiState.PowerDraw;
_lastReceive = uiState.PowerReceive;
}
private void UpdatePowerState(ParticleAcceleratorPowerState state, bool enabled, bool assembled,
ParticleAcceleratorPowerState maxState)
{
_stateSpinBox.OverrideValue(state switch
{
ParticleAcceleratorPowerState.Standby => 0,
ParticleAcceleratorPowerState.Level0 => 1,
ParticleAcceleratorPowerState.Level1 => 2,
ParticleAcceleratorPowerState.Level2 => 3,
ParticleAcceleratorPowerState.Level3 => 4,
_ => 0
});
_shouldContinueAnimating = false;
_alarmControl.StopAnimation("warningAnim");
_alarmControl.Visible = false;
if (maxState == ParticleAcceleratorPowerState.Level3 && enabled == true && assembled == true)
{
_shouldContinueAnimating = true;
_alarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
}
}
private void UpdateUI(bool assembled, bool blocked, bool enabled, bool powerBlock)
{
_onButton.Pressed = enabled;
_offButton.Pressed = !enabled;
var cantUse = !assembled || blocked || powerBlock;
_onButton.Disabled = cantUse;
_offButton.Disabled = cantUse;
_scanButton.Disabled = blocked;
var cantChangeLevel = !assembled || blocked;
_stateSpinBox.SetButtonDisabled(cantChangeLevel);
_blockSpinBox = cantChangeLevel;
}
private void UpdatePreview(ParticleAcceleratorUIState updateMessage)
{
_endCapTexture.SetPowerState(updateMessage, updateMessage.EndCapExists);
_fuelChamberTexture.SetPowerState(updateMessage, updateMessage.FuelChamberExists);
_controlBoxTexture.SetPowerState(updateMessage, true);
_powerBoxTexture.SetPowerState(updateMessage, updateMessage.PowerBoxExists);
_emitterCenterTexture.SetPowerState(updateMessage, updateMessage.EmitterCenterExists);
_emitterLeftTexture.SetPowerState(updateMessage, updateMessage.EmitterLeftExists);
_emitterRightTexture.SetPowerState(updateMessage, updateMessage.EmitterRightExists);
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (!_assembled)
{
_drawLabel.Text = Loc.GetString("Draw: N/A");
return;
}
_time += args.DeltaSeconds;
var watts = 0;
if (_lastDraw != 0)
{
var val = _drawNoiseGenerator.GetNoise(_time);
watts = (int) (_lastDraw + val * 5);
}
_drawLabel.Text = Loc.GetString("Draw: {0:##,##0}/{1:##,##0} W", watts, _lastReceive);
}
private sealed class PASegmentControl : Control
{
private readonly ParticleAcceleratorControlMenu _menu;
private readonly string _baseState;
private readonly TextureRect _base;
private readonly TextureRect _unlit;
private readonly RSI _rsi;
public PASegmentControl(ParticleAcceleratorControlMenu menu, IResourceCache cache, string name)
{
_menu = menu;
_baseState = name;
_rsi = cache.GetResource<RSIResource>($"/Textures/Constructible/Power/PA/{name}.rsi").RSI;
AddChild(_base = new TextureRect {Texture = _rsi[$"{name}c"].Frame0});
AddChild(_unlit = new TextureRect());
}
public void SetPowerState(ParticleAcceleratorUIState state, bool exists)
{
_base.ShaderOverride = exists ? null : _menu._greyScaleShader;
_base.ModulateSelfOverride = exists ? (Color?)null : new Color(127, 127, 127);
if (!state.Enabled || !exists)
{
_unlit.Visible = false;
return;
}
_unlit.Visible = true;
var suffix = state.State switch
{
ParticleAcceleratorPowerState.Standby => "_unlitp",
ParticleAcceleratorPowerState.Level0 => "_unlitp0",
ParticleAcceleratorPowerState.Level1 => "_unlitp1",
ParticleAcceleratorPowerState.Level2 => "_unlitp2",
ParticleAcceleratorPowerState.Level3 => "_unlitp3",
_ => ""
};
if (!_rsi.TryGetState(_baseState + suffix, out var rState))
{
_unlit.Visible = false;
return;
}
_unlit.Texture = rState.Frame0;
}
protected override Vector2 CalculateMinimumSize()
{
return _rsi.Size;
}
}
}
}