Revenant 2: Electric Boogaloo (#11510)

* revenant 2: electric boogaloo

* revevent

* oversights

* Update RevenantSystem.Abilities.cs

* names

* no shoote stouhg walls
This commit is contained in:
Nemanja
2022-09-28 22:30:48 -04:00
committed by GitHub
parent a9dd9257d8
commit 3c3ee60dd2
25 changed files with 427 additions and 203 deletions

View File

@@ -0,0 +1,8 @@
using Content.Shared.Revenant.EntitySystems;
namespace Content.Client.Revenant;
public sealed class CorporealSystem : SharedCorporealSystem
{
}

View File

@@ -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";
}

View File

@@ -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<RevenantOverloadedLightsComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<RevenantOverloadedLightsComponent, ComponentShutdown>(OnShutdown);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var (comp, light) in EntityQuery<RevenantOverloadedLightsComponent, PointLightComponent>())
{
//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<PointLightComponent>(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<PointLightComponent>(component.Owner, out var light))
return;
if (component.OriginalEnergy == null)
{
RemComp<PointLightComponent>(component.Owner);
return;
}
light.Energy = component.OriginalEnergy.Value;
light.Enabled = component.OriginalEnabled;
Dirty(light);
}
protected override void OnZap(RevenantOverloadedLightsComponent component)
{
}
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Revenant; using Content.Shared.Revenant;
using Content.Shared.Revenant.Components;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
namespace Content.Client.Revenant; namespace Content.Client.Revenant;

View File

@@ -1,4 +1,4 @@
namespace Content.Server.Revenant; namespace Content.Server.Revenant.Components;
[RegisterComponent] [RegisterComponent]
public sealed class EssenceComponent : Component public sealed class EssenceComponent : Component
@@ -6,20 +6,20 @@ public sealed class EssenceComponent : Component
/// <summary> /// <summary>
/// Whether or not the entity has been harvested yet. /// Whether or not the entity has been harvested yet.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables(VVAccess.ReadWrite)]
public bool Harvested = false; public bool Harvested = false;
/// <summary> /// <summary>
/// Whether or not a revenant has searched this entity /// Whether or not a revenant has searched this entity
/// for its soul yet. /// for its soul yet.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables(VVAccess.ReadWrite)]
public bool SearchComplete = false; public bool SearchComplete = false;
/// <summary> /// <summary>
/// The total amount of Essence that the entity has. /// The total amount of Essence that the entity has.
/// Changes based on mob state. /// Changes based on mob state.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables(VVAccess.ReadWrite)]
public float EssenceAmount = 0f; public float EssenceAmount = 0f;
} }

View File

