Files
crystall-punk-14/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs

226 lines
9.1 KiB
C#
Raw Permalink Normal View History

using Content.Server.Administration.Logs;
New Thief minor antagonist (#21520) * start working * add right-click thief antagins some architecture restruct * add meh thief greeting audio * add thief subgamemode to Traitors gamemode * add late join thief (not tested yet) add briefing * add pacifism * add Steal tasks to thief * fix crash thief+traitor on person * add new condition: collection steal * add tracking of succes collection objective * add stamp collection target remove some boring steal target add check pulling entity to collection target * finalize first 2 group objective * start merging stealing objective systems * merging * finish merging. Now traitor steal objective work better * we don't check the items of pullable sentient entity * clear naming, enable thief signle item objective start * objective pack add * finish with steal item objectives * convert string to ProtoId<> * some clean up * add thieves to revolution game mode * Update Resources/Locale/en-US/game-ticking/game-presets/preset-thief.ftl Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com> * Update Resources/Locale/en-US/game-ticking/game-presets/preset-thief.ftl Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com> * update pacifism: fix crashing, monkey-thief without pacified * adaptive animal briefing, cleaning locales * add structure steal objectives * remove RCD target * add thiefs to manifest, but bug with traitor duplications * add escape objective * add chat briefing * setup animal objective group system * add animal steal objectives * add animal objectives notroleconditions * add morty * now thief mode has a chance of not launching Now there are a random number of thieves per round from 1 to 3 * 6 hours of trying to fix duplicate tasks. Failure * added thief pinpointer (buggy) * start thief backpack UI work * revert pinpointer for scope reason * UI continue work * add thief starter kits content * remove ERP kit :trollface: * finally! giving starting items to thief. Now it playable, but still need more work * clean up * fix * fox * add merged items into thief new Starting Kit (buggy) * fix YES antag menu * objection tweaks * remove hearts objective, working on spawning things from toolbox * smug * fixes * add race specifier objective condition LAMPS * meh * fix fix fix * the alive * Adding stamps * Update backpack.ftl * Revert1 * Revert ftl * add voice mask to communicator kit * Update Resources/Locale/en-US/administration/antag.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/game-ticking/game-presets/preset-thief.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/thief/backpack.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/objectives/conditions/steal.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/thief/backpack.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/thief/backpack.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/thief/backpack.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/thief/backpack.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/prototypes/roles/antags.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * Update Resources/Locale/en-US/thief/backpack.ftl Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com> * update * fix * more reusable function, add documentation * fix doc * faint fixes --------- Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com> Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>
2023-12-24 12:58:28 +03:00
using Content.Server.Antag;
2023-04-25 20:23:14 -04:00
using Content.Server.GameTicking.Rules.Components;
2023-06-18 11:33:19 -07:00
using Content.Server.Mind;
using Content.Server.Objectives;
using Content.Server.PDA.Ringer;
2021-12-21 21:23:29 +01:00
using Content.Server.Roles;
using Content.Server.Traitor.Uplink;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.GameTicking.Components;
using Content.Shared.Mind;
using Content.Shared.NPC.Systems;
using Content.Shared.PDA;
using Content.Shared.Roles;
using Content.Shared.Roles.Jobs;
using Content.Shared.Roles.RoleCodeword;
2021-12-21 21:23:29 +01:00
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Linq;
using System.Text;
2021-12-21 21:23:29 +01:00
namespace Content.Server.GameTicking.Rules;
2023-04-25 20:23:14 -04:00
public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
2021-12-21 21:23:29 +01:00
{
private static readonly Color TraitorCodewordColor = Color.FromHex("#cc3b3b");
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly SharedJobSystem _jobs = default!;
[Dependency] private readonly MindSystem _mindSystem = default!;
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedRoleCodewordSystem _roleCodewordSystem = default!;
[Dependency] private readonly SharedRoleSystem _roleSystem = default!;
[Dependency] private readonly UplinkSystem _uplink = default!;
2021-12-21 21:23:29 +01:00
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TraitorRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);
SubscribeLocalEvent<TraitorRuleComponent, ObjectivesTextPrependEvent>(OnObjectivesTextPrepend);
2021-12-21 21:23:29 +01:00
}
protected override void Added(EntityUid uid, TraitorRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
{
base.Added(uid, component, gameRule, args);
SetCodewords(component, args.RuleEntity);
}
private void AfterEntitySelected(Entity<TraitorRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
2023-04-24 16:21:05 +10:00
{
MakeTraitor(args.EntityUid, ent);
2021-12-21 21:23:29 +01:00
}
private void SetCodewords(TraitorRuleComponent component, EntityUid ruleEntity)
{
component.Codewords = GenerateTraitorCodewords(component);
_adminLogger.Add(LogType.EventStarted, LogImpact.Low, $"Codewords generated for game rule {ToPrettyString(ruleEntity)}: {string.Join(", ", component.Codewords)}");
}
public string[] GenerateTraitorCodewords(TraitorRuleComponent component)
{
var adjectives = _prototypeManager.Index(component.CodewordAdjectives).Values;
var verbs = _prototypeManager.Index(component.CodewordVerbs).Values;
var codewordPool = adjectives.Concat(verbs).ToList();
var finalCodewordCount = Math.Min(component.CodewordCount, codewordPool.Count);
string[] codewords = new string[finalCodewordCount];
for (var i = 0; i < finalCodewordCount; i++)
{
codewords[i] = _random.PickAndTake(codewordPool);
}
return codewords;
}
public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component)
{
//Grab the mind if it wasn't provided
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
return false;
var briefing = "";
if (component.GiveCodewords)
briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", component.Codewords)));
var issuer = _random.Pick(_prototypeManager.Index(component.ObjectiveIssuers).Values);
// Uplink code will go here if applicable, but we still need the variable if there aren't any
Note[]? code = null;
if (component.GiveUplink)
{
// Calculate the amount of currency on the uplink.
var startingBalance = component.StartingBalance;
if (_jobs.MindTryGetJob(mindId, out var prototype))
{
if (startingBalance < prototype.AntagAdvantage) // Can't use Math functions on FixedPoint2
startingBalance = 0;
else
startingBalance = startingBalance - prototype.AntagAdvantage;
}
// Choose and generate an Uplink, and return the uplink code if applicable
var uplinkParams = RequestUplink(traitor, startingBalance, briefing);
code = uplinkParams.Item1;
briefing = uplinkParams.Item2;
}
2023-04-25 20:23:14 -04:00
string[]? codewords = null;
if (component.GiveCodewords)
codewords = component.Codewords;
if (component.GiveBriefing)
_antag.SendBriefing(traitor, GenerateBriefing(codewords, code, issuer), null, component.GreetSoundNotification);
component.TraitorMinds.Add(mindId);
// Assign briefing
//Since this provides neither an antag/job prototype, nor antag status/roletype,
//and is intrinsically related to the traitor role
//it does not need to be a separate Mind Role Entity
_roleSystem.MindHasRole<TraitorRoleComponent>(mindId, out var traitorRole);
if (traitorRole is not null)
{
AddComp<RoleBriefingComponent>(traitorRole.Value.Owner);
Comp<RoleBriefingComponent>(traitorRole.Value.Owner).Briefing = briefing;
}
2021-12-21 21:23:29 +01:00
// Send codewords to only the traitor client
var color = TraitorCodewordColor; // Fall back to a dark red Syndicate color if a prototype is not found
RoleCodewordComponent codewordComp = EnsureComp<RoleCodewordComponent>(mindId);
_roleCodewordSystem.SetRoleCodewords(codewordComp, "traitor", component.Codewords.ToList(), color);
// Change the faction
_npcFaction.RemoveFaction(traitor, component.NanoTrasenFaction, false);
_npcFaction.AddFaction(traitor, component.SyndicateFaction);
return true;
2021-12-21 21:23:29 +01:00
}
private (Note[]?, string) RequestUplink(EntityUid traitor, FixedPoint2 startingBalance, string briefing)
{
var pda = _uplink.FindUplinkTarget(traitor);
Note[]? code = null;
var uplinked = _uplink.AddUplink(traitor, startingBalance, pda, true);
if (pda is not null && uplinked)
{
// Codes are only generated if the uplink is a PDA
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", "#"))));
return (code, briefing);
}
else if (pda is null && uplinked)
{
briefing += "\n" + Loc.GetString("traitor-role-uplink-implant-short");
}
return (null, briefing);
}
// TODO: AntagCodewordsComponent
private void OnObjectivesTextPrepend(EntityUid uid, TraitorRuleComponent comp, ref ObjectivesTextPrependEvent args)
{
if(comp.GiveCodewords)
args.Text += "\n" + Loc.GetString("traitor-round-end-codewords", ("codewords", string.Join(", ", comp.Codewords)));
2021-12-21 21:23:29 +01:00
}
// 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();
sb.AppendLine(Loc.GetString("traitor-role-greeting", ("corporation", objectiveIssuer ?? Loc.GetString("objective-issuer-unknown"))));
if (codewords != null)
sb.AppendLine(Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords))));
if (uplinkCode != null)
sb.AppendLine(Loc.GetString("traitor-role-uplink-code", ("code", string.Join("-", uplinkCode).Replace("sharp", "#"))));
else
sb.AppendLine(Loc.GetString("traitor-role-uplink-implant"));
return sb.ToString();
}
public List<(EntityUid Id, MindComponent Mind)> GetOtherTraitorMindsAliveAndConnected(MindComponent ourMind)
{
List<(EntityUid Id, MindComponent Mind)> allTraitors = new();
var query = EntityQueryEnumerator<TraitorRuleComponent>();
while (query.MoveNext(out var uid, out var traitor))
2023-04-25 20:23:14 -04:00
{
foreach (var role in GetOtherTraitorMindsAliveAndConnected(ourMind, (uid, traitor)))
2023-04-25 20:23:14 -04:00
{
if (!allTraitors.Contains(role))
allTraitors.Add(role);
}
}
2023-04-25 20:23:14 -04:00
return allTraitors;
}
private List<(EntityUid Id, MindComponent Mind)> GetOtherTraitorMindsAliveAndConnected(MindComponent ourMind, Entity<TraitorRuleComponent> rule)
2023-04-25 20:23:14 -04:00
{
var traitors = new List<(EntityUid Id, MindComponent Mind)>();
foreach (var mind in _antag.GetAntagMinds(rule.Owner))
{
if (mind.Comp == ourMind)
continue;
traitors.Add((mind, mind));
}
return traitors;
}
2021-12-21 21:23:29 +01:00
}