Skip to content

Commit

Permalink
Merge branch 'april-fools-2024' into my-ears
Browse files Browse the repository at this point in the history
  • Loading branch information
VloBoo committed Mar 27, 2024
2 parents 559d5d4 + 9d2c1c4 commit e1ac451
Show file tree
Hide file tree
Showing 116 changed files with 1,389 additions and 252 deletions.
54 changes: 54 additions & 0 deletions Content.Client/LegallyDistinctSpaceFerret/CanBackflipSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Content.Shared.LegallyDistinctSpaceFerret;
using Robust.Client.Animations;
using Robust.Client.Audio;
using Robust.Client.GameObjects;
using Robust.Shared.Animations;
using Robust.Shared.Audio;
using Robust.Shared.Player;

namespace Content.Client.LegallyDistinctSpaceFerret;

public sealed class CanBackflipSystem : EntitySystem
{
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
[Dependency] private readonly AudioSystem _audio = default!;

public const string BackflipKey = "backflip";

public override void Initialize()
{
base.Initialize();

SubscribeNetworkEvent<DoABackFlipEvent>(OnBackflipEvent);
}

public void OnBackflipEvent(DoABackFlipEvent args)
{
if (!TryGetEntity(args.Actioner, out var uid))
{
return;
}

_animation.Play(uid.Value, new Animation
{
Length = TimeSpan.FromSeconds(0.66),
AnimationTracks =
{
new AnimationTrackComponentProperty()
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Rotation),
InterpolationMode = AnimationInterpolationMode.Linear,
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(0), 0f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(180), 0.33f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(360), 0.33f),
}
}
}
}, BackflipKey);

_audio.PlayEntity(new SoundPathSpecifier(args.SfxSource), Filter.Local(), uid.Value, false);
}
}
31 changes: 31 additions & 0 deletions Content.Client/LegallyDistinctSpaceFerret/CanHibernateSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Content.Shared.LegallyDistinctSpaceFerret;
using Robust.Client.Audio;
using Robust.Client.GameObjects;
using Robust.Shared.Audio;

namespace Content.Client.LegallyDistinctSpaceFerret;

public sealed class CanHibernateSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();

SubscribeNetworkEvent<EntityHasHibernated>(OnHibernateEvent);
}

public void OnHibernateEvent(EntityHasHibernated args)
{
if (!TryGetEntity(args.Hibernator, out var uid))
{
return;
}

if (!TryComp<SpriteComponent>(uid, out var comp))
{
return;
}

comp.LayerSetState(0, args.SpriteStateId);
}
}
7 changes: 7 additions & 0 deletions Content.Server/Interaction/InteractionPopupSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@

namespace Content.Server.Interaction;

public sealed class InteractionAttemptFailed(EntityUid target)
{
public EntityUid Target = target;
}

public sealed class InteractionPopupSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
Expand Down Expand Up @@ -96,6 +101,8 @@ private void SharedInteract(

if (component.InteractFailureSpawn != null)
Spawn(component.InteractFailureSpawn, _transform.GetMapCoordinates(uid));

RaiseLocalEvent(target, new InteractionAttemptFailed(target));
}

if (component.MessagePerceivedByOthers != null)
Expand Down
154 changes: 154 additions & 0 deletions Content.Server/LegallyDistinctSpaceFerret/BrainrotSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System.Threading;
using Content.Server.Popups;
using Content.Server.Speech;
using Content.Shared.LegallyDistinctSpaceFerret;
using Content.Shared.Mind;
using Content.Shared.Physics;
using Robust.Shared.Physics.Collision.Shapes;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Random;
using Timer = Robust.Shared.Timing.Timer;

namespace Content.Server.LegallyDistinctSpaceFerret;

/// <summary>
/// Raised locally when a mind gets too close to a Brainrot-causer.
/// </summary>
/// <param name="target">Who got brainrot</param>
/// <param name="cause">Who caused brainrot</param>
/// <param name="time">How long will they have it for</param>
public struct EntityGivenBrainrotEvent(EntityUid target, EntityUid cause, float time)
{
public EntityUid Cause = cause;
public EntityUid Target = target;
public float Time = time;
}

