Skip to content

Commit

Permalink
Merge pull request Simple-Station#92 from SS14-Classic/Update-10/27/2024
Browse files Browse the repository at this point in the history
Update 10/27/2024
  • Loading branch information
VMSolidus authored Oct 28, 2024
2 parents 54b310b + 13d6524 commit 35e786e
Show file tree
Hide file tree
Showing 55 changed files with 3,050 additions and 1,908 deletions.
66 changes: 50 additions & 16 deletions Content.Client/RadialSelector/RadialSelectorMenuBUI.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System.Numerics;
using System.Linq;
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Content.Shared.Construction.Prototypes;
using Content.Shared.RadialSelector;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Prototypes;
Expand All @@ -19,8 +21,9 @@ public sealed class RadialSelectorMenuBUI : BoundUserInterface
{
[Dependency] private readonly IClyde _displayManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IResourceCache _resources = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;

private readonly SpriteSystem _spriteSystem;

Expand All @@ -30,6 +33,7 @@ public sealed class RadialSelectorMenuBUI : BoundUserInterface
private readonly HashSet<RadialContainer> _cachedContainers = new();

private bool _openCentered;
private readonly Vector2 ItemSize = Vector2.One * 64;

public RadialSelectorMenuBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
Expand Down Expand Up @@ -95,10 +99,7 @@ private void CreateMenu(List<RadialSelectorEntry> entries, string parentCategory
else if (entry.Prototype != null)
{
var name = GetName(entry.Prototype);
var icon = GetIcon(entry);
if (icon is null)
return;

var icon = GetTextures(entry);
var button = CreateButton(name, icon);
button.OnButtonUp += _ =>
{
Expand All @@ -115,37 +116,48 @@ private string GetName(string proto)
{
if (_protoManager.TryIndex(proto, out var prototype))
return prototype.Name;

if (_protoManager.TryIndex(proto, out ConstructionPrototype? constructionPrototype))
return constructionPrototype.Name;

return proto;
}

private Texture? GetIcon(RadialSelectorEntry entry)
private List<Texture> GetTextures(RadialSelectorEntry entry)
{
var result = new List<Texture>();
if (entry.Icon is not null)
{
result.Add(_spriteSystem.Frame0(entry.Icon));
return result;
}

if (_protoManager.TryIndex(entry.Prototype!, out var prototype))
return _spriteSystem.Frame0(prototype);
{
result.AddRange(SpriteComponent.GetPrototypeTextures(prototype, _resources).Select(o => o.Default));
return result;
}

if (_protoManager.TryIndex(entry.Prototype!, out ConstructionPrototype? constructionProto))
return _spriteSystem.Frame0(constructionProto.Icon);

if (entry.Icon is not null)
return _spriteSystem.Frame0(entry.Icon);
{
result.Add(_spriteSystem.Frame0(constructionProto.Icon));
return result;
}

// No icons provided and no icons found in prototypes. There's nothing we can do.
return null;
return result;
}

private RadialMenuTextureButton CreateButton(string name, Texture icon)
{
var itemSize = new Vector2(64f, 64f);
var button = new RadialMenuTextureButton
{
ToolTip = Loc.GetString(name),
StyleClasses = { "RadialMenuButton" },
SetSize = itemSize
SetSize = ItemSize
};

var iconScale = itemSize / icon.Size;
var iconScale = ItemSize / icon.Size;
var texture = new TextureRect
{
VerticalAlignment = Control.VAlignment.Center,
Expand All @@ -158,6 +170,28 @@ private RadialMenuTextureButton CreateButton(string name, Texture icon)
return button;
}

private RadialMenuTextureButton CreateButton(string name, List<Texture> icons)
{
var button = new RadialMenuTextureButton
{
ToolTip = Loc.GetString(name),
StyleClasses = { "RadialMenuButton" },
SetSize = ItemSize
};

var iconScale = ItemSize / icons[0].Size;
var texture = new LayeredTextureRect
{
VerticalAlignment = Control.VAlignment.Center,
HorizontalAlignment = Control.HAlignment.Center,
Textures = icons,
TextureScale = iconScale
};

button.AddChild(texture);
return button;
}

private void ClearExistingContainers()
{
foreach (var container in _cachedContainers)
Expand Down
19 changes: 18 additions & 1 deletion Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using System.Linq;
using Robust.Server.Player;
using Content.Server.Chat.Managers;
using Content.Server.Psionics.Glimmer;

namespace Content.Server.Abilities.Psionics
{
Expand All @@ -29,6 +28,7 @@ public sealed class PsionicAbilitiesSystem : EntitySystem
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly PsionicFamiliarSystem _psionicFamiliar = default!;

private ProtoId<WeightedRandomPrototype> _pool = "RandomPsionicPowerPool";
private const string GenericInitializationMessage = "generic-power-initialization-feedback";
Expand Down Expand Up @@ -59,6 +59,7 @@ private void OnPsionicShutdown(EntityUid uid, PsionicComponent component, Compon
|| HasComp<MindbrokenComponent>(uid))
return;

KillFamiliars(component);
RemoveAllPsionicPowers(uid);
}

Expand Down Expand Up @@ -215,6 +216,7 @@ public void RemoveAllPsionicPowers(EntityUid uid, bool mindbreak = false)

_popups.PopupEntity(Loc.GetString(psionic.MindbreakingFeedback, ("entity", MetaData(uid).EntityName)), uid, uid, PopupType.MediumCaution);

KillFamiliars(psionic);
RemComp<PsionicComponent>(uid);
RemComp<InnatePsionicPowersComponent>(uid);

Expand Down Expand Up @@ -368,5 +370,20 @@ private void RemovePsionicStatSources(EntityUid uid, PsionicPowerPrototype proto

RefreshPsionicModifiers(uid, psionic);
}

private void KillFamiliars(PsionicComponent component)
{
if (component.Familiars.Count <= 0)
return;

foreach (var familiar in component.Familiars)
{
if (!TryComp<PsionicFamiliarComponent>(familiar, out var familiarComponent)
|| !familiarComponent.DespawnOnMasterDeath)
continue;

_psionicFamiliar.DespawnFamiliar(familiar, familiarComponent);
}
}
}
}
140 changes: 140 additions & 0 deletions Content.Server/Abilities/Psionics/PsionicFamiliarSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using Content.Server.NPC;
using Content.Server.NPC.Components;
using Content.Server.NPC.HTN;
using Content.Server.NPC.Systems;
using Content.Server.Popups;
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;
using Content.Shared.Interaction.Events;
using Content.Shared.Mobs;
using Robust.Shared.Map;
using System.Numerics;

namespace Content.Server.Abilities.Psionics;

public sealed partial class PsionicFamiliarSystem : EntitySystem
{
[Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!;
[Dependency] private readonly NpcFactionSystem _factions = default!;
[Dependency] private readonly NPCSystem _npc = default!;
[Dependency] private readonly HTNSystem _htn = default!;
[Dependency] private readonly PopupSystem _popup = default!;

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

SubscribeLocalEvent<PsionicComponent, SummonPsionicFamiliarActionEvent>(OnSummon);
SubscribeLocalEvent<PsionicFamiliarComponent, ComponentShutdown>(OnFamiliarShutdown);
SubscribeLocalEvent<PsionicFamiliarComponent, AttackAttemptEvent>(OnFamiliarAttack);
SubscribeLocalEvent<PsionicFamiliarComponent, MobStateChangedEvent>(OnFamiliarDeath);
}

private void OnSummon(EntityUid uid, PsionicComponent psionicComponent, SummonPsionicFamiliarActionEvent args)
{
if (psionicComponent.Familiars.Count >= psionicComponent.FamiliarLimit
|| !_psionics.OnAttemptPowerUse(args.Performer, args.PowerName, args.ManaCost, args.CheckInsulation)
|| args.Handled || args.FamiliarProto is null)
return;

args.Handled = true;
var familiar = Spawn(args.FamiliarProto, Transform(uid).Coordinates);
EnsureComp<PsionicFamiliarComponent>(familiar, out var familiarComponent);
familiarComponent.Master = uid;
psionicComponent.Familiars.Add(familiar);
Dirty(familiar, familiarComponent);
Dirty(uid, psionicComponent);

InheritFactions(uid, familiar, familiarComponent);
HandleBlackboards(uid, familiar, args);
DoGlimmerEffects(uid, psionicComponent, args);
}

private void InheritFactions(EntityUid uid, EntityUid familiar, PsionicFamiliarComponent familiarComponent)
{
if (!familiarComponent.InheritMasterFactions
|| !TryComp<NpcFactionMemberComponent>(uid, out var masterFactions)
|| masterFactions.Factions.Count <= 0)
return;

EnsureComp<NpcFactionMemberComponent>(familiar, out var familiarFactions);
foreach (var faction in masterFactions.Factions)
{
if (familiarFactions.Factions.Contains(faction))
continue;

_factions.AddFaction(familiar, faction, true);
}
}

private void HandleBlackboards(EntityUid master, EntityUid familiar, SummonPsionicFamiliarActionEvent args)
{
if (!args.FollowMaster
|| !TryComp<HTNComponent>(familiar, out var htnComponent))
return;

_npc.SetBlackboard(familiar, NPCBlackboard.FollowTarget, new EntityCoordinates(master, Vector2.Zero), htnComponent);
_htn.Replan(htnComponent);
}

private void DoGlimmerEffects(EntityUid uid, PsionicComponent component, SummonPsionicFamiliarActionEvent args)
{
if (!args.DoGlimmerEffects
|| args.MinGlimmer == 0 && args.MaxGlimmer == 0)
return;

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);
}

private void OnFamiliarShutdown(EntityUid uid, PsionicFamiliarComponent component, ComponentShutdown args)
{
if (!Exists(component.Master)
|| !TryComp<PsionicComponent>(component.Master, out var psionicComponent)
|| !psionicComponent.Familiars.Contains(uid))
return;

psionicComponent.Familiars.Remove(uid);
}

private void OnFamiliarAttack(EntityUid uid, PsionicFamiliarComponent component, AttackAttemptEvent args)
{
if (component.CanAttackMaster || args.Target is null
|| args.Target != component.Master)
return;

args.Cancel();
if (!Loc.TryGetString(component.AttackMasterText, out var attackFailMessage))
return;

_popup.PopupEntity(attackFailMessage, uid, uid, component.AttackPopupType);
}

private void OnFamiliarDeath(EntityUid uid, PsionicFamiliarComponent component, MobStateChangedEvent args)
{
if (!component.DespawnOnFamiliarDeath
|| args.NewMobState != MobState.Dead)
return;

DespawnFamiliar(uid, component);
}

public void DespawnFamiliar(EntityUid uid)
{
if (!TryComp<PsionicFamiliarComponent>(uid, out var familiarComponent))
return;

DespawnFamiliar(uid, familiarComponent);
}

public void DespawnFamiliar(EntityUid uid, PsionicFamiliarComponent component)
{
var popupText = Loc.GetString(component.DespawnText, ("entity", MetaData(uid).EntityName));
_popup.PopupEntity(popupText, uid, component.DespawnPopopType);
QueueDel(uid);
}
}
44 changes: 44 additions & 0 deletions Content.Server/Alert/Click/CheckHealth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Content.Server.Chat.Managers;
using Content.Shared.Alert;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.HealthExaminable;
using JetBrains.Annotations;
using Robust.Server.Player;
using Robust.Shared.Player;

namespace Content.Server.Alert.Click;

[UsedImplicitly]
[DataDefinition]
public sealed partial class CheckHealth : IAlertClick
{
public void AlertClicked(EntityUid player)
{
var chatManager = IoCManager.Resolve<IChatManager>();
var entityManager = IoCManager.Resolve<IEntityManager>();
var playerManager = IoCManager.Resolve<IPlayerManager>();

var healthExaminableSystem = entityManager.System<HealthExaminableSystem>();

if (!entityManager.TryGetComponent(player, out HealthExaminableComponent? healthExaminable) ||
!entityManager.TryGetComponent(player, out DamageableComponent? damageable) ||
!playerManager.TryGetSessionByEntity(player, out var session))
return;

var baseMsg = Loc.GetString("health-alert-start");
SendMessage(chatManager, baseMsg, session);
var markup = healthExaminableSystem.GetMarkup(player, (player, healthExaminable), damageable).ToMarkup();
SendMessage(chatManager, markup, session);
}

private static void SendMessage(IChatManager chatManager, string msg, ICommonSession session)
{
chatManager.ChatMessageToOne(ChatChannel.Emotes,
msg,
msg,
EntityUid.Invalid,
false,
session.Channel);
}
}
6 changes: 6 additions & 0 deletions Content.Server/NPC/Components/NPCRetaliationComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ public sealed partial class NPCRetaliationComponent : Component
/// todo: this needs to support timeoffsetserializer at some point
[DataField("attackMemories")]
public Dictionary<EntityUid, TimeSpan> AttackMemories = new();

/// <summary>
/// Whether this NPC will retaliate against a "Friendly" NPC.
/// </summary>
[DataField]
public bool RetaliateFriendlies;
}
1 change: 0 additions & 1 deletion Content.Server/NPC/Components/NpcFactionMemberComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
namespace Content.Server.NPC.Components
{
[RegisterComponent]
[Access(typeof(NpcFactionSystem))]
public sealed partial class NpcFactionMemberComponent : Component
{
/// <summary>
Expand Down
Loading

0 comments on commit 35e786e

Please sign in to comment.