From a06ea58249889febd1268d9a67397636d69bae57 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sat, 25 May 2024 20:14:48 +0000 Subject: [PATCH] antag objective issuing refactor (#28216) * add AntagObjectives from GenericAntag * add AntagRandomObjectives that traitor and thief can use * make ObjectivesSystem use initial character name which AntagSelection passes * make thief and traitor use AntagRandomObjectives * remove now unused locale * make sleeper agents rule use baseTraitorRule * restore dragon rule oop * bandaid for genericantag * real * typo --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- Content.Server/Antag/AntagObjectivesSystem.cs | 35 +++++++++++++ .../Antag/AntagRandomObjectivesSystem.cs | 52 +++++++++++++++++++ .../Antag/AntagSelectionSystem.API.cs | 2 +- Content.Server/Antag/AntagSelectionSystem.cs | 12 +++++ .../Components/AntagObjectivesComponent.cs | 18 +++++++ .../AntagRandomObjectivesComponent.cs | 52 +++++++++++++++++++ .../Components/AntagSelectionComponent.cs | 7 +++ .../Rules/Components/ThiefRuleComponent.cs | 21 +------- .../Rules/Components/TraitorRuleComponent.cs | 6 --- .../Rules/GenericAntagRuleSystem.cs | 5 +- .../GameTicking/Rules/ThiefRuleSystem.cs | 39 -------------- .../GameTicking/Rules/TraitorRuleSystem.cs | 30 ++--------- Content.Server/Objectives/ObjectivesSystem.cs | 51 ++++++------------ .../Locale/en-US/objectives/round-end.ftl | 1 - Resources/Prototypes/GameRules/events.yml | 5 +- Resources/Prototypes/GameRules/midround.yml | 23 ++++---- Resources/Prototypes/GameRules/roundstart.yml | 18 ++++++- .../Prototypes/Objectives/objectiveGroups.yml | 7 --- 18 files changed, 231 insertions(+), 153 deletions(-) create mode 100644 Content.Server/Antag/AntagObjectivesSystem.cs create mode 100644 Content.Server/Antag/AntagRandomObjectivesSystem.cs create mode 100644 Content.Server/Antag/Components/AntagObjectivesComponent.cs create mode 100644 Content.Server/Antag/Components/AntagRandomObjectivesComponent.cs diff --git a/Content.Server/Antag/AntagObjectivesSystem.cs b/Content.Server/Antag/AntagObjectivesSystem.cs new file mode 100644 index 0000000000..5aa31f66f6 --- /dev/null +++ b/Content.Server/Antag/AntagObjectivesSystem.cs @@ -0,0 +1,35 @@ +using Content.Server.Antag.Components; +using Content.Server.Objectives; +using Content.Shared.Mind; +using Content.Shared.Objectives.Systems; + +namespace Content.Server.Antag; + +/// +/// Adds fixed objectives to an antag made with AntagObjectivesComponent. +/// +public sealed class AntagObjectivesSystem : EntitySystem +{ + [Dependency] private readonly SharedMindSystem _mind = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAntagSelected); + } + + private void OnAntagSelected(Entity ent, ref AfterAntagEntitySelectedEvent args) + { + if (!_mind.TryGetMind(args.Session, out var mindId, out var mind)) + { + Log.Error($"Antag {ToPrettyString(args.EntityUid):player} was selected by {ToPrettyString(ent):rule} but had no mind attached!"); + return; + } + + foreach (var id in ent.Comp.Objectives) + { + _mind.TryAddObjective(mindId, mind, id); + } + } +} diff --git a/Content.Server/Antag/AntagRandomObjectivesSystem.cs b/Content.Server/Antag/AntagRandomObjectivesSystem.cs new file mode 100644 index 0000000000..c935b8c064 --- /dev/null +++ b/Content.Server/Antag/AntagRandomObjectivesSystem.cs @@ -0,0 +1,52 @@ +using Content.Server.Antag.Components; +using Content.Server.Objectives; +using Content.Shared.Mind; +using Content.Shared.Objectives.Components; +using Content.Shared.Objectives.Systems; +using Robust.Shared.Random; + +namespace Content.Server.Antag; + +/// +/// Adds fixed objectives to an antag made with AntagRandomObjectivesComponent. +/// +public sealed class AntagRandomObjectivesSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedMindSystem _mind = default!; + [Dependency] private readonly ObjectivesSystem _objectives = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAntagSelected); + } + + private void OnAntagSelected(Entity ent, ref AfterAntagEntitySelectedEvent args) + { + if (!_mind.TryGetMind(args.Session, out var mindId, out var mind)) + { + Log.Error($"Antag {ToPrettyString(args.EntityUid):player} was selected by {ToPrettyString(ent):rule} but had no mind attached!"); + return; + } + + var difficulty = 0f; + foreach (var set in ent.Comp.Sets) + { + if (!_random.Prob(set.Prob)) + continue; + + for (var pick = 0; pick < set.MaxPicks && ent.Comp.MaxDifficulty > difficulty; pick++) + { + if (_objectives.GetRandomObjective(mindId, mind, set.Groups) is not {} objective) + continue; + + _mind.AddObjective(mindId, mind, objective); + var adding = Comp(objective).Difficulty; + difficulty += adding; + Log.Debug($"Added objective {ToPrettyString(objective):objective} to {ToPrettyString(args.EntityUid):player} with {adding} difficulty"); + } + } + } +} diff --git a/Content.Server/Antag/AntagSelectionSystem.API.cs b/Content.Server/Antag/AntagSelectionSystem.API.cs index 6acd17a35b..d8554e3fb2 100644 --- a/Content.Server/Antag/AntagSelectionSystem.API.cs +++ b/Content.Server/Antag/AntagSelectionSystem.API.cs @@ -124,7 +124,7 @@ public sealed partial class AntagSelectionSystem } /// - /// Helper specifically for + /// Helper to get just the mind entities and not names. /// public List GetAntagMindEntityUids(Entity ent) { diff --git a/Content.Server/Antag/AntagSelectionSystem.cs b/Content.Server/Antag/AntagSelectionSystem.cs index 57df82d6fd..1d1783ed87 100644 --- a/Content.Server/Antag/AntagSelectionSystem.cs +++ b/Content.Server/Antag/AntagSelectionSystem.cs @@ -7,6 +7,7 @@ using Content.Server.GameTicking.Rules; using Content.Server.Ghost.Roles; using Content.Server.Ghost.Roles.Components; using Content.Server.Mind; +using Content.Server.Objectives; using Content.Server.Preferences.Managers; using Content.Server.Roles; using Content.Server.Roles.Jobs; @@ -50,6 +51,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem(OnTakeGhostRole); + SubscribeLocalEvent(OnObjectivesTextGetInfo); + SubscribeLocalEvent(OnPlayerSpawning); SubscribeLocalEvent(OnJobsAssigned); SubscribeLocalEvent(OnSpawnComplete); @@ -423,6 +426,15 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem ent, ref ObjectivesTextGetInfoEvent args) + { + if (ent.Comp.AgentName is not {} name) + return; + + args.Minds = ent.Comp.SelectedMinds; + args.AgentName = Loc.GetString(name); + } } /// diff --git a/Content.Server/Antag/Components/AntagObjectivesComponent.cs b/Content.Server/Antag/Components/AntagObjectivesComponent.cs new file mode 100644 index 0000000000..357c138f46 --- /dev/null +++ b/Content.Server/Antag/Components/AntagObjectivesComponent.cs @@ -0,0 +1,18 @@ +using Content.Server.Antag; +using Content.Shared.Objectives.Components; +using Robust.Shared.Prototypes; + +namespace Content.Server.Antag.Components; + +/// +/// Gives antags selected by this rule a fixed list of objectives. +/// +[RegisterComponent, Access(typeof(AntagObjectivesSystem))] +public sealed partial class AntagObjectivesComponent : Component +{ + /// + /// List of static objectives to give. + /// + [DataField(required: true)] + public List> Objectives = new(); +} diff --git a/Content.Server/Antag/Components/AntagRandomObjectivesComponent.cs b/Content.Server/Antag/Components/AntagRandomObjectivesComponent.cs new file mode 100644 index 0000000000..9a551acc49 --- /dev/null +++ b/Content.Server/Antag/Components/AntagRandomObjectivesComponent.cs @@ -0,0 +1,52 @@ +using Content.Server.Antag; +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Server.Antag.Components; + +/// +/// Gives antags selected by this rule a random list of objectives. +/// +[RegisterComponent, Access(typeof(AntagRandomObjectivesSystem))] +public sealed partial class AntagRandomObjectivesComponent : Component +{ + /// + /// Each set of objectives to add. + /// + [DataField(required: true)] + public List Sets = new(); + + /// + /// If the total difficulty of the currently given objectives exceeds, no more will be given. + /// + [DataField(required: true)] + public float MaxDifficulty; +} + +/// +/// A set of objectives to try picking. +/// Difficulty is checked over all sets, but each set has its own probability and pick count. +/// +[DataRecord] +public record struct AntagObjectiveSet() +{ + /// + /// The grouping used by the objective system to pick random objectives. + /// First a group is picked from these, then an objective from that group. + /// + [DataField(required: true)] + public ProtoId Groups = string.Empty; + + /// + /// Probability of this set being used. + /// + [DataField] + public float Prob = 1f; + + /// + /// Number of times to try picking objectives from this set. + /// Even if there is enough difficulty remaining, no more will be given after this. + /// + [DataField] + public int MaxPicks = 20; +} diff --git a/Content.Server/Antag/Components/AntagSelectionComponent.cs b/Content.Server/Antag/Components/AntagSelectionComponent.cs index 096be14049..3464ee5666 100644 --- a/Content.Server/Antag/Components/AntagSelectionComponent.cs +++ b/Content.Server/Antag/Components/AntagSelectionComponent.cs @@ -42,6 +42,13 @@ public sealed partial class AntagSelectionComponent : Component /// Is not serialized. /// public HashSet SelectedSessions = new(); + + /// + /// Locale id for the name of the antag. + /// If this is set then the antag is listed in the round-end summary. + /// + [DataField] + public LocId? AgentName; } [DataDefinition] diff --git a/Content.Server/GameTicking/Rules/Components/ThiefRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/ThiefRuleComponent.cs index 01a078625a..6ad1e17775 100644 --- a/Content.Server/GameTicking/Rules/Components/ThiefRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/ThiefRuleComponent.cs @@ -8,23 +8,4 @@ namespace Content.Server.GameTicking.Rules.Components; /// Stores data for . /// [RegisterComponent, Access(typeof(ThiefRuleSystem))] -public sealed partial class ThiefRuleComponent : Component -{ - [DataField] - public ProtoId BigObjectiveGroup = "ThiefBigObjectiveGroups"; - - [DataField] - public ProtoId SmallObjectiveGroup = "ThiefObjectiveGroups"; - - [DataField] - public ProtoId EscapeObjectiveGroup = "ThiefEscapeObjectiveGroups"; - - [DataField] - public float BigObjectiveChance = 0.7f; - - [DataField] - public float MaxObjectiveDifficulty = 2.5f; - - [DataField] - public int MaxStealObjectives = 10; -} +public sealed partial class ThiefRuleComponent : Component; diff --git a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs index b85019d8af..62f92963aa 100644 --- a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs @@ -22,9 +22,6 @@ public sealed partial class TraitorRuleComponent : Component [DataField] public ProtoId SyndicateFaction = "Syndicate"; - [DataField] - public ProtoId ObjectiveGroup = "TraitorObjectiveGroups"; - [DataField] public ProtoId CodewordAdjectives = "adjectives"; @@ -72,7 +69,4 @@ public sealed partial class TraitorRuleComponent : Component /// [DataField] public int StartingBalance = 20; - - [DataField] - public int MaxDifficulty = 5; } diff --git a/Content.Server/GameTicking/Rules/GenericAntagRuleSystem.cs b/Content.Server/GameTicking/Rules/GenericAntagRuleSystem.cs index 81bdda706b..0367aa1460 100644 --- a/Content.Server/GameTicking/Rules/GenericAntagRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/GenericAntagRuleSystem.cs @@ -1,6 +1,8 @@ using Content.Server.GameTicking.Rules.Components; using Content.Server.Objectives; +using Content.Shared.Mind; using System.Diagnostics.CodeAnalysis; +using System.Linq; namespace Content.Server.GameTicking.Rules; @@ -47,7 +49,8 @@ public sealed class GenericAntagRuleSystem : GameRuleSystem (mindId, Comp(mindId).CharacterName ?? "?")).ToList(); args.AgentName = Loc.GetString(comp.AgentName); } } diff --git a/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs b/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs index 083085fa0d..faec4a9e9c 100644 --- a/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs @@ -24,7 +24,6 @@ public sealed class ThiefRuleSystem : GameRuleSystem SubscribeLocalEvent(AfterAntagSelected); SubscribeLocalEvent(OnGetBriefing); - SubscribeLocalEvent(OnObjectivesTextGetInfo); } private void AfterAntagSelected(Entity ent, ref AfterAntagEntitySelectedEvent args) @@ -33,41 +32,9 @@ public sealed class ThiefRuleSystem : GameRuleSystem return; //Generate objectives - GenerateObjectives(mindId, mind, ent); _antag.SendBriefing(args.EntityUid, MakeBriefing(args.EntityUid), null, null); } - private void GenerateObjectives(EntityUid mindId, MindComponent mind, ThiefRuleComponent thiefRule) - { - // Give thieves their objectives - var difficulty = 0f; - - if (_random.Prob(thiefRule.BigObjectiveChance)) // 70% chance to 1 big objective (structure or animal) - { - var objective = _objectives.GetRandomObjective(mindId, mind, thiefRule.BigObjectiveGroup); - if (objective != null) - { - _mindSystem.AddObjective(mindId, mind, objective.Value); - difficulty += Comp(objective.Value).Difficulty; - } - } - - for (var i = 0; i < thiefRule.MaxStealObjectives && thiefRule.MaxObjectiveDifficulty > difficulty; i++) // Many small objectives - { - var objective = _objectives.GetRandomObjective(mindId, mind, thiefRule.SmallObjectiveGroup); - if (objective == null) - continue; - - _mindSystem.AddObjective(mindId, mind, objective.Value); - difficulty += Comp(objective.Value).Difficulty; - } - - //Escape target - var escapeObjective = _objectives.GetRandomObjective(mindId, mind, thiefRule.EscapeObjectiveGroup); - if (escapeObjective != null) - _mindSystem.AddObjective(mindId, mind, escapeObjective.Value); - } - //Add mind briefing private void OnGetBriefing(Entity thief, ref GetBriefingEvent args) { @@ -87,10 +54,4 @@ public sealed class ThiefRuleSystem : GameRuleSystem briefing += "\n \n" + Loc.GetString("thief-role-greeting-equipment") + "\n"; return briefing; } - - private void OnObjectivesTextGetInfo(Entity ent, ref ObjectivesTextGetInfoEvent args) - { - args.Minds = _antag.GetAntagMindEntityUids(ent.Owner); - args.AgentName = Loc.GetString("thief-round-end-agent-name"); - } } diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 1c894a460c..29de85a42e 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -31,15 +31,12 @@ public sealed class TraitorRuleSystem : GameRuleSystem [Dependency] private readonly SharedJobSystem _jobs = default!; [Dependency] private readonly ObjectivesSystem _objectives = default!; - public const int MaxPicks = 20; - public override void Initialize() { base.Initialize(); SubscribeLocalEvent(AfterEntitySelected); - SubscribeLocalEvent(OnObjectivesTextGetInfo); SubscribeLocalEvent(OnObjectivesTextPrepend); } @@ -67,7 +64,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem } } - public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool giveUplink = true, bool giveObjectives = true) + public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool giveUplink = true) { //Grab the mind if it wasnt provided if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind)) @@ -112,37 +109,16 @@ public sealed class TraitorRuleSystem : GameRuleSystem _npcFaction.RemoveFaction(traitor, component.NanoTrasenFaction, false); _npcFaction.AddFaction(traitor, component.SyndicateFaction); - // Give traitors their objectives - if (giveObjectives) - { - var difficulty = 0f; - for (var pick = 0; pick < MaxPicks && component.MaxDifficulty > difficulty; pick++) - { - var objective = _objectives.GetRandomObjective(mindId, mind, component.ObjectiveGroup); - if (objective == null) - continue; - - _mindSystem.AddObjective(mindId, mind, objective.Value); - var adding = Comp(objective.Value).Difficulty; - difficulty += adding; - Log.Debug($"Added objective {ToPrettyString(objective):objective} with {adding} difficulty"); - } - } - return true; } - private void OnObjectivesTextGetInfo(EntityUid uid, TraitorRuleComponent comp, ref ObjectivesTextGetInfoEvent args) - { - args.Minds = _antag.GetAntagMindEntityUids(uid); - args.AgentName = Loc.GetString("traitor-round-end-agent-name"); - } - + // TODO: AntagCodewordsComponent private void OnObjectivesTextPrepend(EntityUid uid, TraitorRuleComponent comp, ref ObjectivesTextPrependEvent args) { args.Text += "\n" + Loc.GetString("traitor-round-end-codewords", ("codewords", string.Join(", ", comp.Codewords))); } + // TODO: figure out how to handle this? add priority to briefing event? private string GenerateBriefing(string[] codewords, Note[]? uplinkCode, string? objectiveIssuer = null) { var sb = new StringBuilder(); diff --git a/Content.Server/Objectives/ObjectivesSystem.cs b/Content.Server/Objectives/ObjectivesSystem.cs index 47fe4eb5f8..f8ecc22828 100644 --- a/Content.Server/Objectives/ObjectivesSystem.cs +++ b/Content.Server/Objectives/ObjectivesSystem.cs @@ -36,14 +36,14 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem private void OnRoundEndText(RoundEndTextAppendEvent ev) { // go through each gamerule getting data for the roundend summary. - var summaries = new Dictionary>>(); + var summaries = new Dictionary>>(); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var gameRule)) { if (!_gameTicker.IsGameRuleAdded(uid, gameRule)) continue; - var info = new ObjectivesTextGetInfoEvent(new List(), string.Empty); + var info = new ObjectivesTextGetInfoEvent(new List<(EntityUid, string)>(), string.Empty); RaiseLocalEvent(uid, ref info); if (info.Minds.Count == 0) continue; @@ -51,7 +51,7 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem // first group the gamerules by their agents, for example 2 different dragons var agent = info.AgentName; if (!summaries.ContainsKey(agent)) - summaries[agent] = new Dictionary>(); + summaries[agent] = new Dictionary>(); var prepend = new ObjectivesTextPrependEvent(""); RaiseLocalEvent(uid, ref prepend); @@ -79,7 +79,7 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem foreach (var (_, minds) in summary) { total += minds.Count; - totalInCustody += minds.Where(m => IsInCustody(m)).Count(); + totalInCustody += minds.Where(pair => IsInCustody(pair.Item1)).Count(); } var result = new StringBuilder(); @@ -104,19 +104,16 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem } } - private void AddSummary(StringBuilder result, string agent, List minds) + private void AddSummary(StringBuilder result, string agent, List<(EntityUid, string)> minds) { var agentSummaries = new List<(string summary, float successRate, int completedObjectives)>(); - foreach (var mindId in minds) + foreach (var (mindId, name) in minds) { - if (!TryComp(mindId, out MindComponent? mind)) - continue; - - var title = GetTitle(mindId, mind); - if (title == null) + if (!TryComp(mindId, out var mind)) continue; + var title = GetTitle((mindId, mind), name); var custody = IsInCustody(mindId, mind) ? Loc.GetString("objectives-in-custody") : string.Empty; var objectives = mind.Objectives; @@ -238,34 +235,18 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem /// /// Get the title for a player's mind used in round end. + /// Pass in the original entity name which is shown alongside username. /// - public string? GetTitle(EntityUid mindId, MindComponent? mind = null) + public string GetTitle(Entity mind, string name) { - if (!Resolve(mindId, ref mind)) - return null; - - var name = mind.CharacterName; - var username = (string?) null; - - if (mind.OriginalOwnerUserId != null && - _player.TryGetPlayerData(mind.OriginalOwnerUserId.Value, out var sessionData)) + if (Resolve(mind, ref mind.Comp) && + mind.Comp.OriginalOwnerUserId != null && + _player.TryGetPlayerData(mind.Comp.OriginalOwnerUserId.Value, out var sessionData)) { - username = sessionData.UserName; + var username = sessionData.UserName; + return Loc.GetString("objectives-player-user-named", ("user", username), ("name", name)); } - - if (username != null) - { - if (name != null) - return Loc.GetString("objectives-player-user-named", ("user", username), ("name", name)); - - return Loc.GetString("objectives-player-user", ("user", username)); - } - - // nothing to identify the player by, just give up - if (name == null) - return null; - return Loc.GetString("objectives-player-named", ("name", name)); } } @@ -279,7 +260,7 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem /// The objectives system already checks if the game rule is added so you don't need to check that in this event's handler. /// [ByRefEvent] -public record struct ObjectivesTextGetInfoEvent(List Minds, string AgentName); +public record struct ObjectivesTextGetInfoEvent(List<(EntityUid, string)> Minds, string AgentName); /// /// Raised on the game rule before text for each agent's objectives is added, letting you prepend something. diff --git a/Resources/Locale/en-US/objectives/round-end.ftl b/Resources/Locale/en-US/objectives/round-end.ftl index b4314b2caf..3da81fc964 100644 --- a/Resources/Locale/en-US/objectives/round-end.ftl +++ b/Resources/Locale/en-US/objectives/round-end.ftl @@ -6,7 +6,6 @@ objectives-round-end-result = {$count -> objectives-round-end-result-in-custody = {$custody} out of {$count} {MAKEPLURAL($agent)} were in custody. objectives-player-user-named = [color=White]{$name}[/color] ([color=gray]{$user}[/color]) -objectives-player-user = [color=gray]{$user}[/color] objectives-player-named = [color=White]{$name}[/color] objectives-no-objectives = {$custody}{$title} was a {$agent}. diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 3b9ad5aadf..593122eee5 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -428,9 +428,9 @@ prototype: Nukeops - type: entity - id: SleeperAgentsRule - parent: BaseGameRule noSpawn: true + parent: BaseTraitorRule + id: SleeperAgentsRule components: - type: StationEvent earliestStart: 30 @@ -441,7 +441,6 @@ startAudio: path: /Audio/Announcements/intercept.ogg - type: AlertLevelInterceptionRule - - type: TraitorRule - type: AntagSelection definitions: - prefRoles: [ Traitor ] diff --git a/Resources/Prototypes/GameRules/midround.yml b/Resources/Prototypes/GameRules/midround.yml index 5a4cde3101..1b58ada648 100644 --- a/Resources/Prototypes/GameRules/midround.yml +++ b/Resources/Prototypes/GameRules/midround.yml @@ -35,7 +35,19 @@ id: Thief components: - type: ThiefRule + - type: AntagObjectives + objectives: + - EscapeThiefShuttleObjective + - type: AntagRandomObjectives + sets: + - groups: ThiefBigObjectiveGroups + prob: 0.7 + maxPicks: 1 + - groups: ThiefObjectiveGroups + maxPicks: 10 + maxDifficulty: 2.5 - type: AntagSelection + agentName: thief-round-end-agent-name definitions: - prefRoles: [ Thief ] maxRange: @@ -53,14 +65,3 @@ prototype: Thief briefing: sound: "/Audio/Misc/thief_greeting.ogg" - -#- type: entity -# noSpawn: true -# parent: BaseGameRule -# id: Exterminator -# components: -# - type: GenericAntagRule -# agentName: terminator-round-end-agent-name -# objectives: -# - TerminateObjective -# - ShutDownObjective diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index d87e7ccbe7..be5f617c8d 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -134,16 +134,30 @@ prototype: Nukeops - type: entity - id: Traitor + abstract: true parent: BaseGameRule + id: BaseTraitorRule + components: + - type: TraitorRule + # TODO: codewords in yml + # TODO: uplink in yml + - type: AntagRandomObjectives + sets: + - groups: TraitorObjectiveGroups + maxDifficulty: 5 + - type: AntagSelection + agentName: traitor-round-end-agent-name + +- type: entity noSpawn: true + parent: BaseTraitorRule + id: Traitor components: - type: GameRule minPlayers: 5 delay: min: 240 max: 420 - - type: TraitorRule - type: AntagSelection definitions: - prefRoles: [ Traitor ] diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index ff126eb5d1..bb74c92da3 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -55,13 +55,6 @@ ThiefObjectiveGroupStructure: 0 #Temporarily disabled until obvious ways to steal structures are added ThiefObjectiveGroupAnimal: 2 -- type: weightedRandom - id: ThiefEscapeObjectiveGroups - weights: - ThiefObjectiveGroupEscape: 1 - - - - type: weightedRandom id: ThiefObjectiveGroupCollection weights: