Skip to content

Commit

Permalink
Merge pull request #212 from Mnemotechnician/floof-upstream-merge-202…
Browse files Browse the repository at this point in the history
…4-09-26

Upstream Merge 2024-09-26
  • Loading branch information
FoxxoTrystan committed Sep 27, 2024
2 parents b5da379 + 5c92c52 commit 0da3a5d
Show file tree
Hide file tree
Showing 147 changed files with 3,673 additions and 915 deletions.
95 changes: 53 additions & 42 deletions Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;

// ReSharper disable InconsistentNaming

Expand All @@ -30,7 +31,6 @@ public sealed class ShortConstructionMenuBUI : BoundUserInterface
private readonly SpriteSystem _spriteSystem;

private RadialMenu? _menu;

public ShortConstructionMenuBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
_construction = _entManager.System<ConstructionSystem>();
Expand All @@ -39,8 +39,17 @@ public ShortConstructionMenuBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey

protected override void Open()
{
_menu = FormMenu();
_menu.OnClose += Close;
_menu = new RadialMenu
{
HorizontalExpand = true,
VerticalExpand = true,
BackButtonStyleClass = "RadialMenuBackButton",
CloseButtonStyleClass = "RadialMenuCloseButton"
};

if (_entManager.TryGetComponent<ShortConstructionComponent>(Owner, out var crafting))
CreateMenu(crafting.Entries);

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

Expand All @@ -51,56 +60,58 @@ protected override void Dispose(bool disposing)
_menu?.Dispose();
}

private RadialMenu FormMenu()
private void CreateMenu(List<ShortConstructionEntry> entries, string? parentCategory = null)
{
var menu = new RadialMenu
{
HorizontalExpand = true,
VerticalExpand = true,
BackButtonStyleClass = "RadialMenuBackButton",
CloseButtonStyleClass = "RadialMenuCloseButton"
};

if (!_entManager.TryGetComponent<ShortConstructionComponent>(Owner, out var crafting))
return menu;
if (_menu == null)
return;

var mainContainer = new RadialContainer
var container = new RadialContainer
{
Radius = 36f / MathF.Sin(MathF.PI / 2f / crafting.Prototypes.Count)
Name = parentCategory ?? "Main",
Radius = 48f + 24f * MathF.Log(entries.Count),
};

foreach (var protoId in crafting.Prototypes)
{
if (!_protoManager.TryIndex(protoId, out var proto))
continue;
_menu.AddChild(container);

var button = new RadialMenuTextureButton
foreach (var entry in entries)
{
if (entry.Category != null)
{
ToolTip = Loc.GetString(proto.Name),
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(48f, 48f)
};

var texture = new TextureRect
var button = CreateButton(entry.Category.Name, entry.Category.Icon);
button.TargetLayer = entry.Category.Name;
CreateMenu(entry.Category.Entries, entry.Category.Name);
container.AddChild(button);
}
else if (entry.Prototype != null
&& _protoManager.TryIndex(entry.Prototype, out var proto))
{
VerticalAlignment = Control.VAlignment.Center,
HorizontalAlignment = Control.HAlignment.Center,
Texture = _spriteSystem.Frame0(proto.Icon),
TextureScale = new Vector2(1.5f, 1.5f)
};
var button = CreateButton(proto.Name, proto.Icon);
button.OnButtonUp += _ => ConstructItem(proto);
container.AddChild(button);
}
}

button.AddChild(texture);
}

button.OnButtonUp += _ =>
{
ConstructItem(proto);
};
private RadialMenuTextureButton CreateButton(string name, SpriteSpecifier icon)
{
var button = new RadialMenuTextureButton
{
ToolTip = Loc.GetString(name),
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64f, 64f),
};

mainContainer.AddChild(button);
}
var texture = new TextureRect
{
VerticalAlignment = Control.VAlignment.Center,
HorizontalAlignment = Control.HAlignment.Center,
Texture = _spriteSystem.Frame0(icon),
TextureScale = new Vector2(2f, 2f)
};

menu.AddChild(mainContainer);
return menu;
button.AddChild(texture);
return button;
}

/// <summary>
Expand All @@ -121,6 +132,6 @@ private void ConstructItem(ConstructionPrototype prototype)
}, new ConstructionPlacementHijack(_construction, prototype));