/// <summary>
/// Raised locally when a mind is freed from brainrot
/// </summary>
/// <param name="target">Who had brainrot</param>
public struct EntityLostBrainrotEvent(EntityUid target)
{
public EntityUid Target = target;
}

public sealed class BrainrotSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly FixtureSystem _fixtures = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;

public const string BrainrotFixture = "brainrot";
public const string BrainRotApplied = "brainrot-applied";
public const string BrainRotLost = "brainrot-lost";
public readonly string[] BrainRotReplacementStrings =
[
"brainrot-replacement-1",
"brainrot-replacement-2",
"brainrot-replacement-3",
"brainrot-replacement-4",
"brainrot-replacement-5",
"brainrot-replacement-6"
];

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<BrainrotAuraComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<BrainrotAuraComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<BrainrotAuraComponent, StartCollideEvent>(OnCollide);
SubscribeLocalEvent<EntityGivenBrainrotEvent>(EntityGivenBrainrot);
SubscribeLocalEvent<EntityLostBrainrotEvent>(EntityLostBrainrot);
SubscribeLocalEvent<BrainrotComponent, AccentGetEvent>(ApplyBrainRot);
}

private void OnStartup(EntityUid uid, BrainrotAuraComponent component, ComponentStartup args)
{
if (!TryComp<PhysicsComponent>(uid, out var body))
return;

var shape = new PhysShapeCircle(component.Range);

_fixtures.TryCreateFixture(uid, shape, BrainrotFixture, collisionLayer: (int) CollisionGroup.MobMask, hard: false, body: body);
}

private void OnShutdown(EntityUid uid, BrainrotAuraComponent component, ComponentShutdown args)
{
if (!TryComp<PhysicsComponent>(uid, out var body) ||
MetaData(uid).EntityLifeStage >= EntityLifeStage.Terminating)
{
return;
}

_fixtures.DestroyFixture(uid, BrainrotFixture, body: body);
}

private void OnCollide(EntityUid uid, BrainrotAuraComponent component, ref StartCollideEvent args)
{
// No effect if the mob is mindless
if (!_mind.TryGetMind(args.OtherEntity, out _, out _))
{
return;
}

// No effect if the mob has brainrot or causes brainrot
if (HasComp<BrainrotAuraComponent>(args.OtherEntity) || HasComp<BrainrotComponent>(args.OtherEntity))
{
return;
}

RaiseLocalEvent(new EntityGivenBrainrotEvent(args.OtherEntity, uid, component.Time));
}

private void EntityGivenBrainrot(EntityGivenBrainrotEvent args)
{
if (TryComp<BrainrotComponent>(args.Target, out var comp))
{
comp.Duration += args.Time;
}
else
{
comp = EnsureComp<BrainrotComponent>(args.Target);
}

var cancel = new CancellationTokenSource();

Timer.Spawn(TimeSpan.FromSeconds(comp.Duration), () =>
{
comp.Duration -= args.Time;
if (comp.Duration <= 0.0f)
{
RaiseLocalEvent(new EntityLostBrainrotEvent(args.Target));
}
}, cancel.Token);

comp.Cancels.Add(cancel);

_popup.PopupEntity(Loc.GetString(BrainRotApplied), args.Target, args.Target);
}

private void EntityLostBrainrot(EntityLostBrainrotEvent args)
{
if (TryComp<BrainrotComponent>(args.Target, out var comp))
{
foreach (var cancel in comp.Cancels)
{
cancel.Cancel();
}
}

RemComp<BrainrotComponent>(args.Target);
_popup.PopupEntity(Loc.GetString(BrainRotLost), args.Target, args.Target);
}

private void ApplyBrainRot(EntityUid entity, BrainrotComponent comp, AccentGetEvent args)
{
args.Message = Loc.GetString(_random.Pick(BrainRotReplacementStrings));
}
}
29 changes: 29 additions & 0 deletions Content.Server/LegallyDistinctSpaceFerret/CanBackflipSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Content.Server.Actions;
using Content.Shared.LegallyDistinctSpaceFerret;

namespace Content.Server.LegallyDistinctSpaceFerret;