@@ -1,51 +1,17 @@
using Content.Server.Visible; using Content.Server.Visible;
using Content.Shared.Physics; using Content.Shared.Revenant.Components;
using Content.Shared.Revenant; using Content.Shared.Revenant.EntitySystems;
using Content.Shared.Movement;
using Robust.Server.GameObjects; 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; namespace Content.Server.Revenant.EntitySystems;
/// <summary> public sealed class CorporealSystem : SharedCorporealSystem
/// Makes the revenant solid when the component is applied.
/// Additionally applies a few visual effects.
/// Used for status effect.
/// </summary>
public sealed class CorporealSystem : EntitySystem
{ {
[Dependency] private readonly VisibilitySystem _visibilitySystem = default!; [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(); base.OnStartup(uid, component, args);
SubscribeLocalEvent<CorporealComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<CorporealComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<CorporealComponent, RefreshMovementSpeedModifiersEvent>(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<AppearanceComponent>(uid, out var app))
app.SetData(RevenantVisuals.Corporeal, true);
if (TryComp<FixturesComponent>(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;
}
if (TryComp<VisibilityComponent>(uid, out var visibility)) if (TryComp<VisibilityComponent>(uid, out var visibility))
{ {
@@ -53,21 +19,11 @@ public sealed class CorporealSystem : EntitySystem
_visibilitySystem.AddLayer(visibility, (int) VisibilityFlags.Normal, false); _visibilitySystem.AddLayer(visibility, (int) VisibilityFlags.Normal, false);
_visibilitySystem.RefreshVisibility(visibility); _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<AppearanceComponent>(uid, out var app)) base.OnShutdown(uid, component, args);
app.SetData(RevenantVisuals.Corporeal, false);
if (TryComp<FixturesComponent>(uid, out var fixtures) && fixtures.FixtureCount >= 1)
{
var fixture = fixtures.Fixtures.Values.First();
fixture.CollisionMask = (int) CollisionGroup.GhostImpassable;
fixture.CollisionLayer = 0;
}
if (TryComp<VisibilityComponent>(uid, out var visibility)) if (TryComp<VisibilityComponent>(uid, out var visibility))
{ {

View File

@@ -1,7 +1,9 @@
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.Revenant.Components;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.MobState; using Content.Shared.MobState;
using Content.Shared.MobState.Components; using Content.Shared.MobState.Components;
using Content.Shared.Revenant.Components;
using Robust.Shared.Random; using Robust.Shared.Random;
namespace Content.Server.Revenant.EntitySystems; namespace Content.Server.Revenant.EntitySystems;

View File

@@ -0,0 +1,29 @@
using Content.Server.Beam;
using Content.Shared.Revenant.Components;
using Content.Shared.Revenant.EntitySystems;
namespace Content.Server.Revenant.EntitySystems;
/// <summary>
/// This handles...
/// </summary>
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);
}
}

View File

@@ -20,24 +20,25 @@ using Content.Server.Disease.Components;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.Bed.Sleep; using Content.Shared.Bed.Sleep;
using Content.Shared.MobState; using Content.Shared.MobState;
using Content.Server.Explosion.EntitySystems;
using System.Linq; using System.Linq;
using Content.Server.Beam;
using Content.Server.Emag; using Content.Server.Emag;
using Content.Server.Humanoid; using Content.Server.Humanoid;
using Content.Server.Revenant.Components;
using Content.Server.Store.Components; using Content.Server.Store.Components;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Revenant.Components;
using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Components;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Server.Revenant.EntitySystems; 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 IMapManager _mapManager = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly EntityStorageSystem _entityStorage = default!; [Dependency] private readonly EntityStorageSystem _entityStorage = default!;
[Dependency] private readonly DiseaseSystem _disease = default!; [Dependency] private readonly DiseaseSystem _disease = default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly EmagSystem _emag = default!; [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly GhostSystem _ghost = default!; [Dependency] private readonly GhostSystem _ghost = default!;
@@ -181,8 +182,10 @@ public sealed partial class RevenantSystem : EntitySystem
essence.Harvested = true; essence.Harvested = true;
ChangeEssenceAmount(uid, essence.EssenceAmount, component); ChangeEssenceAmount(uid, essence.EssenceAmount, component);
if (TryComp<StoreComponent>(uid, out var store)) if (TryComp<StoreComponent>(uid, out var store))
{
_store.TryAddCurrency(new Dictionary<string, FixedPoint2>() _store.TryAddCurrency(new Dictionary<string, FixedPoint2>()
{ {component.StolenEssenceCurrencyPrototype, essence.EssenceAmount} }, store); { {component.StolenEssenceCurrencyPrototype, essence.EssenceAmount} }, store);
}
if (!TryComp<MobStateComponent>(args.Target, out var mobstate)) if (!TryComp<MobStateComponent>(args.Target, out var mobstate))
return; return;
@@ -198,7 +201,7 @@ public sealed partial class RevenantSystem : EntitySystem
if (damage == null) if (damage == null)
return; return;
DamageSpecifier dspec = new(); DamageSpecifier dspec = new();
dspec.DamageDict.Add("Cellular", damage.Value); dspec.DamageDict.Add("Poison", damage.Value);
_damage.TryChangeDamage(args.Target, dspec, true); _damage.TryChangeDamage(args.Target, dspec, true);
} }
@@ -280,22 +283,28 @@ public sealed partial class RevenantSystem : EntitySystem
args.Handled = true; args.Handled = true;
var xform = Transform(uid);
var poweredLights = GetEntityQuery<PoweredLightComponent>(); var poweredLights = GetEntityQuery<PoweredLightComponent>();
var mobState = GetEntityQuery<MobStateComponent>();
var lookup = _lookup.GetEntitiesInRange(uid, component.OverloadRadius); var lookup = _lookup.GetEntitiesInRange(uid, component.OverloadRadius);
//TODO: feels like this might be a sin and a half
foreach (var ent in lookup) foreach (var ent in lookup)
{ {
if (!poweredLights.HasComponent(ent)) if (!mobState.HasComponent(ent) || !_mobState.IsAlive(ent))
continue; continue;
var ev = new GhostBooEvent(); //light go flicker var nearbyLights = _lookup.GetEntitiesInRange(ent, component.OverloadZapRadius)
RaiseLocalEvent(ent, ev); .Where(e => poweredLights.HasComponent(e) && !HasComp<RevenantOverloadedLightsComponent>(e) &&
_interact.InRangeUnobstructed(e, uid, -1)).ToArray();
if (_random.Prob(component.OverloadBreakChance)) if (!nearbyLights.Any())
{ continue;
//values
_explosion.QueueExplosion(ent, "RevenantElectric", 15, 3, 5, canCreateVacuum: false); //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<RevenantOverloadedLightsComponent>(allLight.First());
comp.Target = ent; //who they gon fire at?
} }
} }
@@ -310,10 +319,11 @@ public sealed partial class RevenantSystem : EntitySystem
args.Handled = true; args.Handled = true;
var emo = GetEntityQuery<DiseaseCarrierComponent>(); var emo = GetEntityQuery<DiseaseCarrierComponent>();
foreach (var ent in _lookup.GetEntitiesInRange(uid, component.BlightRadius)) foreach (var ent in _lookup.GetEntitiesInRange(uid, component.BlightRadius))
{
if (emo.TryGetComponent(ent, out var comp)) 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) private void OnMalfunctionAction(EntityUid uid, RevenantComponent component, RevenantMalfunctionActionEvent args)
@@ -327,6 +337,8 @@ public sealed partial class RevenantSystem : EntitySystem
args.Handled = true; args.Handled = true;
foreach (var ent in _lookup.GetEntitiesInRange(uid, component.MalfunctionRadius)) foreach (var ent in _lookup.GetEntitiesInRange(uid, component.MalfunctionRadius))
{
_emag.DoEmag(ent, ent); //it emags itself. spooky. _emag.DoEmag(ent, ent); //it emags itself. spooky.
}
} }
} }