// Should only close the menu if we're placing a construction hijack.
_menu!.Close();
// Theres not much point to closing it though. _menu!.Close();
}
}
5 changes: 5 additions & 0 deletions Content.Client/Store/Ui/StoreMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Content.Client.Message;
using Content.Shared.FixedPoint;
using Content.Shared.Store;
using Content.Client.Stylesheets;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
Expand Down Expand Up @@ -147,6 +148,10 @@ private void AddListingGui(ListingData listing)
}

var newListing = new StoreListingControl(listing, GetListingPriceString(listing), hasBalance, texture);

if (listing.DiscountValue > 0)
newListing.StoreItemBuyButton.AddStyleClass(StyleNano.ButtonColorDangerDefault.ToString());

newListing.StoreItemBuyButton.OnButtonDown += args
=> OnListingButtonPressed?.Invoke(args, listing);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,3 @@ public async Task ChangeMachine()
AssertPrototype("Autolathe");
}
}

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

namespace Content.IntegrationTests.Tests.Interaction;

// This partial class contains various constant prototype IDs common to interaction tests.
Expand Down Expand Up @@ -27,8 +28,6 @@ public abstract partial class InteractionTest

// Parts
protected const string Bin1 = "MatterBinStockPart";
protected const string Cap1 = "CapacitorStockPart";
protected const string Manipulator1 = "MicroManipulatorStockPart";
protected const string Battery1 = "PowerCellSmall";
protected const string Battery4 = "PowerCellHyper";
}

164 changes: 164 additions & 0 deletions Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
using Robust.Shared.Player;
using Content.Server.DoAfter;
using Content.Shared.Abilities.Psionics;
using Content.Shared.Damage;
using Content.Shared.DoAfter;
using Content.Shared.Popups;
using Content.Shared.Psionics.Events;
using Content.Shared.Examine;
using static Content.Shared.Examine.ExamineSystemShared;
using Robust.Shared.Timing;
using Content.Shared.Actions.Events;
using Robust.Server.Audio;
using Content.Server.Atmos.Rotting;
using Content.Shared.Mobs.Systems;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Psionics.Glimmer;

namespace Content.Server.Abilities.Psionics;

public sealed class RevivifyPowerSystem : EntitySystem
{
[Dependency] private readonly AudioSystem _audioSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly RottingSystem _rotting = default!;
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly GlimmerSystem _glimmer = default!;


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

SubscribeLocalEvent<PsionicComponent, PsionicHealOtherPowerActionEvent>(OnPowerUsed);
SubscribeLocalEvent<PsionicComponent, DispelledEvent>(OnDispelled);
SubscribeLocalEvent<PsionicComponent, PsionicHealOtherDoAfterEvent>(OnDoAfter);
}


private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args)
{
if (component.DoAfter is not null)
return;

if (!args.Immediate)
AttemptDoAfter(uid, component, args);
else ActivatePower(uid, component, args);

if (args.PopupText is not null
&& _glimmer.Glimmer > args.GlimmerPopupThreshold * component.CurrentDampening)
_popupSystem.PopupEntity(Loc.GetString(args.PopupText, ("entity", uid)), uid,
Filter.Pvs(uid).RemoveWhereAttachedEntity(entity => !_examine.InRangeUnOccluded(uid, entity, ExamineRange, null)),
true,
args.PopupType);

if (args.PlaySound
&& _glimmer.Glimmer > args.GlimmerSoundThreshold * component.CurrentDampening)
_audioSystem.PlayPvs(args.SoundUse, uid, args.AudioParams);

// Sanitize the Glimmer inputs because otherwise the game will crash if someone makes MaxGlimmer lower than MinGlimmer.
var minGlimmer = (int) Math.Round(MathF.MinMagnitude(args.MinGlimmer, args.MaxGlimmer)
+ component.CurrentAmplification - component.CurrentDampening);
var maxGlimmer = (int) Math.Round(MathF.MaxMagnitude(args.MinGlimmer, args.MaxGlimmer)
+ component.CurrentAmplification - component.CurrentDampening);

_psionics.LogPowerUsed(uid, args.PowerName, minGlimmer, maxGlimmer);
args.Handled = true;
}

