diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs
index 2dbe908ea4..d563fe2b1d 100644
--- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs
+++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs
@@ -193,7 +193,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem
var difficulty = 0f;
for (var pick = 0; pick < maxPicks && maxDifficulty > difficulty; pick++)
{
- var objective = _objectivesManager.GetRandomObjective(traitorRole.Mind);
+ var objective = _objectivesManager.GetRandomObjective(traitorRole.Mind, "TraitorObjectiveGroups");
if (objective == null) continue;
if (traitorRole.Mind.TryAddObjective(objective))
difficulty += objective.Difficulty;
diff --git a/Content.Server/Objectives/Interfaces/IObjectivesManager.cs b/Content.Server/Objectives/Interfaces/IObjectivesManager.cs
index 57b36675c1..bee98bc80b 100644
--- a/Content.Server/Objectives/Interfaces/IObjectivesManager.cs
+++ b/Content.Server/Objectives/Interfaces/IObjectivesManager.cs
@@ -2,14 +2,9 @@
{
public interface IObjectivesManager
{
- ///
- /// Returns all objectives the provided mind is valid for.
- ///
- IEnumerable GetAllPossibleObjectives(Mind.Mind mind);
-
///
/// Returns a randomly picked objective the provided mind is valid for.
///
- ObjectivePrototype? GetRandomObjective(Mind.Mind mind);
+ ObjectivePrototype? GetRandomObjective(Mind.Mind mind, string objectiveGroupProto);
}
}
diff --git a/Content.Server/Objectives/ObjectivePrototype.cs b/Content.Server/Objectives/ObjectivePrototype.cs
index 5cc7aa6f10..d9ee76c207 100644
--- a/Content.Server/Objectives/ObjectivePrototype.cs
+++ b/Content.Server/Objectives/ObjectivePrototype.cs
@@ -4,6 +4,9 @@ using Robust.Shared.Prototypes;
namespace Content.Server.Objectives
{
+ ///
+ /// Prototype for objectives. Remember that to be assigned, it should be added to one or more objective groups in prototype. E.g. crew, traitor, wizard
+ ///
[Prototype("objective")]
public sealed class ObjectivePrototype : IPrototype
{
@@ -13,8 +16,6 @@ namespace Content.Server.Objectives
[DataField("issuer")] public string Issuer { get; private set; } = "Unknown";
- [DataField("prob")] public float Probability { get; private set; } = 0.3f;
-
[ViewVariables]
public float Difficulty => _difficultyOverride ?? _conditions.Sum(c => c.Difficulty);
diff --git a/Content.Server/Objectives/ObjectivesManager.cs b/Content.Server/Objectives/ObjectivesManager.cs
index ff3e72ad2a..11563f9934 100644
--- a/Content.Server/Objectives/ObjectivesManager.cs
+++ b/Content.Server/Objectives/ObjectivesManager.cs
@@ -1,5 +1,6 @@
-using System.Linq;
-using Content.Server.Objectives.Interfaces;
+using Content.Server.Objectives.Interfaces;
+using Content.Shared.Random.Helpers;
+using Content.Shared.Random;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@@ -10,21 +11,31 @@ namespace Content.Server.Objectives
[Dependency] private IPrototypeManager _prototypeManager = default!;
[Dependency] private IRobustRandom _random = default!;
- public IEnumerable GetAllPossibleObjectives(Mind.Mind mind)
+ public ObjectivePrototype? GetRandomObjective(Mind.Mind mind, string objectiveGroupProto)
{
- return _prototypeManager.EnumeratePrototypes().Where(objectivePrototype => objectivePrototype.CanBeAssigned(mind));
- }
-
- public ObjectivePrototype? GetRandomObjective(Mind.Mind mind)
- {
- var objectives = GetAllPossibleObjectives(mind).ToList();
- _random.Shuffle(objectives);
-
- //to prevent endless loops
- foreach (var objective in objectives)
+ if (!_prototypeManager.TryIndex(objectiveGroupProto, out var groups))
{
- if (!_random.Prob(objective.Probability)) continue;
- return objective;
+ Logger.Error("Tried to get a random objective, but can't index WeightedRandomPrototype " + objectiveGroupProto);
+ return null;
+ }
+
+ // yeah the old 'preventing infinite loops' thing wasn't super elegant either and it mislead people on what exactly it did
+ var tries = 0;
+ while (tries < 20)
+ {
+ var groupName = groups.Pick(_random);
+
+ if (!_prototypeManager.TryIndex(groupName, out var group))
+ {
+ Logger.Error("Couldn't index objective group prototype" + groupName);
+ return null;
+ }
+
+ if (_prototypeManager.TryIndex(group.Pick(_random), out var objective)
+ && objective.CanBeAssigned(mind))
+ return objective;
+ else
+ tries++;
}
return null;
diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml
new file mode 100644
index 0000000000..e4a6b0907d
--- /dev/null
+++ b/Resources/Prototypes/Objectives/objectiveGroups.yml
@@ -0,0 +1,41 @@
+# Traitor
+- type: weightedRandom
+ id: TraitorObjectiveGroups
+ weights:
+ TraitorObjectiveGroupSteal: 1
+ TraitorObjectiveGroupKill: 1
+ TraitorObjectiveGroupState: 1 #As in, something about your character. Alive, dead, arrested, gained an ability...
+ TraitorObjectiveGroupSocial: 1 #Involves helping/harming others without killing them or stealing their stuff
+
+- type: weightedRandom
+ id: TraitorObjectiveGroupSteal
+ weights:
+ CaptainIDStealObjective: 1
+ CMOHyposprayStealObjective: 1
+ RDHardsuitStealObjective: 1
+ NukeDiskStealObjective: 1
+ IDComputerBoardStealObjective: 1
+ MagbootsStealObjective: 1
+ SupplyConsoleBoardStealObjective: 1
+ CorgiMeatStealObjective: 1
+ CaptainGunStealObjective: 0.5
+ CaptainJetpackStealObjective: 0.5
+
+- type: weightedRandom
+ id: TraitorObjectiveGroupKill
+ weights:
+ KillRandomObjective: 1
+
+- type: weightedRandom
+ id: TraitorObjectiveGroupState
+ weights:
+ EscapeShuttleObjective: 1
+ DieObjective: 0.05
+
+- type: weightedRandom
+ id: TraitorObjectiveGroupSocial
+ weights:
+ RandomTraitorAliveObjective: 1
+ RandomTraitorProgressObjective: 1
+
+#Changeling, crew, wizard, when you code it...
diff --git a/Resources/Prototypes/Objectives/traitorObjectives.yml b/Resources/Prototypes/Objectives/traitorObjectives.yml
index 1258d12047..9946a2e2ac 100644
--- a/Resources/Prototypes/Objectives/traitorObjectives.yml
+++ b/Resources/Prototypes/Objectives/traitorObjectives.yml
@@ -2,7 +2,6 @@
id: CaptainIDStealObjective
issuer: syndicate
difficultyOverride: 2.75
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -42,7 +41,6 @@
- type: objective
id: DieObjective
issuer: syndicate
- prob: 0.03
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -56,7 +54,6 @@
id: CMOHyposprayStealObjective
issuer: syndicate
difficultyOverride: 2.75
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -73,7 +70,6 @@
id: RDHardsuitStealObjective
issuer: syndicate
difficultyOverride: 2.75
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -89,7 +85,6 @@
- type: objective
id: NukeDiskStealObjective
issuer: syndicate
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -116,7 +111,6 @@
- type: objective
id: IDComputerBoardStealObjective
issuer: syndicate
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -133,7 +127,6 @@
id: MagbootsStealObjective
issuer: syndicate
difficultyOverride: 2.75
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -149,7 +142,6 @@
- type: objective
id: SupplyConsoleBoardStealObjective
issuer: syndicate
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -165,7 +157,6 @@
- type: objective
id: CorgiMeatStealObjective
issuer: syndicate
- prob: 0.2
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -182,7 +173,6 @@
id: CaptainGunStealObjective
issuer: syndicate
difficultyOverride: 2.75
- prob: 0.1
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement
@@ -199,7 +189,6 @@
id: CaptainJetpackStealObjective
issuer: syndicate
difficultyOverride: 2.75
- prob: 0.1
requirements:
- !type:TraitorRequirement {}
- !type:IncompatibleConditionsRequirement