View File

@@ -15,14 +15,13 @@ using Content.Shared.Examine;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Content.Shared.Actions.ActionTypes; using Content.Shared.Actions.ActionTypes;
using Content.Shared.Tag; using Content.Shared.Tag;
using Content.Server.Polymorph.Systems;
using Content.Server.Store.Components; using Content.Server.Store.Components;
using Content.Server.Store.Systems; using Content.Server.Store.Systems;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Robust.Shared.Player; using Robust.Shared.Player;
using Content.Shared.Movement.Systems;
using Content.Shared.Maps; using Content.Shared.Maps;
using Content.Shared.Physics; using Content.Shared.Physics;
using Content.Shared.Revenant.Components;
namespace Content.Server.Revenant.EntitySystems; namespace Content.Server.Revenant.EntitySystems;
@@ -36,14 +35,12 @@ public sealed partial class RevenantSystem : EntitySystem
[Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly PolymorphableSystem _polymorphable = default!;
[Dependency] private readonly PhysicsSystem _physics = default!; [Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!; [Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly SharedInteractionSystem _interact = default!; [Dependency] private readonly SharedInteractionSystem _interact = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedStunSystem _stun = default!; [Dependency] private readonly SharedStunSystem _stun = default!;
[Dependency] private readonly TagSystem _tag = default!; [Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly StoreSystem _store = default!; [Dependency] private readonly StoreSystem _store = default!;
public override void Initialize() public override void Initialize()
@@ -89,8 +86,6 @@ public sealed partial class RevenantSystem : EntitySystem
{ {
if (args.Key == "Stun") if (args.Key == "Stun")
_appearance.SetData(uid, RevenantVisuals.Stunned, false); _appearance.SetData(uid, RevenantVisuals.Stunned, false);
else if (args.Key == "Corporeal")
_movement.RefreshMovementSpeedModifiers(uid);
} }
private void OnExamine(EntityUid uid, RevenantComponent component, ExaminedEvent args) private void OnExamine(EntityUid uid, RevenantComponent component, ExaminedEvent args)
@@ -124,16 +119,15 @@ public sealed partial class RevenantSystem : EntitySystem
if (regenCap) if (regenCap)
FixedPoint2.Min(component.Essence, component.EssenceRegenCap); FixedPoint2.Min(component.Essence, component.EssenceRegenCap);
if (TryComp<StoreComponent>(uid, out var store))
_store.UpdateUserInterface(uid, store);
_alerts.ShowAlert(uid, AlertType.Essence, (short) Math.Clamp(Math.Round(component.Essence.Float() / 10f), 0, 16)); _alerts.ShowAlert(uid, AlertType.Essence, (short) Math.Clamp(Math.Round(component.Essence.Float() / 10f), 0, 16));
if (component.Essence <= 0) if (component.Essence <= 0)
{ {
component.Essence = component.EssenceRegenCap; QueueDel(uid);
_polymorphable.PolymorphEntity(uid, "Ectoplasm");
} }
if (TryComp<StoreComponent>(uid, out var store))
_store.UpdateUserInterface(uid, store);
return true; return true;
} }

View File

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

View File

@@ -1,4 +1,4 @@
namespace Content.Server.Revenant; namespace Content.Shared.Revenant.Components;
/// <summary> /// <summary>
/// Makes the target solid, visible, and applies a slowdown. /// Makes the target solid, visible, and applies a slowdown.

View File

@@ -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 System.Threading;
using Content.Shared.Disease;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Store; 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] [RegisterComponent, NetworkedComponent]
public sealed class RevenantComponent : SharedRevenantComponent public sealed class RevenantComponent : Component
{ {
/// <summary> /// <summary>
/// The total amount of Essence the revenant has. Functions /// 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. /// The coefficient of damage taken to actual health lost.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("damageToEssenceCoefficient")] [ViewVariables(VVAccess.ReadWrite), DataField("damageToEssenceCoefficient")]
public float DamageToEssenceCoefficient = 1f; public float DamageToEssenceCoefficient = 0.75f;
/// <summary> /// <summary>
/// The amount of essence passively generated per second. /// The amount of essence passively generated per second.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("essencePerSecond")] [ViewVariables(VVAccess.ReadWrite), DataField("essencePerSecond")]
public FixedPoint2 EssencePerSecond = 0.25f; public FixedPoint2 EssencePerSecond = 0.5f;
[ViewVariables] [ViewVariables]
public float Accumulator = 0; public float Accumulator = 0;
@@ -129,13 +128,13 @@ public sealed class RevenantComponent : SharedRevenantComponent
/// The radius around the user that this ability affects /// The radius around the user that this ability affects
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("overloadRadius")] [ViewVariables(VVAccess.ReadWrite), DataField("overloadRadius")]
public float OverloadRadius = 3.5f; public float OverloadRadius = 5f;
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("overloadBreakChance")] [ViewVariables(VVAccess.ReadWrite), DataField("overloadZapRadius")]
public float OverloadBreakChance = 0.5f; public float OverloadZapRadius = 2f;
#endregion #endregion
#region Blight Ability #region Blight Ability
@@ -187,28 +186,15 @@ public sealed class RevenantComponent : SharedRevenantComponent
[ViewVariables(VVAccess.ReadWrite), DataField("malfunctionRadius")] [ViewVariables(VVAccess.ReadWrite), DataField("malfunctionRadius")]
public float MalfunctionRadius = 3.5f; public float MalfunctionRadius = 3.5f;
#endregion #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 { }

View File

@@ -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;
/// <summary>
/// This is used for tracking lights that are overloaded
/// and are about to zap a player.
/// </summary>
[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<EntityPrototype>))]
public string ZapBeamEntityId = "LightningRevenant";
public float? OriginalEnergy;
public bool OriginalEnabled = false;
}

