From 3c3ee60dd2caa4d6a6676d87dd26c0f972c321de Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Wed, 28 Sep 2022 22:30:48 -0400 Subject: [PATCH] Revenant 2: Electric Boogaloo (#11510) * revenant 2: electric boogaloo * revevent * oversights * Update RevenantSystem.Abilities.cs * names * no shoote stouhg walls --- Content.Client/Revenant/CorporealSystem.cs | 8 +++ Content.Client/Revenant/RevenantComponent.cs | 16 ----- .../RevenantOverloadedLightsSystem.cs | 58 ++++++++++++++++++ Content.Client/Revenant/RevenantSystem.cs | 1 + .../{ => Components}/EssenceComponent.cs | 8 +-- .../Revenant/EntitySystems/CorporealSystem.cs | 60 +++--------------- .../Revenant/EntitySystems/EssenceSystem.cs | 2 + .../RevenantOverloadedLightsSystem.cs | 29 +++++++++ .../EntitySystems/RevenantSystem.Abilities.cs | 44 ++++++++----- .../Revenant/EntitySystems/RevenantSystem.cs | 16 ++--- .../StationEvents/Events/RevenantSpawn.cs | 18 ++++++ .../Components}/CorporealComponent.cs | 2 +- .../Revenant/Components}/RevenantComponent.cs | 60 +++++++----------- .../RevenantOverloadedLightsComponent.cs | 31 ++++++++++ .../EntitySystems/SharedCorporealSystem.cs | 61 +++++++++++++++++++ .../SharedRevenantOverloadedLightsSystem.cs | 28 +++++++++ Content.Shared/Revenant/SharedRevenant.cs | 23 +++++++ .../Revenant/SharedRevenantComponent.cs | 9 --- .../Prototypes/Catalog/revenant_catalog.yml | 2 +- .../Prototypes/Datasets/Names/revenant.yml | 55 +++++++++++++++++ .../Prototypes/Entities/Effects/lightning.yml | 23 +++++++ .../Entities/Mobs/NPCs/revenant.yml | 44 +++---------- Resources/Prototypes/GameRules/events.yml | 11 ++++ Resources/Prototypes/Polymorphs/polymorph.yml | 9 --- Resources/Prototypes/explosion.yml | 12 ---- 25 files changed, 427 insertions(+), 203 deletions(-) create mode 100644 Content.Client/Revenant/CorporealSystem.cs delete mode 100644 Content.Client/Revenant/RevenantComponent.cs create mode 100644 Content.Client/Revenant/RevenantOverloadedLightsSystem.cs rename Content.Server/Revenant/{ => Components}/EssenceComponent.cs (76%) create mode 100644 Content.Server/Revenant/EntitySystems/RevenantOverloadedLightsSystem.cs create mode 100644 Content.Server/StationEvents/Events/RevenantSpawn.cs rename {Content.Server/Revenant => Content.Shared/Revenant/Components}/CorporealComponent.cs (89%) rename {Content.Server/Revenant => Content.Shared/Revenant/Components}/RevenantComponent.cs (86%) create mode 100644 Content.Shared/Revenant/Components/RevenantOverloadedLightsComponent.cs create mode 100644 Content.Shared/Revenant/EntitySystems/SharedCorporealSystem.cs create mode 100644 Content.Shared/Revenant/EntitySystems/SharedRevenantOverloadedLightsSystem.cs delete mode 100644 Content.Shared/Revenant/SharedRevenantComponent.cs create mode 100644 Resources/Prototypes/Datasets/Names/revenant.yml diff --git a/Content.Client/Revenant/CorporealSystem.cs b/Content.Client/Revenant/CorporealSystem.cs new file mode 100644 index 0000000000..98f7a6d375 --- /dev/null +++ b/Content.Client/Revenant/CorporealSystem.cs @@ -0,0 +1,8 @@ +using Content.Shared.Revenant.EntitySystems; + +namespace Content.Client.Revenant; + +public sealed class CorporealSystem : SharedCorporealSystem +{ + +} diff --git a/Content.Client/Revenant/RevenantComponent.cs b/Content.Client/Revenant/RevenantComponent.cs deleted file mode 100644 index a99b744554..0000000000 --- a/Content.Client/Revenant/RevenantComponent.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.Revenant; - -namespace Content.Client.Revenant; - -[RegisterComponent] -public sealed class RevenantComponent : SharedRevenantComponent -{ - [DataField("state")] - public string State = "idle"; - [DataField("corporealState")] - public string CorporealState = "active"; - [DataField("stunnedState")] - public string StunnedState = "stunned"; - [DataField("harvestingState")] - public string HarvestingState = "harvesting"; -} diff --git a/Content.Client/Revenant/RevenantOverloadedLightsSystem.cs b/Content.Client/Revenant/RevenantOverloadedLightsSystem.cs new file mode 100644 index 0000000000..d42fffd6b6 --- /dev/null +++ b/Content.Client/Revenant/RevenantOverloadedLightsSystem.cs @@ -0,0 +1,58 @@ +using Content.Shared.Revenant.Components; +using Content.Shared.Revenant.EntitySystems; +using Robust.Client.GameObjects; + +namespace Content.Client.Revenant; + +public sealed class RevenantOverloadedLightsSystem : SharedRevenantOverloadedLightsSystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnShutdown); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var (comp, light) in EntityQuery()) + { + //this looks cool :HECK: + light.Energy = 2f * Math.Abs((float) Math.Sin(0.25 * Math.PI * comp.Accumulator)); + } + } + + private void OnStartup(EntityUid uid, RevenantOverloadedLightsComponent component, ComponentStartup args) + { + var light = EnsureComp(uid); + component.OriginalEnergy = light.Energy; + component.OriginalEnabled = light.Enabled; + + light.Enabled = component.OriginalEnabled; + Dirty(light); + } + + private void OnShutdown(EntityUid uid, RevenantOverloadedLightsComponent component, ComponentShutdown args) + { + if (!TryComp(component.Owner, out var light)) + return; + + if (component.OriginalEnergy == null) + { + RemComp(component.Owner); + return; + } + + light.Energy = component.OriginalEnergy.Value; + light.Enabled = component.OriginalEnabled; + Dirty(light); + } + + protected override void OnZap(RevenantOverloadedLightsComponent component) + { + + } +} diff --git a/Content.Client/Revenant/RevenantSystem.cs b/Content.Client/Revenant/RevenantSystem.cs index f942911ee9..a074caa0d2 100644 --- a/Content.Client/Revenant/RevenantSystem.cs +++ b/Content.Client/Revenant/RevenantSystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Revenant; +using Content.Shared.Revenant.Components; using Robust.Client.GameObjects; namespace Content.Client.Revenant; diff --git a/Content.Server/Revenant/EssenceComponent.cs b/Content.Server/Revenant/Components/EssenceComponent.cs similarity index 76% rename from Content.Server/Revenant/EssenceComponent.cs rename to Content.Server/Revenant/Components/EssenceComponent.cs index bb05893491..bafd926aca 100644 --- a/Content.Server/Revenant/EssenceComponent.cs +++ b/Content.Server/Revenant/Components/EssenceComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server.Revenant; +namespace Content.Server.Revenant.Components; [RegisterComponent] public sealed class EssenceComponent : Component @@ -6,20 +6,20 @@ public sealed class EssenceComponent : Component /// /// Whether or not the entity has been harvested yet. /// - [ViewVariables] + [ViewVariables(VVAccess.ReadWrite)] public bool Harvested = false; /// /// Whether or not a revenant has searched this entity /// for its soul yet. /// - [ViewVariables] + [ViewVariables(VVAccess.ReadWrite)] public bool SearchComplete = false; /// /// The total amount of Essence that the entity has. /// Changes based on mob state. /// - [ViewVariables] + [ViewVariables(VVAccess.ReadWrite)] public float EssenceAmount = 0f; } diff --git a/Content.Server/Revenant/EntitySystems/CorporealSystem.cs b/Content.Server/Revenant/EntitySystems/CorporealSystem.cs index 28ac7fdd0c..13ec6eb036 100644 --- a/Content.Server/Revenant/EntitySystems/CorporealSystem.cs +++ b/Content.Server/Revenant/EntitySystems/CorporealSystem.cs @@ -1,51 +1,17 @@ -using Content.Server.Visible; -using Content.Shared.Physics; -using Content.Shared.Revenant; -using Content.Shared.Movement; +using Content.Server.Visible; +using Content.Shared.Revenant.Components; +using Content.Shared.Revenant.EntitySystems; using Robust.Server.GameObjects; -using Robust.Server.GameStates; -using Robust.Shared.Physics; -using System.Linq; -using Content.Shared.Movement.Systems; namespace Content.Server.Revenant.EntitySystems; -/// -/// Makes the revenant solid when the component is applied. -/// Additionally applies a few visual effects. -/// Used for status effect. -/// -public sealed class CorporealSystem : EntitySystem +public sealed class CorporealSystem : SharedCorporealSystem { [Dependency] private readonly VisibilitySystem _visibilitySystem = default!; - [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; - public override void Initialize() + public override void OnStartup(EntityUid uid, CorporealComponent component, ComponentStartup args) { - base.Initialize(); - - SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnRefresh); - } - - private void OnRefresh(EntityUid uid, CorporealComponent component, RefreshMovementSpeedModifiersEvent args) - { - args.ModifySpeed(component.MovementSpeedDebuff, component.MovementSpeedDebuff); - } - - private void OnStartup(EntityUid uid, CorporealComponent component, ComponentStartup args) - { - if (TryComp(uid, out var app)) - app.SetData(RevenantVisuals.Corporeal, true); - - if (TryComp(uid, out var fixtures) && fixtures.FixtureCount >= 1) - { - var fixture = fixtures.Fixtures.Values.First(); - - fixture.CollisionMask = (int) (CollisionGroup.SmallMobMask | CollisionGroup.GhostImpassable); - fixture.CollisionLayer = (int) CollisionGroup.SmallMobLayer; - } + base.OnStartup(uid, component, args); if (TryComp(uid, out var visibility)) { @@ -53,21 +19,11 @@ public sealed class CorporealSystem : EntitySystem _visibilitySystem.AddLayer(visibility, (int) VisibilityFlags.Normal, false); _visibilitySystem.RefreshVisibility(visibility); } - _movement.RefreshMovementSpeedModifiers(uid); } - private void OnShutdown(EntityUid uid, CorporealComponent component, ComponentShutdown args) + public override void OnShutdown(EntityUid uid, CorporealComponent component, ComponentShutdown args) { - if (TryComp(uid, out var app)) - app.SetData(RevenantVisuals.Corporeal, false); - - if (TryComp(uid, out var fixtures) && fixtures.FixtureCount >= 1) - { - var fixture = fixtures.Fixtures.Values.First(); - - fixture.CollisionMask = (int) CollisionGroup.GhostImpassable; - fixture.CollisionLayer = 0; - } + base.OnShutdown(uid, component, args); if (TryComp(uid, out var visibility)) { diff --git a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs index 96a67472c1..facbd1ba5a 100644 --- a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs +++ b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs @@ -1,7 +1,9 @@ using Content.Server.Mind.Components; +using Content.Server.Revenant.Components; using Content.Shared.Examine; using Content.Shared.MobState; using Content.Shared.MobState.Components; +using Content.Shared.Revenant.Components; using Robust.Shared.Random; namespace Content.Server.Revenant.EntitySystems; diff --git a/Content.Server/Revenant/EntitySystems/RevenantOverloadedLightsSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantOverloadedLightsSystem.cs new file mode 100644 index 0000000000..dadf1cfa6b --- /dev/null +++ b/Content.Server/Revenant/EntitySystems/RevenantOverloadedLightsSystem.cs @@ -0,0 +1,29 @@ +using Content.Server.Beam; +using Content.Shared.Revenant.Components; +using Content.Shared.Revenant.EntitySystems; + +namespace Content.Server.Revenant.EntitySystems; + +/// +/// This handles... +/// +public sealed class RevenantOverloadedLightsSystem : SharedRevenantOverloadedLightsSystem +{ + [Dependency] private readonly BeamSystem _beam = default!; + + protected override void OnZap(RevenantOverloadedLightsComponent component) + { + if (component.Target == null) + return; + + var lxform = Transform(component.Owner); + var txform = Transform(component.Target.Value); + + if (!lxform.Coordinates.TryDistance(EntityManager, txform.Coordinates, out var distance)) + return; + if (distance > component.ZapRange) + return; + + _beam.TryCreateBeam(component.Owner, component.Target.Value, component.ZapBeamEntityId); + } +} diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs index 9d3b2fe11a..0f2bc2fa25 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs @@ -20,24 +20,25 @@ using Content.Server.Disease.Components; using Content.Shared.Item; using Content.Shared.Bed.Sleep; using Content.Shared.MobState; -using Content.Server.Explosion.EntitySystems; using System.Linq; +using Content.Server.Beam; using Content.Server.Emag; using Content.Server.Humanoid; +using Content.Server.Revenant.Components; using Content.Server.Store.Components; using Content.Shared.FixedPoint; +using Content.Shared.Revenant.Components; using Robust.Shared.Physics.Components; using Robust.Shared.Utility; namespace Content.Server.Revenant.EntitySystems; -public sealed partial class RevenantSystem : EntitySystem +public sealed partial class RevenantSystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly EntityStorageSystem _entityStorage = default!; [Dependency] private readonly DiseaseSystem _disease = default!; - [Dependency] private readonly ExplosionSystem _explosion = default!; [Dependency] private readonly EmagSystem _emag = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly GhostSystem _ghost = default!; @@ -181,8 +182,10 @@ public sealed partial class RevenantSystem : EntitySystem essence.Harvested = true; ChangeEssenceAmount(uid, essence.EssenceAmount, component); if (TryComp(uid, out var store)) + { _store.TryAddCurrency(new Dictionary() - { {component.StolenEssenceCurrencyPrototype, essence.EssenceAmount} }, store); + { {component.StolenEssenceCurrencyPrototype, essence.EssenceAmount} }, store); + } if (!TryComp(args.Target, out var mobstate)) return; @@ -198,7 +201,7 @@ public sealed partial class RevenantSystem : EntitySystem if (damage == null) return; DamageSpecifier dspec = new(); - dspec.DamageDict.Add("Cellular", damage.Value); + dspec.DamageDict.Add("Poison", damage.Value); _damage.TryChangeDamage(args.Target, dspec, true); } @@ -280,22 +283,28 @@ public sealed partial class RevenantSystem : EntitySystem args.Handled = true; + var xform = Transform(uid); var poweredLights = GetEntityQuery(); + var mobState = GetEntityQuery(); var lookup = _lookup.GetEntitiesInRange(uid, component.OverloadRadius); - + //TODO: feels like this might be a sin and a half foreach (var ent in lookup) { - if (!poweredLights.HasComponent(ent)) + if (!mobState.HasComponent(ent) || !_mobState.IsAlive(ent)) continue; - var ev = new GhostBooEvent(); //light go flicker - RaiseLocalEvent(ent, ev); + var nearbyLights = _lookup.GetEntitiesInRange(ent, component.OverloadZapRadius) + .Where(e => poweredLights.HasComponent(e) && !HasComp(e) && + _interact.InRangeUnobstructed(e, uid, -1)).ToArray(); - if (_random.Prob(component.OverloadBreakChance)) - { - //values - _explosion.QueueExplosion(ent, "RevenantElectric", 15, 3, 5, canCreateVacuum: false); - } + if (!nearbyLights.Any()) + continue; + + //get the closest light + var allLight = nearbyLights.OrderBy(e => + Transform(e).Coordinates.TryDistance(EntityManager, xform.Coordinates, out var dist) ? component.OverloadZapRadius : dist); + var comp = EnsureComp(allLight.First()); + comp.Target = ent; //who they gon fire at? } } @@ -310,10 +319,11 @@ public sealed partial class RevenantSystem : EntitySystem args.Handled = true; var emo = GetEntityQuery(); - foreach (var ent in _lookup.GetEntitiesInRange(uid, component.BlightRadius)) + { if (emo.TryGetComponent(ent, out var comp)) - _disease.TryInfect(comp, component.BlightDiseasePrototypeId); + _disease.TryAddDisease(ent, component.BlightDiseasePrototypeId, comp); + } } private void OnMalfunctionAction(EntityUid uid, RevenantComponent component, RevenantMalfunctionActionEvent args) @@ -327,6 +337,8 @@ public sealed partial class RevenantSystem : EntitySystem args.Handled = true; foreach (var ent in _lookup.GetEntitiesInRange(uid, component.MalfunctionRadius)) + { _emag.DoEmag(ent, ent); //it emags itself. spooky. + } } } diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs index ef7d1269b4..b3b99a46b3 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs @@ -15,14 +15,13 @@ using Content.Shared.Examine; using Robust.Shared.Prototypes; using Content.Shared.Actions.ActionTypes; using Content.Shared.Tag; -using Content.Server.Polymorph.Systems; using Content.Server.Store.Components; using Content.Server.Store.Systems; using Content.Shared.FixedPoint; using Robust.Shared.Player; -using Content.Shared.Movement.Systems; using Content.Shared.Maps; using Content.Shared.Physics; +using Content.Shared.Revenant.Components; namespace Content.Server.Revenant.EntitySystems; @@ -36,14 +35,12 @@ public sealed partial class RevenantSystem : EntitySystem [Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly PolymorphableSystem _polymorphable = default!; [Dependency] private readonly PhysicsSystem _physics = default!; [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; [Dependency] private readonly SharedInteractionSystem _interact = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedStunSystem _stun = default!; [Dependency] private readonly TagSystem _tag = default!; - [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; [Dependency] private readonly StoreSystem _store = default!; public override void Initialize() @@ -89,8 +86,6 @@ public sealed partial class RevenantSystem : EntitySystem { if (args.Key == "Stun") _appearance.SetData(uid, RevenantVisuals.Stunned, false); - else if (args.Key == "Corporeal") - _movement.RefreshMovementSpeedModifiers(uid); } private void OnExamine(EntityUid uid, RevenantComponent component, ExaminedEvent args) @@ -124,16 +119,15 @@ public sealed partial class RevenantSystem : EntitySystem if (regenCap) FixedPoint2.Min(component.Essence, component.EssenceRegenCap); + if (TryComp(uid, out var store)) + _store.UpdateUserInterface(uid, store); + _alerts.ShowAlert(uid, AlertType.Essence, (short) Math.Clamp(Math.Round(component.Essence.Float() / 10f), 0, 16)); if (component.Essence <= 0) { - component.Essence = component.EssenceRegenCap; - _polymorphable.PolymorphEntity(uid, "Ectoplasm"); + QueueDel(uid); } - - if (TryComp(uid, out var store)) - _store.UpdateUserInterface(uid, store); return true; } diff --git a/Content.Server/StationEvents/Events/RevenantSpawn.cs b/Content.Server/StationEvents/Events/RevenantSpawn.cs new file mode 100644 index 0000000000..3375b2b3c2 --- /dev/null +++ b/Content.Server/StationEvents/Events/RevenantSpawn.cs @@ -0,0 +1,18 @@ +namespace Content.Server.StationEvents.Events; + +public sealed class RevenantSpawn : StationEventSystem +{ + public override string Prototype => "RevenantSpawn"; + private static readonly string RevenantPrototype = "MobRevenant"; + + public override void Started() + { + base.Started(); + + if (TryFindRandomTile(out _, out _, out _, out var coords)) + { + Sawmill.Info($"Spawning revenant at {coords}"); + EntityManager.SpawnEntity(RevenantPrototype, coords); + } + } +} diff --git a/Content.Server/Revenant/CorporealComponent.cs b/Content.Shared/Revenant/Components/CorporealComponent.cs similarity index 89% rename from Content.Server/Revenant/CorporealComponent.cs rename to Content.Shared/Revenant/Components/CorporealComponent.cs index bb0b50d6ab..174d267cc9 100644 --- a/Content.Server/Revenant/CorporealComponent.cs +++ b/Content.Shared/Revenant/Components/CorporealComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server.Revenant; +namespace Content.Shared.Revenant.Components; /// /// Makes the target solid, visible, and applies a slowdown. diff --git a/Content.Server/Revenant/RevenantComponent.cs b/Content.Shared/Revenant/Components/RevenantComponent.cs similarity index 86% rename from Content.Server/Revenant/RevenantComponent.cs rename to Content.Shared/Revenant/Components/RevenantComponent.cs index 6484821862..3a50ebc9d6 100644 --- a/Content.Server/Revenant/RevenantComponent.cs +++ b/Content.Shared/Revenant/Components/RevenantComponent.cs @@ -1,15 +1,14 @@ -using Content.Shared.Disease; -using Content.Shared.Revenant; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using System.Threading; +using Content.Shared.Disease; using Content.Shared.FixedPoint; using Content.Shared.Store; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.Revenant; +namespace Content.Shared.Revenant.Components; -[RegisterComponent] -public sealed class RevenantComponent : SharedRevenantComponent +[RegisterComponent, NetworkedComponent] +public sealed class RevenantComponent : Component { /// /// The total amount of Essence the revenant has. Functions @@ -32,13 +31,13 @@ public sealed class RevenantComponent : SharedRevenantComponent /// The coefficient of damage taken to actual health lost. /// [ViewVariables(VVAccess.ReadWrite), DataField("damageToEssenceCoefficient")] - public float DamageToEssenceCoefficient = 1f; + public float DamageToEssenceCoefficient = 0.75f; /// /// The amount of essence passively generated per second. /// [ViewVariables(VVAccess.ReadWrite), DataField("essencePerSecond")] - public FixedPoint2 EssencePerSecond = 0.25f; + public FixedPoint2 EssencePerSecond = 0.5f; [ViewVariables] public float Accumulator = 0; @@ -129,13 +128,13 @@ public sealed class RevenantComponent : SharedRevenantComponent /// The radius around the user that this ability affects /// [ViewVariables(VVAccess.ReadWrite), DataField("overloadRadius")] - public float OverloadRadius = 3.5f; + public float OverloadRadius = 5f; /// - /// The chance that each light in the radius of the ability will break and explode. + /// How close to the light the entity has to be in order to be zapped. /// - [ViewVariables(VVAccess.ReadWrite), DataField("overloadBreakChance")] - public float OverloadBreakChance = 0.5f; + [ViewVariables(VVAccess.ReadWrite), DataField("overloadZapRadius")] + public float OverloadZapRadius = 2f; #endregion #region Blight Ability @@ -187,28 +186,15 @@ public sealed class RevenantComponent : SharedRevenantComponent [ViewVariables(VVAccess.ReadWrite), DataField("malfunctionRadius")] public float MalfunctionRadius = 3.5f; #endregion + + #region Visualizer + [DataField("state")] + public string State = "idle"; + [DataField("corporealState")] + public string CorporealState = "active"; + [DataField("stunnedState")] + public string StunnedState = "stunned"; + [DataField("harvestingState")] + public string HarvestingState = "harvesting"; + #endregion } - -public sealed class SoulSearchDoAfterComplete : EntityEventArgs -{ - public readonly EntityUid Target; - - public SoulSearchDoAfterComplete(EntityUid target) - { - Target = target; - } -} - -public sealed class SoulSearchDoAfterCancelled : EntityEventArgs { } - -public sealed class HarvestDoAfterComplete : EntityEventArgs -{ - public readonly EntityUid Target; - - public HarvestDoAfterComplete(EntityUid target) - { - Target = target; - } -} - -public sealed class HarvestDoAfterCancelled : EntityEventArgs { } diff --git a/Content.Shared/Revenant/Components/RevenantOverloadedLightsComponent.cs b/Content.Shared/Revenant/Components/RevenantOverloadedLightsComponent.cs new file mode 100644 index 0000000000..b383f2640c --- /dev/null +++ b/Content.Shared/Revenant/Components/RevenantOverloadedLightsComponent.cs @@ -0,0 +1,31 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Revenant.Components; + +/// +/// This is used for tracking lights that are overloaded +/// and are about to zap a player. +/// +[RegisterComponent, NetworkedComponent] +public sealed class RevenantOverloadedLightsComponent : Component +{ + [ViewVariables] + public EntityUid? Target; + + [ViewVariables(VVAccess.ReadWrite)] + public float Accumulator = 0; + + [ViewVariables(VVAccess.ReadWrite)] + public float ZapDelay = 3f; + + [ViewVariables(VVAccess.ReadWrite)] + public float ZapRange = 4f; + + [DataField("zapBeamEntityId",customTypeSerializer: typeof(PrototypeIdSerializer))] + public string ZapBeamEntityId = "LightningRevenant"; + + public float? OriginalEnergy; + public bool OriginalEnabled = false; +} diff --git a/Content.Shared/Revenant/EntitySystems/SharedCorporealSystem.cs b/Content.Shared/Revenant/EntitySystems/SharedCorporealSystem.cs new file mode 100644 index 0000000000..7d277a5198 --- /dev/null +++ b/Content.Shared/Revenant/EntitySystems/SharedCorporealSystem.cs @@ -0,0 +1,61 @@ +using Content.Shared.Physics; +using Robust.Shared.Physics; +using System.Linq; +using Content.Shared.Movement.Systems; +using Content.Shared.Revenant.Components; + +namespace Content.Shared.Revenant.EntitySystems; + +/// +/// Makes the revenant solid when the component is applied. +/// Additionally applies a few visual effects. +/// Used for status effect. +/// +public abstract class SharedCorporealSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnRefresh); + } + + private void OnRefresh(EntityUid uid, CorporealComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.MovementSpeedDebuff, component.MovementSpeedDebuff); + } + + public virtual void OnStartup(EntityUid uid, CorporealComponent component, ComponentStartup args) + { + _appearance.SetData(uid, RevenantVisuals.Corporeal, true); + + if (TryComp(uid, out var fixtures) && fixtures.FixtureCount >= 1) + { + var fixture = fixtures.Fixtures.Values.First(); + + fixture.CollisionMask = (int) (CollisionGroup.SmallMobMask | CollisionGroup.GhostImpassable); + fixture.CollisionLayer = (int) CollisionGroup.SmallMobLayer; + } + _movement.RefreshMovementSpeedModifiers(uid); + } + + public virtual void OnShutdown(EntityUid uid, CorporealComponent component, ComponentShutdown args) + { + _appearance.SetData(uid, RevenantVisuals.Corporeal, false); + + if (TryComp(uid, out var fixtures) && fixtures.FixtureCount >= 1) + { + var fixture = fixtures.Fixtures.Values.First(); + + fixture.CollisionMask = (int) CollisionGroup.GhostImpassable; + fixture.CollisionLayer = 0; + } + component.MovementSpeedDebuff = 1; //just so we can avoid annoying code elsewhere + _movement.RefreshMovementSpeedModifiers(uid); + } +} diff --git a/Content.Shared/Revenant/EntitySystems/SharedRevenantOverloadedLightsSystem.cs b/Content.Shared/Revenant/EntitySystems/SharedRevenantOverloadedLightsSystem.cs new file mode 100644 index 0000000000..1b3be0a820 --- /dev/null +++ b/Content.Shared/Revenant/EntitySystems/SharedRevenantOverloadedLightsSystem.cs @@ -0,0 +1,28 @@ +using Content.Shared.Revenant.Components; + +namespace Content.Shared.Revenant.EntitySystems; + +/// +/// This handles... +/// +public abstract class SharedRevenantOverloadedLightsSystem : EntitySystem +{ + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var comp in EntityQuery()) + { + comp.Accumulator += frameTime; + + + if (comp.Accumulator < comp.ZapDelay) + continue; + + OnZap(comp); + RemComp(comp.Owner, comp); + } + } + + protected abstract void OnZap(RevenantOverloadedLightsComponent component); +} diff --git a/Content.Shared/Revenant/SharedRevenant.cs b/Content.Shared/Revenant/SharedRevenant.cs index 25be1d0310..6de9a5d7a2 100644 --- a/Content.Shared/Revenant/SharedRevenant.cs +++ b/Content.Shared/Revenant/SharedRevenant.cs @@ -3,6 +3,29 @@ using Robust.Shared.Serialization; namespace Content.Shared.Revenant; +public sealed class SoulSearchDoAfterComplete : EntityEventArgs +{ + public readonly EntityUid Target; + + public SoulSearchDoAfterComplete(EntityUid target) + { + Target = target; + } +} + +public sealed class SoulSearchDoAfterCancelled : EntityEventArgs { } + +public sealed class HarvestDoAfterComplete : EntityEventArgs +{ + public readonly EntityUid Target; + + public HarvestDoAfterComplete(EntityUid target) + { + Target = target; + } +} + +public sealed class HarvestDoAfterCancelled : EntityEventArgs { } public sealed class RevenantShopActionEvent : InstantActionEvent { } public sealed class RevenantDefileActionEvent : InstantActionEvent { } public sealed class RevenantOverloadLightsActionEvent : InstantActionEvent { } diff --git a/Content.Shared/Revenant/SharedRevenantComponent.cs b/Content.Shared/Revenant/SharedRevenantComponent.cs deleted file mode 100644 index 83957a7448..0000000000 --- a/Content.Shared/Revenant/SharedRevenantComponent.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Robust.Shared.GameStates; - -namespace Content.Shared.Revenant; - -[NetworkedComponent] -public abstract class SharedRevenantComponent : Component -{ - -} diff --git a/Resources/Prototypes/Catalog/revenant_catalog.yml b/Resources/Prototypes/Catalog/revenant_catalog.yml index 977282b370..b51a92b82c 100644 --- a/Resources/Prototypes/Catalog/revenant_catalog.yml +++ b/Resources/Prototypes/Catalog/revenant_catalog.yml @@ -14,7 +14,7 @@ - type: listing id: RevenantOverloadLights name: Overload Lights - description: Overloads all nearby lights, causing the bulbs to shatter and sending out damaging sparks. Using it leaves you vulnerable to attacks for a long period of time. + description: Overloads all nearby lights, causing lights to pulse and sending out dangerous lightning. Using it leaves you vulnerable to attacks for a long period of time. productAction: RevenantOverloadLights cost: StolenEssence: 25 diff --git a/Resources/Prototypes/Datasets/Names/revenant.yml b/Resources/Prototypes/Datasets/Names/revenant.yml new file mode 100644 index 0000000000..86bdb4855b --- /dev/null +++ b/Resources/Prototypes/Datasets/Names/revenant.yml @@ -0,0 +1,55 @@ +- type: dataset + id: RevenantType + values: + - Essence + - Ghost + - Phantom + - Poltergeist + - Revenant + - Soul + - Spectre + - Spirit + +- type: dataset + id: RevenantAdjective + values: + - Abysmal + - Abyssal + - Brutal + - Dark + - Endless + - Eternal + - Fiery + - Hateful + - Hideous + - Hilarious + - Indifferent + - Malevolent + - Peaceful + - Searing + - Silent + - Spiteful + - Vicious + - Violent + +- type: dataset + id: RevenantTheme + values: + - Agony + - Anger + - Death + - Despair + - Desperation + - Destruction + - Disease + - Grief + - Hate + - Hellfire + - Laughter + - Misery + - Ruin + - Salt + - Screams + - Sorrow + - Suffering + - Vengeance \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Effects/lightning.yml b/Resources/Prototypes/Entities/Effects/lightning.yml index 88a2032cba..c4b1dcd1f1 100644 --- a/Resources/Prototypes/Entities/Effects/lightning.yml +++ b/Resources/Prototypes/Entities/Effects/lightning.yml @@ -37,6 +37,29 @@ - type: Lightning canArc: true +- type: entity + name: spooky lightning + id: LightningRevenant + parent: BaseLightning + components: + - type: Sprite + sprite: /Textures/Effects/lightning.rsi + drawdepth: Effects + layers: + - state: "lightning_3" + color: plum + shader: unshaded + - type: PointLight + enabled: true + color: plum + radius: 3.5 + softness: 1 + autoRot: true + castShadows: false + - type: Lightning + canArc: false + shockDamage: 30 + - type: entity name: charged lightning id: ChargedLightning diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index ed3df2e40d..2cc04c8a39 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -56,8 +56,8 @@ - type: Revenant - type: PointLight color: MediumPurple - radius: 1.5 - softness: 0.75 + radius: 2 + softness: 1 - type: UserInterface interfaces: - key: enum.StoreUiKey.Key @@ -70,36 +70,10 @@ - RevenantAbilities currencyWhitelist: - StolenEssence - -- type: entity - parent: BaseItem - id: RevenantEctoplasm - name: ectoplasm - description: A weird bit of goo. You probably shouldn't leave it lying around like this. - noSpawn: true - components: - - type: Sprite - noRot: true - netsync: false - sprite: Mobs/Ghosts/revenant.rsi - layers: - - state: ectoplasm - - type: Eye - - type: MovementSpeedModifier - baseWalkSpeed: 0 - baseSprintSpeed: 0 - - type: Damageable - damageContainer: Inorganic - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 5 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - type: DamageOnLand - ignoreResistances: true - damage: - types: - Blunt: 5 \ No newline at end of file + - type: RandomMetadata + nameSegments: + - The + - RevenantType + - of + - RevenantAdjective + - RevenantTheme diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 30e2222b79..5405f2ecbe 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -43,6 +43,17 @@ maxOccurrences: 7 minimumPlayers: 15 +- type: gameRule + id: RevenantSpawn + config: + !type:StationEventRuleConfiguration + id: RevenantSpawn + weight: 5 + endAfter: 1 + earliestStart: 45 + maxOccurrences: 1 + minimumPlayers: 20 + - type: gameRule id: FalseAlarm config: diff --git a/Resources/Prototypes/Polymorphs/polymorph.yml b/Resources/Prototypes/Polymorphs/polymorph.yml index d7afc79833..628c1aa8e8 100644 --- a/Resources/Prototypes/Polymorphs/polymorph.yml +++ b/Resources/Prototypes/Polymorphs/polymorph.yml @@ -18,15 +18,6 @@ revertOnCrit: true revertOnDeath: true -- type: polymorph - id: Ectoplasm - entity: RevenantEctoplasm - forced: true - duration: 60 - inventory: Drop - revertOnCrit: false - revertOnDeath: false - - type: polymorph id: WizardForcedCarp entity: MobCarpMagic diff --git a/Resources/Prototypes/explosion.yml b/Resources/Prototypes/explosion.yml index a516380abf..b49037341c 100644 --- a/Resources/Prototypes/explosion.yml +++ b/Resources/Prototypes/explosion.yml @@ -54,15 +54,3 @@ fireColor: Blue texturePath: /Textures/Effects/fire_greyscale.rsi fireStates: 3 - -- type: explosion - id: RevenantElectric - damagePerIntensity: - types: - Shock: 4 - tileBreakChance: [0] - tileBreakIntensity: [0] - lightColor: Plum - fireColor: Plum - texturePath: /Textures/Effects/fire_greyscale.rsi - fireStates: 3