mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
parent
42f0073a71
commit
040d28fb9d
7 changed files with 50 additions and 9 deletions
|
|
@ -35,10 +35,13 @@ public sealed partial class ServerChangelingLastResortSystem : ChangelingLastRes
|
|||
args.Handled = true;
|
||||
|
||||
Audio.PlayPvs(ent.Comp.Sound, ent.Owner);
|
||||
_popup.PopupEntity(Loc.GetString("changeling-takeover-start-others", ("user", Identity.Entity(ent.Owner, EntityManager))),
|
||||
_popup.PopupEntity(Loc.GetString("changeling-takeover-start-others",
|
||||
("user", Identity.Entity(ent.Owner, EntityManager))),
|
||||
ent.Owner,
|
||||
PopupType.MediumCaution);
|
||||
|
||||
var examine = Loc.GetString("changeling-takeover-doafter", ("user", Identity.Entity(ent, EntityManager)), ("target", Identity.Entity(args.Target, EntityManager)));
|
||||
|
||||
var doAfter = new DoAfterArgs(EntityManager,
|
||||
ent.Owner,
|
||||
ent.Comp.TakeOverDuration,
|
||||
|
|
@ -50,6 +53,7 @@ public sealed partial class ServerChangelingLastResortSystem : ChangelingLastRes
|
|||
BreakOnMove = true,
|
||||
DuplicateCondition = DuplicateConditions.None,
|
||||
RequireCanInteract = false,
|
||||
ExamineText = examine
|
||||
};
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfter);
|
||||
|
|
@ -92,17 +96,21 @@ public sealed partial class ServerChangelingLastResortSystem : ChangelingLastRes
|
|||
if (!_mind.TryGetMind(args.User, out var mindId, out var mind))
|
||||
return;
|
||||
|
||||
TakeOverCorpse(args.User, target, mindId, mind);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("changeling-takeover-success-self"), target, target, PopupType.Large);
|
||||
TakeOverCorpse(ent, target, mindId, mind);
|
||||
}
|
||||
|
||||
private void TakeOverCorpse(EntityUid user, EntityUid target, EntityUid mindId, MindComponent mind)
|
||||
private void TakeOverCorpse(Entity<ChangelingSlugComponent> ent,
|
||||
EntityUid target,
|
||||
EntityUid mindId,
|
||||
MindComponent mind)
|
||||
{
|
||||
_mind.TransferTo(mindId, target, mind: mind);
|
||||
|
||||
_antag.AssignAntagComponents(target, ChangelingAntag);
|
||||
|
||||
QueueDel(user);
|
||||
var ev = new BodyTakenByHeadslugEvent(target, ent.Comp.AutoStasis, ent.Comp.AutoStasisDurationMultiplier);
|
||||
RaiseLocalEvent(target, ref ev);
|
||||
|
||||
QueueDel(ent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Shared.Actions.Components;
|
||||
using Content.Shared.Changeling.Systems;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.Ghost.Systems;
|
||||
using Content.Shared.Mobs;
|
||||
|
|
@ -9,6 +10,7 @@ public abstract partial class SharedActionsSystem
|
|||
{
|
||||
private void InitializeRelay()
|
||||
{
|
||||
SubscribeLocalEvent<ActionsComponent, BodyTakenByHeadslugEvent>(RefRelayActionEvent);
|
||||
SubscribeLocalEvent<ActionsComponent, MobStateChangedEvent>(RefRelayActionEvent);
|
||||
SubscribeLocalEvent<ActionsComponent, GhostAttemptEvent>(RefRelayActionEvent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ public sealed partial class ChangelingSlugComponent : Component
|
|||
[DataField]
|
||||
public TimeSpan TakeOverDuration = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the body should automatically enter regen stasis after being taken over.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool AutoStasis = true;
|
||||
|
||||
/// <summary>
|
||||
/// The multiplier for the duration of the automatic stasis.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float AutoStasisDurationMultiplier = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// The sound to play when starting the takeover.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -52,3 +52,11 @@ public abstract partial class ChangelingLastResortSystem : EntitySystem
|
|||
_gibbing.Gib(args.Performer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised on a body after a headslug takes it over.
|
||||
/// </summary>
|
||||
/// <param name="StartStasis">Whether the body should instantly start regen stasis after being taken over.</param>
|
||||
/// <param name="StasisDurationMultiplier">Time multiplier for the regen stasis, if one is started.</param>
|
||||
[ByRefEvent]
|
||||
public record struct BodyTakenByHeadslugEvent(EntityUid Target, bool StartStasis = true, float StasisDurationMultiplier = 1f);
|
||||
|
|
|
|||
|
|
@ -62,10 +62,17 @@ public sealed partial class RegenerativeStasisSystem : EntitySystem
|
|||
EnterStasis((ent, ent.Comp), args.Performer);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnHeadslugTookBody(Entity<RegenerativeStasisActionComponent> ent, ref ActionRelayedEvent<BodyTakenByHeadslugEvent> args)
|
||||
{
|
||||
if (args.Args.StartStasis)
|
||||
EnterStasis(ent.AsNullable(), args.Args.Target, args.Args.StasisDurationMultiplier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enter the stasis and set the action cooldown depending on the damage you have taken.
|
||||
/// </summary>
|
||||
public void EnterStasis(Entity<RegenerativeStasisActionComponent?> ent, EntityUid target)
|
||||
public void EnterStasis(Entity<RegenerativeStasisActionComponent?> ent, EntityUid target, float durationMultiplier = 1f)
|
||||
{
|
||||
if (!Resolve(ent.Owner, ref ent.Comp))
|
||||
return;
|
||||
|
|
@ -92,7 +99,8 @@ public sealed partial class RegenerativeStasisSystem : EntitySystem
|
|||
var stasisDuration = ent.Comp.MinStasisCooldown;
|
||||
|
||||
stasisDuration += ent.Comp.BonusCooldownPerDamage * (double)_damage.GetTotalDamage(target);
|
||||
stasisDuration = new TimeSpan(Math.Clamp(stasisDuration.Ticks, ent.Comp.MinStasisCooldown.Ticks, ent.Comp.MaxStasisCooldown.Ticks)); // No clamp method for TimeSpans
|
||||
var calculatedDuration = (long)(Math.Clamp(stasisDuration.Ticks, ent.Comp.MinStasisCooldown.Ticks, ent.Comp.MaxStasisCooldown.Ticks) * durationMultiplier); // No clamp method for TimeSpans
|
||||
stasisDuration = new TimeSpan(calculatedDuration);
|
||||
|
||||
_metaData.SetEntityName(ent, Loc.GetString("changeling-stasis-active-name"));
|
||||
_metaData.SetEntityDescription(ent, Loc.GetString("changeling-stasis-active-desc"));
|
||||
|
|
@ -160,6 +168,7 @@ public sealed partial class RegenerativeStasisSystem : EntitySystem
|
|||
_metaData.SetEntityDescription(ent, ent.Comp.InitialDescription);
|
||||
|
||||
_actions.SetToggled(ent.Owner, ent.Comp.IsInStasis);
|
||||
_actions.SetCooldown(ent.Owner, ent.Comp.MinStasisCooldown); // Don't allow entering stasis right after cancelling it.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ changeling-biodegrade-used-popup-self = We vomit acid over our {$restraint}!
|
|||
changeling-takeover-not-dead = This body yet lives! We cannot infest it alive.
|
||||
changeling-takeover-is-changeling = This body rejects our attempts to take over!
|
||||
changeling-takeover-start-others = {CAPITALIZE(THE($user))} begins to crawl inside the corpse!
|
||||
changeling-takeover-success-self = We have successfully infested the body and assumed its form.
|
||||
changeling-takeover-doafter = [color=red]{ CAPITALIZE(SUBJECT($user)) } { CONJUGATE-BE($user) } crawling inside of {$target}![/color]
|
||||
|
||||
# stings
|
||||
changeling-sting-success = We silently sting {THE($target)}!
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@
|
|||
interactSuccessSpawn: EffectHearts
|
||||
interactSuccessSound:
|
||||
path: /Audio/Animals/cat_meow.ogg # meow
|
||||
- type: ChangelingSlug
|
||||
autoStasisDurationMultiplier: 0.5 # Mercy upon headslugs who already took forever to find a body.
|
||||
|
||||
- type: entity # dummy prototype for the store listing
|
||||
id: ChangelingFleshClothingAbilityStoreDummy
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue