Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Content.Server/Ghost/GhostSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Content.Server.GameTicking;
using Content.Server.Mind;
using Content.Server.Roles.Jobs;
using Content.Shared._ES.Changeling; // ES Change
using Content.Shared.Actions;
using Content.Shared.CCVar;
using Content.Shared.Damage;
Expand Down Expand Up @@ -535,6 +536,15 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma
// Pass in the whole mind entity
var handleEv = new GhostAttemptHandleEvent((mindId, mind), canReturnGlobal);
RaiseLocalEvent(mindId, handleEv);

if (playerEntity != null)
{
var entityCancelEv = new ESGhostAttemptEvent(mindId);
RaiseLocalEvent(playerEntity.Value, ref entityCancelEv);

if (entityCancelEv.Cancelled)
return false;
}
// ES END

// Something else has handled the ghost attempt for us! We return its result.
Expand Down
28 changes: 28 additions & 0 deletions Content.Server/_ES/Changeling/ESChangelingDevourSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Content.Server.Polymorph.Systems;
using Content.Shared.Changeling;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;

namespace Content.Server._ES.Changeling;

public sealed class ESChangelingDevourSystem : EntitySystem
{
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly PolymorphSystem _polymorph = default!;

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

SubscribeLocalEvent<MobStateComponent, ESEntityDevouredEvent>(OnDevoured);
}

public void OnDevoured(EntityUid uid, MobStateComponent component, ref ESEntityDevouredEvent args)
{
if (_mobState.IsDead(uid))
{
_polymorph.PolymorphEntity(uid, args.HuskProto);
}
}

}
7 changes: 7 additions & 0 deletions Content.Server/_ES/Radstorm/ESRadstormConditionComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Content.Server._ES.Radstorm;

[RegisterComponent]
public sealed partial class ESRadstormObjectiveComponent : Component
{

}
7 changes: 7 additions & 0 deletions Content.Server/_ES/Radstorm/ESRadstormImmuneComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Content.Server._ES.Radstorm;

[RegisterComponent]
public sealed partial class ESRadstormImmuneComponent : Component
{

}
31 changes: 28 additions & 3 deletions Content.Server/_ES/Radstorm/ESRadstormRoundEndRuleSystem.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Content.Server._ES.Objectives;
using Content.Server._ES.Radio;
using Content.Server.Chat.Systems;
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.RoundEnd;
using Content.Shared._ES.CCVar;
using Content.Shared._ES.Objectives.Components;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
Expand Down Expand Up @@ -37,6 +39,7 @@ public sealed class ESRadstormRoundEndRuleSystem : GameRuleSystem<ESRadstormRoun
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly ESObjectiveSystem _objective = default!;