View File

@@ -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;
/// <summary>
/// Makes the revenant solid when the component is applied.
/// Additionally applies a few visual effects.
/// Used for status effect.
/// </summary>
public abstract class SharedCorporealSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CorporealComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<CorporealComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<CorporealComponent, RefreshMovementSpeedModifiersEvent>(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<FixturesComponent>(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<FixturesComponent>(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);
}
}

View File

@@ -0,0 +1,28 @@
using Content.Shared.Revenant.Components;
namespace Content.Shared.Revenant.EntitySystems;
/// <summary>
/// This handles...
/// </summary>
public abstract class SharedRevenantOverloadedLightsSystem : EntitySystem
{
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var comp in EntityQuery<RevenantOverloadedLightsComponent>())
{
comp.Accumulator += frameTime;
if (comp.Accumulator < comp.ZapDelay)
continue;
OnZap(comp);
RemComp(comp.Owner, comp);
}
}
protected abstract void OnZap(RevenantOverloadedLightsComponent component);
}

View File

@@ -3,6 +3,29 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Revenant; 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 RevenantShopActionEvent : InstantActionEvent { }
public sealed class RevenantDefileActionEvent : InstantActionEvent { } public sealed class RevenantDefileActionEvent : InstantActionEvent { }
public sealed class RevenantOverloadLightsActionEvent : InstantActionEvent { } public sealed class RevenantOverloadLightsActionEvent : InstantActionEvent { }