private void AttemptDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args)
{
var ev = new PsionicHealOtherDoAfterEvent(_gameTiming.CurTime);
if (args.HealingAmount is not null)
ev.HealingAmount = args.HealingAmount;
if (args.RotReduction is not null)
ev.RotReduction = args.RotReduction.Value;
ev.DoRevive = args.DoRevive;
var doAfterArgs = new DoAfterArgs(EntityManager, uid, args.UseDelay, ev, uid, target: args.Target)
{
BreakOnUserMove = args.BreakOnUserMove,
BreakOnTargetMove = args.BreakOnTargetMove,
Hidden = _glimmer.Glimmer > args.GlimmerDoAfterVisibilityThreshold * component.CurrentDampening,
};

if (!_doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId))
return;

component.DoAfter = doAfterId;
}

private void OnDispelled(EntityUid uid, PsionicComponent component, DispelledEvent args)
{
if (component.DoAfter is null)
return;

_doAfterSystem.Cancel(component.DoAfter);
component.DoAfter = null;
args.Handled = true;
}

private void OnDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOtherDoAfterEvent args)
{
// It's entirely possible for the caster to stop being Psionic(due to mindbreaking) mid cast
if (component is null
|| args.Cancelled)
return;
component.DoAfter = null;

// The target can also cease existing mid-cast
if (args.Target is null)
return;

if (args.RotReduction is not null)
_rotting.ReduceAccumulator(args.Target.Value, TimeSpan.FromSeconds(args.RotReduction.Value * component.CurrentAmplification));

if (!TryComp<DamageableComponent>(args.Target.Value, out var damageableComponent))
return;

if (args.HealingAmount is not null)
_damageable.TryChangeDamage(args.Target.Value, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid);

if (!args.DoRevive
|| _rotting.IsRotten(args.Target.Value)
|| !TryComp<MobStateComponent>(args.Target.Value, out var mob)
|| !_mobState.IsDead(args.Target.Value, mob)
|| !_mobThreshold.TryGetThresholdForState(args.Target.Value, MobState.Dead, out var threshold)
|| damageableComponent.TotalDamage > threshold)
return;

_mobState.ChangeMobState(args.Target.Value, MobState.Critical, mob, uid);
}

// This would be the same thing as OnDoAfter, except that here the target isn't nullable, so I have to reuse code with different arguments.
private void ActivatePower(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args)
{
if (component is null)
return;

if (args.RotReduction is not null)
_rotting.ReduceAccumulator(args.Target, TimeSpan.FromSeconds(args.RotReduction.Value * component.CurrentAmplification));

if (!TryComp<DamageableComponent>(args.Target, out var damageableComponent))
return;

if (args.HealingAmount is not null)
_damageable.TryChangeDamage(args.Target, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid);

if (!args.DoRevive
|| _rotting.IsRotten(args.Target)
|| !TryComp<MobStateComponent>(args.Target, out var mob)
|| !_mobState.IsDead(args.Target, mob)
|| !_mobThreshold.TryGetThresholdForState(args.Target, MobState.Dead, out var threshold)
|| damageableComponent.TotalDamage > threshold)
return;

_mobState.ChangeMobState(args.Target, MobState.Critical, mob, uid);
}
}
7 changes: 7 additions & 0 deletions Content.Server/Anomaly/AnomalySystem.Vessel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Server.Anomaly.Components;
using Content.Server.Construction;
using Content.Server.Power.EntitySystems;
using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components;
Expand All @@ -20,6 +21,7 @@ private void InitializeVessel()
{
SubscribeLocalEvent<AnomalyVesselComponent, ComponentShutdown>(OnVesselShutdown);
SubscribeLocalEvent<AnomalyVesselComponent, MapInitEvent>(OnVesselMapInit);
SubscribeLocalEvent<AnomalyVesselComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<AnomalyVesselComponent, InteractUsingEvent>(OnVesselInteractUsing);
SubscribeLocalEvent<AnomalyVesselComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<AnomalyVesselComponent, ResearchServerGetPointsPerSecondEvent>(OnVesselGetPointsPerSecond);
Expand Down Expand Up @@ -65,6 +67,11 @@ private void OnVesselMapInit(EntityUid uid, AnomalyVesselComponent component, Ma
UpdateVesselAppearance(uid, component);
}

private void OnUpgradeExamine(EntityUid uid, AnomalyVesselComponent component, UpgradeExamineEvent args)
{
args.AddPercentageUpgrade("anomaly-vessel-component-upgrade-output", component.PointMultiplier);
}

private void OnVesselInteractUsing(EntityUid uid, AnomalyVesselComponent component, InteractUsingEvent args)
{
if (component.Anomaly != null ||
Expand Down
Loading

0 comments on commit 0da3a5d

Please sign in to comment.