Skip to content

Commit

Permalink
traitor flavor
Browse files Browse the repository at this point in the history
  • Loading branch information
whateverusername0 authored and TokenStyle committed Oct 31, 2024
1 parent c90af7f commit e94e2a8
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ public sealed partial class TraitorRuleComponent : Component
public ProtoId<DatasetPrototype> CodewordVerbs = "verbs";

[DataField]
public ProtoId<DatasetPrototype> ObjectiveIssuers = "TraitorCorporations";
public ProtoId<DatasetPrototype> ObjectiveIssuers = "TraitorFlavor";

public int TotalTraitors => TraitorMinds.Count;
public string[] Codewords = new string[3];
public string ObjectiveIssuer = string.Empty;

public enum SelectionState
{
Expand Down
53 changes: 43 additions & 10 deletions Content.Server/GameTicking/Rules/TraitorRuleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public override void Initialize()

SubscribeLocalEvent<TraitorRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);

SubscribeLocalEvent<TraitorRuleComponent, ObjectivesTextGetInfoEvent>(OnObjectivesTextGetInfo, after: new[] { typeof(AntagSelectionSystem) });
SubscribeLocalEvent<TraitorRuleComponent, ObjectivesTextPrependEvent>(OnObjectivesTextPrepend);
}

Expand Down Expand Up @@ -82,6 +83,7 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool

var briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", component.Codewords)));
var issuer = _random.Pick(_prototypeManager.Index(component.ObjectiveIssuers).Values);
component.ObjectiveIssuer = issuer;

Note[]? code = null;
if (giveUplink)
Expand All @@ -99,21 +101,17 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool

// Give traitors their codewords and uplink code to keep in their character info menu
code = EnsureComp<RingerUplinkComponent>(pda.Value).Code;

// If giveUplink is false the uplink code part is omitted
briefing = string.Format("{0}\n{1}", briefing,
Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", code).Replace("sharp", "#"))));
}

_antag.SendBriefing(traitor, GenerateBriefing(component.Codewords, code, issuer), null, component.GreetSoundNotification);
_antag.SendBriefing(traitor, GenerateBriefing(component.Codewords, code, issuer), Color.Crimson, component.GreetSoundNotification);


component.TraitorMinds.Add(mindId);

// Assign briefing
_roleSystem.MindAddRole(mindId, new RoleBriefingComponent
{
Briefing = briefing
Briefing = GenerateBriefingCharacter(component.Codewords, code, issuer)
}, mind, true);

// Send codewords to only the traitor client
Expand All @@ -129,20 +127,55 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool
return true;
}

private void OnObjectivesTextGetInfo(EntityUid uid, TraitorRuleComponent comp, ref ObjectivesTextGetInfoEvent args)
{
args.AgentName = Loc.GetString($"traitor-{comp.ObjectiveIssuer}-roundend");
args.Faction = 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)
private string GenerateBriefing(string[] codewords, Note[]? uplinkCode, string objectiveIssuer)
{
var sb = new StringBuilder();
sb.AppendLine("\n" + Loc.GetString($"traitor-{objectiveIssuer}-intro"));

if (uplinkCode != null)
{
sb.AppendLine("\n" + Loc.GetString($"traitor-{objectiveIssuer}-uplink"));
sb.AppendLine(Loc.GetString($"traitor-role-uplink-code", ("code", string.Join("-", uplinkCode).Replace("sharp", "#"))));
}
else sb.AppendLine("\n" + Loc.GetString($"traitor-role-nouplink"));

sb.AppendLine("\n" + Loc.GetString($"traitor-role-codewords", ("codewords", string.Join(", ", codewords))));

sb.AppendLine("\n" + Loc.GetString($"traitor-role-moreinfo"));

return sb.ToString();
}
private string GenerateBriefingCharacter(string[] codewords, Note[]? uplinkCode, string objectiveIssuer)
{
var sb = new StringBuilder();
sb.AppendLine(Loc.GetString("traitor-role-greeting", ("corporation", objectiveIssuer ?? Loc.GetString("objective-issuer-unknown"))));
sb.AppendLine(Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords))));
sb.AppendLine("\n" + Loc.GetString($"traitor-{objectiveIssuer}-intro"));

if (uplinkCode != null)
sb.AppendLine(Loc.GetString("traitor-role-uplink-code", ("code", string.Join("-", uplinkCode).Replace("sharp", "#"))));
sb.AppendLine(Loc.GetString($"traitor-role-uplink-code-short", ("code", string.Join("-", uplinkCode).Replace("sharp", "#"))));
else sb.AppendLine("\n" + Loc.GetString($"traitor-role-nouplink"));