View File

@@ -1,9 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Revenant;
[NetworkedComponent]
public abstract class SharedRevenantComponent : Component
{
}

View File

@@ -14,7 +14,7 @@
- type: listing - type: listing
id: RevenantOverloadLights id: RevenantOverloadLights
name: Overload Lights 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 productAction: RevenantOverloadLights
cost: cost:
StolenEssence: 25 StolenEssence: 25

View File

@@ -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

View File

@@ -37,6 +37,29 @@
- type: Lightning - type: Lightning
canArc: true 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 - type: entity
name: charged lightning name: charged lightning
id: ChargedLightning id: ChargedLightning

View File

@@ -56,8 +56,8 @@
- type: Revenant - type: Revenant
- type: PointLight - type: PointLight
color: MediumPurple color: MediumPurple
radius: 1.5 radius: 2
softness: 0.75 softness: 1
- type: UserInterface - type: UserInterface
interfaces: interfaces:
- key: enum.StoreUiKey.Key - key: enum.StoreUiKey.Key
@@ -70,36 +70,10 @@
- RevenantAbilities - RevenantAbilities
currencyWhitelist: currencyWhitelist:
- StolenEssence - StolenEssence
- type: RandomMetadata
- type: entity nameSegments:
parent: BaseItem - The
id: RevenantEctoplasm - RevenantType
name: ectoplasm - of
description: A weird bit of goo. You probably shouldn't leave it lying around like this. - RevenantAdjective
noSpawn: true - RevenantTheme
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

View File

@@ -43,6 +43,17 @@
maxOccurrences: 7 maxOccurrences: 7
minimumPlayers: 15 minimumPlayers: 15
- type: gameRule
id: RevenantSpawn
config:
!type:StationEventRuleConfiguration
id: RevenantSpawn
weight: 5
endAfter: 1
earliestStart: 45
maxOccurrences: 1
minimumPlayers: 20
- type: gameRule - type: gameRule
id: FalseAlarm id: FalseAlarm
config: config:

View File

@@ -18,15 +18,6 @@
revertOnCrit: true revertOnCrit: true
revertOnDeath: true revertOnDeath: true
- type: polymorph
id: Ectoplasm
entity: RevenantEctoplasm
forced: true
duration: 60
inventory: Drop
revertOnCrit: false
revertOnDeath: false
- type: polymorph - type: polymorph
id: WizardForcedCarp id: WizardForcedCarp
entity: MobCarpMagic entity: MobCarpMagic

View File

@@ -54,15 +54,3 @@
fireColor: Blue fireColor: Blue
texturePath: /Textures/Effects/fire_greyscale.rsi texturePath: /Textures/Effects/fire_greyscale.rsi
fireStates: 3 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