forked from space-wizards/space-station-14
-
-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #262 from TGRCdev/revenant-stasis
Revenants enter stasis on death
- Loading branch information
Showing
21 changed files
with
389 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Robust.Shared.GameStates; | ||
|
||
namespace Content.Client.Revenant; | ||
|
||
[RegisterComponent] | ||
[NetworkedComponent] | ||
public sealed partial class RevenantStasisComponent : Component | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using Content.Shared.Examine; | ||
using Content.Shared.Interaction.Events; | ||
|
||
namespace Content.Client.Revenant; | ||
|
||
public sealed partial class RevenantStasisSystem : EntitySystem | ||
{ | ||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<RevenantStasisComponent, ChangeDirectionAttemptEvent>(OnAttemptDirection); | ||
SubscribeLocalEvent<RevenantStasisComponent, ExaminedEvent>(OnExamine); | ||
} | ||
|
||
private void OnExamine(Entity<RevenantStasisComponent> entity, ref ExaminedEvent args) | ||
{ | ||
args.PushMarkup(Loc.GetString("revenant-stasis-regenerating")); | ||
} | ||
|
||
private void OnAttemptDirection(EntityUid uid, RevenantStasisComponent comp, ChangeDirectionAttemptEvent args) | ||
{ | ||
args.Cancel(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
Content.Server/Revenant/Components/RevenantStatisComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using Content.Server.Revenant.EntitySystems; | ||
using Content.Shared.Revenant.Components; | ||
using Robust.Shared.GameStates; | ||
|
||
namespace Content.Server.Revenant.Components; | ||
|
||
[RegisterComponent] | ||
[Access(typeof(RevenantStasisSystem))] | ||
[NetworkedComponent] | ||
public sealed partial class RevenantStasisComponent : Component | ||
{ | ||
[ViewVariables(VVAccess.ReadOnly)] | ||
public Entity<RevenantComponent> Revenant; | ||
|
||
[ViewVariables(VVAccess.ReadOnly)] | ||
public TimeSpan StasisDuration = TimeSpan.FromSeconds(60); | ||
|
||
public RevenantStasisComponent(TimeSpan stasisDuration, Entity<RevenantComponent> revenant) | ||
{ | ||
StasisDuration = stasisDuration; | ||
Revenant = revenant; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
205 changes: 205 additions & 0 deletions
205
Content.Server/Revenant/EntitySystems/RevenantStasisSystem.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
using Content.Server.Bible; | ||
using Content.Server.Bible.Components; | ||
using Content.Server.Construction; | ||
using Content.Server.Explosion.EntitySystems; | ||
using Content.Server.Ghost.Roles; | ||
using Content.Server.Ghost.Roles.Components; | ||
using Content.Server.Kitchen.EntitySystems; | ||
using Content.Server.Mind; | ||
using Content.Server.Revenant.Components; | ||
using Content.Server.VoiceMask; | ||
using Content.Shared.Alert; | ||
using Content.Shared.DoAfter; | ||
using Content.Shared.Examine; | ||
using Content.Shared.Interaction; | ||
using Content.Shared.Interaction.Events; | ||
using Content.Shared.Movement.Components; | ||
using Content.Shared.Popups; | ||
using Content.Shared.Revenant; | ||
using Content.Shared.Speech; | ||
using Content.Shared.StatusEffect; | ||
using Content.Shared.Tag; | ||
using Robust.Shared.Player; | ||
|
||
namespace Content.Server.Revenant.EntitySystems; | ||
|
||
public sealed partial class RevenantStasisSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!; | ||
[Dependency] private readonly MindSystem _mind = default!; | ||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!; | ||
[Dependency] private readonly GhostRoleSystem _ghostRoles = default!; | ||
[Dependency] private readonly MetaDataSystem _meta = default!; | ||
[Dependency] private readonly SharedPopupSystem _popup = default!; | ||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!; | ||
[Dependency] private readonly TagSystem _tags = default!; | ||
[Dependency] private readonly ExplosionSystem _explosion = default!; | ||
|
||
[ValidatePrototypeId<StatusEffectPrototype>] | ||
private const string RevenantStasisId = "Stasis"; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<RevenantStasisComponent, ComponentStartup>(OnStartup); | ||
SubscribeLocalEvent<RevenantStasisComponent, ComponentShutdown>(OnShutdown); | ||
SubscribeLocalEvent<RevenantStasisComponent, StatusEffectEndedEvent>(OnStatusEnded); | ||
SubscribeLocalEvent<RevenantStasisComponent, ChangeDirectionAttemptEvent>(OnAttemptDirection); | ||
SubscribeLocalEvent<RevenantStasisComponent, ExaminedEvent>(OnExamine); | ||
SubscribeLocalEvent<RevenantStasisComponent, ConstructionConsumedObjectEvent>(OnCrafted); | ||
SubscribeLocalEvent<RevenantStasisComponent, GrindAttemptEvent>(OnGrindAttempt); | ||
|
||
SubscribeLocalEvent<RevenantStasisComponent, AfterInteractUsingEvent>(OnBibleInteract, before: [typeof(BibleSystem)]); | ||
SubscribeLocalEvent<RevenantStasisComponent, ExorciseRevenantDoAfterEvent>(OnExorcise); | ||
} | ||
|
||
private void OnStartup(EntityUid uid, RevenantStasisComponent component, ComponentStartup args) | ||
{ | ||
EnsureComp<AlertsComponent>(uid); | ||
|
||
EnsureComp<StatusEffectsComponent>(uid); | ||
_statusEffects.TryAddStatusEffect(uid, RevenantStasisId, component.StasisDuration, true); | ||
|
||
var mover = EnsureComp<InputMoverComponent>(uid); | ||
mover.CanMove = false; | ||
Dirty(uid, mover); | ||
|
||
var speech = EnsureComp<SpeechComponent>(uid); | ||
speech.SpeechVerb = "Ghost"; | ||
Dirty(uid, speech); | ||
|
||
var voice = EnsureComp<VoiceMaskComponent>(uid); | ||
voice.VoiceName = Comp<MetaDataComponent>(component.Revenant).EntityName; | ||
|
||
if (TryComp<GhostRoleComponent>(uid, out var ghostRole)) | ||
_ghostRoles.UnregisterGhostRole((uid, ghostRole)); | ||
} | ||
|
||
private void OnShutdown(EntityUid uid, RevenantStasisComponent component, ComponentShutdown args) | ||
{ | ||
if (_statusEffects.HasStatusEffect(uid, RevenantStasisId)) | ||
{ | ||
if (_mind.TryGetMind(uid, out var mindId, out var _)) | ||
_mind.TransferTo(mindId, null); | ||
QueueDel(component.Revenant); | ||
} | ||
} | ||
|
||
private void OnStatusEnded(EntityUid uid, RevenantStasisComponent component, StatusEffectEndedEvent args) | ||
{ | ||
if (args.Key == "Stasis") | ||
{ | ||
_transformSystem.SetCoordinates(component.Revenant, Transform(uid).Coordinates); | ||
_transformSystem.AttachToGridOrMap(component.Revenant); | ||
_meta.SetEntityPaused(component.Revenant, false); | ||
if (_mind.TryGetMind(uid, out var mindId, out var _)) | ||
_mind.TransferTo(mindId, component.Revenant); | ||
QueueDel(uid); | ||
} | ||
} | ||
|
||
private void OnExamine(Entity<RevenantStasisComponent> entity, ref ExaminedEvent args) | ||
{ | ||
args.PushMarkup(Loc.GetString("revenant-stasis-regenerating")); | ||
} | ||
|
||
private void OnCrafted(EntityUid uid, RevenantStasisComponent comp, ConstructionConsumedObjectEvent args) | ||
{ | ||
// Permanently sealed into revenant plushie | ||
|
||
var speech = EnsureComp<SpeechComponent>(args.New); | ||
speech.SpeechVerb = "Ghost"; | ||
Dirty(args.New, speech); | ||
|
||
EnsureComp<InputMoverComponent>(args.New); | ||
|
||
var voice = EnsureComp<VoiceMaskComponent>(args.New); | ||
voice.VoiceName = Comp<MetaDataComponent>(comp.Revenant).EntityName; | ||
|
||
if (_mind.TryGetMind(uid, out var mindId, out var _)) | ||
_mind.TransferTo(mindId, args.New); | ||
} | ||
|
||
private void OnGrindAttempt(EntityUid uid, RevenantStasisComponent comp, GrindAttemptEvent args) | ||
{ | ||
foreach (var reagent in args.Reagents) | ||
{ | ||
if (_tags.HasAnyTag(reagent, "Salt", "Holy")) | ||
return; | ||
} | ||
|
||
// Ripped off the changeling blood explosion variables | ||
_explosion.QueueExplosion( | ||
args.Grinder.Owner, | ||
"Default", | ||
7.5f, // totalIntensity | ||
4f, // slope | ||
2f // maxTileIntensity | ||
); | ||
|
||
args.Cancel(); | ||
} | ||
|
||
private void OnAttemptDirection(EntityUid uid, RevenantStasisComponent comp, ChangeDirectionAttemptEvent args) | ||
{ | ||
args.Cancel(); | ||
} | ||
|
||
private void OnBibleInteract(EntityUid uid, RevenantStasisComponent comp, ref AfterInteractUsingEvent args) | ||
{ | ||
if (args.Handled) | ||
return; | ||
if (args.Target == null) | ||
return; | ||
var bible = args.Used; | ||
var target = args.Target.Value; | ||
var user = args.User; | ||
if (!HasComp<BibleComponent>(args.Used)) | ||
return; | ||
|
||
if (!TryComp<RevenantStasisComponent>(target, out var stasis)) | ||
return; | ||
|
||
var revenant = stasis.Revenant; | ||
|
||
if (revenant.Comp.ExorcismRequiresBibleUser && !HasComp<BibleUserComponent>(args.User)) | ||
{ | ||
_popup.PopupEntity(Loc.GetString("revenant-exorcise-fail", ("bible", bible)), user, user); | ||
return; | ||
} | ||
|
||
var doAfterEventArgs = new DoAfterArgs(EntityManager, user, TimeSpan.FromSeconds(10), new ExorciseRevenantDoAfterEvent(), target, target, bible) | ||
{ | ||
BreakOnMove = true, | ||
BreakOnWeightlessMove = false, | ||
BreakOnDamage = true, | ||
NeedHand = true, | ||
DistanceThreshold = 1f | ||
}; | ||
|
||
if (!_doAfter.TryStartDoAfter(doAfterEventArgs)) | ||
return; | ||
|
||
args.Handled = true; | ||
|
||
_popup.PopupEntity(Loc.GetString("revenant-exorcise-begin-user", [("bible", bible), ("user", user), ("revenant", revenant.Owner)]), user, user); | ||
_popup.PopupEntity(Loc.GetString("revenant-exorcise-begin-target", [("bible", bible), ("user", user), ("revenant", revenant.Owner)]), target, target, PopupType.MediumCaution); | ||
_popup.PopupEntity(Loc.GetString("revenant-exorcise-begin-other", [("bible", bible), ("user", user), ("revenant", revenant.Owner)]), target, Filter.Pvs(target).RemovePlayersByAttachedEntity([user, target]), true); | ||
} | ||
|
||
private void OnExorcise(EntityUid uid, RevenantStasisComponent comp, ExorciseRevenantDoAfterEvent args) | ||
{ | ||
if (args.Cancelled) | ||
return; | ||
if (args.Target == null || args.Used == null) | ||
return; | ||
|
||
var target = args.Target.Value; | ||
var used = args.Used.Value; | ||
|
||
_popup.PopupEntity(Loc.GetString("revenant-exorcise-success", [("bible", used), ("user", args.User), ("revenant", comp.Revenant.Owner)]), target); | ||
|
||
RemComp<RevenantStasisComponent>(args.Target.Value); | ||
} | ||
} |
Oops, something went wrong.