protected override void Started(EntityUid uid,
ESRadstormRoundEndRuleComponent component,
Expand All @@ -47,19 +50,34 @@ protected override void Started(EntityUid uid,
if (component.RadstormStartTime != TimeSpan.Zero)
return;

var randomMins = _random.NextGaussian(component.RadstormStartTimeAvg.TotalMinutes, component.RadstormStartTimeStdDev.TotalMinutes);
var randomMins = _random.NextGaussian(component.RadstormStartTimeAvg.TotalMinutes,
component.RadstormStartTimeStdDev.TotalMinutes);

// account for arrivals time
if (_cfg.GetCVar(ESCVars.ESArrivalsEnabled))
randomMins += (_cfg.GetCVar(ESCVars.ESArrivalsFTLTime) / 60f);

// round to nearest minute
randomMins = Math.Round(randomMins);
}


public override void Initialize()
{
SubscribeLocalEvent<ESRadstormObjectiveComponent, ESGetObjectiveProgressEvent>(OnGetObjectiveProgress);
}

component.RadstormStartTime = _timing.CurTime + TimeSpan.FromMinutes(randomMins);
Log.Info($"Picked {randomMins} minutes into the round as the start time for the radstorm.");
private void OnGetObjectiveProgress(Entity<ESRadstormObjectiveComponent> ent, ref ESGetObjectiveProgressEvent args)
{
foreach (var comp in EntityQuery<ESRadstormRoundEndRuleComponent>())
{
// Might be a bit shitty logic but from my testing it works fine I think
args.Progress = (float)(_timing.CurTime / comp.RadstormStartTime);
return;
}
}


protected override void ActiveTick(EntityUid uid, ESRadstormRoundEndRuleComponent component, GameRuleComponent gameRule, float frameTime)
{
base.ActiveTick(uid, component, gameRule, frameTime);
Expand Down Expand Up @@ -87,6 +105,9 @@ protected override void ActiveTick(EntityUid uid, ESRadstormRoundEndRuleComponen
if (state.CurrentState == MobState.Dead)
continue;

if (HasComp<ESRadstormImmuneComponent>(mob))
return;

// if they're not in space (i.e. not parented to the map)
// and we haven't technically started yet, that means we're only space-dangerous, so don't hurt them
if (xform.ParentUid != mapUid && _timing.CurTime < component.RadstormStartTime)
Expand All @@ -98,6 +119,8 @@ protected override void ActiveTick(EntityUid uid, ESRadstormRoundEndRuleComponen
stillAlive += 1;
}

_objective.RefreshObjectiveProgress<ESRadstormObjectiveComponent>();

// show is over
// (make sure we only actually do this if after time and not just deadly space)
// (i kind of implemented that in a weird way huh)
Expand Down Expand Up @@ -164,6 +187,8 @@ private void DoPhase(ESRadstormRoundEndRuleComponent comp, ESRadstormPhaseConfig
if (phase.SpaceDangerous)
comp.SpaceDangerous = true;

_objective.RefreshObjectiveProgress<ESRadstormObjectiveComponent>();

phase.Completed = true;
}
}
28 changes: 26 additions & 2 deletions Content.Shared/Changeling/ChangelingDevourEvents.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
using Content.Shared.Actions;
using Content.Shared.DoAfter;
using Content.Shared.Polymorph;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared.Changeling;

/// <summary>
/// Action event for Devour, someone has initiated a devour on someone, begin to windup.
/// </summary>
public sealed partial class ChangelingDevourActionEvent : EntityTargetActionEvent;
public sealed partial class ChangelingDevourActionEvent : EntityTargetActionEvent
// ES Start
{
[DataField]
public bool RequireIncapacitated;
}
// ES End

/// <summary>
/// A windup has either successfully been completed or has been canceled. If successful start the devouring DoAfter.
Expand All @@ -19,4 +27,20 @@ public sealed partial class ChangelingDevourWindupDoAfterEvent : SimpleDoAfterEv
/// The Consumption DoAfter has either successfully been completed or was canceled.
/// </summary>
[Serializable, NetSerializable]
public sealed partial class ChangelingDevourConsumeDoAfterEvent : SimpleDoAfterEvent;
public sealed partial class ChangelingDevourConsumeDoAfterEvent : SimpleDoAfterEvent
// ES Start
{
[DataField]
public bool DoHusk;
}

/// <summary>
/// Raised on the person devoured
/// </summary>
[ByRefEvent]
public record struct ESEntityDevouredEvent()
{
[DataField]
public ProtoId<PolymorphPrototype> HuskProto = "HuskPolymorph";
}
// ES End
13 changes: 13 additions & 0 deletions Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ private void OnDevourAction(Entity<ChangelingDevourComponent> ent, ref Changelin
return;
}

// ES Start - adds option to require a target to be crit or dead before devouring, unsure why you were just able to devour live things anyway
if (args.RequireIncapacitated && !_mobState.IsIncapacitated(args.Target))
{
_popupSystem.PopupClient(Loc.GetString("changeling-devour-attempt-failed-incapacitated"), ent, ent, PopupType.Medium);
return;
}
// ES end

if (_net.IsServer)
{
var pvsSound = _audio.PlayPvs(ent.Comp.DevourWindupNoise, ent);
Expand Down Expand Up @@ -260,6 +268,11 @@ private void OnDevourConsume(Entity<ChangelingDevourComponent> ent, ref Changeli
RipClothing(target.Value, (item.Value, butcherable));
}

// ES Start
var ev = new ESEntityDevouredEvent();
RaiseLocalEvent((EntityUid)args.Target!, ref ev);
// ES End

Dirty(ent);
}

Expand Down
14 changes: 12 additions & 2 deletions Content.Shared/Roles/Components/ChangelingRoleComponent.cs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't show the line I was trying to show, it's "ActionExistStasis"

Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
using Robust.Shared.GameStates;
using Content.Shared.Actions.Components;
using Robust.Shared.GameStates;

namespace Content.Shared.Roles.Components;

/// <summary>
/// Added to mind role entities to tag that they are a changeling.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class ChangelingRoleComponent : BaseMindRoleComponent;
public sealed partial class ChangelingRoleComponent : BaseMindRoleComponent
// ES Start
{
[DataField]
public string? StatisAction = "ActionExistStatis";

[DataField]
public EntityUid? StatisActionEntity;
}

13 changes: 13 additions & 0 deletions Content.Shared/_ES/Actions/ESRandomActionGrantComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Content.Shared.EntityTable.EntitySelectors;

namespace Content.Shared._ES.Actions;

[RegisterComponent]
public sealed partial class ESRandomActionGrantComponent : Component
{
/// <summary>
/// The objectives that this troupe gives to its members
/// </summary>
[DataField]
public EntityTableSelector Actions = new NoneSelector();
}
27 changes: 27 additions & 0 deletions Content.Shared/_ES/Actions/RandomActionGrantSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Content.Shared.Actions;
using Content.Shared.EntityTable;

namespace Content.Shared._ES.Actions;

public sealed class RandomActionGrantSystem : EntitySystem
{
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly EntityTableSystem _entityTable = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ESRandomActionGrantComponent, MapInitEvent>(OnMapInit);
}

private void OnMapInit(Entity<ESRandomActionGrantComponent> ent, ref MapInitEvent args)
{
var Actions = _entityTable.GetSpawns(ent.Comp.Actions);

foreach (var action in Actions)
{
EntityUid? actionEnt = null;
_actions.AddAction(ent.Owner, ref actionEnt, action);
}
}
}
12 changes: 12 additions & 0 deletions Content.Shared/_ES/Masks/Changeling/ChemicalStingEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Content.Shared.Actions;

namespace Content.Shared._ES.Changeling;

public sealed partial class ESChemicalStingEvent : EntityTargetActionEvent
{
/// <summary>
/// Name of the solution to draw the injection chems from (what will be injected)
/// </summary>
[DataField]
public string SolutionName = "Injector";
}
29 changes: 29 additions & 0 deletions Content.Shared/_ES/Masks/Changeling/ChemicalStingSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Content.Shared.Chemistry.EntitySystems;

namespace Content.Shared._ES.Changeling;

public sealed class ChemicalStingSystem : EntitySystem
{
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;

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

SubscribeLocalEvent<ESChemicalStingEvent>(OnChemicalInjection);
}

private void OnChemicalInjection(ESChemicalStingEvent args)
{
if (args.Handled)
return;

if (!_solutionContainer.TryGetSolution(args.Action.Owner, args.SolutionName, out _, out var solution) ||
!_solutionContainer.TryGetInjectableSolution(args.Target, out var targetSolution, out _))
return;

_solutionContainer.AddSolution(targetSolution.Value, solution);

args.Handled = true;
}
}
14 changes: 14 additions & 0 deletions Content.Shared/_ES/Masks/Changeling/ESChangelingStatisEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Content.Shared.Actions;

namespace Content.Shared._ES.Changeling;

public sealed partial class ESChangelingStatisEvent : InstantActionEvent
{
}

/// <summary>
/// Raised on an entity when Its mind is attempting to ghost out.
/// </summary>
[ByRefEvent]
public record struct ESGhostAttemptEvent(EntityUid Mind, bool Cancelled = false);

Loading
Loading