From 2ca649edfa4963215919f3fc4dc621899cd8c595 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Mon, 25 Dec 2023 01:20:55 +0000 Subject: [PATCH] add limits to steal objectives (#22672) * add ObjectiveLimit comp/system * give ian and disk limits * all * up limit --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Components/ObjectiveLimitComponent.cs | 20 ++++++ .../Systems/ObjectiveLimitSystem.cs | 64 +++++++++++++++++++ Resources/Prototypes/Objectives/traitor.yml | 4 ++ 3 files changed, 88 insertions(+) create mode 100644 Content.Server/Objectives/Components/ObjectiveLimitComponent.cs create mode 100644 Content.Server/Objectives/Systems/ObjectiveLimitSystem.cs diff --git a/Content.Server/Objectives/Components/ObjectiveLimitComponent.cs b/Content.Server/Objectives/Components/ObjectiveLimitComponent.cs new file mode 100644 index 0000000000..c94a60ed1b --- /dev/null +++ b/Content.Server/Objectives/Components/ObjectiveLimitComponent.cs @@ -0,0 +1,20 @@ +using Content.Server.Objectives.Systems; + +namespace Content.Server.Objectives.Components; + +/// +/// Limits the number of traitors that can have the same objective. +/// Checked by the prototype id, so only considers the exact same objectives. +/// +/// +/// Only works for traitors so don't use for anything else. +/// +[RegisterComponent, Access(typeof(ObjectiveLimitSystem))] +public sealed partial class ObjectiveLimitComponent : Component +{ + /// + /// Max number of players + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public uint Limit; +} diff --git a/Content.Server/Objectives/Systems/ObjectiveLimitSystem.cs b/Content.Server/Objectives/Systems/ObjectiveLimitSystem.cs new file mode 100644 index 0000000000..0102304668 --- /dev/null +++ b/Content.Server/Objectives/Systems/ObjectiveLimitSystem.cs @@ -0,0 +1,64 @@ +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Objectives.Components; +using Content.Shared.Mind; +using Content.Shared.Objectives.Components; + +public sealed class ObjectiveLimitSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnCheck); + } + + private void OnCheck(Entity ent, ref RequirementCheckEvent args) + { + if (args.Cancelled) + return; + + if (Prototype(ent)?.ID is not {} proto) + { + Log.Error($"ObjectiveLimit used for non-prototyped objective {ent}"); + return; + } + + var remaining = ent.Comp.Limit; + // all traitor rules are considered + // maybe this would interfere with multistation stuff in the future but eh + foreach (var rule in EntityQuery()) + { + foreach (var mindId in rule.TraitorMinds) + { + if (mindId == args.MindId || !HasObjective(mindId, proto)) + continue; + + remaining--; + + // limit has been reached, prevent adding the objective + if (remaining == 0) + { + args.Cancelled = true; + return; + } + } + } + } + + /// + /// Returns true if the mind has an objective of a certain prototype. + /// + public bool HasObjective(EntityUid mindId, string proto, MindComponent? mind = null) + { + if (!Resolve(mindId, ref mind)) + return false; + + foreach (var objective in mind.AllObjectives) + { + if (Prototype(objective)?.ID == proto) + return true; + } + + return false; + } +} diff --git a/Resources/Prototypes/Objectives/traitor.yml b/Resources/Prototypes/Objectives/traitor.yml index 4684e2d343..f4530e0168 100644 --- a/Resources/Prototypes/Objectives/traitor.yml +++ b/Resources/Prototypes/Objectives/traitor.yml @@ -30,6 +30,8 @@ verifyMapExistance: false - type: Objective difficulty: 2.75 + - type: ObjectiveLimit + limit: 2 # there is usually only 1 of each steal objective, have 2 max for drama # state @@ -226,6 +228,8 @@ components: - type: NotJobRequirement job: HeadOfPersonnel + - type: ObjectiveLimit + limit: 3 # ian only has 2 slices, 3 obj for drama - type: StealCondition stealGroup: FoodMeatCorgi owner: objective-condition-steal-Ian -- 2.51.2