Skip to content

Commit

Permalink
https://github.com/Simple-Station/Parkstation/pull/209
Browse files Browse the repository at this point in the history
  • Loading branch information
DEATHB4DEFEAT committed Aug 20, 2024
1 parent 995676b commit 9ce2fea
Show file tree
Hide file tree
Showing 77 changed files with 786 additions and 180 deletions.
11 changes: 11 additions & 0 deletions Content.Server/Cloning/CloningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.GameObjects.Components.Localization; //DeltaV End Metem Usings
using Content.Server.EntityList;
using Content.Server.Parkstation.Cloning;
using Content.Shared.SSDIndicator;
using Content.Shared.Damage.ForceSay;
using Content.Server.Polymorph.Components;
Expand Down Expand Up @@ -249,6 +250,12 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponen
}
// end of genetic damage checks

// For other systems checking if they should be getting cloned
var beingCloned = new BeingClonedEvent(pref, mind, clonePod.Owner);
RaiseLocalEvent(ref beingCloned);
if (beingCloned.Cancelled)
return false;

var mob = FetchAndSpawnMob(clonePod, pref, speciesPrototype, humanoid, bodyToClone, karmaBonus); //DeltaV Replaces CloneAppearance with Metem/Clone via FetchAndSpawnMob

///Nyano - Summary: adds the potential psionic trait to the reanimated mob.
Expand All @@ -270,6 +277,10 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponen

AddComp<ActiveCloningPodComponent>(uid);

// For other systems adding components to the mob
var bce = new BeenClonedEvent(pref, mind, mob, bodyToClone, clonePod.Owner);
RaiseLocalEvent(bce);

// TODO: Ideally, components like this should be components on the mind entity so this isn't necessary.
// Add on special job components to the mob.
if (_jobs.MindTryGetJob(mindEnt, out _, out var prototype))
Expand Down
21 changes: 21 additions & 0 deletions Content.Server/Parkstation/Cloning/CloningEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Content.Shared.Mind;
using Content.Shared.Preferences;

namespace Content.Server.Parkstation.Cloning;

[ByRefEvent]
public sealed class BeingClonedEvent(HumanoidCharacterProfile profile, MindComponent mind, EntityUid cloner) : CancellableEntityEventArgs
{
public HumanoidCharacterProfile Profile = profile;
public MindComponent Mind = mind;
public EntityUid Cloner = cloner;
}

public sealed class BeenClonedEvent(HumanoidCharacterProfile profile, MindComponent mind, EntityUid mob, EntityUid OriginalMob, EntityUid cloner) : EntityEventArgs
{
public HumanoidCharacterProfile Profile = profile;
public MindComponent Mind = mind;
public EntityUid Mob = mob;
public EntityUid OriginalMob = OriginalMob;
public EntityUid Cloner = cloner;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,36 @@ public sealed partial class ShadowkinDarkSwapPowerComponent : Component

[DataField("shadowkinDarkSwapActionEntity")]
public EntityUid? ShadowkinDarkSwapActionEntity;


/// <summary>
/// If the entity should be sent to the dark
/// </summary>
[DataField("invisible")]
public bool Invisible = true;

/// <summary>
/// If it should be pacified
/// </summary>
[DataField("pacify")]
public bool Pacify = true;

/// <summary>
/// If the entity should dim nearby lights when swapped
/// </summary>
[DataField("darken"), ViewVariables(VVAccess.ReadWrite)]
public bool Darken = true;

/// <summary>
/// How far to dim nearby lights
/// </summary>
[DataField("range"), ViewVariables(VVAccess.ReadWrite)]
public float DarkenRange = 5f;

/// <summary>
/// How fast to refresh nearby light dimming in seconds
/// Without this performance would be significantly worse
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float DarkenRate = 0.084f; // 1/12th of a second
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Content.Server.Parkstation.Species.Shadowkin.Components;

[RegisterComponent]
public sealed partial class ShadowkinSightComponent : Component;
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,17 @@ private void Shutdown(EntityUid uid, ShadowkinDarkSwapPowerComponent component,
private void OnInvisStartup(EntityUid uid, ShadowkinDarkSwappedComponent component, ComponentStartup args)
{
if (component.Pacify)
EnsureComp<PacifiedComponent>(uid);

if (!component.Invisible)
return;
{
var pax = EnsureComp<PacifiedComponent>(uid);
pax.DisallowAllCombat = true;
pax.DisallowDisarm = true;
}

SetVisibility(uid, true);
SuppressFactions(uid, true);
if (component.Invisible)
{
SetVisibility(uid, true, true, true);
SuppressFactions(uid, true);
}
}

private void OnInvisShutdown(EntityUid uid, ShadowkinDarkSwappedComponent component, ComponentShutdown args)
Expand All @@ -80,13 +84,15 @@ private void OnInvisShutdown(EntityUid uid, ShadowkinDarkSwappedComponent compon

if (component.Invisible)
{
SetVisibility(uid, false);
SetVisibility(uid, false, true, true);
SuppressFactions(uid, false);
}

// Prevent more updates while cleaning up
component.Darken = false;

foreach (var light in component.DarkenedLights.ToArray())
// In case more updates occur for some reason. create a copy of the list to prevent error
foreach (var light in component.DarkenedLights.ToList())
{
if (!_entity.TryGetComponent<PointLightComponent>(light, out var pointLight) ||
!_entity.TryGetComponent<ShadowkinLightComponent>(light, out var shadowkinLight))
Expand All @@ -95,6 +101,7 @@ private void OnInvisShutdown(EntityUid uid, ShadowkinDarkSwappedComponent compon
_darken.ResetLight(pointLight, shadowkinLight);
}

// Clear the original list
component.DarkenedLights.Clear();
}

Expand All @@ -103,73 +110,108 @@ private void DarkSwap(EntityUid uid, ShadowkinDarkSwapPowerComponent component,
{
var performer = _entity.GetNetEntity(args.Performer);

// Need power to drain power
if (!_entity.HasComponent<ShadowkinComponent>(args.Performer))
// Need power to drain power
if (!_entity.HasComponent<ShadowkinComponent>(args.Performer)
|| _entity.TryGetComponent<HandcuffComponent>(args.Performer, out var cuff)
&& cuff.AntiShadowkin)
return;

// Don't activate abilities if handcuffed
// TODO: Something like the Psionic Headcage to disable powers for Shadowkin
if (_entity.HasComponent<HandcuffComponent>(args.Performer))
return;


var hasComp = _entity.HasComponent<ShadowkinDarkSwappedComponent>(args.Performer);

if (hasComp)
Darkened(performer, args.StaminaCostOff, args.PowerCostOff, args.SoundOff, args.VolumeOff, args);
else
UnDarkened(performer, args.StaminaCostOn, args.PowerCostOn, args.SoundOn, args.VolumeOn, args);
SetDarkened(performer, !_entity.HasComponent<ShadowkinDarkSwappedComponent>(args.Performer), args.SoundOn,
args.VolumeOn, args.SoundOff, args.VolumeOff, args, args.StaminaCostOn, args.PowerCostOn,
args.StaminaCostOff, args.PowerCostOff);

_magic.Speak(args, false);
}

public void Darkened(NetEntity performer, float staminaCostOff, float powerCostOff, SoundSpecifier soundOff, float volumeOff, ShadowkinDarkSwapEvent? args)

/// <summary>
/// Handles the effects of darkswapping
/// </summary>
/// <param name="performer">The entity being modified</param>
/// <param name="addComp">Is the entity swapping in to or out of The Dark?</param>
/// <param name="soundOn">Sound for the darkswapping</param>
/// <param name="volumeOn">Volume for the on sound</param>
/// <param name="soundOff">Sound for the un swapping</param>
/// <param name="volumeOff">Volume for the off sound</param>
/// <param name="staminaCostOn">Stamina cost for darkswapping</param>
/// <param name="powerCostOn">Power cost for darkswapping</param>
/// <param name="staminaCostOff">Stamina cost for un swapping</param>
/// <param name="powerCostOff">Power cost for un swapping</param>
/// <param name="args">If from an event, handle it</param>
public void SetDarkened(
NetEntity performer,
bool addComp,
SoundSpecifier? soundOn,
float? volumeOn,
SoundSpecifier? soundOff,
float? volumeOff,
ShadowkinDarkSwapEvent? args,
float staminaCostOn = 0,
float powerCostOn = 0,
float staminaCostOff = 0,
float powerCostOff = 0)
{
var performerUid = _entity.GetEntity(performer);
var ent = _entity.GetEntity(performer);

var ev = new ShadowkinDarkSwapAttemptEvent(performerUid);
RaiseLocalEvent(ev);
if (ev.Cancelled)
// We require the power component to DarkSwap
if (!_entity.TryGetComponent<ShadowkinDarkSwapPowerComponent>(ent, out var power))
return;

_entity.RemoveComponent<ShadowkinDarkSwappedComponent>(performerUid);
RaiseNetworkEvent(new ShadowkinDarkSwappedEvent(performer, false));

_audio.PlayPvs(soundOff, performerUid, AudioParams.Default.WithVolume(volumeOff));

_power.TryAddPowerLevel(performerUid, -powerCostOff);
_stamina.TakeStaminaDamage(performerUid, staminaCostOff);

if (args != null)
args.Handled = true;
}

public void UnDarkened(NetEntity performer, float staminaCostOn, float powerCostOn, SoundSpecifier soundOn, float volumeOn, ShadowkinDarkSwapEvent? args)
{
var performerUid = _entity.GetEntity(performer);

var ev = new ShadowkinDarkSwapAttemptEvent(performerUid);
// Ask other systems if we can DarkSwap
var ev = new ShadowkinDarkSwapAttemptEvent(ent);
RaiseLocalEvent(ev);
if (ev.Cancelled)
return;

var comp = _entity.EnsureComponent<ShadowkinDarkSwappedComponent>(performerUid);
comp.Invisible = true;
comp.Pacify = true;
comp.Darken = true;
if (addComp) // Into The Dark
{
// Add the DarkSwapped component and set variables to match the power component
var comp = _entity.EnsureComponent<ShadowkinDarkSwappedComponent>(ent);
comp.Invisible = power.Invisible;
comp.Pacify = power.Pacify;
comp.Darken = power.Darken;
comp.DarkenRange = power.DarkenRange;
comp.DarkenRate = power.DarkenRate;

// Tell other systems we've DarkSwapped
RaiseNetworkEvent(new ShadowkinDarkSwappedEvent(performer, true));

// Play a sound if there is one
if (soundOn != null)
_audio.PlayPvs(soundOn, ent, AudioParams.Default.WithVolume(volumeOn ?? 5f));

// Drain power and stamina if we have a cost
_power.TryAddPowerLevel(ent, -powerCostOn);
_stamina.TakeStaminaDamage(ent, staminaCostOn);
}
else // Out on The Dark
{
// Remove the DarkSwapped component, the rest is handled in the shutdown event
_entity.RemoveComponent<ShadowkinDarkSwappedComponent>(ent);

RaiseNetworkEvent(new ShadowkinDarkSwappedEvent(performer, true));
// Tell other systems we've un DarkSwapped
RaiseNetworkEvent(new ShadowkinDarkSwappedEvent(performer, false));

_audio.PlayPvs(soundOn, performerUid, AudioParams.Default.WithVolume(volumeOn));
// Play a sound if there is one
if (soundOff != null)
_audio.PlayPvs(soundOff, ent, AudioParams.Default.WithVolume(volumeOff ?? 5f));

_power.TryAddPowerLevel(performerUid, -powerCostOn);
_stamina.TakeStaminaDamage(performerUid, staminaCostOn);
// Drain power and stamina if we have a cost
_power.TryAddPowerLevel(ent, -powerCostOff);
_stamina.TakeStaminaDamage(ent, staminaCostOff);
}

// If we have an event, handle it
if (args != null)
args.Handled = true;
}

public void SetVisibility(EntityUid uid, bool set)
public void SetVisibility(EntityUid uid, bool set, bool invisibility, bool stealth)
{
// We require the visibility component for this to work
EnsureComp<VisibilityComponent>(uid);
Expand All @@ -180,29 +222,38 @@ public void SetVisibility(EntityUid uid, bool set)
if (_entity.TryGetComponent(uid, out EyeComponent? eye))
_eye.SetVisibilityMask(uid, eye.VisibilityMask | (int) VisibilityFlags.DarkSwapInvisibility, eye);

// Make other entities unable to see the entity unless also DarkSwapped
_visibility.AddLayer(uid, (ushort) VisibilityFlags.DarkSwapInvisibility, false);
_visibility.RemoveLayer(uid, (ushort) VisibilityFlags.Normal, false);
if (invisibility)
{
// Make other entities unable to see the entity unless also DarkSwapped
_visibility.AddLayer(uid, (ushort) VisibilityFlags.DarkSwapInvisibility, false);
_visibility.RemoveLayer(uid, (ushort) VisibilityFlags.Normal, false);
}
_visibility.RefreshVisibility(uid);

// Add a stealth shader to the entity
if (!_entity.HasComponent<GhostComponent>(uid))
if (!_entity.HasComponent<GhostComponent>(uid) && stealth)
{
_stealth.SetVisibility(uid, 0.8f, _entity.EnsureComponent<StealthComponent>(uid));
_stealth.SetEnabled(uid, true);
}
}
else // Visible
{
// Remove the ability to see DarkSwapped entities
if (_entity.TryGetComponent(uid, out EyeComponent? eye))
_eye.SetVisibilityMask(uid, eye.VisibilityMask & ~(int) VisibilityFlags.DarkSwapInvisibility, eye);

// Make other entities able to see the entity again
_visibility.RemoveLayer(uid, (ushort) VisibilityFlags.DarkSwapInvisibility, false);
_visibility.AddLayer(uid, (ushort) VisibilityFlags.Normal, false);
if (invisibility)
{
// Make other entities able to see the entity again
_visibility.RemoveLayer(uid, (ushort) VisibilityFlags.DarkSwapInvisibility, false);
_visibility.AddLayer(uid, (ushort) VisibilityFlags.Normal, false);
}
_visibility.RefreshVisibility(uid);

// Remove the stealth shader from the entity
if (!_entity.HasComponent<GhostComponent>(uid))
_stealth.SetVisibility(uid, 1f, _entity.EnsureComponent<StealthComponent>(uid));
_stealth.SetEnabled(uid, false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private void Rest(EntityUid uid, ShadowkinRestPowerComponent component, Shadowki
if (_entity.TryGetComponent<SleepingComponent>(uid, out var sleepingComponent))
_actions.RemoveAction(args.Performer, sleepingComponent.WakeAction);

_power.TryAddMultiplier(args.Performer, 1.5f);
_power.TryAddMultiplier(args.Performer, 2f);

// No action cooldown
_actions.ClearCooldown(sleepingComponent?.WakeAction);
Expand All @@ -72,7 +72,7 @@ private void Rest(EntityUid uid, ShadowkinRestPowerComponent component, Shadowki
// Wake up
_entity.RemoveComponent<ForcedSleepingComponent>(args.Performer);
_entity.RemoveComponent<SleepingComponent>(args.Performer);
_power.TryAddMultiplier(args.Performer, -1.5f);
_power.TryAddMultiplier(args.Performer, -2f);

// Action cooldown
args.Handled = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,16 @@ private void Shutdown(EntityUid uid, ShadowkinTeleportPowerComponent component,

private void Teleport(EntityUid uid, ShadowkinTeleportPowerComponent component, ShadowkinTeleportEvent args)
{
// Need power to drain power
if (!_entity.TryGetComponent<ShadowkinComponent>(args.Performer, out var comp))
return;

// Don't activate abilities if handcuffed
// TODO: Something like the Psionic Headcage to disable powers for Shadowkin
if (_entity.HasComponent<HandcuffComponent>(args.Performer))
// Need power to drain power
if (!_entity.TryGetComponent<ShadowkinComponent>(args.Performer, out var comp)
// Don't activate abilities if handcuffed
|| _entity.TryGetComponent<HandcuffComponent>(args.Performer, out var cuff)
&& cuff.AntiShadowkin)
return;


var transform = Transform(args.Performer);
// Must be on the same map
if (transform.MapID != args.Target.GetMapId(EntityManager))
return;

Expand Down Expand Up @@ -98,7 +97,6 @@ private void Teleport(EntityUid uid, ShadowkinTeleportPowerComponent component,
_transform.AttachToGridOrMap(pullable.Owner);

// Resume pulling
// TODO: This does nothing? // This does things sometimes, but the client never knows // This does nothing??
_pulling.TryStartPull(args.Performer, pullable.Owner);
}

Expand Down
Loading

0 comments on commit 9ce2fea

Please sign in to comment.