Skip to content

Commit

Permalink
Merge pull request Fansana#505 from Mnemotechnician/floof/cherrypick/…
Browse files Browse the repository at this point in the history
…ee-2024-01-21

Merges & Cherry-Picks From EE up to 2025-01-24
  • Loading branch information
FoxxoTrystan authored Feb 2, 2025
2 parents 9676430 + 5172ab1 commit e6e3087
Show file tree
Hide file tree
Showing 237 changed files with 14,322 additions and 6,961 deletions.
23 changes: 15 additions & 8 deletions Content.Server/Anomaly/AnomalySystem.Scanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,24 @@ private void OnScannerUiOpened(EntityUid uid, AnomalyScannerComponent component,

private void OnScannerAfterInteract(EntityUid uid, AnomalyScannerComponent component, AfterInteractEvent args)
{
if (args.Target is not { } target)
return;
if (!HasComp<AnomalyComponent>(target))
return;
if (!args.CanReach)
if (args.Target is not { } target || !args.CanReach)
return;

_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.ScanDoAfterDuration, new ScannerDoAfterEvent(), uid, target: target, used: uid)
// If interacting with an anomaly, start a scan do-after
if (HasComp<AnomalyComponent>(target))
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.ScanDoAfterDuration, new ScannerDoAfterEvent(), uid, target: target, used: uid)
{
DistanceThreshold = 2f
});

// If interacting with another scanner, copy the anomaly data
if (component.ScannedAnomaly is not { Valid: true }
&& TryComp<AnomalyScannerComponent>(args.Target, out var otherScanner)
&& otherScanner.ScannedAnomaly is {} otherAnomaly)
{
DistanceThreshold = 2f
});
UpdateScannerWithNewAnomaly(uid, otherAnomaly, component);
Popup.PopupEntity(Loc.GetString("anomaly-scanner-scan-copied"), uid);
}
}

private void OnDoAfter(EntityUid uid, AnomalyScannerComponent component, DoAfterEvent args)
Expand Down
5 changes: 3 additions & 2 deletions Content.Server/Humanoid/Systems/RandomHumanoidSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ public EntityUid SpawnRandomHumanoid(string prototypeId, EntityCoordinates coord

_metaData.SetEntityName(humanoid, prototype.RandomizeName ? profile.Name : name);

// Floof - moved initialization of the humanoid to before the profile load,
// as initializing a humanoid appearance overrides the random appearance applied here. Move back down if/when it's fixed.
EntityManager.InitializeAndStartEntity(humanoid);
_humanoid.LoadProfile(humanoid, profile);

if (prototype.Components != null)
Expand All @@ -57,8 +60,6 @@ public EntityUid SpawnRandomHumanoid(string prototypeId, EntityCoordinates coord
}
}

EntityManager.InitializeAndStartEntity(humanoid);

return humanoid;
}
}
3 changes: 3 additions & 0 deletions Content.Server/LifeDrainer/LifeDrainerSystem.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Server.Abilities.Psionics;
using Content.Server.Carrying;
using Content.Server.NPC.Systems;
using Content.Shared.ActionBlocker;
Expand Down Expand Up @@ -27,6 +28,7 @@ public sealed class LifeDrainerSystem : EntitySystem
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly PsionicAbilitiesSystem _psionicAbilitiesSystem = default!;

public override void Initialize()
{
Expand Down Expand Up @@ -88,6 +90,7 @@ private void OnDrain(Entity<LifeDrainerComponent> ent, ref LifeDrainDoAfterEvent
_audio.PlayPvs(comp.FinishSound, uid);

_damageable.TryChangeDamage(target, comp.Damage, true, origin: uid);
_psionicAbilitiesSystem.MindBreak(target);
}

public bool CanDrain(Entity<LifeDrainerComponent> ent, EntityUid target)
Expand Down
137 changes: 137 additions & 0 deletions Content.Server/Traits/TraitSystem.Functions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
using Content.Server.Language;
using Content.Shared.Mood;
using Content.Server.NPC.Systems;
using Content.Shared.Traits.Assorted.Components;
using Content.Shared.Damage;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Mobs;
using Content.Shared.Damage.Components;

namespace Content.Server.Traits;

Expand Down Expand Up @@ -263,3 +271,132 @@ public override void OnPlayerSpawn(EntityUid uid,
vvm.WritePath(path, value);
}
}

/// Used for writing to an entity's ExtendDescriptionComponent. If one is not present, it will be added!
/// Use this to create traits that add special descriptions for when a character is shift-click examined.
[UsedImplicitly]
public sealed partial class TraitPushDescription : TraitFunction
{
[DataField, AlwaysPushInheritance]
public List<DescriptionExtension> DescriptionExtensions { get; private set; } = new();

public override void OnPlayerSpawn(EntityUid uid,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager)
{
entityManager.EnsureComponent<ExtendDescriptionComponent>(uid, out var descComp);
foreach (var descExtension in DescriptionExtensions)
descComp.DescriptionList.Add(descExtension);
}
}

[UsedImplicitly]
public sealed partial class TraitAddArmor : TraitFunction
{
/// <summary>
/// The list of prototype ID's of DamageModifierSets to be added to the enumerable damage modifiers of an entity.
/// </summary>
/// <remarks>
/// Dear Maintainer, I'm well aware that validating protoIds is a thing. Unfortunately, this is for a legacy system that doesn't have validated prototypes.
/// And refactoring the entire DamageableSystem is way the hell outside of the scope of the PR adding this function.
/// {FaridaIsCute.png} - Solidus
/// </remarks>
[DataField, AlwaysPushInheritance]
public List<string> DamageModifierSets { get; private set; } = new();

public override void OnPlayerSpawn(EntityUid uid,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager)
{
entityManager.EnsureComponent<DamageableComponent>(uid, out var damageableComponent);
foreach (var modifierSet in DamageModifierSets)
damageableComponent.DamageModifierSets.Add(modifierSet);
}
}

[UsedImplicitly]
public sealed partial class TraitAddSolutionContainer : TraitFunction
{
[DataField, AlwaysPushInheritance]
public Dictionary<string, SolutionComponent> Solutions { get; private set; } = new();

public override void OnPlayerSpawn(EntityUid uid,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager)
{
var solutionContainer = entityManager.System<SharedSolutionContainerSystem>();

foreach (var (containerKey, solution) in Solutions)
{
var hasSolution = solutionContainer.EnsureSolution(uid, containerKey, out Solution? newSolution);

if (!hasSolution)
return;

newSolution!.AddSolution(solution.Solution, null);
}
}
}

[UsedImplicitly]
public sealed partial class TraitModifyMobThresholds : TraitFunction
{
[DataField, AlwaysPushInheritance]
public int CritThresholdModifier;

[DataField, AlwaysPushInheritance]
public int DeadThresholdModifier;

public override void OnPlayerSpawn(EntityUid uid,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager)
{
if (!entityManager.TryGetComponent<MobThresholdsComponent>(uid, out var threshold))
return;

var thresholdSystem = entityManager.System<MobThresholdSystem>();
if (CritThresholdModifier != 0)
{
var critThreshold = thresholdSystem.GetThresholdForState(uid, MobState.Critical, threshold);
if (critThreshold != 0)
thresholdSystem.SetMobStateThreshold(uid, critThreshold + CritThresholdModifier, MobState.Critical);
}

if (DeadThresholdModifier != 0)
{
var deadThreshold = thresholdSystem.GetThresholdForState(uid, MobState.Dead, threshold);
if (deadThreshold != 0)
thresholdSystem.SetMobStateThreshold(uid, deadThreshold + DeadThresholdModifier, MobState.Dead);
}
}
}

[UsedImplicitly]
public sealed partial class TraitModifyStamina : TraitFunction
{
[DataField, AlwaysPushInheritance]
public float StaminaModifier;

[DataField, AlwaysPushInheritance]
public float DecayModifier;

[DataField, AlwaysPushInheritance]
public float CooldownModifier;

public override void OnPlayerSpawn(EntityUid uid,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager)
{
if (!entityManager.TryGetComponent<StaminaComponent>(uid, out var staminaComponent))
return;

staminaComponent.CritThreshold += StaminaModifier;
staminaComponent.Decay += DecayModifier;
staminaComponent.Cooldown += CooldownModifier;
}
}
10 changes: 10 additions & 0 deletions Content.Server/Weapons/Melee/MeleeWeaponSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Utility;
using System.Linq;
using System.Numerics;
using Content.Shared.Chat;
Expand Down Expand Up @@ -60,6 +61,15 @@ private void OnMeleeExamineDamage(EntityUid uid, MeleeWeaponComponent component,

if (damageSpec * component.HeavyDamageBaseModifier != damageSpec)
_damageExamine.AddDamageExamine(args.Message, damageSpec * component.HeavyDamageBaseModifier, Loc.GetString("damage-melee-heavy"));

if (component.HeavyStaminaCost != 0)
{
var staminaCostMarkup = FormattedMessage.FromMarkupOrThrow(
Loc.GetString("damage-melee-heavy-stamina-cost",
("type", Loc.GetString("damage-melee-heavy")), ("cost", component.HeavyStaminaCost)));
args.Message.PushNewline();
args.Message.AddMessage(staminaCostMarkup);
}
}