sb.AppendLine(Loc.GetString($"traitor-role-codewords-short", ("codewords", string.Join(", ", codewords))));

sb.AppendLine("\n" + Loc.GetString($"traitor-role-allegiances"));
sb.AppendLine(Loc.GetString($"traitor-{objectiveIssuer}-allies"));

sb.AppendLine("\n" + Loc.GetString($"traitor-role-notes"));
sb.AppendLine(Loc.GetString($"traitor-{objectiveIssuer}-goal"));

sb.AppendLine("\n" + Loc.GetString($"traitor-role-clarity"));

return sb.ToString();
}
Expand Down
69 changes: 38 additions & 31 deletions Content.Server/Objectives/ObjectivesSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override void Shutdown()
private void OnRoundEndText(RoundEndTextAppendEvent ev)
{
// go through each gamerule getting data for the roundend summary.
var summaries = new Dictionary<string, Dictionary<string, List<(EntityUid, string)>>>();
var summaries = new Dictionary<string, Dictionary<string, Dictionary<string, List<(EntityUid, string)>>>>();
var query = EntityQueryEnumerator<GameRuleComponent>();
while (query.MoveNext(out var uid, out var gameRule))
{
Expand All @@ -64,17 +64,21 @@ private void OnRoundEndText(RoundEndTextAppendEvent ev)
if (info.Minds.Count == 0)
continue;

// first group the gamerules by their agents, for example 2 different dragons
var agent = info.AgentName;
// first group the gamerules by their factions, for example 2 different dragons
var agent = info.Faction ?? info.AgentName;
if (!summaries.ContainsKey(agent))
summaries[agent] = new Dictionary<string, List<(EntityUid, string)>>();
summaries[agent] = new Dictionary<string, Dictionary<string, List<(EntityUid, string)>>>();

// next group them by agent names, for example different traitors, blood brother teams, etc.
if (!summaries[agent].ContainsKey(info.AgentName))
summaries[agent][info.AgentName] = new Dictionary<string, List<(EntityUid, string)>>();

var prepend = new ObjectivesTextPrependEvent("");
RaiseLocalEvent(uid, ref prepend);

// next group them by their prepended texts
// for example with traitor rule, group them by the codewords they share
var summary = summaries[agent];
var summary = summaries[agent][info.AgentName];
if (summary.ContainsKey(prepend.Text))
{
// same prepended text (usually empty) so combine them
Expand All @@ -87,36 +91,39 @@ private void OnRoundEndText(RoundEndTextAppendEvent ev)
}

// convert the data into summary text
foreach (var (agent, summary) in summaries)
foreach (var (faction, summariesFaction) in summaries)
{
// first get the total number of players that were in these game rules combined
var total = 0;
var totalInCustody = 0;
foreach (var (_, minds) in summary)
foreach (var (agent, summary) in summariesFaction)
{
total += minds.Count;
totalInCustody += minds.Where(pair => IsInCustody(pair.Item1)).Count();
}
// first get the total number of players that were in these game rules combined
var total = 0;
var totalInCustody = 0;
foreach (var (_, minds) in summary)
{
total += minds.Count;
totalInCustody += minds.Where(m => IsInCustody(m.Item1)).Count();
}

var result = new StringBuilder();
result.AppendLine(Loc.GetString("objectives-round-end-result", ("count", total), ("agent", agent)));
if (agent == Loc.GetString("traitor-round-end-agent-name"))
{
result.AppendLine(Loc.GetString("objectives-round-end-result-in-custody", ("count", total), ("custody", totalInCustody), ("agent", agent)));
}
// next add all the players with its own prepended text
foreach (var (prepend, minds) in summary)
{
if (prepend != string.Empty)
result.Append(prepend);
var result = new StringBuilder();
result.AppendLine(Loc.GetString("objectives-round-end-result", ("count", total), ("agent", faction)));
if (agent == Loc.GetString("traitor-round-end-agent-name"))
{
result.AppendLine(Loc.GetString("objectives-round-end-result-in-custody", ("count", total), ("custody", totalInCustody), ("agent", faction)));
}
// next add all the players with its own prepended text
foreach (var (prepend, minds) in summary)
{
if (prepend != string.Empty)
result.Append(prepend);

// add space between the start text and player list
result.AppendLine();
// add space between the start text and player list
result.AppendLine();

AddSummary(result, agent, minds);
}
AddSummary(result, agent, minds);
}

ev.AddLine(result.AppendLine().ToString());
ev.AddLine(result.AppendLine().ToString());
}
}
}