public sealed class CanBackflipSystem : EntitySystem
{
[Dependency] private readonly ActionsSystem _actions = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<CanBackflipComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<CanBackflipComponent, BackflipActionEvent>(OnBackflipAction);
}

private void OnInit(EntityUid uid, CanBackflipComponent component, MapInitEvent args)
{
_actions.AddAction(uid, ref component.BackflipActionEntity, component.BackflipAction, uid);
}

public void OnBackflipAction(EntityUid uid, CanBackflipComponent comp, BackflipActionEvent args)
{
RaiseNetworkEvent(new DoABackFlipEvent(GetNetEntity(uid), comp.ClappaSfx));

args.Handled = true;
}
}
86 changes: 86 additions & 0 deletions Content.Server/LegallyDistinctSpaceFerret/CanHibernateSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Content.Server.Actions;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.GameTicking;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Popups;
using Content.Shared.Interaction.Components;
using Content.Shared.LegallyDistinctSpaceFerret;
using Content.Shared.Mind;
using Content.Shared.NPC;
using Content.Shared.Popups;
using Robust.Server.Audio;
using Robust.Shared.Audio;

namespace Content.Server.LegallyDistinctSpaceFerret;

public sealed class CanHibernateSystem : EntitySystem
{
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly GameTicker _ticker = default!;
[Dependency] private readonly AudioSystem _audio = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<CanHibernateComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<CanHibernateComponent, EepyActionEvent>(OnEepyAction);
}

private void OnInit(EntityUid uid, CanHibernateComponent component, MapInitEvent args)
{
_actions.AddAction(uid, ref component.EepyActionEntity, component.EepyAction, uid);
}

public void OnEepyAction(EntityUid uid, CanHibernateComponent comp, EepyActionEvent args)
{
// If you require food before hibernating, assert that this condition has been fulfilled.
if (_mind.TryGetObjectiveComp<ConsumeNutrientsConditionComponent>(uid, out var nutrientsCondition) && nutrientsCondition.NutrientsConsumed / nutrientsCondition.NutrientsRequired < 1.0)
{
_popup.PopupEntity(Loc.GetString(comp.NotEnoughNutrientsMessage), uid, PopupType.SmallCaution);

return;
}

// Assert that you're near a hibernation point (scrubbers)
var scrubbers = _lookup.GetEntitiesInRange<GasVentScrubberComponent>(Transform(uid).Coordinates, 2f);
if (scrubbers.Count <= 0)
{
_popup.PopupEntity(Loc.GetString(comp.TooFarFromHibernationSpot), uid, PopupType.SmallCaution);

return;
}

if (_mind.TryGetObjectiveComp<HibernateConditionComponent>(uid, out var hibernateCondition))
{
_audio.PlayPvs(new SoundPathSpecifier(hibernateCondition.SuccessSfx), uid);
_popup.PopupEntity(Loc.GetString(hibernateCondition.SuccessMessage), uid, PopupType.Large);
hibernateCondition.Hibernated = true;
}

// Kick player out
var mind = _mind.GetMind(uid);
if (mind != null)
{
_ticker.OnGhostAttempt(mind.Value, false);
}

// End ghost-role
AddComp<BlockMovementComponent>(uid);
RemComp<ActiveNPCComponent>(uid);
RemComp<GhostTakeoverAvailableComponent>(uid);

// Notify
RaiseNetworkEvent(new EntityHasHibernated(GetNetEntity(uid), comp.SpriteStateId));

args.Handled = true;
}
}

public struct EntityHibernateAttemptSuccessEvent(EntityUid entity)
{
public EntityUid Entity = entity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Content.Shared.LegallyDistinctSpaceFerret;
using Content.Shared.Objectives.Components;

namespace Content.Server.LegallyDistinctSpaceFerret;

public sealed class ConsumeNutrientsObjectiveSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<ConsumeNutrientsConditionComponent, ObjectiveGetProgressEvent>(OnConsumeNutrientsGetProgress);
}

private static void OnConsumeNutrientsGetProgress(EntityUid uid, ConsumeNutrientsConditionComponent comp, ref ObjectiveGetProgressEvent args)
{
args.Progress = comp.NutrientsConsumed / comp.NutrientsRequired;
}
}
Loading

0 comments on commit e1ac451

Please sign in to comment.