protected override bool ArcRaySuccessful(EntityUid targetUid, Vector2 position, Angle angle, Angle arcWidth, float range, MapId mapId,
Expand Down
2 changes: 1 addition & 1 deletion Content.Shared/Body/Systems/SharedBodySystem.Targeting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public partial class SharedBodySystem
[Dependency] private readonly DamageableSystem _damageable = default!;

[Dependency] private readonly SharedPopupSystem _popup = default!;
private readonly string[] _severingDamageTypes = { "Slash", "Pierce", "Blunt" };
private readonly string[] _severingDamageTypes = { "Slash", "Piercing", "Blunt" };
private const double IntegrityJobTime = 0.005;
private readonly JobQueue _integrityJobQueue = new(IntegrityJobTime);
public sealed class IntegrityJob : Job<object>
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/Damage/Components/DamageableComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ public sealed partial class DamageableComponent : Component
[DataField("damageModifierSet", customTypeSerializer: typeof(PrototypeIdSerializer<DamageModifierSetPrototype>))]
public string? DamageModifierSetId;

/// <summary>
/// List of all Modifier Sets stored by this entity. The above single format is a deprecated function used only to support legacy yml.
/// </summary>
[DataField]
public List<string> DamageModifierSets = new();

/// <summary>
/// All the damage information is stored in this <see cref="DamageSpecifier"/>.
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions Content.Shared/Damage/Systems/DamageableSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSp
// TODO: We need to add a check to see if the given armor covers the targeted part (if any) to modify or not.
damage = DamageSpecifier.ApplyModifierSet(damage, modifierSet);
}

// From Solidus: If you are reading this, I owe you a more comprehensive refactor of this entire system.
if (damageable.DamageModifierSets.Count > 0)
foreach (var enumerableModifierSet in damageable.DamageModifierSets)
if (_prototypeManager.TryIndex<DamageModifierSetPrototype>(enumerableModifierSet, out var enumerableModifier))
damage = DamageSpecifier.ApplyModifierSet(damage, enumerableModifier);

var ev = new DamageModifyEvent(damage, origin, targetPart);
RaiseLocalEvent(uid.Value, ev);
damage = ev.Damage;
Expand Down
2 changes: 2 additions & 0 deletions Content.Shared/Preferences/HumanoidCharacterProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ public static HumanoidCharacterProfile DefaultWithSpecies(string species = Share
return new()
{
Species = species,
// Floof: Added a part about loading the default appearance. Not sure why/when it was removed.
Appearance = HumanoidCharacterAppearance.DefaultWithSpecies(species)
};
}

Expand Down
11 changes: 0 additions & 11 deletions Content.Shared/Traits/Assorted/Components/CyberEyesComponent.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Robust.Shared.Serialization;

namespace Content.Shared.Traits.Assorted.Components;

[Serializable, NetSerializable, DataDefinition]
public sealed partial class DescriptionExtension
{
[DataField]
public string Description = "";

[DataField]
public int FontSize = 12;

[DataField]
public string Color = "#ffffff";

[DataField]
public bool RequireDetailRange = true;
}

[RegisterComponent]
public sealed partial class ExtendDescriptionComponent : Component
{
/// <summary>
/// The list of all descriptions to add to an entity when examined at close range.
/// </summary>
[DataField]
public List<DescriptionExtension> DescriptionList = new();
}
21 changes: 0 additions & 21 deletions Content.Shared/Traits/Assorted/Systems/CyberEyesSystem.cs

This file was deleted.

27 changes: 27 additions & 0 deletions Content.Shared/Traits/Assorted/Systems/ExtendDescriptionSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Content.Shared.Examine;
using Content.Shared.Traits.Assorted.Components;

namespace Content.Shared.Traits.Assorted.Systems;

public sealed class ExtendDescriptionSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ExtendDescriptionComponent, ExaminedEvent>(OnExamined);
}

private void OnExamined(EntityUid uid, ExtendDescriptionComponent component, ExaminedEvent args)
{
if (component.DescriptionList.Count <= 0)
return;

foreach (var desc in component.DescriptionList)
{
if (!args.IsInDetailsRange && desc.RequireDetailRange)
continue;

args.PushMarkup($"[font size ={desc.FontSize}][color={desc.Color}]{Loc.GetString(desc.Description, ("entity", uid))}[/color][/font]");
}
}
}
Loading

0 comments on commit e6e3087

Please sign in to comment.