Expand Down Expand Up @@ -252,7 +259,7 @@ private bool IsInCustody(EntityUid mindId, MindComponent? mind = null)
/// Get the title for a player's mind used in round end.
/// Pass in the original entity name which is shown alongside username.
/// </summary>
public string GetTitle(Entity<MindComponent?> mind, string name)
public string GetTitle(Entity<MindComponent?> mind, string name = "")
{
if (Resolve(mind, ref mind.Comp) &&
mind.Comp.OriginalOwnerUserId != null &&
Expand Down Expand Up @@ -306,7 +313,7 @@ private void CreateCompletions()
/// The objectives system already checks if the game rule is added so you don't need to check that in this event's handler.
/// </remarks>
[ByRefEvent]
public record struct ObjectivesTextGetInfoEvent(List<(EntityUid, string)> Minds, string AgentName);
public record struct ObjectivesTextGetInfoEvent(List<(EntityUid, string)> Minds, string AgentName, string? Faction = null);

/// <summary>
/// Raised on the game rule before text for each agent's objectives is added, letting you prepend something.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ traitor-death-match-end-round-description-entry = {$originalName}'s PDA, with {$
## TraitorRole

# TraitorRole
traitor-role-greeting =
You are an agent sent by {$corporation} on behalf of [color = darkred]The Syndicate.[/color]
Your objectives and codewords are listed in the character menu.
Use the uplink loaded into your PDA to buy the tools you'll need for this mission.
Death to Nanotrasen!
traitor-role-codewords =
The codewords are: [color = lightgray]
{$codewords}.[/color]
Expand All @@ -37,6 +32,21 @@ traitor-role-uplink-code =
Set your ringtone to the notes [color = lightgray]{$code}[/color] to lock or unlock your uplink.
Remember to lock it after, or the stations crew will easily open it too!
traitor-role-moreinfo =
Find more information about your role in the character menu.
traitor-role-nouplink =
You do not have a syndicate uplink. Make it count.
traitor-role-allegiances =
Your allegiances:
traitor-role-notes =
Notes from your employer:
traitor-role-clarity =
Allegiances and additional notes are recommendations. You do not have to strictly follow them.
# don't need all the flavour text for character menu
traitor-role-codewords-short =
The codewords are:
Expand Down
4 changes: 2 additions & 2 deletions Resources/Locale/en-US/objectives/round-end.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ objectives-round-end-result-in-custody = {$custody} out of {$count} {MAKEPLURAL(
objectives-player-user-named = [color=White]{$name}[/color] ([color=gray]{$user}[/color])
objectives-player-named = [color=White]{$name}[/color]
objectives-no-objectives = {$custody}{$title} was a {$agent}.
objectives-with-objectives = {$custody}{$title} was a {$agent} who had the following objectives:
objectives-no-objectives = {$custody}{$title} was {$agent}.
objectives-with-objectives = {$custody}{$title} was {$agent} who had the following objectives:
objectives-objective-success = {$objective} | [color={$markupColor}]Success![/color]
objectives-objective-fail = {$objective} | [color={$markupColor}]Failure![/color] ({$progress}%)
Expand Down
8 changes: 4 additions & 4 deletions Resources/Locale/en-US/prototypes/roles/antags.ftl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
roles-antag-syndicate-agent-name = Syndicate agent
roles-antag-syndicate-agent-objective = Complete your objectives without being caught.
roles-antag-traitor-name = Traitor
roles-antag-traitor-objective = Complete your objectives without being caught.
roles-antag-syndicate-agent-sleeper-name = Syndicate sleeper agent
roles-antag-syndicate-agent-sleeper-objective = A form of syndicate agent that can activate at any point in the middle of the shift.
Expand All @@ -17,13 +17,13 @@ roles-antag-suspicion-suspect-name = Suspect
roles-antag-suspicion-suspect-objective = Kill the innocents.
roles-antag-nuclear-operative-commander-name = Nuclear operative commander
roles-antag-nuclear-operative-commander-objective = Lead your team to the destruction of the station.
roles-antag-nuclear-operative-commander-objective = Lead your team to the destruction of the station!
roles-antag-nuclear-operative-agent-name = Nuclear operative agent
roles-antag-nuclear-operative-agent-objective = Like default operative, the team's treatment will have priority.
roles-antag-nuclear-operative-name = Nuclear operative
roles-antag-nuclear-operative-objective = Find the nuke disk and blow up the station.
roles-antag-nuclear-operative-objective = Find the nuke disk and blow up the station!
roles-antag-subverted-silicon-name = Subverted silicon
roles-antag-subverted-silicon-objective = Follow your new laws and do bad unto the station.
Expand Down
Loading

0 comments on commit e94e2a8

Please sign in to comment.