diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs index 6aebd60e2e..ccd2778008 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs @@ -2,6 +2,7 @@ using Content.Server.GameTicking.Rules; using Content.Server.Zombies; using Content.Shared.Administration; using Content.Shared.Database; +using Content.Shared.Humanoid; using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Verbs; @@ -21,7 +22,7 @@ public sealed partial class AdminVerbSystem // All antag verbs have names so invokeverb works. private void AddAntagVerbs(GetVerbsEvent args) { - if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) + if (!TryComp(args.User, out var actor)) return; var player = actor.PlayerSession; @@ -29,8 +30,7 @@ public sealed partial class AdminVerbSystem if (!_adminManager.HasAdminFlag(player, AdminFlags.Fun)) return; - var targetHasMind = TryComp(args.Target, out MindContainerComponent? targetMindComp); - if (!targetHasMind || targetMindComp == null) + if (!TryComp(args.Target, out var targetMindComp)) return; Verb traitor = new() @@ -43,7 +43,9 @@ public sealed partial class AdminVerbSystem if (!_minds.TryGetSession(targetMindComp.Mind, out var session)) return; - _traitorRule.MakeTraitor(session); + // if its a monkey or mouse or something dont give uplink or objectives + var isHuman = HasComp(args.Target); + _traitorRule.MakeTraitor(session, giveUplink: isHuman, giveObjectives: isHuman); }, Impact = LogImpact.High, Message = Loc.GetString("admin-verb-make-traitor"), diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 5dffd35ad4..210425526c 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -205,7 +205,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem return results; } - public bool MakeTraitor(ICommonSession traitor) + public bool MakeTraitor(ICommonSession traitor, bool giveUplink = true, bool giveObjectives = true) { var traitorRule = EntityQuery().FirstOrDefault(); if (traitorRule == null) @@ -240,19 +240,25 @@ public sealed class TraitorRuleSystem : GameRuleSystem if (_jobs.MindTryGetJob(mindId, out _, out var prototype)) startingBalance = Math.Max(startingBalance - prototype.AntagAdvantage, 0); - // creadth: we need to create uplink for the antag. - // PDA should be in place already - var pda = _uplink.FindUplinkTarget(mind.OwnedEntity!.Value); - if (pda == null || !_uplink.AddUplink(mind.OwnedEntity.Value, startingBalance)) - return false; + // Give traitors their codewords and uplink code to keep in their character info menu + var briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords))); + Note[]? code = null; + if (giveUplink) + { + // creadth: we need to create uplink for the antag. + // PDA should be in place already + var pda = _uplink.FindUplinkTarget(mind.OwnedEntity!.Value); + if (pda == null || !_uplink.AddUplink(mind.OwnedEntity.Value, startingBalance)) + return false; - // Add the ringtone uplink and get its code for greeting - var code = EnsureComp(pda.Value).Code; + // Give traitors their codewords and uplink code to keep in their character info menu + code = EnsureComp(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","#")))); + } // Prepare traitor role - // Give traitors their codewords and uplink code to keep in their character info menu - var briefing = - $"{Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords)))}\n{Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", code).Replace("sharp", "#")))}"; var traitorRole = new TraitorRoleComponent { PrototypeId = traitorRule.TraitorPrototypeId, @@ -282,17 +288,20 @@ public sealed class TraitorRuleSystem : GameRuleSystem _npcFaction.AddFaction(entity, "Syndicate"); // Give traitors their objectives - var maxDifficulty = _cfg.GetCVar(CCVars.TraitorMaxDifficulty); - var maxPicks = _cfg.GetCVar(CCVars.TraitorMaxPicks); - var difficulty = 0f; - for (var pick = 0; pick < maxPicks && maxDifficulty > difficulty; pick++) + if (giveObjectives) { - var objective = _objectives.GetRandomObjective(mindId, mind, "TraitorObjectiveGroups"); + var maxDifficulty = _cfg.GetCVar(CCVars.TraitorMaxDifficulty); + var maxPicks = _cfg.GetCVar(CCVars.TraitorMaxPicks); + var difficulty = 0f; + for (var pick = 0; pick < maxPicks && maxDifficulty > difficulty; pick++) + { + var objective = _objectives.GetRandomObjective(mindId, mind, "TraitorObjectiveGroups"); + if (objective == null) + continue; - if (objective == null) - continue; - if (_mindSystem.TryAddObjective(mindId, mind, objective)) - difficulty += objective.Difficulty; + if (_mindSystem.TryAddObjective(mindId, mind, objective)) + difficulty += objective.Difficulty; + } } return true; @@ -304,14 +313,15 @@ public sealed class TraitorRuleSystem : GameRuleSystem /// A mind (player) /// Codewords /// Uplink codes - private void SendTraitorBriefing(EntityUid mind, string[] codewords, Note[] code) + private void SendTraitorBriefing(EntityUid mind, string[] codewords, Note[]? code) { - if (_mindSystem.TryGetSession(mind, out var session)) - { - _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-greeting")); - _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords)))); + if (!_mindSystem.TryGetSession(mind, out var session)) + return; + + _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-greeting")); + _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords)))); + if (code != null) _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-uplink-code", ("code", string.Join("-", code).Replace("sharp","#")))); - } } private void HandleLatejoin(PlayerSpawnCompleteEvent ev) diff --git a/Content.Server/Traitor/Components/AutoTraitorComponent.cs b/Content.Server/Traitor/Components/AutoTraitorComponent.cs new file mode 100644 index 0000000000..ab4bee2f26 --- /dev/null +++ b/Content.Server/Traitor/Components/AutoTraitorComponent.cs @@ -0,0 +1,22 @@ +using Content.Server.Traitor.Systems; + +namespace Content.Server.Traitor.Components; + +/// +/// Makes the entity a traitor either instantly if it has a mind or when a mind is added. +/// +[RegisterComponent, Access(typeof(AutoTraitorSystem))] +public sealed partial class AutoTraitorComponent : Component +{ + /// + /// Whether to give the traitor an uplink or not. + /// + [DataField("giveUplink"), ViewVariables(VVAccess.ReadWrite)] + public bool GiveUplink = true; + + /// + /// Whether to give the traitor objectives or not. + /// + [DataField("giveObjectives"), ViewVariables(VVAccess.ReadWrite)] + public bool GiveObjectives = true; +} diff --git a/Content.Server/Traitor/Systems/AutoTraitorSystem.cs b/Content.Server/Traitor/Systems/AutoTraitorSystem.cs new file mode 100644 index 0000000000..70fefd4c90 --- /dev/null +++ b/Content.Server/Traitor/Systems/AutoTraitorSystem.cs @@ -0,0 +1,76 @@ +using Content.Server.GameTicking.Rules; +using Content.Server.Traitor.Components; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; + +namespace Content.Server.Traitor.Systems; + +/// +/// Makes entities with a traitor either immediately if they have a mind or when a mind is added. +/// +public sealed class AutoTraitorSystem : EntitySystem +{ + [Dependency] private readonly TraitorRuleSystem _traitorRule = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnMindAdded); + } + + private void OnMapInit(EntityUid uid, AutoTraitorComponent comp, MapInitEvent args) + { + TryMakeTraitor(uid, comp); + } + + private void OnMindAdded(EntityUid uid, AutoTraitorComponent comp, MindAddedMessage args) + { + TryMakeTraitor(uid, comp); + } + + /// + /// Sets the GiveUplink field. + /// + public void SetGiveUplink(EntityUid uid, bool giveUplink, AutoTraitorComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + comp.GiveUplink = giveUplink; + } + + /// + /// Sets the GiveObjectives field. + /// + public void SetGiveObjectives(EntityUid uid, bool giveObjectives, AutoTraitorComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + comp.GiveObjectives = giveObjectives; + } + + /// + /// Checks if there is a mind, then makes it a traitor using the options. + /// + public bool TryMakeTraitor(EntityUid uid, AutoTraitorComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return false; + + if (!TryComp(uid, out var mindContainer) || mindContainer.Mind == null) + return false; + + var mindId = mindContainer.Mind.Value; + if (!TryComp(mindId, out var mind) || mind.Session == null) + return false; + + var session = mind.Session; + _traitorRule.MakeTraitor(session, giveUplink: comp.GiveUplink, giveObjectives: comp.GiveObjectives); + // prevent spamming anything if it fails + RemComp(uid); + return true; + } +} diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index add7717298..7ff922bc01 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -811,6 +811,7 @@ - MobMask layer: - MobLayer + - type: Stripping - type: Strippable - type: UserInterface interfaces: @@ -985,6 +986,7 @@ - Trash - VimPilot - Mouse + - DoorBumpOpener - type: Respirator damage: types: @@ -1494,6 +1496,11 @@ - type: Tag tags: - VimPilot + - DoorBumpOpener + # make the player a traitor once its taken + - type: AutoTraitor + giveUplink: false + giveObjectives: false # I have included a snake_hiss.ogg sound file so if you want to use that be my guest - type: entity diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index f401a75fae..4fedd7f1a6 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -710,5 +710,6 @@ tags: - CannotSuicide - DoorBumpOpener + - VimPilot - type: Loadout prototypes: [ MobMonkeyGear ]