From 21493705385cabfb1dd942954a5cc26e27843526 Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Mon, 9 Mar 2026 02:38:19 +0100 Subject: [PATCH 1/9] feat: effigy-driven colossus --- .../Abilities/Colossus/CosmicEffigySystem.cs | 94 +++++++++++++++++- .../Components/CosmicCorruptingComponent.cs | 3 +- .../Components/CosmicEffigyComponent.cs | 20 ++++ .../CosmicCult/CosmicCultObjectiveSystem.cs | 24 ++++- .../EntitySystems/CosmicColossusSystem.cs | 2 +- .../Components/CosmicColossusComponent.cs | 8 +- .../Locale/en-US/_DV/cosmiccult/colossus.ftl | 1 + .../_DV/CosmicCult/Effects/effects.yml | 30 ++++++ .../_DV/CosmicCult/Tileset/effigy.yml | 1 + .../Effects/colossus_upgradevfx.rsi/meta.json | 39 ++++++++ .../Effects/colossus_upgradevfx.rsi/vfx.png | Bin 0 -> 4735 bytes 11 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs create mode 100644 Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl create mode 100644 Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/meta.json create mode 100644 Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/vfx.png diff --git a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs index 32a1cb0836..08bb7998b6 100644 --- a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs +++ b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs @@ -1,15 +1,28 @@ using System.Numerics; +using Content.Server._DV.CosmicCult.Components; using Content.Server.Actions; +using Content.Server.Objectives; using Content.Server.Objectives.Components; using Content.Server.Objectives.Systems; using Content.Server.Popups; using Content.Shared._DV.CosmicCult; using Content.Shared._DV.CosmicCult.Components; +using Content.Shared.Anomaly.Components; +using Content.Shared.Damage.Components; +using Content.Shared.Damage.Systems; using Content.Shared.Maps; using Content.Shared.Mind; +using Content.Shared.Mind.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Content.Shared.Popups; using Content.Shared.Warps; +using Content.Shared.Weapons.Melee; +using Robust.Server.Audio; +using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Timing; namespace Content.Server._DV.CosmicCult.Abilities; @@ -23,12 +36,83 @@ public sealed class CosmicEffigySystem : EntitySystem [Dependency] private readonly SharedMapSystem _map = default!; [Dependency] private readonly SharedMindSystem _mind = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly DamageableSystem _damage = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly CosmicCultObjectiveSystem _cultObjective = default!; + [Dependency] private readonly IGameTiming _time = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnColossusEffigy); + SubscribeLocalEvent(OnSupercritical); + SubscribeLocalEvent(OnAnomShutdown); + } + + private void OnAnomShutdown(Entity ent, ref AnomalyShutdownEvent args) + { + if (args.Supercritical || !Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp)) + return; + + colossusComp.Timed = true; + colossusComp.DeathTimer = _time.CurTime; + } + + private void OnSupercritical(Entity ent, ref AnomalySupercriticalEvent args) + { + if (!Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp) || !_mind.TryGetMind(ent.Comp.Colossus.Value, out var mindId, out var mind)) + return; + + var colossus = ent.Comp.Colossus.Value; + + if (TryComp(colossus, out var weapon)) + { + weapon.AttackRate = Math.Clamp(weapon.AttackRate * ent.Comp.ColossusAttackRateMultiplier, 0, ent.Comp.ColossusAttackRateMax ?? float.MaxValue); + } + + if (TryComp(colossus, out var corrupting)) + { + corrupting.CorruptionSpeed *= ent.Comp.ColossusCorruptionSpeedMultiplier; + } + + if (ent.Comp.ColossusHeal && TryComp(colossus, out var damageable)) + { + _damage.TryChangeDamage(ent.Comp.Colossus.Value, damageable.Damage / 2 * -1, true); + } + + Spawn(colossusComp.UpgradeVfx, Transform(ent.Comp.Colossus.Value).Coordinates); + if (!colossusComp.CompletedFirstEffigy) + { + _audio.PlayGlobal(colossusComp.ReawakenSfx, ent); + colossusComp.CompletedFirstEffigy = true; + } + else + { + _audio.PlayPvs(colossusComp.ReawakenSfx, ent); + } + + var objIndex = mind.Objectives.FindIndex(HasComp); + if (objIndex == -1 || + !TryComp(mind.Objectives[objIndex], out var conditionComp)) + { + Log.Error($"Failed to find effigy objective on {ToPrettyString(colossus)}!"); + return; + } + + var objective = mind.Objectives[objIndex]; + if (!_cultObjective.RandomizeEffigyTarget(objective, conditionComp)) + { + Log.Error("Failed to randomize effigy objective location!"); + return; + } + _codeCondition.SetCompleted(objective, false); + + colossusComp.EffigyPlaceActionEntity = _actions.AddAction(colossus, colossusComp.EffigyPlaceAction); + colossusComp.DeathTimer = _time.CurTime + colossusComp.DeathWaitEffigy; + colossusComp.Timed = true; + + _popup.PopupEntity(Loc.GetString("colossus-upgrade-popup"), colossus, PopupType.Medium); } private void OnColossusEffigy(Entity ent, ref EventCosmicColossusEffigy args) @@ -38,8 +122,16 @@ public sealed class CosmicEffigySystem : EntitySystem _actions.RemoveAction(ent.Owner, ent.Comp.EffigyPlaceActionEntity); _codeCondition.SetCompleted(ent.Owner, ent.Comp.EffigyObjective); - Spawn(ent.Comp.EffigyPrototype, pos); + var effigy = Spawn(ent.Comp.EffigyPrototype, pos); ent.Comp.Timed = false; + + if (!TryComp(effigy, out var effigyComp)) + { + Log.Error("Colossus tried to place Effigy prototype missing CosmicEffigyComponent!"); + return; + } + + effigyComp.Colossus = ent.Owner; } private bool VerifyPlacement(Entity ent, out EntityCoordinates outPos) diff --git a/Content.Server/_DV/CosmicCult/Components/CosmicCorruptingComponent.cs b/Content.Server/_DV/CosmicCult/Components/CosmicCorruptingComponent.cs index f403587dd7..9b41f34167 100644 --- a/Content.Server/_DV/CosmicCult/Components/CosmicCorruptingComponent.cs +++ b/Content.Server/_DV/CosmicCult/Components/CosmicCorruptingComponent.cs @@ -1,3 +1,4 @@ +using Content.Server._DV.CosmicCult.Abilities; using Content.Server._DV.CosmicCult.EntitySystems; using Content.Shared.Maps; using Robust.Shared.Prototypes; @@ -5,7 +6,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server._DV.CosmicCult.Components; -[RegisterComponent, Access(typeof(CosmicCorruptingSystem))] +[RegisterComponent, Access(typeof(CosmicCorruptingSystem), typeof(CosmicEffigySystem))] [AutoGenerateComponentPause] public sealed partial class CosmicCorruptingComponent : Component { diff --git a/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs b/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs new file mode 100644 index 0000000000..68ee1c3a49 --- /dev/null +++ b/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs @@ -0,0 +1,20 @@ +namespace Content.Server._DV.CosmicCult.Components; + +[RegisterComponent] +public sealed partial class CosmicEffigyComponent : Component +{ + [DataField] + public EntityUid? Colossus; + + [DataField] + public float ColossusAttackRateMultiplier = 1.2f; + + [DataField] + public float? ColossusAttackRateMax = 1.5f; + + [DataField] + public float ColossusCorruptionSpeedMultiplier = 0.9f; + + [DataField] + public bool ColossusHeal = true; +} diff --git a/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs b/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs index fc6acaab93..c2269e2c1e 100644 --- a/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs +++ b/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs @@ -35,6 +35,12 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem if (args.Cancelled || !_roles.MindHasRole(args.MindId)) return; + if (!RandomizeEffigyTarget(uid, comp)) + args.Cancelled = true; + } + + public bool RandomizeEffigyTarget(EntityUid uid, CosmicEffigyConditionComponent comp, bool setDescription = false) + { var warps = new List(); var query = EntityQueryEnumerator(); var effigyBlacklist = comp.Blacklist; @@ -51,10 +57,22 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem if (warps.Count <= 0) { - args.Cancelled = true; - return; + return false; } - comp.EffigyTarget = _random.Pick(warps); + + var newWarp = _random.Pick(warps); + var warpComp = Comp(newWarp); + + comp.EffigyTarget = newWarp; + + if (setDescription) + { + _metaData.SetEntityDescription(uid, + warpComp.Location != null + ? Loc.GetString("objective-condition-effigy", ("location", warpComp.Location ?? "UNNAMED")) + : Loc.GetString("objective-condition-effigy-no-target")); + } + return true; } private void OnEffigyAfterAssign(EntityUid uid, CosmicEffigyConditionComponent comp, ref ObjectiveAfterAssignEvent args) diff --git a/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs b/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs index d1cceeb15e..3848f8ada5 100644 --- a/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs +++ b/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs @@ -82,7 +82,7 @@ public sealed class CosmicColossusSystem : EntitySystem private void OnSpawn(Entity ent, ref ComponentInit args) // I WANT THIS BIG GUY HURLED TOWARDS THE STATION { - ent.Comp.DeathTimer = _timing.CurTime + ent.Comp.DeathWait; + ent.Comp.DeathTimer = _timing.CurTime + ent.Comp.DeathWaitSpawn; var station = _station.GetStationInMap(Transform(ent).MapID); if (TryComp(station, out var stationData)) { diff --git a/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs b/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs index cad6a3eb98..bb7f97bf62 100644 --- a/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs +++ b/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs @@ -36,6 +36,8 @@ public sealed partial class CosmicColossusComponent : Component [DataField] public EntProtoId Attack1Vfx = "CosmicColossusAttack1Vfx"; + [DataField] public EntProtoId UpgradeVfx = "ColossusUpgradeVFX"; + [DataField] public EntProtoId TileDetonations = "MobTileDamageZone"; [DataField] public EntProtoId EffigyPrototype = "CosmicEffigy"; @@ -52,13 +54,17 @@ public sealed partial class CosmicColossusComponent : Component [DataField] public TimeSpan HibernationWait = TimeSpan.FromSeconds(30); - [DataField] public TimeSpan DeathWait = TimeSpan.FromMinutes(15); + [DataField] public TimeSpan DeathWaitSpawn = TimeSpan.FromMinutes(15); + + [DataField] public TimeSpan DeathWaitEffigy = TimeSpan.FromMinutes(10); [DataField] public bool Attacking; [DataField] public bool Hibernating; [DataField] public bool Timed; + + [DataField] public bool CompletedFirstEffigy; } [Serializable, NetSerializable] diff --git a/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl b/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl new file mode 100644 index 0000000000..bc222da212 --- /dev/null +++ b/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl @@ -0,0 +1 @@ +colossus-upgrade-popup = You grow stronger. Another space calls for you. diff --git a/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml b/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml index 57c5a553be..08a46ccc36 100644 --- a/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml +++ b/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml @@ -169,6 +169,36 @@ isLooped: true reverseWhenFinished: true +- type: entity + categories: [ HideSpawnMenu ] + parent: BaseCosmicVFX + id: ColossusUpgradeVFX + components: + - type: TimedDespawn + lifetime: 0.8 + - type: Sprite + layers: + - sprite: _DV/CosmicCult/Effects/colossus_upgradevfx.rsi + state: vfx + shader: unshaded + - type: PointLight + color: "#a35d7b" + radius: 1.5 + energy: 2.5 + castShadows: false + - type: LightBehaviour + behaviours: + - !type:FadeBehaviour + interpolate: Linear + minDuration: 0.8 + maxDuration: 0.8 + startValue: 0.1 + endValue: 2 + property: Energy + enabled: true + isLooped: true + reverseWhenFinished: true + - type: entity categories: [ HideSpawnMenu ] parent: BaseCosmicVFX diff --git a/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml b/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml index 22f0154b77..423094c8bc 100644 --- a/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml +++ b/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml @@ -23,6 +23,7 @@ - type: CosmicCultExamine cultistText: cosmic-examine-text-culteffigy othersText: cosmic-examine-text-effigy + - type: CosmicEffigy - type: CosmicCorrupting corruptionReduction: 0.02 enabled: true diff --git a/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/meta.json b/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/meta.json new file mode 100644 index 0000000000..0b6078963e --- /dev/null +++ b/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/meta.json @@ -0,0 +1,39 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "by DisposableCrewmember42 on GitHub", + "size": { + "x": 61, + "y": 118 + }, + "states": [ + { + "name": "vfx", + "delays": [ + [ + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04, + 0.04 + ] + ] + } + ] +} diff --git a/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/vfx.png b/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/vfx.png new file mode 100644 index 0000000000000000000000000000000000000000..bd5e373703295c03d3fc52bb6ecd85eacc86a01c GIT binary patch literal 4735 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 Date: Tue, 10 Mar 2026 12:54:32 +0100 Subject: [PATCH 2/9] feat: impl final stage, tweaks, randomization, fixes --- Content.Server/Anomaly/AnomalySystem.cs | 2 +- .../Abilities/Colossus/CosmicEffigySystem.cs | 37 +++++++++++------- .../Components/CosmicEffigyComponent.cs | 10 +++-- .../CosmicCult/CosmicCultObjectiveSystem.cs | 2 +- .../EntitySystems/CosmicColossusSystem.cs | 7 ++++ .../Anomaly/Components/AnomalyComponent.cs | 2 +- Content.Shared/Anomaly/SharedAnomalySystem.cs | 5 ++- .../Components/CosmicColossusComponent.cs | 13 +++++- .../Locale/en-US/_DV/cosmiccult/colossus.ftl | 3 +- .../en-US/_DV/cosmiccult/ghostroles.ftl | 2 +- .../_DV/CosmicCult/Effects/effects.yml | 4 +- .../_DV/CosmicCult/Tileset/effigy.yml | 2 +- .../meta.json | 0 .../vfx.png | Bin 14 files changed, 59 insertions(+), 30 deletions(-) rename Resources/Textures/_DV/CosmicCult/Effects/{colossus_upgradevfx.rsi => colossus_buffvfx.rsi}/meta.json (100%) rename Resources/Textures/_DV/CosmicCult/Effects/{colossus_upgradevfx.rsi => colossus_buffvfx.rsi}/vfx.png (100%) diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs index 7a39544178..ea579c3bc0 100644 --- a/Content.Server/Anomaly/AnomalySystem.cs +++ b/Content.Server/Anomaly/AnomalySystem.cs @@ -89,7 +89,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem if (anomaly.Comp.CurrentBehavior is not null) RemoveBehavior(anomaly, anomaly.Comp.CurrentBehavior.Value); - EndAnomaly(anomaly, spawnCore: false); + EndAnomaly(anomaly, spawnCore: false, forced: true); } private void OnStartCollide(Entity anomaly, ref StartCollideEvent args) diff --git a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs index 08bb7998b6..7a917805f1 100644 --- a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs +++ b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs @@ -8,20 +8,18 @@ using Content.Server.Popups; using Content.Shared._DV.CosmicCult; using Content.Shared._DV.CosmicCult.Components; using Content.Shared.Anomaly.Components; +using Content.Shared.Damage; using Content.Shared.Damage.Components; using Content.Shared.Damage.Systems; using Content.Shared.Maps; using Content.Shared.Mind; -using Content.Shared.Mind.Components; -using Content.Shared.Movement.Components; -using Content.Shared.Movement.Systems; using Content.Shared.Popups; using Content.Shared.Warps; using Content.Shared.Weapons.Melee; using Robust.Server.Audio; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Server._DV.CosmicCult.Abilities; @@ -40,6 +38,7 @@ public sealed class CosmicEffigySystem : EntitySystem [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly CosmicCultObjectiveSystem _cultObjective = default!; [Dependency] private readonly IGameTiming _time = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; public override void Initialize() { @@ -52,23 +51,23 @@ public sealed class CosmicEffigySystem : EntitySystem private void OnAnomShutdown(Entity ent, ref AnomalyShutdownEvent args) { - if (args.Supercritical || !Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp)) + if (args.Forced || args.Supercritical || !Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp)) return; - colossusComp.Timed = true; colossusComp.DeathTimer = _time.CurTime; + colossusComp.Timed = true; } private void OnSupercritical(Entity ent, ref AnomalySupercriticalEvent args) { - if (!Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp) || !_mind.TryGetMind(ent.Comp.Colossus.Value, out var mindId, out var mind)) + if (!Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp) || !_mind.TryGetMind(ent.Comp.Colossus.Value, out _, out var mind)) return; var colossus = ent.Comp.Colossus.Value; if (TryComp(colossus, out var weapon)) { - weapon.AttackRate = Math.Clamp(weapon.AttackRate * ent.Comp.ColossusAttackRateMultiplier, 0, ent.Comp.ColossusAttackRateMax ?? float.MaxValue); + weapon.AttackRate *= ent.Comp.ColossusAttackRateMultiplier; } if (TryComp(colossus, out var corrupting)) @@ -81,17 +80,29 @@ public sealed class CosmicEffigySystem : EntitySystem _damage.TryChangeDamage(ent.Comp.Colossus.Value, damageable.Damage / 2 * -1, true); } - Spawn(colossusComp.UpgradeVfx, Transform(ent.Comp.Colossus.Value).Coordinates); - if (!colossusComp.CompletedFirstEffigy) + colossusComp.BonusDamage += new DamageSpecifier(_proto.Index(colossusComp.BonusDamageType), ent.Comp.ColossusBonusDamage); + + Spawn(colossusComp.BuffVfx, Transform(ent.Comp.Colossus.Value).Coordinates); + if (colossusComp.CompletedEffigies == 0) { _audio.PlayGlobal(colossusComp.ReawakenSfx, ent); - colossusComp.CompletedFirstEffigy = true; } else { _audio.PlayPvs(colossusComp.ReawakenSfx, ent); } + colossusComp.CompletedEffigies += 1; + + if (colossusComp.CompletedEffigies >= colossusComp.MaxEffigies) + { + colossusComp.Timed = false; + _popup.PopupEntity(Loc.GetString("colossus-buff-final-popup"), colossus, PopupType.Large); + return; + } + + _popup.PopupEntity(Loc.GetString("colossus-buff-popup"), colossus, PopupType.Large); + var objIndex = mind.Objectives.FindIndex(HasComp); if (objIndex == -1 || !TryComp(mind.Objectives[objIndex], out var conditionComp)) @@ -101,7 +112,7 @@ public sealed class CosmicEffigySystem : EntitySystem } var objective = mind.Objectives[objIndex]; - if (!_cultObjective.RandomizeEffigyTarget(objective, conditionComp)) + if (!_cultObjective.RandomizeEffigyTarget(objective, conditionComp, setDescription: true)) { Log.Error("Failed to randomize effigy objective location!"); return; @@ -111,8 +122,6 @@ public sealed class CosmicEffigySystem : EntitySystem colossusComp.EffigyPlaceActionEntity = _actions.AddAction(colossus, colossusComp.EffigyPlaceAction); colossusComp.DeathTimer = _time.CurTime + colossusComp.DeathWaitEffigy; colossusComp.Timed = true; - - _popup.PopupEntity(Loc.GetString("colossus-upgrade-popup"), colossus, PopupType.Medium); } private void OnColossusEffigy(Entity ent, ref EventCosmicColossusEffigy args) diff --git a/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs b/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs index 68ee1c3a49..1f8a01ee65 100644 --- a/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs +++ b/Content.Server/_DV/CosmicCult/Components/CosmicEffigyComponent.cs @@ -1,3 +1,5 @@ +using Content.Shared.FixedPoint; + namespace Content.Server._DV.CosmicCult.Components; [RegisterComponent] @@ -7,14 +9,14 @@ public sealed partial class CosmicEffigyComponent : Component public EntityUid? Colossus; [DataField] - public float ColossusAttackRateMultiplier = 1.2f; - - [DataField] - public float? ColossusAttackRateMax = 1.5f; + public float ColossusAttackRateMultiplier = 1.1f; [DataField] public float ColossusCorruptionSpeedMultiplier = 0.9f; + [DataField] + public FixedPoint2 ColossusBonusDamage = 10; + [DataField] public bool ColossusHeal = true; } diff --git a/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs b/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs index c2269e2c1e..557fb85975 100644 --- a/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs +++ b/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs @@ -69,7 +69,7 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem { _metaData.SetEntityDescription(uid, warpComp.Location != null - ? Loc.GetString("objective-condition-effigy", ("location", warpComp.Location ?? "UNNAMED")) + ? Loc.GetString("objective-condition-effigy", ("location", warpComp.Location)) : Loc.GetString("objective-condition-effigy-no-target")); } return true; diff --git a/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs b/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs index 3848f8ada5..e8013312d6 100644 --- a/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs +++ b/Content.Server/_DV/CosmicCult/EntitySystems/CosmicColossusSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Popups; using Content.Shared.Station.Components; using Content.Shared.Throwing; using Content.Shared.Warps; +using Content.Shared.Weapons.Melee.Events; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Physics.Components; @@ -41,6 +42,7 @@ public sealed class CosmicColossusSystem : EntitySystem base.Initialize(); SubscribeLocalEvent(OnSpawn); SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnMeleeHit); } public override void Update(float frameTime) @@ -115,4 +117,9 @@ public sealed class CosmicColossusSystem : EntitySystem RemComp(ent); RemComp(ent); } + + private void OnMeleeHit(Entity colossus, ref MeleeHitEvent args) + { + args.BonusDamage += colossus.Comp.BonusDamage; + } } diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs index e5fc4be7d1..f1ce3bdccc 100644 --- a/Content.Shared/Anomaly/Components/AnomalyComponent.cs +++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs @@ -308,7 +308,7 @@ public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly, float /// The anomaly being shut down. /// Whether or not the anomaly shut down passively or via a supercritical event. [ByRefEvent] -public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Supercritical); +public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Supercritical, bool Forced); // DeltaV - Add Forced /// /// Event broadcast when an anomaly's severity is changed. diff --git a/Content.Shared/Anomaly/SharedAnomalySystem.cs b/Content.Shared/Anomaly/SharedAnomalySystem.cs index 4799d82b7a..dc7ad04592 100644 --- a/Content.Shared/Anomaly/SharedAnomalySystem.cs +++ b/Content.Shared/Anomaly/SharedAnomalySystem.cs @@ -190,7 +190,8 @@ public abstract class SharedAnomalySystem : EntitySystem /// Whether or not the anomaly ended via supercritical event /// Create anomaly cores based on the result of completing an anomaly? /// Whether or not the anomaly decaying/going supercritical is logged - public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false, bool spawnCore = true, bool logged = false) + /// Whether or not the anomaly shutdown was caused by component shutdown // DeltaV - Add forced + public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false, bool spawnCore = true, bool logged = false, bool forced = false) // DeltaV - Add forced { if (logged) { @@ -205,7 +206,7 @@ public abstract class SharedAnomalySystem : EntitySystem if (!Resolve(uid, ref component)) return; - var ev = new AnomalyShutdownEvent(uid, supercritical); + var ev = new AnomalyShutdownEvent(uid, supercritical, forced); // DeltaV - Add forced RaiseLocalEvent(uid, ref ev, true); if (Terminating(uid) || _net.IsClient) diff --git a/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs b/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs index bb7f97bf62..6bdaec1499 100644 --- a/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs +++ b/Content.Shared/_DV/CosmicCult/Components/CosmicColossusComponent.cs @@ -1,3 +1,5 @@ +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -36,7 +38,7 @@ public sealed partial class CosmicColossusComponent : Component [DataField] public EntProtoId Attack1Vfx = "CosmicColossusAttack1Vfx"; - [DataField] public EntProtoId UpgradeVfx = "ColossusUpgradeVFX"; + [DataField] public EntProtoId BuffVfx = "ColossusBuffVfx"; [DataField] public EntProtoId TileDetonations = "MobTileDamageZone"; @@ -64,7 +66,14 @@ public sealed partial class CosmicColossusComponent : Component [DataField] public bool Timed; - [DataField] public bool CompletedFirstEffigy; + [DataField] public short CompletedEffigies; + + [DataField] public short MaxEffigies = 3; + + [DataField] public DamageSpecifier BonusDamage = new(); + + [DataField] public ProtoId BonusDamageType = "Blunt"; + } [Serializable, NetSerializable] diff --git a/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl b/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl index bc222da212..30d1ab6b7c 100644 --- a/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl +++ b/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl @@ -1 +1,2 @@ -colossus-upgrade-popup = You grow stronger. Another space calls for you. +colossus-buff-popup = You grow stronger. Another space calls for you. +colossus-buff-final-popup = You have grown strong enough. The curtains must fall. diff --git a/Resources/Locale/en-US/_DV/cosmiccult/ghostroles.ftl b/Resources/Locale/en-US/_DV/cosmiccult/ghostroles.ftl index 7273d5dc86..a4f2027fa9 100644 --- a/Resources/Locale/en-US/_DV/cosmiccult/ghostroles.ftl +++ b/Resources/Locale/en-US/_DV/cosmiccult/ghostroles.ftl @@ -7,7 +7,7 @@ ghost-role-information-theunknown-rules = ... # COLOSSUS ghost-role-information-colossus-name = Entropic Colossus -ghost-role-information-colossus-description = Call upon an Effigy of Entropy to perpetuate your existence and accelerate the end of all things! You have 15 minutes to do so or your energies will be extinguished. +ghost-role-information-colossus-description = Call upon three Effigies of Entropy to grow in power and accelerate the end of all things, starting with the station! You have 15 minutes to place your first effigy. If you don't place one or your effigy decays, your energies will be extinguished. ghost-role-information-colossus-rules = You are a [color={role-type-team-antagonist-color}][bold]{role-type-team-antagonist-name}[/bold][/color] with any cosmic cultists that may be present. terror-colossus = Attention crew, it appears that someone on your station has drawn the attention of an enormous malign anomaly. diff --git a/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml b/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml index 08a46ccc36..0b6c8347c9 100644 --- a/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml +++ b/Resources/Prototypes/_DV/CosmicCult/Effects/effects.yml @@ -172,13 +172,13 @@ - type: entity categories: [ HideSpawnMenu ] parent: BaseCosmicVFX - id: ColossusUpgradeVFX + id: ColossusBuffVfx components: - type: TimedDespawn lifetime: 0.8 - type: Sprite layers: - - sprite: _DV/CosmicCult/Effects/colossus_upgradevfx.rsi + - sprite: _DV/CosmicCult/Effects/colossus_buffvfx.rsi state: vfx shader: unshaded - type: PointLight diff --git a/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml b/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml index 423094c8bc..caf3b7e955 100644 --- a/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml +++ b/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml @@ -81,7 +81,7 @@ maxPulseLength: 80 minContituty: 0.4 maxContituty: 0.8 - growthThreshold: 0.35 + growthThreshold: 0.15 - type: EntitySpawnAnomaly entries: - settings: diff --git a/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/meta.json b/Resources/Textures/_DV/CosmicCult/Effects/colossus_buffvfx.rsi/meta.json similarity index 100% rename from Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/meta.json rename to Resources/Textures/_DV/CosmicCult/Effects/colossus_buffvfx.rsi/meta.json diff --git a/Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/vfx.png b/Resources/Textures/_DV/CosmicCult/Effects/colossus_buffvfx.rsi/vfx.png similarity index 100% rename from Resources/Textures/_DV/CosmicCult/Effects/colossus_upgradevfx.rsi/vfx.png rename to Resources/Textures/_DV/CosmicCult/Effects/colossus_buffvfx.rsi/vfx.png From d339f7e0dfeaea5490955b1871ad23b67b3ebffc Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Wed, 25 Mar 2026 21:24:16 +0100 Subject: [PATCH 3/9] fix: actually broadcast first effigy audio --- .../CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs index 7a917805f1..8916ea1da2 100644 --- a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs +++ b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs @@ -19,6 +19,7 @@ using Content.Shared.Weapons.Melee; using Robust.Server.Audio; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -82,10 +83,12 @@ public sealed class CosmicEffigySystem : EntitySystem colossusComp.BonusDamage += new DamageSpecifier(_proto.Index(colossusComp.BonusDamageType), ent.Comp.ColossusBonusDamage); - Spawn(colossusComp.BuffVfx, Transform(ent.Comp.Colossus.Value).Coordinates); + var transform = Transform(ent.Comp.Colossus.Value); + Spawn(colossusComp.BuffVfx, transform.Coordinates); + if (colossusComp.CompletedEffigies == 0) { - _audio.PlayGlobal(colossusComp.ReawakenSfx, ent); + _audio.PlayStatic(colossusComp.ReawakenSfx, Filter.BroadcastMap(transform.MapID), transform.Coordinates, true); } else { From c8b894dcc11c8e42d6e2c42db0a239afd8b46e66 Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Thu, 26 Mar 2026 09:36:41 +0100 Subject: [PATCH 4/9] style: add some newlines --- .../Abilities/Colossus/CosmicEffigySystem.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs index 8916ea1da2..3c7ff1ce3e 100644 --- a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs +++ b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs @@ -61,7 +61,9 @@ public sealed class CosmicEffigySystem : EntitySystem private void OnSupercritical(Entity ent, ref AnomalySupercriticalEvent args) { - if (!Exists(ent.Comp.Colossus) || !TryComp(ent.Comp.Colossus, out var colossusComp) || !_mind.TryGetMind(ent.Comp.Colossus.Value, out _, out var mind)) + if (!Exists(ent.Comp.Colossus) + || !TryComp(ent.Comp.Colossus, out var colossusComp) + || !_mind.TryGetMind(ent.Comp.Colossus.Value, out _, out var mind)) return; var colossus = ent.Comp.Colossus.Value; @@ -81,14 +83,18 @@ public sealed class CosmicEffigySystem : EntitySystem _damage.TryChangeDamage(ent.Comp.Colossus.Value, damageable.Damage / 2 * -1, true); } - colossusComp.BonusDamage += new DamageSpecifier(_proto.Index(colossusComp.BonusDamageType), ent.Comp.ColossusBonusDamage); + colossusComp.BonusDamage += + new DamageSpecifier(_proto.Index(colossusComp.BonusDamageType), ent.Comp.ColossusBonusDamage); var transform = Transform(ent.Comp.Colossus.Value); Spawn(colossusComp.BuffVfx, transform.Coordinates); if (colossusComp.CompletedEffigies == 0) { - _audio.PlayStatic(colossusComp.ReawakenSfx, Filter.BroadcastMap(transform.MapID), transform.Coordinates, true); + _audio.PlayStatic(colossusComp.ReawakenSfx, + Filter.BroadcastMap(transform.MapID), + transform.Coordinates, + true); } else { From eed75df225091bd08a228f499e0128f0fdb8d7bb Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Thu, 26 Mar 2026 13:23:26 +0100 Subject: [PATCH 5/9] feat: notify player about updated target location in chat --- .../Abilities/Colossus/CosmicEffigySystem.cs | 13 +++++++++++-- .../_DV/CosmicCult/CosmicCultObjectiveSystem.cs | 8 ++++---- Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs index 3c7ff1ce3e..69eb4c0f84 100644 --- a/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs +++ b/Content.Server/_DV/CosmicCult/Abilities/Colossus/CosmicEffigySystem.cs @@ -1,7 +1,7 @@ using System.Numerics; using Content.Server._DV.CosmicCult.Components; using Content.Server.Actions; -using Content.Server.Objectives; +using Content.Server.Chat.Managers; using Content.Server.Objectives.Components; using Content.Server.Objectives.Systems; using Content.Server.Popups; @@ -17,6 +17,7 @@ using Content.Shared.Popups; using Content.Shared.Warps; using Content.Shared.Weapons.Melee; using Robust.Server.Audio; +using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Player; @@ -40,6 +41,8 @@ public sealed class CosmicEffigySystem : EntitySystem [Dependency] private readonly CosmicCultObjectiveSystem _cultObjective = default!; [Dependency] private readonly IGameTiming _time = default!; [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IChatManager _chat = default!; + [Dependency] private readonly IPlayerManager _player = default!; public override void Initialize() { @@ -121,11 +124,17 @@ public sealed class CosmicEffigySystem : EntitySystem } var objective = mind.Objectives[objIndex]; - if (!_cultObjective.RandomizeEffigyTarget(objective, conditionComp, setDescription: true)) + if (_cultObjective.RandomizeEffigyTarget(objective, conditionComp, setDescription: true) is not {} nextTarget) { Log.Error("Failed to randomize effigy objective location!"); return; } + + if (mind.UserId is { } userId) + { + _chat.DispatchServerMessage(_player.GetSessionById(userId), Loc.GetString("colossus-next-target", ("location", nextTarget))); + } + _codeCondition.SetCompleted(objective, false); colossusComp.EffigyPlaceActionEntity = _actions.AddAction(colossus, colossusComp.EffigyPlaceAction); diff --git a/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs b/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs index 557fb85975..50d29dcf87 100644 --- a/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs +++ b/Content.Server/_DV/CosmicCult/CosmicCultObjectiveSystem.cs @@ -35,11 +35,11 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem if (args.Cancelled || !_roles.MindHasRole(args.MindId)) return; - if (!RandomizeEffigyTarget(uid, comp)) + if (RandomizeEffigyTarget(uid, comp) is null) args.Cancelled = true; } - public bool RandomizeEffigyTarget(EntityUid uid, CosmicEffigyConditionComponent comp, bool setDescription = false) + public string? RandomizeEffigyTarget(EntityUid uid, CosmicEffigyConditionComponent comp, bool setDescription = false) { var warps = new List(); var query = EntityQueryEnumerator(); @@ -57,7 +57,7 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem if (warps.Count <= 0) { - return false; + return null; } var newWarp = _random.Pick(warps); @@ -72,7 +72,7 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem ? Loc.GetString("objective-condition-effigy", ("location", warpComp.Location)) : Loc.GetString("objective-condition-effigy-no-target")); } - return true; + return warpComp.Location; } private void OnEffigyAfterAssign(EntityUid uid, CosmicEffigyConditionComponent comp, ref ObjectiveAfterAssignEvent args) diff --git a/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl b/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl index 30d1ab6b7c..55f4f5d642 100644 --- a/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl +++ b/Resources/Locale/en-US/_DV/cosmiccult/colossus.ftl @@ -1,2 +1,3 @@ colossus-buff-popup = You grow stronger. Another space calls for you. colossus-buff-final-popup = You have grown strong enough. The curtains must fall. +colossus-next-target = {$location} calls for you. Beckon your next effigy there. From 70dc532dd027612325784158a2a3179abed558cf Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Thu, 26 Mar 2026 14:24:27 +0100 Subject: [PATCH 6/9] tweak: effigy always grows --- Content.Server/Anomaly/AnomalySystem.cs | 8 ++++++-- .../Anomaly/Components/AnomalyComponent.cs | 5 +++++ Content.Shared/Anomaly/SharedAnomalySystem.cs | 12 ++++++++++-- .../Prototypes/_DV/CosmicCult/Tileset/effigy.yml | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs index ea579c3bc0..bb16aba676 100644 --- a/Content.Server/Anomaly/AnomalySystem.cs +++ b/Content.Server/Anomaly/AnomalySystem.cs @@ -145,7 +145,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem return 0; var multiplier = 1f; - if (component.Stability > component.GrowthThreshold) + if (component.AlwaysGrow || component.Stability > component.GrowthThreshold) // DeltaV - Add AlwaysGrow multiplier = component.GrowingPointMultiplier; //more points for unstable //penalty of up to 50% based on health @@ -255,7 +255,11 @@ public sealed partial class AnomalySystem : SharedAnomalySystem else { string stateLoc; - if (anomalyComp.Stability < anomalyComp.DecayThreshold) + // DeltaV - Colossus Additions START + if (anomalyComp.AlwaysGrow) + stateLoc = Loc.GetString("anomaly-scanner-stability-high"); + // DeltaV - Colossus Additions END + else if (anomalyComp.Stability < anomalyComp.DecayThreshold) // DeltaV - Add else stateLoc = Loc.GetString("anomaly-scanner-stability-low"); else if (anomalyComp.Stability > anomalyComp.GrowthThreshold) stateLoc = Loc.GetString("anomaly-scanner-stability-high"); diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs index f1ce3bdccc..8d5bb34e6b 100644 --- a/Content.Shared/Anomaly/Components/AnomalyComponent.cs +++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs @@ -285,6 +285,11 @@ public sealed partial class AnomalyComponent : Component [DataField] public bool DeleteEntity = true; + + // DeltaV - Colossus additions START + [DataField] + public bool AlwaysGrow; + // DeltaV - Colossus additions END } /// diff --git a/Content.Shared/Anomaly/SharedAnomalySystem.cs b/Content.Shared/Anomaly/SharedAnomalySystem.cs index dc7ad04592..ebd23096df 100644 --- a/Content.Shared/Anomaly/SharedAnomalySystem.cs +++ b/Content.Shared/Anomaly/SharedAnomalySystem.cs @@ -82,7 +82,7 @@ public abstract class SharedAnomalySystem : EntitySystem Log.Info($"Performing anomaly pulse. Entity: {ToPrettyString(uid)}"); // if we are above the growth threshold, then grow before the pulse - if (component.Stability > component.GrowthThreshold) + if (component.AlwaysGrow || component.Stability > component.GrowthThreshold) // DeltaV - Add AlwaysGrow { ChangeAnomalySeverity(uid, GetSeverityIncreaseFromGrowth(component), component); } @@ -344,7 +344,7 @@ public abstract class SharedAnomalySystem : EntitySystem // if the stability is under the death threshold, // update it every second to start killing it slowly. - if (anomaly.Stability < anomaly.DecayThreshold) + if (!anomaly.AlwaysGrow && anomaly.Stability < anomaly.DecayThreshold) // DeltaV - Add AlwaysGrow { ChangeAnomalyHealth(ent, anomaly.HealthChangePerSecond * frameTime, anomaly); } @@ -478,6 +478,14 @@ public abstract class SharedAnomalySystem : EntitySystem if (!Resolve(ent, ref ent.Comp, logMissing: false)) return false; + // DeltaV - Colossus Additions START + if (ent.Comp.AlwaysGrow) + { + visual = AnomalyStabilityVisuals.Growing; + return true; + } + // DeltaV - Colossus Additions END + visual = AnomalyStabilityVisuals.Stable; if (ent.Comp.Stability <= ent.Comp.DecayThreshold) { diff --git a/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml b/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml index caf3b7e955..8a3384cf4b 100644 --- a/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml +++ b/Resources/Prototypes/_DV/CosmicCult/Tileset/effigy.yml @@ -81,7 +81,7 @@ maxPulseLength: 80 minContituty: 0.4 maxContituty: 0.8 - growthThreshold: 0.15 + alwaysGrow: true - type: EntitySpawnAnomaly entries: - settings: From 41a7cb9011cf04be02e6d940fd52def3859375e6 Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Thu, 26 Mar 2026 15:01:19 +0100 Subject: [PATCH 7/9] feat: make alwaysGrow show on anom scanner --- Content.Server/Anomaly/AnomalySystem.cs | 11 ++++++++++- Resources/Locale/en-US/anomaly/anomaly.ftl | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs index bb16aba676..41d54bf1fa 100644 --- a/Content.Server/Anomaly/AnomalySystem.cs +++ b/Content.Server/Anomaly/AnomalySystem.cs @@ -351,6 +351,15 @@ public sealed partial class AnomalySystem : SharedAnomalySystem msg.AddMarkupOrThrow(Loc.GetString("anomaly-behavior-unknown")); else { + // DeltaV - Colossus Additions START + if (anomalyComp.AlwaysGrow) + { + msg.AddMarkupOrThrow("- " + Loc.GetString("anomaly-behavior-always-grow")); + if (anomalyComp.CurrentBehavior != null) + msg.PushNewline(); + } + // DeltaV - Colossus Additions END + if (anomalyComp.CurrentBehavior != null) { var behavior = _prototype.Index(anomalyComp.CurrentBehavior.Value); @@ -360,7 +369,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem var mod = Math.Floor((behavior.EarnPointModifier) * 100); msg.AddMarkupOrThrow("- " + Loc.GetString("anomaly-behavior-point", ("mod", mod))); } - else + else if(!anomalyComp.AlwaysGrow) // DeltaV - Add condition, previously regular else { msg.AddMarkupOrThrow(Loc.GetString("anomaly-behavior-balanced")); } diff --git a/Resources/Locale/en-US/anomaly/anomaly.ftl b/Resources/Locale/en-US/anomaly/anomaly.ftl index cb6841ca4b..97deb936b6 100644 --- a/Resources/Locale/en-US/anomaly/anomaly.ftl +++ b/Resources/Locale/en-US/anomaly/anomaly.ftl @@ -98,3 +98,7 @@ anomaly-behavior-fast = [color=crimson]The pulsation frequency is strongly incre anomaly-behavior-strenght = [color=crimson]The pulsation power is significantly increased.[/color] anomaly-behavior-moving = [color=crimson]Coordinate instability was detected.[/color] anomaly-secret-admin = [color=red](ERROR)[/color] + +# DeltaV - Additions START +anomaly-behavior-always-grow = [color=red]Anomaly never stops growing.[/color] +# DeltaV - Additions END From b8dbf394c259493f070b479473635d4ca7bf6c4b Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Thu, 26 Mar 2026 19:50:21 +0100 Subject: [PATCH 8/9] tweak: raise minimumPlayers to 35 --- Resources/Prototypes/_DV/CosmicCult/events.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/_DV/CosmicCult/events.yml b/Resources/Prototypes/_DV/CosmicCult/events.yml index 1e06f3f469..8e3476637b 100644 --- a/Resources/Prototypes/_DV/CosmicCult/events.yml +++ b/Resources/Prototypes/_DV/CosmicCult/events.yml @@ -6,7 +6,7 @@ weight: 4.5 earliestStart: 45 reoccurrenceDelay: 20 - minimumPlayers: 25 + minimumPlayers: 35 duration: null - type: PrecognitionResult message: psionic-power-precognition-colossus-spawn-result-message From 840418c50d3de7c93ae03bb485816b2e08c3932a Mon Sep 17 00:00:00 2001 From: DisposableCrewmember42 Date: Sat, 11 Apr 2026 21:46:28 +0200 Subject: [PATCH 9/9] refactor: move FTL additions to _DV --- Resources/Locale/en-US/_DV/anomaly/anomaly.ftl | 1 + Resources/Locale/en-US/anomaly/anomaly.ftl | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) create mode 100644 Resources/Locale/en-US/_DV/anomaly/anomaly.ftl diff --git a/Resources/Locale/en-US/_DV/anomaly/anomaly.ftl b/Resources/Locale/en-US/_DV/anomaly/anomaly.ftl new file mode 100644 index 0000000000..8691f64c4e --- /dev/null +++ b/Resources/Locale/en-US/_DV/anomaly/anomaly.ftl @@ -0,0 +1 @@ +anomaly-behavior-always-grow = [color=red]Anomaly never stops growing.[/color] diff --git a/Resources/Locale/en-US/anomaly/anomaly.ftl b/Resources/Locale/en-US/anomaly/anomaly.ftl index 97deb936b6..cb6841ca4b 100644 --- a/Resources/Locale/en-US/anomaly/anomaly.ftl +++ b/Resources/Locale/en-US/anomaly/anomaly.ftl @@ -98,7 +98,3 @@ anomaly-behavior-fast = [color=crimson]The pulsation frequency is strongly incre anomaly-behavior-strenght = [color=crimson]The pulsation power is significantly increased.[/color] anomaly-behavior-moving = [color=crimson]Coordinate instability was detected.[/color] anomaly-secret-admin = [color=red](ERROR)[/color] - -# DeltaV - Additions START -anomaly-behavior-always-grow = [color=red]Anomaly never stops growing.[/color] -# DeltaV - Additions END