diff --git a/Content.Server/_Starlight/Changeling/ChangelingSystem.Abilities.cs b/Content.Server/_Starlight/Changeling/ChangelingSystem.Abilities.cs index ceff81484470..f9d476f44319 100644 --- a/Content.Server/_Starlight/Changeling/ChangelingSystem.Abilities.cs +++ b/Content.Server/_Starlight/Changeling/ChangelingSystem.Abilities.cs @@ -33,6 +33,7 @@ using Content.Shared._Starlight.Changeling; using Content.Server._Starlight.Objectives.Components; using Content.Shared.Flash; +using Content.Shared.Atmos.Rotting; using Content.Shared.Store; // Starlight edit end @@ -45,6 +46,7 @@ public sealed partial class ChangelingSystem : EntitySystem [Dependency] private ChangelingIdentitySystem _changelingIdentitySystem = default!; [Dependency] private LanguageSystem _language = default!; [Dependency] private SharedFlashSystem _flashSystem = default!; + [Dependency] private SharedRottingSystem _rotting = default!; private static readonly ProtoId FerrochromicAcidPrototype = "FerrochromicAcid"; private static readonly ProtoId PolytrinicAcidPrototype = "PolytrinicAcid"; @@ -134,6 +136,7 @@ private void OnAbsorb(EntityUid uid, ChangelingComponent comp, ref AbsorbDNAEven }; _doAfter.TryStartDoAfter(dargs); } + public ProtoId AbsorbedDamageGroup = "Genetic"; private void OnDevouredPerson(EntityUid uid, ChangelingComponent comp, ref OnLingDevour args) { @@ -161,6 +164,10 @@ private void OnDevouredPerson(EntityUid uid, ChangelingComponent comp, ref OnLin // Starlight edit end EnsureComp(target); + if (TryComp(target, out var perishable)) + { + _rotting.SetRotAfter(target, TimeSpan.FromMinutes(20), perishable); + } var popup = Loc.GetString("changeling-absorb-end-self-ling"); var bonusChemicals = 0f; @@ -306,16 +313,16 @@ private void OnShriekResonant(EntityUid uid, ChangelingComponent comp, ref Shrie DoScreech(uid, comp); var power = comp.ShriekPower; - _flash.FlashArea(uid, uid, power, TimeSpan.FromMilliseconds(power * 2f * 1000f)); + List ignoreList = new() { uid }; + _flash.FlashArea(uid, uid, power, TimeSpan.FromMilliseconds(power * 2f * 1000f), 0.8f, false, 1f, null, ignoreList); var lookup = _lookup.GetEntitiesInRange(uid, power); var lights = GetEntityQuery(); - foreach (var ent in lookup) + // breaks lights if (lights.HasComponent(ent)) _light.TryDestroyBulb(ent); } - private void OnToggleStrainedMuscles(EntityUid uid, ChangelingComponent comp, ref ToggleStrainedMusclesEvent args) => ToggleStrainedMuscles(uid, comp); private void ToggleStrainedMuscles(EntityUid uid, ChangelingComponent comp) diff --git a/Content.Shared/Flash/SharedFlashSystem.cs b/Content.Shared/Flash/SharedFlashSystem.cs index 5e4da0172706..c6ba4ed254c4 100644 --- a/Content.Shared/Flash/SharedFlashSystem.cs +++ b/Content.Shared/Flash/SharedFlashSystem.cs @@ -222,7 +222,17 @@ public void Flash( /// Whether or not to show a popup to the target player. /// Chance to be flashed. Rolled separately for each target in range. /// Additional sound to play at the source. - public void FlashArea(EntityUid source, EntityUid? user, float range, TimeSpan flashDuration, float slowTo = 0.8f, bool displayPopup = false, float probability = 1f, SoundSpecifier? sound = null) + /// Entities to ignore when flashing. (STARLIGHT EDIT) + public void FlashArea( + EntityUid source, + EntityUid? user, + float range, + TimeSpan flashDuration, + float slowTo = 0.8f, + bool displayPopup = false, + float probability = 1f, + SoundSpecifier? sound = null, + List? ignoreEntities = null) { var transform = Transform(source); var mapPosition = _transform.GetMapCoordinates(transform); @@ -231,6 +241,13 @@ public void FlashArea(EntityUid source, EntityUid? user, float range, TimeSpan f _entityLookup.GetEntitiesInRange(transform.Coordinates, range, _entSet); foreach (var entity in _entSet) { + // starlight edit - functionality to ignore certain entities when flashing + if (ignoreEntities != null) + { + if (ignoreEntities.Contains(entity)) + continue; + } + // TODO: Use RandomPredicted https://github.com/space-wizards/RobustToolbox/pull/5849 var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(entity).Id); var rand = new System.Random(seed); diff --git a/Content.Shared/_Starlight/Atmos/Rotting/RotTimerSystem.cs b/Content.Shared/_Starlight/Atmos/Rotting/RotTimerSystem.cs new file mode 100644 index 000000000000..59fbcb847dc2 --- /dev/null +++ b/Content.Shared/_Starlight/Atmos/Rotting/RotTimerSystem.cs @@ -0,0 +1,15 @@ +using Content.Shared.Atmos.Rotting; + +namespace Content.Shared.Atmos.Rotting; + +public abstract partial class SharedRottingSystem +{ + public bool SetRotAfter(EntityUid uid, TimeSpan newTime, PerishableComponent? perishable = null) + { + if (!Resolve(uid, ref perishable)) + return false; + + perishable.RotAfter = newTime; + return true; + } +} \ No newline at end of file diff --git a/Content.Shared/_Starlight/Changeling/AbsorbedSystem.cs b/Content.Shared/_Starlight/Changeling/AbsorbedSystem.cs index 2fa3378623ee..794803a5edec 100644 --- a/Content.Shared/_Starlight/Changeling/AbsorbedSystem.cs +++ b/Content.Shared/_Starlight/Changeling/AbsorbedSystem.cs @@ -1,10 +1,13 @@ using Content.Shared.Examine; using Content.Shared.Mobs; +using Content.Shared.Atmos.Rotting; // starlight edit namespace Content.Shared._Starlight.Changeling; public sealed partial class AbsorbedSystem : EntitySystem { + [Dependency] private SharedRottingSystem _rotting = default!; + public override void Initialize() { base.Initialize(); @@ -21,7 +24,13 @@ private void OnExamine(Entity ent, ref ExaminedEvent args) private void OnMobStateChange(Entity ent, ref MobStateChangedEvent args) { // in case one somehow manages to dehusk someone - if (args.NewMobState != MobState.Dead) + if (args.NewMobState != MobState.Dead) { RemComp(ent); + // The changeling devour changes the rot timer, so we need to reset it when reviving someone + if (TryComp(ent, out var perishable)) + { + _rotting.SetRotAfter(ent, TimeSpan.FromMinutes(10), perishable); + } + } } } diff --git a/Content.Shared/_Starlight/Changeling/ChangelingComponent.cs b/Content.Shared/_Starlight/Changeling/ChangelingComponent.cs index 7f783d29a263..76cea913b880 100644 --- a/Content.Shared/_Starlight/Changeling/ChangelingComponent.cs +++ b/Content.Shared/_Starlight/Changeling/ChangelingComponent.cs @@ -49,7 +49,7 @@ public sealed partial class ChangelingComponent : Component public bool StealthEnabled = false; [DataField] - public float StealthDrain = 1.5f; + public float StealthDrain = 1.25f; // 1.5 -> 1.25; 3.3 minutes -> 6.6 minutes to fully drain 100 chemicals [DataField] public float StasisDrain = 0.2f; diff --git a/Resources/Locale/en-US/store/changeling-catalog.ftl b/Resources/Locale/en-US/store/changeling-catalog.ftl index 6368516d9aa9..d4ec937a6a1f 100644 --- a/Resources/Locale/en-US/store/changeling-catalog.ftl +++ b/Resources/Locale/en-US/store/changeling-catalog.ftl @@ -117,8 +117,10 @@ evolutionmenu-utility-stims-desc = Costs 20 chemicals. evolutionmenu-utility-fleshmend-name = Fleshmend +# Starlight edit: Added warning about requiring two absorbtions evolutionmenu-utility-fleshmend-desc = - Rapidly heal yourself of all bruises and burns. + Rapidly heal yourself of all bruises and burns. + WARNING: Requires you to absorb at least 2 organics to use the ability. Costs 35 chemicals. # Starlight - monkey form is permanent (until transform is fixed, at least) diff --git a/Resources/Prototypes/_Starlight/Actions/changeling.yml b/Resources/Prototypes/_Starlight/Actions/changeling.yml index e1764cd42ced..1ca4412475b7 100644 --- a/Resources/Prototypes/_Starlight/Actions/changeling.yml +++ b/Resources/Prototypes/_Starlight/Actions/changeling.yml @@ -609,6 +609,7 @@ event: !type:ActionFleshmendEvent {} - type: ChangelingAction chemicalCost: 35 + requireAbsorbed: 2 # easily one of the strongest combat abilities. Shouldn't be available round start useInLesserForm: true - type: entity