-
Notifications
You must be signed in to change notification settings - Fork 381
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add hostage ops (Nuke ops alternative objective) (#2545)
* first commit * Some fixes * final fixes * Partly working * More fixes + you can now win * More fixes * Forget * Final fixes * Update the number of hostages to 4 * Add feedback popups * Use mind rolls like a cool person * bruh * NOW I'm mad * Bruh * Signed-off-by: deltanedas <[email protected]> * Signed-off-by: deltanedas <[email protected]> * Bruh I forget --------- Signed-off-by: deltanedas <[email protected]> Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: deltanedas <[email protected]>
- Loading branch information
1 parent
2324562
commit 13ccf59
Showing
29 changed files
with
763 additions
and
6 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using Content.Shared._DV.Antag; | ||
using Content.Shared.Random; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Server._DV.Antag; | ||
|
||
/// <summary> | ||
/// Component holds what operations are possible and their weights. | ||
/// </summary> | ||
[RegisterComponent, Access(typeof(NukieOperationSystem))] | ||
public sealed partial class NukieOperationComponent : Component | ||
{ | ||
/// <summary> | ||
/// The different nukie operations. | ||
/// </summary> | ||
[DataField(required: true)] | ||
public ProtoId<WeightedRandomPrototype> Operations; | ||
|
||
/// <summary> | ||
/// The chosen operation. Is set after the first nukie spawns. | ||
/// </summary> | ||
[DataField] | ||
public ProtoId<NukieOperationPrototype>? ChosenOperation; | ||
} | ||
|
||
/// <summary> | ||
/// Event to get update the nuke code paper to not actually have the code anymore. | ||
/// </summary> | ||
[ByRefEvent] | ||
public record struct GetNukeCodePaperWriting(string? ToWrite); |
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,70 @@ | ||
using Content.Server.Antag; | ||
using Content.Server.Objectives; | ||
using Content.Shared._DV.FeedbackOverwatch; | ||
using Content.Shared.Mind; | ||
using Content.Shared.Random.Helpers; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Random; | ||
|
||
namespace Content.Server._DV.Antag; | ||
|
||
public sealed class NukieOperationSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly IRobustRandom _random = default!; | ||
[Dependency] private readonly SharedMindSystem _mind = default!; | ||
[Dependency] private readonly ObjectivesSystem _objectives = default!; | ||
[Dependency] private readonly IPrototypeManager _proto = default!; | ||
[Dependency] private readonly SharedFeedbackOverwatchSystem _feedback = default!; | ||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<NukieOperationComponent, AfterAntagEntitySelectedEvent>(OnAntagSelected); | ||
SubscribeLocalEvent<GetNukeCodePaperWriting>(OnNukeCodePaperWritingEvent); | ||
} | ||
|
||
private void OnAntagSelected(Entity<NukieOperationComponent> ent, ref AfterAntagEntitySelectedEvent args) | ||
{ | ||
// Yes this is bad, but I couldn't easily find an event that would work. | ||
if (ent.Comp.ChosenOperation == null) | ||
{ | ||
if (!_proto.TryIndex(ent.Comp.Operations, out var opProto)) | ||
return; | ||
|
||
ent.Comp.ChosenOperation = _random.Pick(opProto.Weights); | ||
} | ||
|
||
if (!_mind.TryGetMind(args.Session, out var mindId, out var mind)) | ||
return; | ||
|
||
if (!_proto.TryIndex(ent.Comp.ChosenOperation, out var chosenOp)) | ||
return; | ||
|
||
foreach (var objectiveProto in chosenOp.OperationObjectives) | ||
{ | ||
if (!_objectives.TryCreateObjective((mindId, mind), objectiveProto, out var objective)) | ||
{ | ||
Log.Error("Couldn't create objective for nukie: " + mindId); // This should never happen. | ||
continue; | ||
} | ||
|
||
_mind.AddObjective(mindId, mind, objective.Value); | ||
|
||
// TODO: Remove once enough feedback has been received! | ||
if (objectiveProto.Id == "KidnapHeadsObjective") | ||
_feedback.SendPopupMind(mindId, "NukieHostageRoundStartPopup"); | ||
} | ||
} | ||
|
||
private void OnNukeCodePaperWritingEvent(ref GetNukeCodePaperWriting ev) | ||
{ | ||
// This is suspect AT BEST | ||
var query = EntityQueryEnumerator<NukieOperationComponent>(); | ||
while (query.MoveNext(out _, out var nukieOperation)) // this should only loop once. | ||
{ | ||
if (!_proto.TryIndex(nukieOperation.ChosenOperation, out var opProto) || opProto.NukeCodePaperOverride == null) | ||
continue; | ||
ev.ToWrite = Loc.GetString(opProto.NukeCodePaperOverride); | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
Content.Server/_DV/FeedbackPopup/NukeHostageFeedbackPopupSystem.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,60 @@ | ||
using Content.Server._DV.Objectives.Components; | ||
using Content.Shared._DV.FeedbackOverwatch; | ||
using Content.Shared.GameTicking; | ||
using Content.Shared.Mind; | ||
using Content.Shared.Mobs; | ||
using Content.Shared.Roles; | ||
using Content.Server.Roles; | ||
|
||
namespace Content.Server._DV.FeedbackPopup; | ||
|
||
/// <summary> | ||
/// System to get feedback on the new objective! | ||
/// </summary> | ||
public sealed class NukeHostageFeedbackPopupSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly SharedMindSystem _mind = default!; | ||
[Dependency] private readonly SharedFeedbackOverwatchSystem _feedback = default!; | ||
[Dependency] private readonly SharedRoleSystem _role = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd); | ||
SubscribeLocalEvent<MobStateChangedEvent>(OnMobStateChanged); | ||
} | ||
|
||
private void OnRoundEnd(RoundEndMessageEvent ev) | ||
{ | ||
if (!IsHostageOps()) | ||
return; | ||
|
||
var allMinds = _mind.GetAliveHumans(); | ||
|
||
foreach (var mind in allMinds) | ||
{ | ||
if (mind.Comp.OwnedEntity != null && _role.MindHasRole<NukeopsRoleComponent>(mind)) | ||
_feedback.SendPopupMind(mind, "NukieHostageRoundEndPopup"); | ||
else | ||
_feedback.SendPopupMind(mind, "NukieHostageRoundEndCrewPopup"); | ||
} | ||
} | ||
|
||
private void OnMobStateChanged(MobStateChangedEvent args) | ||
{ | ||
if (args.NewMobState != MobState.Dead || !_mind.TryGetMind(args.Target, out var mindUid, out _) || !IsHostageOps()) | ||
return; | ||
|
||
if (_role.MindHasRole<NukeopsRoleComponent>(mindUid)) | ||
_feedback.SendPopup(args.Target, "NukieHostageRoundEndPopup"); | ||
} | ||
|
||
|
||
/// <remarks> | ||
/// If even one person has the kidnap heads objective this will return true. | ||
/// </remarks> | ||
private bool IsHostageOps() | ||
{ | ||
return EntityQueryEnumerator<KidnapHeadsConditionComponent>().MoveNext(out _); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
Content.Server/_DV/Objectives/Components/KidnapHeadsConditionComponent.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,9 @@ | ||
using Content.Server._DV.Objectives.Systems; | ||
|
||
namespace Content.Server._DV.Objectives.Components; | ||
|
||
/// <summary> | ||
/// Kidnap some number of heads. Use the NumberObjective to set the exact number | ||
/// </summary> | ||
[RegisterComponent, Access(typeof(KidnapHeadsConditionSystem))] | ||
public sealed partial class KidnapHeadsConditionComponent: Component; |
9 changes: 9 additions & 0 deletions
9
Content.Server/_DV/Objectives/Components/NukeStationConditionComponent.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,9 @@ | ||
using Content.Server._DV.Objectives.Systems; | ||
|
||
namespace Content.Server._DV.Objectives.Components; | ||
|
||
/// <summary> | ||
/// For nuclear operatives trying to nuke the station. Should only be completed if the correct station is exploded. | ||
/// </summary> | ||
[RegisterComponent, Access(typeof(NukeStationConditionSystem))] | ||
public sealed partial class NukeStationConditionComponent : Component; |
68 changes: 68 additions & 0 deletions
68
Content.Server/_DV/Objectives/Systems/KidnapHeadsConditionSystem.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,68 @@ | ||
using Content.Server._DV.Objectives.Components; | ||
using Content.Server.Objectives.Systems; | ||
using Content.Server.Revolutionary.Components; | ||
using Content.Shared.Cuffs; | ||
using Content.Shared.Cuffs.Components; | ||
using Content.Shared.Mind; | ||
using Content.Shared.Objectives.Components; | ||
|
||
namespace Content.Server._DV.Objectives.Systems; | ||
|
||
public sealed class KidnapHeadsConditionSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly SharedMindSystem _mind = default!; | ||
[Dependency] private readonly NumberObjectiveSystem _number = default!; | ||
[Dependency] private readonly SharedCuffableSystem _cuffable = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<KidnapHeadsConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress); | ||
} | ||
|
||
private void OnGetProgress(Entity<KidnapHeadsConditionComponent> condition, ref ObjectiveGetProgressEvent args) | ||
{ | ||
args.Progress = GetProgress(condition); | ||
} | ||
|
||
public float GetProgress(Entity<KidnapHeadsConditionComponent> condition) | ||
{ | ||
GetTotalAndCuffedHeads(out var totalHeads, out var cuffedHeads); | ||
|
||
if (totalHeads == 0) | ||
return 1.0f; | ||
|
||
return (float) cuffedHeads / Math.Min(totalHeads, _number.GetTarget(condition)); | ||
} | ||
|
||
public bool IsCompleted(Entity<KidnapHeadsConditionComponent> condition) | ||
{ | ||
GetTotalAndCuffedHeads(out var totalHeads, out var cuffedHeads); | ||
if (totalHeads == 0) | ||
return false; | ||
|
||
return cuffedHeads == Math.Min(totalHeads, _number.GetTarget(condition)); | ||
} | ||
|
||
private void GetTotalAndCuffedHeads(out int totalHeads, out int cuffedHeads) | ||
{ | ||
var allHumanMinds = _mind.GetAliveHumans(); | ||
totalHeads = 0; | ||
cuffedHeads = 0; | ||
foreach (var mind in allHumanMinds) | ||
{ | ||
if (mind.Comp.OwnedEntity is not { } mob) | ||
continue; | ||
|
||
if (!HasComp<CommandStaffComponent>(mob)) | ||
continue; | ||
totalHeads++; | ||
|
||
if (!TryComp<CuffableComponent>(mob, out var cuffable) || !_cuffable.IsCuffed((mob, cuffable))) | ||
continue; | ||
cuffedHeads++; | ||
} | ||
} | ||
} | ||
|
43 changes: 43 additions & 0 deletions
43
Content.Server/_DV/Objectives/Systems/NukeStationConditionSystem.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,43 @@ | ||
using Content.Server._DV.Objectives.Components; | ||
using Content.Server.GameTicking.Rules.Components; | ||
using Content.Server.Nuke; | ||
using Content.Server.Objectives.Systems; | ||
using Content.Server.Station.Components; | ||
using Content.Shared.Objectives.Components; | ||
|
||
namespace Content.Server._DV.Objectives.Systems; | ||
|
||
public sealed class NukeStationConditionSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly CodeConditionSystem _codeCondition = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<NukeExplodedEvent>(OnNukeExploded); | ||
} | ||
|
||
private void OnNukeExploded(NukeExplodedEvent ev) | ||
{ | ||
var nukeOpsQuery = EntityQueryEnumerator<NukeopsRuleComponent>(); | ||
while (nukeOpsQuery.MoveNext(out _, out var nukeopsRule)) // this should only loop once. | ||
{ | ||
if (!TryComp<StationDataComponent>(nukeopsRule.TargetStation, out var data)) | ||
return; | ||
|
||
foreach (var grid in data.Grids) | ||
{ | ||
if (grid != ev.OwningStation) // They nuked the target station! | ||
continue; | ||
|
||
// Set all the objectives to true. | ||
var nukeStationQuery = EntityQueryEnumerator<NukeStationConditionComponent>(); | ||
while (nukeStationQuery.MoveNext(out var uid, out _)) | ||
{ | ||
_codeCondition.SetCompleted(uid); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.