Mind Role Entities (#31318)
* Mind Role Entities wip * headrev count fix * silicon stuff, cleanup * exclusive antag config, cleanup * jobroleadd overwerite * logging stuff * MindHasRole cleanup, admin log stuff * last second cleanup * ocd * minor cleanup * remove createdTime datafield * now actually using the event replacement I made for role time tracking * weh
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
@@ -120,8 +121,8 @@ public sealed class NukeOpsTest
|
|||||||
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(mind));
|
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(mind));
|
||||||
Assert.That(factionSys.IsMember(player, "Syndicate"), Is.True);
|
Assert.That(factionSys.IsMember(player, "Syndicate"), Is.True);
|
||||||
Assert.That(factionSys.IsMember(player, "NanoTrasen"), Is.False);
|
Assert.That(factionSys.IsMember(player, "NanoTrasen"), Is.False);
|
||||||
var roles = roleSys.MindGetAllRoles(mind);
|
var roles = roleSys.MindGetAllRoleInfo(mind);
|
||||||
var cmdRoles = roles.Where(x => x.Prototype == "NukeopsCommander" && x.Component is NukeopsRoleComponent);
|
var cmdRoles = roles.Where(x => x.Prototype == "NukeopsCommander");
|
||||||
Assert.That(cmdRoles.Count(), Is.EqualTo(1));
|
Assert.That(cmdRoles.Count(), Is.EqualTo(1));
|
||||||
|
|
||||||
// The second dummy player should be a medic
|
// The second dummy player should be a medic
|
||||||
@@ -131,8 +132,8 @@ public sealed class NukeOpsTest
|
|||||||
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(dummyMind));
|
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(dummyMind));
|
||||||
Assert.That(factionSys.IsMember(dummyEnts[1], "Syndicate"), Is.True);
|
Assert.That(factionSys.IsMember(dummyEnts[1], "Syndicate"), Is.True);
|
||||||
Assert.That(factionSys.IsMember(dummyEnts[1], "NanoTrasen"), Is.False);
|
Assert.That(factionSys.IsMember(dummyEnts[1], "NanoTrasen"), Is.False);
|
||||||
roles = roleSys.MindGetAllRoles(dummyMind);
|
roles = roleSys.MindGetAllRoleInfo(dummyMind);
|
||||||
cmdRoles = roles.Where(x => x.Prototype == "NukeopsMedic" && x.Component is NukeopsRoleComponent);
|
cmdRoles = roles.Where(x => x.Prototype == "NukeopsMedic");
|
||||||
Assert.That(cmdRoles.Count(), Is.EqualTo(1));
|
Assert.That(cmdRoles.Count(), Is.EqualTo(1));
|
||||||
|
|
||||||
// The other two players should have just spawned in as normal.
|
// The other two players should have just spawned in as normal.
|
||||||
@@ -141,13 +142,14 @@ public sealed class NukeOpsTest
|
|||||||
void CheckDummy(int i)
|
void CheckDummy(int i)
|
||||||
{
|
{
|
||||||
var ent = dummyEnts[i];
|
var ent = dummyEnts[i];
|
||||||
var mind = mindSys.GetMind(ent)!.Value;
|
var mindCrew = mindSys.GetMind(ent)!.Value;
|
||||||
Assert.That(entMan.HasComponent<NukeOperativeComponent>(ent), Is.False);
|
Assert.That(entMan.HasComponent<NukeOperativeComponent>(ent), Is.False);
|
||||||
Assert.That(roleSys.MindIsAntagonist(mind), Is.False);
|
Assert.That(roleSys.MindIsAntagonist(mindCrew), Is.False);
|
||||||
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(mind), Is.False);
|
Assert.That(roleSys.MindHasRole<NukeopsRoleComponent>(mindCrew), Is.False);
|
||||||
Assert.That(factionSys.IsMember(ent, "Syndicate"), Is.False);
|
Assert.That(factionSys.IsMember(ent, "Syndicate"), Is.False);
|
||||||
Assert.That(factionSys.IsMember(ent, "NanoTrasen"), Is.True);
|
Assert.That(factionSys.IsMember(ent, "NanoTrasen"), Is.True);
|
||||||
Assert.That(roleSys.MindGetAllRoles(mind).Any(x => x.Component is NukeopsRoleComponent), Is.False);
|
var nukeroles = new List<string>() { "Nukeops", "NukeopsMedic", "NukeopsCommander" };
|
||||||
|
Assert.That(roleSys.MindGetAllRoleInfo(mindCrew).Any(x => nukeroles.Contains(x.Prototype)), Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The game rule exists, and all the stations/shuttles/maps are properly initialized
|
// The game rule exists, and all the stations/shuttles/maps are properly initialized
|
||||||
@@ -238,7 +240,8 @@ public sealed class NukeOpsTest
|
|||||||
for (var i = 0; i < nukies.Length - 1; i++)
|
for (var i = 0; i < nukies.Length - 1; i++)
|
||||||
{
|
{
|
||||||
entMan.DeleteEntity(nukies[i]);
|
entMan.DeleteEntity(nukies[i]);
|
||||||
Assert.That(roundEndSys.IsRoundEndRequested, Is.False,
|
Assert.That(roundEndSys.IsRoundEndRequested,
|
||||||
|
Is.False,
|
||||||
$"The round ended, but {nukies.Length - i - 1} nukies are still alive!");
|
$"The round ended, but {nukies.Length - i - 1} nukies are still alive!");
|
||||||
}
|
}
|
||||||
// Delete the last nukie and make sure the round ends.
|
// Delete the last nukie and make sure the round ends.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Content.Server.Atmos.EntitySystems;
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles.Jobs;
|
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.Internals;
|
namespace Content.IntegrationTests.Tests.Internals;
|
||||||
|
|
||||||
@@ -25,10 +24,7 @@ public sealed class AutoInternalsTests
|
|||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var profile = new HumanoidCharacterProfile();
|
var profile = new HumanoidCharacterProfile();
|
||||||
var dummy = stationSpawning.SpawnPlayerMob(testMap.GridCoords, new JobComponent()
|
var dummy = stationSpawning.SpawnPlayerMob(testMap.GridCoords, "TestInternalsDummy", profile, station: null);
|
||||||
{
|
|
||||||
Prototype = "TestInternalsDummy"
|
|
||||||
}, profile, station: null);
|
|
||||||
|
|
||||||
Assert.That(atmos.HasAtmosphere(testMap.Grid), Is.False, "Test map has atmosphere - test needs adjustment!");
|
Assert.That(atmos.HasAtmosphere(testMap.Grid), Is.False, "Test map has atmosphere - test needs adjustment!");
|
||||||
Assert.That(internals.AreInternalsWorking(dummy), "Internals did not automatically connect!");
|
Assert.That(internals.AreInternalsWorking(dummy), "Internals did not automatically connect!");
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Ghost;
|
|
||||||
using Content.Server.Ghost.Roles;
|
using Content.Server.Ghost.Roles;
|
||||||
using Content.Server.Ghost.Roles.Components;
|
using Content.Server.Ghost.Roles.Components;
|
||||||
using Content.Server.Mind.Commands;
|
using Content.Server.Mind.Commands;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
@@ -18,7 +16,6 @@ using Robust.Server.Console;
|
|||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
@@ -287,27 +284,27 @@ public sealed partial class MindTests
|
|||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
||||||
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId), Is.False);
|
Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId), Is.False);
|
||||||
});
|
});
|
||||||
|
|
||||||
var traitorRole = new TraitorRoleComponent();
|
var traitorRole = "MindRoleTraitor";
|
||||||
|
|
||||||
roleSystem.MindAddRole(mindId, traitorRole);
|
roleSystem.MindAddRole(mindId, traitorRole);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
|
||||||
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId), Is.False);
|
Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId), Is.False);
|
||||||
});
|
});
|
||||||
|
|
||||||
var jobRole = new JobComponent();
|
var jobRole = "";
|
||||||
|
|
||||||
roleSystem.MindAddRole(mindId, jobRole);
|
roleSystem.MindAddJobRole(mindId, jobPrototype:jobRole);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
|
||||||
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId));
|
Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
roleSystem.MindRemoveRole<TraitorRoleComponent>(mindId);
|
roleSystem.MindRemoveRole<TraitorRoleComponent>(mindId);
|
||||||
@@ -315,15 +312,15 @@ public sealed partial class MindTests
|
|||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
||||||
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId));
|
Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
roleSystem.MindRemoveRole<JobComponent>(mindId);
|
roleSystem.MindRemoveRole<JobRoleComponent>(mindId);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
||||||
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId), Is.False);
|
Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId), Is.False);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Content.Server.Station.Systems;
|
|||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Preferences.Loadouts;
|
using Content.Shared.Preferences.Loadouts;
|
||||||
using Content.Shared.Roles.Jobs;
|
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
@@ -68,10 +67,7 @@ public sealed class LoadoutTests
|
|||||||
|
|
||||||
profile.SetLoadout(new RoleLoadout("LoadoutTester"));
|
profile.SetLoadout(new RoleLoadout("LoadoutTester"));
|
||||||
|
|
||||||
var tester = stationSystem.SpawnPlayerMob(testMap.GridCoords, job: new JobComponent()
|
var tester = stationSystem.SpawnPlayerMob(testMap.GridCoords, job: "LoadoutTester", profile, station: null);
|
||||||
{
|
|
||||||
Prototype = "LoadoutTester"
|
|
||||||
}, profile, station: null);
|
|
||||||
|
|
||||||
var slotQuery = inventorySystem.GetSlotEnumerator(tester);
|
var slotQuery = inventorySystem.GetSlotEnumerator(tester);
|
||||||
var checkedCount = 0;
|
var checkedCount = 0;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using Content.Server.Preferences.Managers;
|
|||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
using Content.Server.Roles.Jobs;
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Antag;
|
using Content.Shared.Antag;
|
||||||
using Content.Shared.Clothing;
|
using Content.Shared.Clothing;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -20,7 +19,6 @@ using Content.Shared.Ghost;
|
|||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Players;
|
using Content.Shared.Players;
|
||||||
using Content.Shared.Preferences.Loadouts;
|
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Server.Audio;
|
using Robust.Server.Audio;
|
||||||
@@ -37,14 +35,14 @@ namespace Content.Server.Antag;
|
|||||||
|
|
||||||
public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelectionComponent>
|
public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelectionComponent>
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IChatManager _chat = default!;
|
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
||||||
[Dependency] private readonly IServerPreferencesManager _pref = default!;
|
|
||||||
[Dependency] private readonly AudioSystem _audio = default!;
|
[Dependency] private readonly AudioSystem _audio = default!;
|
||||||
|
[Dependency] private readonly IChatManager _chat = default!;
|
||||||
[Dependency] private readonly GhostRoleSystem _ghostRole = default!;
|
[Dependency] private readonly GhostRoleSystem _ghostRole = default!;
|
||||||
[Dependency] private readonly JobSystem _jobs = default!;
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
[Dependency] private readonly LoadoutSystem _loadout = default!;
|
[Dependency] private readonly LoadoutSystem _loadout = default!;
|
||||||
[Dependency] private readonly MindSystem _mind = default!;
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] private readonly IServerPreferencesManager _pref = default!;
|
||||||
[Dependency] private readonly RoleSystem _role = default!;
|
[Dependency] private readonly RoleSystem _role = default!;
|
||||||
[Dependency] private readonly TransformSystem _transform = default!;
|
[Dependency] private readonly TransformSystem _transform = default!;
|
||||||
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||||
@@ -193,6 +191,9 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Chooses antagonists from the given selection of players
|
/// Chooses antagonists from the given selection of players
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="ent">The antagonist rule entity</param>
|
||||||
|
/// <param name="pool">The players to choose from</param>
|
||||||
|
/// <param name="midround">Disable picking players for pre-spawn antags in the middle of a round</param>
|
||||||
public void ChooseAntags(Entity<AntagSelectionComponent> ent, IList<ICommonSession> pool, bool midround = false)
|
public void ChooseAntags(Entity<AntagSelectionComponent> ent, IList<ICommonSession> pool, bool midround = false)
|
||||||
{
|
{
|
||||||
if (ent.Comp.SelectionsComplete)
|
if (ent.Comp.SelectionsComplete)
|
||||||
@@ -209,8 +210,14 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Chooses antagonists from the given selection of players for the given antag definition.
|
/// Chooses antagonists from the given selection of players for the given antag definition.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="ent">The antagonist rule entity</param>
|
||||||
|
/// <param name="pool">The players to choose from</param>
|
||||||
|
/// <param name="def">The antagonist selection parameters and criteria</param>
|
||||||
/// <param name="midround">Disable picking players for pre-spawn antags in the middle of a round</param>
|
/// <param name="midround">Disable picking players for pre-spawn antags in the middle of a round</param>
|
||||||
public void ChooseAntags(Entity<AntagSelectionComponent> ent, IList<ICommonSession> pool, AntagSelectionDefinition def, bool midround = false)
|
public void ChooseAntags(Entity<AntagSelectionComponent> ent,
|
||||||
|
IList<ICommonSession> pool,
|
||||||
|
AntagSelectionDefinition def,
|
||||||
|
bool midround = false)
|
||||||
{
|
{
|
||||||
var playerPool = GetPlayerPool(ent, pool, def);
|
var playerPool = GetPlayerPool(ent, pool, def);
|
||||||
var count = GetTargetAntagCount(ent, GetTotalPlayerCount(pool), def);
|
var count = GetTargetAntagCount(ent, GetTotalPlayerCount(pool), def);
|
||||||
@@ -331,7 +338,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
EntityManager.AddComponents(player, def.Components);
|
EntityManager.AddComponents(player, def.Components);
|
||||||
|
|
||||||
// Equip the entity's RoleLoadout and LoadoutGroup
|
// Equip the entity's RoleLoadout and LoadoutGroup
|
||||||
List<ProtoId<StartingGearPrototype>>? gear = new();
|
List<ProtoId<StartingGearPrototype>> gear = new();
|
||||||
if (def.StartingGear is not null)
|
if (def.StartingGear is not null)
|
||||||
gear.Add(def.StartingGear.Value);
|
gear.Add(def.StartingGear.Value);
|
||||||
|
|
||||||
@@ -340,8 +347,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
if (session != null)
|
if (session != null)
|
||||||
{
|
{
|
||||||
var curMind = session.GetMind();
|
var curMind = session.GetMind();
|
||||||
|
|
||||||
if (curMind == null ||
|
if (curMind == null ||
|
||||||
!TryComp<MindComponent>(curMind.Value, out var mindComp) ||
|
!TryComp<MindComponent>(curMind.Value, out var mindComp) ||
|
||||||
mindComp.OwnedEntity != antagEnt)
|
mindComp.OwnedEntity != antagEnt)
|
||||||
{
|
{
|
||||||
@@ -350,7 +357,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
|||||||
}
|
}
|
||||||
|
|
||||||
_mind.TransferTo(curMind.Value, antagEnt, ghostCheckOverride: true);
|
_mind.TransferTo(curMind.Value, antagEnt, ghostCheckOverride: true);
|
||||||
_role.MindAddRoles(curMind.Value, def.MindComponents, null, true);
|
_role.MindAddRoles(curMind.Value, def.MindRoles, null, true);
|
||||||
ent.Comp.SelectedMinds.Add((curMind.Value, Name(player)));
|
ent.Comp.SelectedMinds.Add((curMind.Value, Name(player)));
|
||||||
SendBriefing(session, def.Briefing);
|
SendBriefing(session, def.Briefing);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Content.Shared.Antag;
|
|||||||
using Content.Shared.Destructible.Thresholds;
|
using Content.Shared.Destructible.Thresholds;
|
||||||
using Content.Shared.Preferences.Loadouts;
|
using Content.Shared.Preferences.Loadouts;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Storage;
|
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
@@ -145,10 +144,17 @@ public partial struct AntagSelectionDefinition()
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Components added to the player's mind.
|
/// Components added to the player's mind.
|
||||||
|
/// Do NOT use this to add role-type components. Add those as MindRoles instead
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public ComponentRegistry MindComponents = new();
|
public ComponentRegistry MindComponents = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of Mind Role Prototypes to be added to the player's mind.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public List<ProtoId<EntityPrototype>>? MindRoles;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A set of starting gear that's equipped to the player.
|
/// A set of starting gear that's equipped to the player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ namespace Content.Server.Cloning
|
|||||||
|
|
||||||
// TODO: Ideally, components like this should be components on the mind entity so this isn't necessary.
|
// TODO: Ideally, components like this should be components on the mind entity so this isn't necessary.
|
||||||
// Add on special job components to the mob.
|
// Add on special job components to the mob.
|
||||||
if (_jobs.MindTryGetJob(mindEnt, out _, out var prototype))
|
if (_jobs.MindTryGetJob(mindEnt, out var prototype))
|
||||||
{
|
{
|
||||||
foreach (var special in prototype.Special)
|
foreach (var special in prototype.Special)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,49 +1,45 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.EntityEffects;
|
using Content.Shared.EntityEffects;
|
||||||
using Content.Shared.Mobs;
|
|
||||||
using Content.Shared.Mobs.Components;
|
|
||||||
using Content.Shared.Localizations;
|
using Content.Shared.Localizations;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Mind.Components;
|
using Content.Shared.Mind.Components;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Roles.Jobs;
|
using Content.Shared.Roles.Jobs;
|
||||||
using Content.Shared.Station;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
|
|
||||||
namespace Content.Server.EntityEffects.EffectConditions;
|
namespace Content.Server.EntityEffects.EffectConditions;
|
||||||
|
|
||||||
public sealed partial class JobCondition : EntityEffectCondition
|
public sealed partial class JobCondition : EntityEffectCondition
|
||||||
{
|
{
|
||||||
[DataField(required: true)] public List<ProtoId<JobPrototype>> Job;
|
[DataField(required: true)] public List<ProtoId<JobPrototype>> Job;
|
||||||
|
|
||||||
public override bool Condition(EntityEffectBaseArgs args)
|
public override bool Condition(EntityEffectBaseArgs args)
|
||||||
{
|
{
|
||||||
args.EntityManager.TryGetComponent<MindContainerComponent>(args.TargetEntity, out var mindContainer);
|
args.EntityManager.TryGetComponent<MindContainerComponent>(args.TargetEntity, out var mindContainer);
|
||||||
if (mindContainer != null && mindContainer.Mind != null)
|
|
||||||
|
if ( mindContainer is null
|
||||||
|
|| !args.EntityManager.TryGetComponent<MindComponent>(mindContainer.Mind, out var mind))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var roleId in mind.MindRoles)
|
||||||
{
|
{
|
||||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
if(!args.EntityManager.HasComponent<JobRoleComponent>(roleId))
|
||||||
if (args.EntityManager.TryGetComponent<JobComponent>(mindContainer?.Mind, out var comp) && prototypeManager.TryIndex(comp.Prototype, out var prototype))
|
continue;
|
||||||
{
|
|
||||||
foreach (var jobId in Job)
|
if(!args.EntityManager.TryGetComponent<MindRoleComponent>(roleId, out var mindRole)
|
||||||
{
|
|| mindRole.JobPrototype is null)
|
||||||
if (prototype.ID == jobId)
|
continue;
|
||||||
{
|
|
||||||
return true;
|
if (Job.Contains(mindRole.JobPrototype.Value))
|
||||||
}
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||||
{
|
{
|
||||||
var localizedNames = Job.Select(jobId => prototype.Index(jobId).LocalizedName).ToList();
|
var localizedNames = Job.Select(jobId => prototype.Index(jobId).LocalizedName).ToList();
|
||||||
return Loc.GetString("reagent-effect-condition-guidebook-job-condition", ("job", ContentLocalizationManager.FormatListToOr(localizedNames)));
|
return Loc.GetString("reagent-effect-condition-guidebook-job-condition", ("job", ContentLocalizationManager.FormatListToOr(localizedNames)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Discord;
|
|||||||
using Content.Server.GameTicking.Events;
|
using Content.Server.GameTicking.Events;
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
|
using Content.Server.Roles;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -26,6 +27,7 @@ namespace Content.Server.GameTicking
|
|||||||
public sealed partial class GameTicker
|
public sealed partial class GameTicker
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DiscordWebhook _discord = default!;
|
[Dependency] private readonly DiscordWebhook _discord = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _role = default!;
|
||||||
[Dependency] private readonly ITaskManager _taskManager = default!;
|
[Dependency] private readonly ITaskManager _taskManager = default!;
|
||||||
|
|
||||||
private static readonly Counter RoundNumberMetric = Metrics.CreateCounter(
|
private static readonly Counter RoundNumberMetric = Metrics.CreateCounter(
|
||||||
@@ -373,7 +375,7 @@ namespace Content.Server.GameTicking
|
|||||||
var userId = mind.UserId ?? mind.OriginalOwnerUserId;
|
var userId = mind.UserId ?? mind.OriginalOwnerUserId;
|
||||||
|
|
||||||
var connected = false;
|
var connected = false;
|
||||||
var observer = HasComp<ObserverRoleComponent>(mindId);
|
var observer = _role.MindHasRole<ObserverRoleComponent>(mindId);
|
||||||
// Continuing
|
// Continuing
|
||||||
if (userId != null && _playerManager.ValidSessionId(userId.Value))
|
if (userId != null && _playerManager.ValidSessionId(userId.Value))
|
||||||
{
|
{
|
||||||
@@ -400,7 +402,7 @@ namespace Content.Server.GameTicking
|
|||||||
_pvsOverride.AddGlobalOverride(GetNetEntity(entity.Value), recursive: true);
|
_pvsOverride.AddGlobalOverride(GetNetEntity(entity.Value), recursive: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var roles = _roles.MindGetAllRoles(mindId);
|
var roles = _roles.MindGetAllRoleInfo(mindId);
|
||||||
|
|
||||||
var playerEndRoundInfo = new RoundEndMessageEvent.RoundEndPlayerInfo()
|
var playerEndRoundInfo = new RoundEndMessageEvent.RoundEndPlayerInfo()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using System.Linq;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.GameTicking.Events;
|
using Content.Server.GameTicking.Events;
|
||||||
using Content.Server.Ghost;
|
|
||||||
using Content.Server.Shuttles.Components;
|
|
||||||
using Content.Server.Spawners.Components;
|
using Content.Server.Spawners.Components;
|
||||||
using Content.Server.Speech.Components;
|
using Content.Server.Speech.Components;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
@@ -224,13 +222,12 @@ namespace Content.Server.GameTicking
|
|||||||
_mind.SetUserId(newMind, data.UserId);
|
_mind.SetUserId(newMind, data.UserId);
|
||||||
|
|
||||||
var jobPrototype = _prototypeManager.Index<JobPrototype>(jobId);
|
var jobPrototype = _prototypeManager.Index<JobPrototype>(jobId);
|
||||||
var job = new JobComponent {Prototype = jobId};
|
_roles.MindAddJobRole(newMind, silent: silent, jobPrototype:jobId);
|
||||||
_roles.MindAddRole(newMind, job, silent: silent);
|
|
||||||
var jobName = _jobs.MindTryGetJobName(newMind);
|
var jobName = _jobs.MindTryGetJobName(newMind);
|
||||||
|
|
||||||
_playTimeTrackings.PlayerRolesChanged(player);
|
_playTimeTrackings.PlayerRolesChanged(player);
|
||||||
|
|
||||||
var mobMaybe = _stationSpawning.SpawnPlayerCharacterOnStation(station, job, character);
|
var mobMaybe = _stationSpawning.SpawnPlayerCharacterOnStation(station, jobId, character);
|
||||||
DebugTools.AssertNotNull(mobMaybe);
|
DebugTools.AssertNotNull(mobMaybe);
|
||||||
var mob = mobMaybe!.Value;
|
var mob = mobMaybe!.Value;
|
||||||
|
|
||||||
@@ -269,13 +266,17 @@ namespace Content.Server.GameTicking
|
|||||||
_stationJobs.TryAssignJob(station, jobPrototype, player.UserId);
|
_stationJobs.TryAssignJob(station, jobPrototype, player.UserId);
|
||||||
|
|
||||||
if (lateJoin)
|
if (lateJoin)
|
||||||
|
{
|
||||||
_adminLogger.Add(LogType.LateJoin,
|
_adminLogger.Add(LogType.LateJoin,
|
||||||
LogImpact.Medium,
|
LogImpact.Medium,
|
||||||
$"Player {player.Name} late joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}.");
|
$"Player {player.Name} late joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}.");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_adminLogger.Add(LogType.RoundStartJoin,
|
_adminLogger.Add(LogType.RoundStartJoin,
|
||||||
LogImpact.Medium,
|
LogImpact.Medium,
|
||||||
$"Player {player.Name} joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}.");
|
$"Player {player.Name} joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {jobName:jobName}.");
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure they're aware of extended access.
|
// Make sure they're aware of extended access.
|
||||||
if (Comp<StationJobsComponent>(station).ExtendedAccess
|
if (Comp<StationJobsComponent>(station).ExtendedAccess
|
||||||
@@ -361,7 +362,7 @@ namespace Content.Server.GameTicking
|
|||||||
var (mindId, mindComp) = _mind.CreateMind(player.UserId, name);
|
var (mindId, mindComp) = _mind.CreateMind(player.UserId, name);
|
||||||
mind = (mindId, mindComp);
|
mind = (mindId, mindComp);
|
||||||
_mind.SetUserId(mind.Value, player.UserId);
|
_mind.SetUserId(mind.Value, player.UserId);
|
||||||
_roles.MindAddRole(mind.Value, new ObserverRoleComponent());
|
_roles.MindAddRole(mind.Value, "MindRoleObserver");
|
||||||
}
|
}
|
||||||
|
|
||||||
var ghost = _ghost.SpawnGhost(mind.Value);
|
var ghost = _ghost.SpawnGhost(mind.Value);
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ using Content.Server.RoundEnd;
|
|||||||
using Content.Server.Shuttles.Events;
|
using Content.Server.Shuttles.Events;
|
||||||
using Content.Server.Shuttles.Systems;
|
using Content.Server.Shuttles.Systems;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.Store.Components;
|
|
||||||
using Content.Server.Store.Systems;
|
using Content.Server.Store.Systems;
|
||||||
using Content.Shared.GameTicking.Components;
|
using Content.Shared.GameTicking.Components;
|
||||||
using Content.Shared.Mobs;
|
using Content.Shared.Mobs;
|
||||||
@@ -31,9 +30,9 @@ namespace Content.Server.GameTicking.Rules;
|
|||||||
|
|
||||||
public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
||||||
[Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
|
[Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
|
||||||
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
|
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
|
||||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
||||||
[Dependency] private readonly StoreSystem _store = default!;
|
[Dependency] private readonly StoreSystem _store = default!;
|
||||||
@@ -57,6 +56,8 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
SubscribeLocalEvent<NukeOperativeComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<NukeOperativeComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
SubscribeLocalEvent<NukeOperativeComponent, EntityZombifiedEvent>(OnOperativeZombified);
|
SubscribeLocalEvent<NukeOperativeComponent, EntityZombifiedEvent>(OnOperativeZombified);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<NukeopsRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
||||||
|
|
||||||
SubscribeLocalEvent<ConsoleFTLAttemptEvent>(OnShuttleFTLAttempt);
|
SubscribeLocalEvent<ConsoleFTLAttemptEvent>(OnShuttleFTLAttempt);
|
||||||
SubscribeLocalEvent<WarDeclaredEvent>(OnWarDeclared);
|
SubscribeLocalEvent<WarDeclaredEvent>(OnWarDeclared);
|
||||||
SubscribeLocalEvent<CommunicationConsoleCallShuttleAttemptEvent>(OnShuttleCallAttempt);
|
SubscribeLocalEvent<CommunicationConsoleCallShuttleAttemptEvent>(OnShuttleCallAttempt);
|
||||||
@@ -65,7 +66,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
SubscribeLocalEvent<NukeopsRuleComponent, RuleLoadedGridsEvent>(OnRuleLoadedGrids);
|
SubscribeLocalEvent<NukeopsRuleComponent, RuleLoadedGridsEvent>(OnRuleLoadedGrids);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Started(EntityUid uid, NukeopsRuleComponent component, GameRuleComponent gameRule,
|
protected override void Started(EntityUid uid,
|
||||||
|
NukeopsRuleComponent component,
|
||||||
|
GameRuleComponent gameRule,
|
||||||
GameRuleStartedEvent args)
|
GameRuleStartedEvent args)
|
||||||
{
|
{
|
||||||
var eligible = new List<Entity<StationEventEligibleComponent, NpcFactionMemberComponent>>();
|
var eligible = new List<Entity<StationEventEligibleComponent, NpcFactionMemberComponent>>();
|
||||||
@@ -85,7 +88,9 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Event Handlers
|
#region Event Handlers
|
||||||
protected override void AppendRoundEndText(EntityUid uid, NukeopsRuleComponent component, GameRuleComponent gameRule,
|
protected override void AppendRoundEndText(EntityUid uid,
|
||||||
|
NukeopsRuleComponent component,
|
||||||
|
GameRuleComponent gameRule,
|
||||||
ref RoundEndTextAppendEvent args)
|
ref RoundEndTextAppendEvent args)
|
||||||
{
|
{
|
||||||
var winText = Loc.GetString($"nukeops-{component.WinType.ToString().ToLower()}");
|
var winText = Loc.GetString($"nukeops-{component.WinType.ToString().ToLower()}");
|
||||||
@@ -227,7 +232,8 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
|
|
||||||
// If the disk is currently at Central Command, the crew wins - just slightly.
|
// If the disk is currently at Central Command, the crew wins - just slightly.
|
||||||
// This also implies that some nuclear operatives have died.
|
// This also implies that some nuclear operatives have died.
|
||||||
SetWinType(ent, diskAtCentCom
|
SetWinType(ent,
|
||||||
|
diskAtCentCom
|
||||||
? WinType.CrewMinor
|
? WinType.CrewMinor
|
||||||
: WinType.OpsMinor);
|
: WinType.OpsMinor);
|
||||||
ent.Comp.WinConditions.Add(diskAtCentCom
|
ent.Comp.WinConditions.Add(diskAtCentCom
|
||||||
@@ -456,8 +462,11 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
: WinCondition.AllNukiesDead);
|
: WinCondition.AllNukiesDead);
|
||||||
|
|
||||||
SetWinType(ent, WinType.CrewMajor, false);
|
SetWinType(ent, WinType.CrewMajor, false);
|
||||||
_roundEndSystem.DoRoundEndBehavior(
|
_roundEndSystem.DoRoundEndBehavior(nukeops.RoundEndBehavior,
|
||||||
nukeops.RoundEndBehavior, nukeops.EvacShuttleTime, nukeops.RoundEndTextSender, nukeops.RoundEndTextShuttleCall, nukeops.RoundEndTextAnnouncement);
|
nukeops.EvacShuttleTime,
|
||||||
|
nukeops.RoundEndTextSender,
|
||||||
|
nukeops.RoundEndTextShuttleCall,
|
||||||
|
nukeops.RoundEndTextAnnouncement);
|
||||||
|
|
||||||
// prevent it called multiple times
|
// prevent it called multiple times
|
||||||
nukeops.RoundEndBehavior = RoundEndBehavior.Nothing;
|
nukeops.RoundEndBehavior = RoundEndBehavior.Nothing;
|
||||||
@@ -465,16 +474,22 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
|
|
||||||
private void OnAfterAntagEntSelected(Entity<NukeopsRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
|
private void OnAfterAntagEntSelected(Entity<NukeopsRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
|
||||||
{
|
{
|
||||||
if (ent.Comp.TargetStation is not { } station)
|
var target = (ent.Comp.TargetStation is not null) ? Name(ent.Comp.TargetStation.Value) : "the target";
|
||||||
return;
|
|
||||||
|
|
||||||
_antag.SendBriefing(args.Session, Loc.GetString("nukeops-welcome",
|
_antag.SendBriefing(args.Session,
|
||||||
("station", station),
|
Loc.GetString("nukeops-welcome",
|
||||||
|
("station", target),
|
||||||
("name", Name(ent))),
|
("name", Name(ent))),
|
||||||
Color.Red,
|
Color.Red,
|
||||||
ent.Comp.GreetSoundNotification);
|
ent.Comp.GreetSoundNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGetBriefing(Entity<NukeopsRoleComponent> role, ref GetBriefingEvent args)
|
||||||
|
{
|
||||||
|
// TODO Different character screen briefing for the 3 nukie types
|
||||||
|
args.Append(Loc.GetString("nukeops-briefing"));
|
||||||
|
}
|
||||||
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Is this method the shitty glue holding together the last of my sanity? yes.
|
/// Is this method the shitty glue holding together the last of my sanity? yes.
|
||||||
/// Do i have a better solution? not presently.
|
/// Do i have a better solution? not presently.
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ using Content.Shared.Database;
|
|||||||
using Content.Shared.GameTicking.Components;
|
using Content.Shared.GameTicking.Components;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Mind;
|
|
||||||
using Content.Shared.Mind.Components;
|
using Content.Shared.Mind.Components;
|
||||||
using Content.Shared.Mindshield.Components;
|
using Content.Shared.Mindshield.Components;
|
||||||
using Content.Shared.Mobs;
|
using Content.Shared.Mobs;
|
||||||
@@ -38,8 +37,8 @@ namespace Content.Server.GameTicking.Rules;
|
|||||||
public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleComponent>
|
public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleComponent>
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogManager = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogManager = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
|
||||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
||||||
|
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
|
||||||
[Dependency] private readonly EuiManager _euiMan = default!;
|
[Dependency] private readonly EuiManager _euiMan = default!;
|
||||||
[Dependency] private readonly MindSystem _mind = default!;
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
@@ -49,7 +48,7 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
[Dependency] private readonly SharedStunSystem _stun = default!;
|
[Dependency] private readonly SharedStunSystem _stun = default!;
|
||||||
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
||||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||||
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
//Used in OnPostFlash, no reference to the rule component is available
|
//Used in OnPostFlash, no reference to the rule component is available
|
||||||
public readonly ProtoId<NpcFactionPrototype> RevolutionaryNpcFaction = "Revolutionary";
|
public readonly ProtoId<NpcFactionPrototype> RevolutionaryNpcFaction = "Revolutionary";
|
||||||
@@ -59,9 +58,12 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<CommandStaffComponent, MobStateChangedEvent>(OnCommandMobStateChanged);
|
SubscribeLocalEvent<CommandStaffComponent, MobStateChangedEvent>(OnCommandMobStateChanged);
|
||||||
SubscribeLocalEvent<HeadRevolutionaryComponent, MobStateChangedEvent>(OnHeadRevMobStateChanged);
|
|
||||||
SubscribeLocalEvent<RevolutionaryRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
|
||||||
SubscribeLocalEvent<HeadRevolutionaryComponent, AfterFlashedEvent>(OnPostFlash);
|
SubscribeLocalEvent<HeadRevolutionaryComponent, AfterFlashedEvent>(OnPostFlash);
|
||||||
|
SubscribeLocalEvent<HeadRevolutionaryComponent, MobStateChangedEvent>(OnHeadRevMobStateChanged);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<RevolutionaryRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Started(EntityUid uid, RevolutionaryRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
protected override void Started(EntityUid uid, RevolutionaryRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||||
@@ -85,7 +87,9 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AppendRoundEndText(EntityUid uid, RevolutionaryRuleComponent component, GameRuleComponent gameRule,
|
protected override void AppendRoundEndText(EntityUid uid,
|
||||||
|
RevolutionaryRuleComponent component,
|
||||||
|
GameRuleComponent gameRule,
|
||||||
ref RoundEndTextAppendEvent args)
|
ref RoundEndTextAppendEvent args)
|
||||||
{
|
{
|
||||||
base.AppendRoundEndText(uid, component, gameRule, ref args);
|
base.AppendRoundEndText(uid, component, gameRule, ref args);
|
||||||
@@ -101,7 +105,9 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
args.AddLine(Loc.GetString("rev-headrev-count", ("initialCount", sessionData.Count)));
|
args.AddLine(Loc.GetString("rev-headrev-count", ("initialCount", sessionData.Count)));
|
||||||
foreach (var (mind, data, name) in sessionData)
|
foreach (var (mind, data, name) in sessionData)
|
||||||
{
|
{
|
||||||
var count = CompOrNull<RevolutionaryRoleComponent>(mind)?.ConvertedCount ?? 0;
|
_role.MindHasRole<RevolutionaryRoleComponent>(mind, out var role);
|
||||||
|
var count = CompOrNull<RevolutionaryRoleComponent>(role)?.ConvertedCount ?? 0;
|
||||||
|
|
||||||
args.AddLine(Loc.GetString("rev-headrev-name-user",
|
args.AddLine(Loc.GetString("rev-headrev-name-user",
|
||||||
("name", name),
|
("name", name),
|
||||||
("username", data.UserName),
|
("username", data.UserName),
|
||||||
@@ -113,10 +119,8 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
|
|
||||||
private void OnGetBriefing(EntityUid uid, RevolutionaryRoleComponent comp, ref GetBriefingEvent args)
|
private void OnGetBriefing(EntityUid uid, RevolutionaryRoleComponent comp, ref GetBriefingEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindComponent>(uid, out var mind) || mind.OwnedEntity == null)
|
var ent = args.Mind.Comp.OwnedEntity;
|
||||||
return;
|
var head = HasComp<HeadRevolutionaryComponent>(ent);
|
||||||
|
|
||||||
var head = HasComp<HeadRevolutionaryComponent>(mind.OwnedEntity);
|
|
||||||
args.Append(Loc.GetString(head ? "head-rev-briefing" : "rev-briefing"));
|
args.Append(Loc.GetString(head ? "head-rev-briefing" : "rev-briefing"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,15 +149,20 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
|
|
||||||
if (ev.User != null)
|
if (ev.User != null)
|
||||||
{
|
{
|
||||||
_adminLogManager.Add(LogType.Mind, LogImpact.Medium, $"{ToPrettyString(ev.User.Value)} converted {ToPrettyString(ev.Target)} into a Revolutionary");
|
_adminLogManager.Add(LogType.Mind,
|
||||||
|
LogImpact.Medium,
|
||||||
|
$"{ToPrettyString(ev.User.Value)} converted {ToPrettyString(ev.Target)} into a Revolutionary");
|
||||||
|
|
||||||
if (_mind.TryGetRole<RevolutionaryRoleComponent>(ev.User.Value, out var headrev))
|
if (_mind.TryGetMind(ev.User.Value, out var revMindId, out _))
|
||||||
headrev.ConvertedCount++;
|
{
|
||||||
|
if (_role.MindHasRole<RevolutionaryRoleComponent>(revMindId, out _, out var role))
|
||||||
|
role.Value.Comp.ConvertedCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mindId == default || !_role.MindHasRole<RevolutionaryRoleComponent>(mindId))
|
if (mindId == default || !_role.MindHasRole<RevolutionaryRoleComponent>(mindId))
|
||||||
{
|
{
|
||||||
_role.MindAddRole(mindId, new RevolutionaryRoleComponent { PrototypeId = RevPrototypeId });
|
_role.MindAddRole(mindId, "MindRoleRevolutionary");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mind?.Session != null)
|
if (mind?.Session != null)
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
using Content.Server.Antag;
|
using Content.Server.Antag;
|
||||||
using Content.Server.GameTicking.Rules.Components;
|
using Content.Server.GameTicking.Rules.Components;
|
||||||
using Content.Server.Mind;
|
|
||||||
using Content.Server.Objectives;
|
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Mind;
|
|
||||||
using Content.Shared.Objectives.Components;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Server.GameTicking.Rules;
|
namespace Content.Server.GameTicking.Rules;
|
||||||
|
|
||||||
public sealed class ThiefRuleSystem : GameRuleSystem<ThiefRuleComponent>
|
public sealed class ThiefRuleSystem : GameRuleSystem<ThiefRuleComponent>
|
||||||
{
|
{
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
|
||||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -24,32 +18,33 @@ public sealed class ThiefRuleSystem : GameRuleSystem<ThiefRuleComponent>
|
|||||||
SubscribeLocalEvent<ThiefRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
SubscribeLocalEvent<ThiefRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AfterAntagSelected(Entity<ThiefRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
|
// Greeting upon thief activation
|
||||||
|
private void AfterAntagSelected(Entity<ThiefRuleComponent> mindId, ref AfterAntagEntitySelectedEvent args)
|
||||||
{
|
{
|
||||||
if (!_mindSystem.TryGetMind(args.EntityUid, out var mindId, out var mind))
|
var ent = args.EntityUid;
|
||||||
return;
|
_antag.SendBriefing(ent, MakeBriefing(ent), null, null);
|
||||||
|
|
||||||
//Generate objectives
|
|
||||||
_antag.SendBriefing(args.EntityUid, MakeBriefing(args.EntityUid), null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add mind briefing
|
// Character screen briefing
|
||||||
private void OnGetBriefing(Entity<ThiefRoleComponent> thief, ref GetBriefingEvent args)
|
private void OnGetBriefing(Entity<ThiefRoleComponent> role, ref GetBriefingEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindComponent>(thief.Owner, out var mind) || mind.OwnedEntity == null)
|
var ent = args.Mind.Comp.OwnedEntity;
|
||||||
return;
|
|
||||||
|
|
||||||
args.Append(MakeBriefing(mind.OwnedEntity.Value));
|
if (ent is null)
|
||||||
|
return;
|
||||||
|
args.Append(MakeBriefing(ent.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MakeBriefing(EntityUid thief)
|
private string MakeBriefing(EntityUid ent)
|
||||||
{
|
{
|
||||||
var isHuman = HasComp<HumanoidAppearanceComponent>(thief);
|
var isHuman = HasComp<HumanoidAppearanceComponent>(ent);
|
||||||
var briefing = isHuman
|
var briefing = isHuman
|
||||||
? Loc.GetString("thief-role-greeting-human")
|
? Loc.GetString("thief-role-greeting-human")
|
||||||
: Loc.GetString("thief-role-greeting-animal");
|
: Loc.GetString("thief-role-greeting-animal");
|
||||||
|
|
||||||
briefing += "\n \n" + Loc.GetString("thief-role-greeting-equipment") + "\n";
|
if (isHuman)
|
||||||
|
briefing += "\n \n" + Loc.GetString("thief-role-greeting-equipment") + "\n";
|
||||||
|
|
||||||
return briefing;
|
return briefing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ using Content.Shared.Database;
|
|||||||
using Content.Shared.GameTicking.Components;
|
using Content.Shared.GameTicking.Components;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.NPC.Systems;
|
using Content.Shared.NPC.Systems;
|
||||||
using Content.Shared.Objectives.Components;
|
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Shared.Radio;
|
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Roles.Jobs;
|
using Content.Shared.Roles.Jobs;
|
||||||
using Content.Shared.Roles.RoleCodeword;
|
using Content.Shared.Roles.RoleCodeword;
|
||||||
@@ -28,22 +26,21 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
private static readonly Color TraitorCodewordColor = Color.FromHex("#cc3b3b");
|
private static readonly Color TraitorCodewordColor = Color.FromHex("#cc3b3b");
|
||||||
|
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[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 IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
|
|
||||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
|
||||||
[Dependency] private readonly UplinkSystem _uplink = default!;
|
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
|
||||||
[Dependency] private readonly SharedRoleSystem _roleSystem = default!;
|
|
||||||
[Dependency] private readonly SharedJobSystem _jobs = default!;
|
|
||||||
[Dependency] private readonly SharedRoleCodewordSystem _roleCodewordSystem = default!;
|
[Dependency] private readonly SharedRoleCodewordSystem _roleCodewordSystem = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roleSystem = default!;
|
||||||
|
[Dependency] private readonly UplinkSystem _uplink = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<TraitorRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);
|
SubscribeLocalEvent<TraitorRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);
|
||||||
|
|
||||||
SubscribeLocalEvent<TraitorRuleComponent, ObjectivesTextPrependEvent>(OnObjectivesTextPrepend);
|
SubscribeLocalEvent<TraitorRuleComponent, ObjectivesTextPrependEvent>(OnObjectivesTextPrepend);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +77,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
|
|
||||||
public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool giveUplink = true)
|
public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool giveUplink = true)
|
||||||
{
|
{
|
||||||
//Grab the mind if it wasnt provided
|
//Grab the mind if it wasn't provided
|
||||||
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
|
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -92,7 +89,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
{
|
{
|
||||||
// Calculate the amount of currency on the uplink.
|
// Calculate the amount of currency on the uplink.
|
||||||
var startingBalance = component.StartingBalance;
|
var startingBalance = component.StartingBalance;
|
||||||
if (_jobs.MindTryGetJob(mindId, out _, out var prototype))
|
if (_jobs.MindTryGetJob(mindId, out var prototype))
|
||||||
startingBalance = Math.Max(startingBalance - prototype.AntagAdvantage, 0);
|
startingBalance = Math.Max(startingBalance - prototype.AntagAdvantage, 0);
|
||||||
|
|
||||||
// creadth: we need to create uplink for the antag.
|
// creadth: we need to create uplink for the antag.
|
||||||
@@ -111,14 +108,18 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
|
|
||||||
_antag.SendBriefing(traitor, GenerateBriefing(component.Codewords, code, issuer), null, component.GreetSoundNotification);
|
_antag.SendBriefing(traitor, GenerateBriefing(component.Codewords, code, issuer), null, component.GreetSoundNotification);
|
||||||
|
|
||||||
|
|
||||||
component.TraitorMinds.Add(mindId);
|
component.TraitorMinds.Add(mindId);
|
||||||
|
|
||||||
// Assign briefing
|
// Assign briefing
|
||||||
_roleSystem.MindAddRole(mindId, new RoleBriefingComponent
|
//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)
|
||||||
{
|
{
|
||||||
Briefing = briefing
|
AddComp<RoleBriefingComponent>(traitorRole.Value.Owner);
|
||||||
}, mind, true);
|
Comp<RoleBriefingComponent>(traitorRole.Value.Owner).Briefing = briefing;
|
||||||
|
}
|
||||||
|
|
||||||
// Send codewords to only the traitor client
|
// Send codewords to only the traitor client
|
||||||
var color = TraitorCodewordColor; // Fall back to a dark red Syndicate color if a prototype is not found
|
var color = TraitorCodewordColor; // Fall back to a dark red Syndicate color if a prototype is not found
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using Content.Shared.Mind;
|
|||||||
using Content.Shared.Mobs;
|
using Content.Shared.Mobs;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Zombies;
|
using Content.Shared.Zombies;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -22,15 +23,16 @@ namespace Content.Server.GameTicking.Rules;
|
|||||||
|
|
||||||
public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ChatSystem _chat = default!;
|
|
||||||
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
|
||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
|
||||||
[Dependency] private readonly ZombieSystem _zombie = default!;
|
|
||||||
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
|
||||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
||||||
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
|
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
|
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
||||||
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly ZombieSystem _zombie = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -41,23 +43,20 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
SubscribeLocalEvent<IncurableZombieComponent, ZombifySelfActionEvent>(OnZombifySelf);
|
SubscribeLocalEvent<IncurableZombieComponent, ZombifySelfActionEvent>(OnZombifySelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetBriefing(EntityUid uid, InitialInfectedRoleComponent component, ref GetBriefingEvent args)
|
private void OnGetBriefing(Entity<InitialInfectedRoleComponent> role, ref GetBriefingEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindComponent>(uid, out var mind) || mind.OwnedEntity == null)
|
if (!_roles.MindHasRole<ZombieRoleComponent>(args.Mind.Owner))
|
||||||
return;
|
args.Append(Loc.GetString("zombie-patientzero-role-greeting"));
|
||||||
if (HasComp<ZombieRoleComponent>(uid)) // don't show both briefings
|
|
||||||
return;
|
|
||||||
args.Append(Loc.GetString("zombie-patientzero-role-greeting"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetBriefing(EntityUid uid, ZombieRoleComponent component, ref GetBriefingEvent args)
|
private void OnGetBriefing(Entity<ZombieRoleComponent> role, ref GetBriefingEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindComponent>(uid, out var mind) || mind.OwnedEntity == null)
|
|
||||||
return;
|
|
||||||
args.Append(Loc.GetString("zombie-infection-greeting"));
|
args.Append(Loc.GetString("zombie-infection-greeting"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AppendRoundEndText(EntityUid uid, ZombieRuleComponent component, GameRuleComponent gameRule,
|
protected override void AppendRoundEndText(EntityUid uid,
|
||||||
|
ZombieRuleComponent component,
|
||||||
|
GameRuleComponent gameRule,
|
||||||
ref RoundEndTextAppendEvent args)
|
ref RoundEndTextAppendEvent args)
|
||||||
{
|
{
|
||||||
base.AppendRoundEndText(uid, component, gameRule, ref args);
|
base.AppendRoundEndText(uid, component, gameRule, ref args);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
namespace Content.Server.Ghost.Roles;
|
using Content.Shared.Roles;
|
||||||
|
|
||||||
|
namespace Content.Server.Ghost.Roles;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is used for round end display of ghost roles.
|
/// This is used for round end display of ghost roles.
|
||||||
/// It may also be used to ensure some ghost roles count as antagonists in future.
|
/// It may also be used to ensure some ghost roles count as antagonists in future.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class GhostRoleMarkerRoleComponent : Component
|
public sealed partial class GhostRoleMarkerRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
[DataField("name")] public string? Name;
|
[DataField("name")] public string? Name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,18 +71,22 @@ public sealed class GhostRoleSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
|
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
|
||||||
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
|
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
|
||||||
|
|
||||||
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindAddedMessage>(OnMindAdded);
|
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindAddedMessage>(OnMindAdded);
|
||||||
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindRemovedMessage>(OnMindRemoved);
|
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindRemovedMessage>(OnMindRemoved);
|
||||||
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
|
SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
|
||||||
|
|
||||||
SubscribeLocalEvent<GhostRoleComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<GhostRoleComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<GhostRoleComponent, ComponentStartup>(OnRoleStartup);
|
SubscribeLocalEvent<GhostRoleComponent, ComponentStartup>(OnRoleStartup);
|
||||||
SubscribeLocalEvent<GhostRoleComponent, ComponentShutdown>(OnRoleShutdown);
|
SubscribeLocalEvent<GhostRoleComponent, ComponentShutdown>(OnRoleShutdown);
|
||||||
SubscribeLocalEvent<GhostRoleComponent, EntityPausedEvent>(OnPaused);
|
SubscribeLocalEvent<GhostRoleComponent, EntityPausedEvent>(OnPaused);
|
||||||
SubscribeLocalEvent<GhostRoleComponent, EntityUnpausedEvent>(OnUnpaused);
|
SubscribeLocalEvent<GhostRoleComponent, EntityUnpausedEvent>(OnUnpaused);
|
||||||
|
|
||||||
SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentInit>(OnRaffleInit);
|
SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentInit>(OnRaffleInit);
|
||||||
SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentShutdown>(OnRaffleShutdown);
|
SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentShutdown>(OnRaffleShutdown);
|
||||||
|
|
||||||
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
|
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
|
||||||
SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
|
|
||||||
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GetVerbsEvent<Verb>>(OnVerb);
|
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GetVerbsEvent<Verb>>(OnVerb);
|
||||||
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GhostRoleRadioMessage>(OnGhostRoleRadioMessage);
|
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GhostRoleRadioMessage>(OnGhostRoleRadioMessage);
|
||||||
_playerManager.PlayerStatusChanged += PlayerStatusChanged;
|
_playerManager.PlayerStatusChanged += PlayerStatusChanged;
|
||||||
@@ -509,7 +513,11 @@ public sealed class GhostRoleSystem : EntitySystem
|
|||||||
|
|
||||||
var newMind = _mindSystem.CreateMind(player.UserId,
|
var newMind = _mindSystem.CreateMind(player.UserId,
|
||||||
EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
|
EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
|
||||||
_roleSystem.MindAddRole(newMind, new GhostRoleMarkerRoleComponent { Name = role.RoleName });
|
|
||||||
|
_roleSystem.MindAddRole(newMind, "MindRoleGhostMarker");
|
||||||
|
|
||||||
|
if(_roleSystem.MindHasRole<GhostRoleMarkerRoleComponent>(newMind, out _, out var markerRole))
|
||||||
|
markerRole.Value.Comp.Name = role.RoleName;
|
||||||
|
|
||||||
_mindSystem.SetUserId(newMind, player.UserId);
|
_mindSystem.SetUserId(newMind, player.UserId);
|
||||||
_mindSystem.TransferTo(newMind, mob);
|
_mindSystem.TransferTo(newMind, mob);
|
||||||
@@ -602,10 +610,7 @@ public sealed class GhostRoleSystem : EntitySystem
|
|||||||
|
|
||||||
if (ghostRole.JobProto != null)
|
if (ghostRole.JobProto != null)
|
||||||
{
|
{
|
||||||
if (HasComp<JobComponent>(args.Mind))
|
_roleSystem.MindAddJobRole(args.Mind, args.Mind, silent:false,ghostRole.JobProto);
|
||||||
_roleSystem.MindRemoveRole<JobComponent>(args.Mind);
|
|
||||||
|
|
||||||
_roleSystem.MindAddRole(args.Mind, new JobComponent { Prototype = ghostRole.JobProto });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ghostRole.Taken = true;
|
ghostRole.Taken = true;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Content.Server.Mind.Commands
|
|||||||
builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedEntity);
|
builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedEntity);
|
||||||
|
|
||||||
var roles = _entities.System<SharedRoleSystem>();
|
var roles = _entities.System<SharedRoleSystem>();
|
||||||
foreach (var role in roles.MindGetAllRoles(mindId))
|
foreach (var role in roles.MindGetAllRoleInfo(mindId))
|
||||||
{
|
{
|
||||||
builder.AppendFormat("{0} ", role.Name);
|
builder.AppendFormat("{0} ", role.Name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public sealed class KillPersonConditionSystem : EntitySystem
|
|||||||
foreach (var mind in allHumans)
|
foreach (var mind in allHumans)
|
||||||
{
|
{
|
||||||
// RequireAdminNotify used as a cheap way to check for command department
|
// RequireAdminNotify used as a cheap way to check for command department
|
||||||
if (_job.MindTryGetJob(mind, out _, out var prototype) && prototype.RequireAdminNotify)
|
if (_job.MindTryGetJob(mind, out var prototype) && prototype.RequireAdminNotify)
|
||||||
allHeads.Add(mind);
|
allHeads.Add(mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using Content.Server.Objectives.Components;
|
using Content.Server.Objectives.Components;
|
||||||
|
using Content.Server.Roles;
|
||||||
using Content.Server.Warps;
|
using Content.Server.Warps;
|
||||||
using Content.Shared.Objectives.Components;
|
using Content.Shared.Objectives.Components;
|
||||||
using Content.Shared.Ninja.Components;
|
using Content.Shared.Ninja.Components;
|
||||||
|
using Content.Shared.Roles;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Content.Server.Roles;
|
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Systems;
|
namespace Content.Server.Objectives.Systems;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ public sealed class NinjaConditionsSystem : EntitySystem
|
|||||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
[Dependency] private readonly NumberObjectiveSystem _number = default!;
|
[Dependency] private readonly NumberObjectiveSystem _number = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -46,10 +48,8 @@ public sealed class NinjaConditionsSystem : EntitySystem
|
|||||||
// spider charge
|
// spider charge
|
||||||
private void OnSpiderChargeRequirementCheck(EntityUid uid, SpiderChargeConditionComponent comp, ref RequirementCheckEvent args)
|
private void OnSpiderChargeRequirementCheck(EntityUid uid, SpiderChargeConditionComponent comp, ref RequirementCheckEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || !HasComp<NinjaRoleComponent>(args.MindId))
|
if (args.Cancelled || !_roles.MindHasRole<NinjaRoleComponent>(args.MindId))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// choose spider charge detonation point
|
// choose spider charge detonation point
|
||||||
var warps = new List<EntityUid>();
|
var warps = new List<EntityUid>();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public sealed class NotCommandRequirementSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// cheap equivalent to checking that job department is command, since all command members require admin notification when leaving
|
// cheap equivalent to checking that job department is command, since all command members require admin notification when leaving
|
||||||
if (_job.MindTryGetJob(args.MindId, out _, out var prototype) && prototype.RequireAdminNotify)
|
if (_job.MindTryGetJob(args.MindId, out var prototype) && prototype.RequireAdminNotify)
|
||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace Content.Server.Objectives.Systems;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class NotJobRequirementSystem : EntitySystem
|
public sealed class NotJobRequirementSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly SharedJobSystem _jobs = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -20,11 +22,10 @@ public sealed class NotJobRequirementSystem : EntitySystem
|
|||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if player has no job then don't care
|
_jobs.MindTryGetJob(args.MindId, out var proto);
|
||||||
if (!TryComp<JobComponent>(args.MindId, out var job))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (job.Prototype == comp.Job)
|
// if player has no job then don't care
|
||||||
|
if (proto is not null && proto.ID == comp.Job)
|
||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ public sealed class RoleRequirementSystem : EntitySystem
|
|||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// this whitelist trick only works because roles are components on the mind and not entities
|
|
||||||
// if that gets reworked then this will need changing
|
|
||||||
if (_whitelistSystem.IsWhitelistFail(comp.Roles, args.MindId))
|
if (_whitelistSystem.IsWhitelistFail(comp.Roles, args.MindId))
|
||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,14 +30,15 @@ namespace Content.Server.Players.PlayTimeTracking;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PlayTimeTrackingSystem : EntitySystem
|
public sealed class PlayTimeTrackingSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||||
[Dependency] private readonly IAfkManager _afk = default!;
|
[Dependency] private readonly IAfkManager _afk = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
||||||
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
|
||||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
[Dependency] private readonly MindSystem _minds = default!;
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
[Dependency] private readonly PlayTimeTrackingManager _tracking = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
|
||||||
[Dependency] private readonly IServerPreferencesManager _preferencesManager = default!;
|
[Dependency] private readonly IServerPreferencesManager _preferencesManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
|
[Dependency] private readonly PlayTimeTrackingManager _tracking = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -101,10 +102,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
|
|||||||
|
|
||||||
public IEnumerable<string> GetTimedRoles(EntityUid mindId)
|
public IEnumerable<string> GetTimedRoles(EntityUid mindId)
|
||||||
{
|
{
|
||||||
var ev = new MindGetAllRolesEvent(new List<RoleInfo>());
|
foreach (var role in _roles.MindGetAllRoleInfo(mindId))
|
||||||
RaiseLocalEvent(mindId, ref ev);
|
|
||||||
|
|
||||||
foreach (var role in ev.Roles)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(role.PlayTimeTrackerId))
|
if (string.IsNullOrWhiteSpace(role.PlayTimeTrackerId))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -10,3 +10,5 @@ public sealed partial class CommandStaffComponent : Component
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO this should probably be on a mind role, not the mob
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ using Content.Shared.Roles;
|
|||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Role used to keep track of space dragons for antag purposes.
|
/// Added to mind role entities to tag that they are a space dragon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, Access(typeof(DragonSystem)), ExclusiveAntagonist]
|
[RegisterComponent, Access(typeof(DragonSystem))]
|
||||||
public sealed partial class DragonRoleComponent : AntagonistRoleComponent
|
public sealed partial class DragonRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ using Content.Shared.Roles;
|
|||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
[RegisterComponent, ExclusiveAntagonist]
|
/// <summary>
|
||||||
public sealed partial class InitialInfectedRoleComponent : AntagonistRoleComponent
|
/// Added to mind role entities to tag that they are an initial infected.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class InitialInfectedRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public sealed class JobSystem : SharedJobSystem
|
|||||||
if (!_mind.TryGetSession(mindId, out var session))
|
if (!_mind.TryGetSession(mindId, out var session))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!MindTryGetJob(mindId, out _, out var prototype))
|
if (!MindTryGetJob(mindId, out var prototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_chat.DispatchServerMessage(session, Loc.GetString("job-greet-introduce-job-name",
|
_chat.DispatchServerMessage(session, Loc.GetString("job-greet-introduce-job-name",
|
||||||
@@ -47,6 +47,6 @@ public sealed class JobSystem : SharedJobSystem
|
|||||||
if (MindHasJobWithId(mindId, jobPrototypeId))
|
if (MindHasJobWithId(mindId, jobPrototypeId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_roles.MindAddRole(mindId, new JobComponent { Prototype = jobPrototypeId });
|
_roles.MindAddJobRole(mindId, null, false, jobPrototypeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ using Content.Shared.Roles;
|
|||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
[RegisterComponent, ExclusiveAntagonist]
|
/// <summary>
|
||||||
public sealed partial class NinjaRoleComponent : AntagonistRoleComponent
|
/// Added to mind role entities to tag that they are a space ninja.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class NinjaRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ using Content.Shared.Roles;
|
|||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Added to mind entities to tag that they are a nuke operative.
|
/// Added to mind role entities to tag that they are a nuke operative.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, ExclusiveAntagonist]
|
[RegisterComponent]
|
||||||
public sealed partial class NukeopsRoleComponent : AntagonistRoleComponent
|
public sealed partial class NukeopsRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace Content.Server.Roles
|
|||||||
var roles = _entityManager.System<SharedRoleSystem>();
|
var roles = _entityManager.System<SharedRoleSystem>();
|
||||||
var jobs = _entityManager.System<SharedJobSystem>();
|
var jobs = _entityManager.System<SharedJobSystem>();
|
||||||
if (jobs.MindHasJobWithId(mind, args[1]))
|
if (jobs.MindHasJobWithId(mind, args[1]))
|
||||||
roles.MindRemoveRole<JobComponent>(mind.Value);
|
roles.MindTryRemoveRole<JobRoleComponent>(mind.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ using Content.Shared.Roles;
|
|||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Added to mind entities to tag that they are a Revolutionary.
|
/// Added to mind role entities to tag that they are a Revolutionary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, ExclusiveAntagonist]
|
[RegisterComponent]
|
||||||
public sealed partial class RevolutionaryRoleComponent : AntagonistRoleComponent
|
public sealed partial class RevolutionaryRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For headrevs, how many people you have converted.
|
/// For headrevs, how many people you have converted.
|
||||||
|
|||||||
@@ -1,32 +1,40 @@
|
|||||||
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
public sealed class RoleSystem : SharedRoleSystem
|
public sealed class RoleSystem : SharedRoleSystem
|
||||||
{
|
{
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
// TODO make roles entities
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeAntagEvents<DragonRoleComponent>();
|
|
||||||
SubscribeAntagEvents<InitialInfectedRoleComponent>();
|
|
||||||
SubscribeAntagEvents<NinjaRoleComponent>();
|
|
||||||
SubscribeAntagEvents<NukeopsRoleComponent>();
|
|
||||||
SubscribeAntagEvents<RevolutionaryRoleComponent>();
|
|
||||||
SubscribeAntagEvents<SubvertedSiliconRoleComponent>();
|
|
||||||
SubscribeAntagEvents<TraitorRoleComponent>();
|
|
||||||
SubscribeAntagEvents<ZombieRoleComponent>();
|
|
||||||
SubscribeAntagEvents<ThiefRoleComponent>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string? MindGetBriefing(EntityUid? mindId)
|
public string? MindGetBriefing(EntityUid? mindId)
|
||||||
{
|
{
|
||||||
if (mindId == null)
|
if (mindId == null)
|
||||||
|
{
|
||||||
|
Log.Error($"MingGetBriefing failed for mind {mindId}");
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TryComp<MindComponent>(mindId.Value, out var mindComp);
|
||||||
|
|
||||||
|
if (mindComp is null)
|
||||||
|
{
|
||||||
|
Log.Error($"MingGetBriefing failed for mind {mindId}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var ev = new GetBriefingEvent();
|
var ev = new GetBriefingEvent();
|
||||||
RaiseLocalEvent(mindId.Value, ref ev);
|
|
||||||
|
// This is on the event because while this Entity<T> is also present on every Mind Role Entity's MindRoleComp
|
||||||
|
// getting to there from a GetBriefing event subscription can be somewhat boilerplate
|
||||||
|
// and this needs to be looked up for the event anyway so why calculate it again later
|
||||||
|
ev.Mind = (mindId.Value, mindComp);
|
||||||
|
|
||||||
|
// Briefing is no longer raised on the mind entity itself
|
||||||
|
// because all the components that briefings subscribe to should be on Mind Role Entities
|
||||||
|
foreach(var role in mindComp.MindRoles)
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(role, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
return ev.Briefing;
|
return ev.Briefing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,8 +46,16 @@ public sealed class RoleSystem : SharedRoleSystem
|
|||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public sealed class GetBriefingEvent
|
public sealed class GetBriefingEvent
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The text that will be shown on the Character Screen
|
||||||
|
/// </summary>
|
||||||
public string? Briefing;
|
public string? Briefing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Mind to whose Mind Role Entities the briefing is sent to
|
||||||
|
/// </summary>
|
||||||
|
public Entity<MindComponent> Mind;
|
||||||
|
|
||||||
public GetBriefingEvent(string? briefing = null)
|
public GetBriefingEvent(string? briefing = null)
|
||||||
{
|
{
|
||||||
Briefing = briefing;
|
Briefing = briefing;
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to mind role entities to tag that they are a hacked borg.
|
||||||
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class SubvertedSiliconRoleComponent : AntagonistRoleComponent
|
public sealed partial class SubvertedSiliconRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ using Content.Shared.Roles;
|
|||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to mind role entities to tag that they are a thief.
|
||||||
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class ThiefRoleComponent : AntagonistRoleComponent
|
public sealed partial class ThiefRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ using Content.Shared.Roles;
|
|||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
[RegisterComponent, ExclusiveAntagonist]
|
/// <summary>
|
||||||
public sealed partial class TraitorRoleComponent : AntagonistRoleComponent
|
/// Added to mind role entities to tag that they are a syndicate traitor.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class TraitorRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ using Content.Shared.Roles;
|
|||||||
|
|
||||||
namespace Content.Server.Roles;
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
[RegisterComponent, ExclusiveAntagonist]
|
/// <summary>
|
||||||
public sealed partial class ZombieRoleComponent : AntagonistRoleComponent
|
/// Added to mind role entities to tag that they are a zombie.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class ZombieRoleComponent : BaseMindRoleComponent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ namespace Content.Server.Silicons.Laws;
|
|||||||
public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
|
||||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
|
||||||
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
|
||||||
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
|
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
||||||
|
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -178,10 +178,8 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
|||||||
if (component.AntagonistRole == null || !_mind.TryGetMind(uid, out var mindId, out _))
|
if (component.AntagonistRole == null || !_mind.TryGetMind(uid, out var mindId, out _))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_roles.MindHasRole<SubvertedSiliconRoleComponent>(mindId))
|
if (!_roles.MindHasRole<SubvertedSiliconRoleComponent>(mindId))
|
||||||
return;
|
_roles.MindAddRole(mindId, "MindRoleSubvertedSilicon");
|
||||||
|
|
||||||
_roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null)
|
public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null)
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ namespace Content.Server.Spawners.EntitySystems;
|
|||||||
|
|
||||||
public sealed class ContainerSpawnPointSystem : EntitySystem
|
public sealed class ContainerSpawnPointSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
|
||||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
|
||||||
[Dependency] private readonly ContainerSystem _container = default!;
|
[Dependency] private readonly ContainerSystem _container = default!;
|
||||||
|
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
|
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ public sealed class ContainerSpawnPointSystem : EntitySystem
|
|||||||
|
|
||||||
// If it's just a spawn pref check if it's for cryo (silly).
|
// If it's just a spawn pref check if it's for cryo (silly).
|
||||||
if (args.HumanoidCharacterProfile?.SpawnPriority != SpawnPriorityPreference.Cryosleep &&
|
if (args.HumanoidCharacterProfile?.SpawnPriority != SpawnPriorityPreference.Cryosleep &&
|
||||||
(!_proto.TryIndex(args.Job?.Prototype, out var jobProto) || jobProto.JobEntity == null))
|
(!_proto.TryIndex(args.Job, out var jobProto) || jobProto.JobEntity == null))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ public sealed class ContainerSpawnPointSystem : EntitySystem
|
|||||||
if (spawnPoint.SpawnType == SpawnPointType.Unset)
|
if (spawnPoint.SpawnType == SpawnPointType.Unset)
|
||||||
{
|
{
|
||||||
// make sure we also check the job here for various reasons.
|
// make sure we also check the job here for various reasons.
|
||||||
if (spawnPoint.Job == null || spawnPoint.Job == args.Job?.Prototype)
|
if (spawnPoint.Job == null || spawnPoint.Job == args.Job)
|
||||||
possibleContainers.Add((uid, spawnPoint, container, xform));
|
possibleContainers.Add((uid, spawnPoint, container, xform));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ public sealed class ContainerSpawnPointSystem : EntitySystem
|
|||||||
|
|
||||||
if (_gameTicker.RunLevel != GameRunLevel.InRound &&
|
if (_gameTicker.RunLevel != GameRunLevel.InRound &&
|
||||||
spawnPoint.SpawnType == SpawnPointType.Job &&
|
spawnPoint.SpawnType == SpawnPointType.Job &&
|
||||||
(args.Job == null || spawnPoint.Job == args.Job.Prototype))
|
(args.Job == null || spawnPoint.Job == args.Job))
|
||||||
{
|
{
|
||||||
possibleContainers.Add((uid, spawnPoint, container, xform));
|
possibleContainers.Add((uid, spawnPoint, container, xform));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public sealed class SpawnPointSystem : EntitySystem
|
|||||||
|
|
||||||
if (_gameTicker.RunLevel != GameRunLevel.InRound &&
|
if (_gameTicker.RunLevel != GameRunLevel.InRound &&
|
||||||
spawnPoint.SpawnType == SpawnPointType.Job &&
|
spawnPoint.SpawnType == SpawnPointType.Job &&
|
||||||
(args.Job == null || spawnPoint.Job == args.Job.Prototype))
|
(args.Job == null || spawnPoint.Job == args.Job))
|
||||||
{
|
{
|
||||||
possiblePositions.Add(xform.Coordinates);
|
possiblePositions.Add(xform.Coordinates);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Server.Access.Systems;
|
using Content.Server.Access.Systems;
|
||||||
using Content.Server.DetailExaminable;
|
using Content.Server.DetailExaminable;
|
||||||
using Content.Server.Humanoid;
|
using Content.Server.Humanoid;
|
||||||
@@ -17,13 +16,10 @@ using Content.Shared.Humanoid.Prototypes;
|
|||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Preferences.Loadouts;
|
using Content.Shared.Preferences.Loadouts;
|
||||||
using Content.Shared.Preferences.Loadouts.Effects;
|
|
||||||
using Content.Shared.Random;
|
using Content.Shared.Random;
|
||||||
using Content.Shared.Random.Helpers;
|
using Content.Shared.Random.Helpers;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Roles.Jobs;
|
|
||||||
using Content.Shared.Station;
|
using Content.Shared.Station;
|
||||||
using Content.Shared.StatusIcon;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
@@ -41,16 +37,18 @@ namespace Content.Server.Station.Systems;
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
[Dependency] private readonly SharedAccessSystem _accessSystem = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
|
||||||
[Dependency] private readonly ActorSystem _actors = default!;
|
[Dependency] private readonly ActorSystem _actors = default!;
|
||||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
[Dependency] private readonly ArrivalsSystem _arrivalsSystem = default!;
|
||||||
[Dependency] private readonly IdCardSystem _cardSystem = default!;
|
[Dependency] private readonly IdCardSystem _cardSystem = default!;
|
||||||
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||||
|
[Dependency] private readonly ContainerSpawnPointSystem _containerSpawnPointSystem = default!;
|
||||||
|
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
||||||
[Dependency] private readonly IdentitySystem _identity = default!;
|
[Dependency] private readonly IdentitySystem _identity = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
|
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
|
||||||
[Dependency] private readonly PdaSystem _pdaSystem = default!;
|
[Dependency] private readonly PdaSystem _pdaSystem = default!;
|
||||||
[Dependency] private readonly SharedAccessSystem _accessSystem = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
private bool _randomizeCharacters;
|
private bool _randomizeCharacters;
|
||||||
|
|
||||||
@@ -73,7 +71,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This only spawns the character, and does none of the mind-related setup you'd need for it to be playable.
|
/// This only spawns the character, and does none of the mind-related setup you'd need for it to be playable.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public EntityUid? SpawnPlayerCharacterOnStation(EntityUid? station, JobComponent? job, HumanoidCharacterProfile? profile, StationSpawningComponent? stationSpawning = null)
|
public EntityUid? SpawnPlayerCharacterOnStation(EntityUid? station, ProtoId<JobPrototype>? job, HumanoidCharacterProfile? profile, StationSpawningComponent? stationSpawning = null)
|
||||||
{
|
{
|
||||||
if (station != null && !Resolve(station.Value, ref stationSpawning))
|
if (station != null && !Resolve(station.Value, ref stationSpawning))
|
||||||
throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
|
throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
|
||||||
@@ -101,12 +99,12 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
|||||||
/// <returns>The spawned entity</returns>
|
/// <returns>The spawned entity</returns>
|
||||||
public EntityUid SpawnPlayerMob(
|
public EntityUid SpawnPlayerMob(
|
||||||
EntityCoordinates coordinates,
|
EntityCoordinates coordinates,
|
||||||
JobComponent? job,
|
ProtoId<JobPrototype>? job,
|
||||||
HumanoidCharacterProfile? profile,
|
HumanoidCharacterProfile? profile,
|
||||||
EntityUid? station,
|
EntityUid? station,
|
||||||
EntityUid? entity = null)
|
EntityUid? entity = null)
|
||||||
{
|
{
|
||||||
_prototypeManager.TryIndex(job?.Prototype ?? string.Empty, out var prototype);
|
_prototypeManager.TryIndex(job ?? string.Empty, out var prototype);
|
||||||
RoleLoadout? loadout = null;
|
RoleLoadout? loadout = null;
|
||||||
|
|
||||||
// Need to get the loadout up-front to handle names if we use an entity spawn override.
|
// Need to get the loadout up-front to handle names if we use an entity spawn override.
|
||||||
@@ -200,9 +198,9 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
|||||||
return entity.Value;
|
return entity.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoJobSpecials(JobComponent? job, EntityUid entity)
|
private void DoJobSpecials(ProtoId<JobPrototype>? job, EntityUid entity)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.TryIndex(job?.Prototype ?? string.Empty, out JobPrototype? prototype))
|
if (!_prototypeManager.TryIndex(job ?? string.Empty, out JobPrototype? prototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var jobSpecial in prototype.Special)
|
foreach (var jobSpecial in prototype.Special)
|
||||||
@@ -269,7 +267,7 @@ public sealed class PlayerSpawningEvent : EntityEventArgs
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The job to use, if any.
|
/// The job to use, if any.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly JobComponent? Job;
|
public readonly ProtoId<JobPrototype>? Job;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The profile to use, if any.
|
/// The profile to use, if any.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -279,7 +277,7 @@ public sealed class PlayerSpawningEvent : EntityEventArgs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly EntityUid? Station;
|
public readonly EntityUid? Station;
|
||||||
|
|
||||||
public PlayerSpawningEvent(JobComponent? job, HumanoidCharacterProfile? humanoidCharacterProfile, EntityUid? station)
|
public PlayerSpawningEvent(ProtoId<JobPrototype>? job, HumanoidCharacterProfile? humanoidCharacterProfile, EntityUid? station)
|
||||||
{
|
{
|
||||||
Job = job;
|
Job = job;
|
||||||
HumanoidCharacterProfile = humanoidCharacterProfile;
|
HumanoidCharacterProfile = humanoidCharacterProfile;
|
||||||
|
|||||||
@@ -33,16 +33,16 @@ public sealed partial class BuyerAntagCondition : ListingCondition
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
var roleSystem = ent.System<SharedRoleSystem>();
|
var roleSystem = ent.System<SharedRoleSystem>();
|
||||||
var roles = roleSystem.MindGetAllRoles(mindId);
|
var roles = roleSystem.MindGetAllRoleInfo(mindId);
|
||||||
|
|
||||||
if (Blacklist != null)
|
if (Blacklist != null)
|
||||||
{
|
{
|
||||||
foreach (var role in roles)
|
foreach (var role in roles)
|
||||||
{
|
{
|
||||||
if (role.Component is not AntagonistRoleComponent blacklistantag)
|
if (!role.Antagonist || string.IsNullOrEmpty(role.Prototype))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (blacklistantag.PrototypeId != null && Blacklist.Contains(blacklistantag.PrototypeId))
|
if (Blacklist.Contains(role.Prototype))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,10 +52,11 @@ public sealed partial class BuyerAntagCondition : ListingCondition
|
|||||||
var found = false;
|
var found = false;
|
||||||
foreach (var role in roles)
|
foreach (var role in roles)
|
||||||
{
|
{
|
||||||
if (role.Component is not AntagonistRoleComponent antag)
|
|
||||||
|
if (!role.Antagonist || string.IsNullOrEmpty(role.Prototype))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (antag.PrototypeId != null && Whitelist.Contains(antag.PrototypeId))
|
if (Whitelist.Contains(role.Prototype))
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ public sealed partial class BuyerDepartmentCondition : ListingCondition
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
var jobs = ent.System<SharedJobSystem>();
|
var jobs = ent.System<SharedJobSystem>();
|
||||||
jobs.MindTryGetJob(mindId, out var job, out _);
|
jobs.MindTryGetJob(mindId, out var job);
|
||||||
|
|
||||||
if (Blacklist != null && job?.Prototype != null)
|
if (Blacklist != null && job != null)
|
||||||
{
|
{
|
||||||
foreach (var department in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
|
foreach (var department in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
|
||||||
{
|
{
|
||||||
if (department.Roles.Contains(job.Prototype.Value) && Blacklist.Contains(department.ID))
|
if (department.Roles.Contains(job.ID) && Blacklist.Contains(department.ID))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,11 +52,11 @@ public sealed partial class BuyerDepartmentCondition : ListingCondition
|
|||||||
{
|
{
|
||||||
var found = false;
|
var found = false;
|
||||||
|
|
||||||
if (job?.Prototype != null)
|
if (job != null)
|
||||||
{
|
{
|
||||||
foreach (var department in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
|
foreach (var department in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
|
||||||
{
|
{
|
||||||
if (department.Roles.Contains(job.Prototype.Value) && Whitelist.Contains(department.ID))
|
if (department.Roles.Contains(job.ID) && Whitelist.Contains(department.ID))
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -34,17 +34,17 @@ public sealed partial class BuyerJobCondition : ListingCondition
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
var jobs = ent.System<SharedJobSystem>();
|
var jobs = ent.System<SharedJobSystem>();
|
||||||
jobs.MindTryGetJob(mindId, out var job, out _);
|
jobs.MindTryGetJob(mindId, out var job);
|
||||||
|
|
||||||
if (Blacklist != null)
|
if (Blacklist != null)
|
||||||
{
|
{
|
||||||
if (job?.Prototype != null && Blacklist.Contains(job.Prototype))
|
if (job is not null && Blacklist.Contains(job.ID))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Whitelist != null)
|
if (Whitelist != null)
|
||||||
{
|
{
|
||||||
if (job?.Prototype == null || !Whitelist.Contains(job.Prototype))
|
if (job == null || !Whitelist.Contains(job.ID))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using Content.Server.Mind.Commands;
|
|||||||
using Content.Server.NPC;
|
using Content.Server.NPC;
|
||||||
using Content.Server.NPC.HTN;
|
using Content.Server.NPC.HTN;
|
||||||
using Content.Server.NPC.Systems;
|
using Content.Server.NPC.Systems;
|
||||||
using Content.Server.Roles;
|
|
||||||
using Content.Server.Speech.Components;
|
using Content.Server.Speech.Components;
|
||||||
using Content.Server.Temperature.Components;
|
using Content.Server.Temperature.Components;
|
||||||
using Content.Shared.CombatMode;
|
using Content.Shared.CombatMode;
|
||||||
@@ -47,18 +46,18 @@ namespace Content.Server.Zombies;
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public sealed partial class ZombieSystem
|
public sealed partial class ZombieSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly ServerInventorySystem _inventory = default!;
|
[Dependency] private readonly IChatManager _chatMan = default!;
|
||||||
|
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
|
||||||
[Dependency] private readonly NpcFactionSystem _faction = default!;
|
[Dependency] private readonly NpcFactionSystem _faction = default!;
|
||||||
[Dependency] private readonly NPCSystem _npc = default!;
|
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
|
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
|
||||||
[Dependency] private readonly IdentitySystem _identity = default!;
|
[Dependency] private readonly IdentitySystem _identity = default!;
|
||||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
[Dependency] private readonly ServerInventorySystem _inventory = default!;
|
||||||
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
|
|
||||||
[Dependency] private readonly IChatManager _chatMan = default!;
|
|
||||||
[Dependency] private readonly MindSystem _mind = default!;
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
|
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
||||||
|
[Dependency] private readonly NPCSystem _npc = default!;
|
||||||
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles an entity turning into a zombie when they die or go into crit
|
/// Handles an entity turning into a zombie when they die or go into crit
|
||||||
@@ -234,7 +233,7 @@ public sealed partial class ZombieSystem
|
|||||||
if (hasMind && _mind.TryGetSession(mindId, out var session))
|
if (hasMind && _mind.TryGetSession(mindId, out var session))
|
||||||
{
|
{
|
||||||
//Zombie role for player manifest
|
//Zombie role for player manifest
|
||||||
_roles.MindAddRole(mindId, new ZombieRoleComponent { PrototypeId = zombiecomp.ZombieRoleId });
|
_roles.MindAddRole(mindId, "MindRoleZombie", mind: null, silent: true);
|
||||||
|
|
||||||
//Greeting message for new bebe zombers
|
//Greeting message for new bebe zombers
|
||||||
_chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
|
_chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ public sealed partial class MindContainerComponent : Component
|
|||||||
/// The mind controlling this mob. Can be null.
|
/// The mind controlling this mob. Can be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
[Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
|
|
||||||
public EntityUid? Mind { get; set; }
|
public EntityUid? Mind { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,7 +34,6 @@ public sealed partial class MindContainerComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("ghostOnShutdown")]
|
[DataField("ghostOnShutdown")]
|
||||||
[Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
|
|
||||||
public bool GhostOnShutdown { get; set; } = true;
|
public bool GhostOnShutdown { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Shared.Actions;
|
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Mind.Components;
|
using Content.Shared.Mind.Components;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
@@ -87,17 +86,21 @@ public sealed partial class MindComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents user from ghosting out
|
/// Prevents user from ghosting out
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[DataField]
|
||||||
[DataField("preventGhosting")]
|
|
||||||
public bool PreventGhosting { get; set; }
|
public bool PreventGhosting { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents user from suiciding
|
/// Prevents user from suiciding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[DataField]
|
||||||
[DataField("preventSuicide")]
|
|
||||||
public bool PreventSuicide { get; set; }
|
public bool PreventSuicide { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mind Role Entities belonging to this Mind
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public List<EntityUid> MindRoles = new List<EntityUid>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The session of the player owning this mind.
|
/// The session of the player owning this mind.
|
||||||
/// Can be null, in which case the player is currently not logged in.
|
/// Can be null, in which case the player is currently not logged in.
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Shared.Roles;
|
|
||||||
|
|
||||||
public abstract partial class AntagonistRoleComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
|
||||||
public string? PrototypeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Mark the antagonist role component as being exclusive
|
|
||||||
/// IE by default other antagonists should refuse to select the same entity for a different antag role
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
|
||||||
[BaseTypeRequired(typeof(AntagonistRoleComponent))]
|
|
||||||
public sealed partial class ExclusiveAntagonistAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using Robust.Shared.GameStates;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Shared.Roles.Jobs;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Added to mind entities to hold the data for the player's current job.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
|
||||||
public sealed partial class JobComponent : Component
|
|
||||||
{
|
|
||||||
[DataField(required: true), AutoNetworkedField]
|
|
||||||
public ProtoId<JobPrototype>? Prototype;
|
|
||||||
}
|
|
||||||
12
Content.Shared/Roles/Jobs/JobRoleComponent.cs
Normal file
12
Content.Shared/Roles/Jobs/JobRoleComponent.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Roles.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to mind role entities to mark them as a job role entity.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class JobRoleComponent : BaseMindRoleComponent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,8 +13,10 @@ namespace Content.Shared.Roles.Jobs;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class SharedJobSystem : EntitySystem
|
public abstract class SharedJobSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
|
||||||
[Dependency] private readonly SharedPlayerSystem _playerSystem = default!;
|
[Dependency] private readonly SharedPlayerSystem _playerSystem = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _inverseTrackerLookup = new();
|
private readonly Dictionary<string, string> _inverseTrackerLookup = new();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -100,32 +102,44 @@ public abstract class SharedJobSystem : EntitySystem
|
|||||||
|
|
||||||
public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
|
public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
|
||||||
{
|
{
|
||||||
return CompOrNull<JobComponent>(mindId)?.Prototype == prototypeId;
|
|
||||||
|
MindRoleComponent? comp = null;
|
||||||
|
if (mindId is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_roles.MindHasRole<JobRoleComponent>(mindId.Value, out var role);
|
||||||
|
|
||||||
|
if (role is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
comp = role.Value.Comp;
|
||||||
|
|
||||||
|
return (comp.JobPrototype == prototypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MindTryGetJob(
|
public bool MindTryGetJob(
|
||||||
[NotNullWhen(true)] EntityUid? mindId,
|
[NotNullWhen(true)] EntityUid? mindId,
|
||||||
[NotNullWhen(true)] out JobComponent? comp,
|
|
||||||
[NotNullWhen(true)] out JobPrototype? prototype)
|
[NotNullWhen(true)] out JobPrototype? prototype)
|
||||||
{
|
{
|
||||||
comp = null;
|
|
||||||
prototype = null;
|
prototype = null;
|
||||||
|
MindTryGetJobId(mindId, out var protoId);
|
||||||
|
|
||||||
return TryComp(mindId, out comp) &&
|
return (_prototypes.TryIndex<JobPrototype>(protoId, out prototype) || prototype is not null);
|
||||||
comp.Prototype != null &&
|
|
||||||
_prototypes.TryIndex(comp.Prototype, out prototype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MindTryGetJobId([NotNullWhen(true)] EntityUid? mindId, out ProtoId<JobPrototype>? job)
|
public bool MindTryGetJobId(
|
||||||
|
[NotNullWhen(true)] EntityUid? mindId,
|
||||||
|
out ProtoId<JobPrototype>? job)
|
||||||
{
|
{
|
||||||
if (!TryComp(mindId, out JobComponent? comp))
|
job = null;
|
||||||
{
|
|
||||||
job = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
job = comp.Prototype;
|
if (mindId is null)
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
|
if (_roles.MindHasRole<JobRoleComponent>(mindId.Value, out var role))
|
||||||
|
job = role.Value.Comp.JobPrototype;
|
||||||
|
|
||||||
|
return (job is not null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -134,7 +148,7 @@ public abstract class SharedJobSystem : EntitySystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool MindTryGetJobName([NotNullWhen(true)] EntityUid? mindId, out string name)
|
public bool MindTryGetJobName([NotNullWhen(true)] EntityUid? mindId, out string name)
|
||||||
{
|
{
|
||||||
if (MindTryGetJob(mindId, out _, out var prototype))
|
if (MindTryGetJob(mindId, out var prototype))
|
||||||
{
|
{
|
||||||
name = prototype.LocalizedName;
|
name = prototype.LocalizedName;
|
||||||
return true;
|
return true;
|
||||||
@@ -161,7 +175,7 @@ public abstract class SharedJobSystem : EntitySystem
|
|||||||
if (_playerSystem.ContentData(player) is not { Mind: { } mindId })
|
if (_playerSystem.ContentData(player) is not { Mind: { } mindId })
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!MindTryGetJob(mindId, out _, out var prototype))
|
if (!MindTryGetJob(mindId, out var prototype))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return prototype.CanBeAntag;
|
return prototype.CanBeAntag;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Content.Shared.Roles;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="Roles">The list of roles on the player.</param>
|
/// <param name="Roles">The list of roles on the player.</param>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public readonly record struct MindGetAllRolesEvent(List<RoleInfo> Roles);
|
public readonly record struct MindGetAllRoleInfoEvent(List<RoleInfo> Roles);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returned by <see cref="MindGetAllRolesEvent"/> to give some information about a player's role.
|
/// Returned by <see cref="MindGetAllRolesEvent"/> to give some information about a player's role.
|
||||||
@@ -17,4 +17,4 @@ public readonly record struct MindGetAllRolesEvent(List<RoleInfo> Roles);
|
|||||||
/// <param name="Antagonist">Whether or not this role makes this player an antagonist.</param>
|
/// <param name="Antagonist">Whether or not this role makes this player an antagonist.</param>
|
||||||
/// <param name="PlayTimeTrackerId">The <see cref="PlayTimeTrackerPrototype"/> id associated with the role.</param>
|
/// <param name="PlayTimeTrackerId">The <see cref="PlayTimeTrackerPrototype"/> id associated with the role.</param>
|
||||||
/// <param name="Prototype">The prototype ID of the role</param>
|
/// <param name="Prototype">The prototype ID of the role</param>
|
||||||
public readonly record struct RoleInfo(Component Component, string Name, bool Antagonist, string? PlayTimeTrackerId, string Prototype);
|
public readonly record struct RoleInfo(string Name, bool Antagonist, string? PlayTimeTrackerId, string Prototype);
|
||||||
48
Content.Shared/Roles/MindRoleComponent.cs
Normal file
48
Content.Shared/Roles/MindRoleComponent.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using Content.Shared.Mind;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This holds data for, and indicates, a Mind Role entity
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class MindRoleComponent : BaseMindRoleComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Marks this Mind Role as Antagonist
|
||||||
|
/// A single antag Mind Role is enough to make the owner mind count as Antagonist.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool Antag { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if this mindrole is an exclusive antagonist. Antag setting is not checked if this is True.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool ExclusiveAntag { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Mind that this role belongs to
|
||||||
|
/// </summary>
|
||||||
|
public Entity<MindComponent> Mind { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Antagonist prototype of this role
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<AntagPrototype>? AntagPrototype { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Job prototype of this role
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<JobPrototype>? JobPrototype { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract partial class BaseMindRoleComponent : Component
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,34 +1,31 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Ghost.Roles;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Roles.Jobs;
|
using Content.Shared.Roles.Jobs;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Shared.Roles;
|
namespace Content.Shared.Roles;
|
||||||
|
|
||||||
public abstract class SharedRoleSystem : EntitySystem
|
public abstract class SharedRoleSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedMindSystem _minds = default!;
|
|
||||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
// TODO please lord make role entities
|
[Dependency] private readonly SharedGameTicker _gameTicker = default!;
|
||||||
private readonly HashSet<Type> _antagTypes = new();
|
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
||||||
|
|
||||||
private JobRequirementOverridePrototype? _requirementOverride;
|
private JobRequirementOverridePrototype? _requirementOverride;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
// TODO make roles entities
|
|
||||||
SubscribeLocalEvent<JobComponent, MindGetAllRolesEvent>(OnJobGetAllRoles);
|
|
||||||
Subs.CVar(_cfg, CCVars.GameRoleTimerOverride, SetRequirementOverride, true);
|
Subs.CVar(_cfg, CCVars.GameRoleTimerOverride, SetRequirementOverride, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,124 +41,117 @@ public abstract class SharedRoleSystem : EntitySystem
|
|||||||
Log.Error($"Unknown JobRequirementOverridePrototype: {value}");
|
Log.Error($"Unknown JobRequirementOverridePrototype: {value}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnJobGetAllRoles(EntityUid uid, JobComponent component, ref MindGetAllRolesEvent args)
|
|
||||||
{
|
|
||||||
var name = "game-ticker-unknown-role";
|
|
||||||
var prototype = "";
|
|
||||||
string? playTimeTracker = null;
|
|
||||||
if (component.Prototype != null && _prototypes.TryIndex(component.Prototype, out JobPrototype? job))
|
|
||||||
{
|
|
||||||
name = job.Name;
|
|
||||||
prototype = job.ID;
|
|
||||||
playTimeTracker = job.PlayTimeTracker;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = Loc.GetString(name);
|
|
||||||
|
|
||||||
args.Roles.Add(new RoleInfo(component, name, false, playTimeTracker, prototype));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SubscribeAntagEvents<T>() where T : AntagonistRoleComponent
|
|
||||||
{
|
|
||||||
SubscribeLocalEvent((EntityUid _, T component, ref MindGetAllRolesEvent args) =>
|
|
||||||
{
|
|
||||||
var name = "game-ticker-unknown-role";
|
|
||||||
var prototype = "";
|
|
||||||
if (component.PrototypeId != null && _prototypes.TryIndex(component.PrototypeId, out AntagPrototype? antag))
|
|
||||||
{
|
|
||||||
name = antag.Name;
|
|
||||||
prototype = antag.ID;
|
|
||||||
}
|
|
||||||
name = Loc.GetString(name);
|
|
||||||
|
|
||||||
args.Roles.Add(new RoleInfo(component, name, true, null, prototype));
|
|
||||||
});
|
|
||||||
|
|
||||||
SubscribeLocalEvent((EntityUid _, T _, ref MindIsAntagonistEvent args) => { args.IsAntagonist = true; args.IsExclusiveAntagonist |= typeof(T).TryGetCustomAttribute<ExclusiveAntagonistAttribute>(out _); });
|
|
||||||
_antagTypes.Add(typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MindAddRoles(EntityUid mindId, ComponentRegistry components, MindComponent? mind = null, bool silent = false)
|
|
||||||
{
|
|
||||||
if (!Resolve(mindId, ref mind))
|
|
||||||
return;
|
|
||||||
|
|
||||||
EntityManager.AddComponents(mindId, components);
|
|
||||||
var antagonist = false;
|
|
||||||
foreach (var compReg in components.Values)
|
|
||||||
{
|
|
||||||
var compType = compReg.Component.GetType();
|
|
||||||
|
|
||||||
var comp = EntityManager.ComponentFactory.GetComponent(compType);
|
|
||||||
if (IsAntagonistRole(comp.GetType()))
|
|
||||||
{
|
|
||||||
antagonist = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mindEv = new MindRoleAddedEvent(silent);
|
|
||||||
RaiseLocalEvent(mindId, ref mindEv);
|
|
||||||
|
|
||||||
var message = new RoleAddedEvent(mindId, mind, antagonist, silent);
|
|
||||||
if (mind.OwnedEntity != null)
|
|
||||||
{
|
|
||||||
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low,
|
|
||||||
$"Role components {string.Join(components.Keys.ToString(), ", ")} added to mind of {_minds.MindOwnerLoggingString(mind)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MindAddRole(EntityUid mindId, Component component, MindComponent? mind = null, bool silent = false)
|
|
||||||
{
|
|
||||||
if (!Resolve(mindId, ref mind))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (HasComp(mindId, component.GetType()))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"We already have this role: {component}");
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityManager.AddComponent(mindId, component);
|
|
||||||
var antagonist = IsAntagonistRole(component.GetType());
|
|
||||||
|
|
||||||
var mindEv = new MindRoleAddedEvent(silent);
|
|
||||||
RaiseLocalEvent(mindId, ref mindEv);
|
|
||||||
|
|
||||||
var message = new RoleAddedEvent(mindId, mind, antagonist, silent);
|
|
||||||
if (mind.OwnedEntity != null)
|
|
||||||
{
|
|
||||||
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low,
|
|
||||||
$"'Role {component}' added to mind of {_minds.MindOwnerLoggingString(mind)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gives this mind a new role.
|
/// Adds multiple mind roles to a mind
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mindId">The mind to add the role to.</param>
|
/// <param name="mindId">The mind entity to add the role to</param>
|
||||||
/// <param name="component">The role instance to add.</param>
|
/// <param name="roles">The list of mind roles to add</param>
|
||||||
/// <typeparam name="T">The role type to add.</typeparam>
|
/// <param name="mind">If the mind component is provided, it will be checked if it belongs to the mind entity</param>
|
||||||
/// <param name="silent">Whether or not the role should be added silently</param>
|
/// <param name="silent">If true, no briefing will be generated upon receiving the mind role</param>
|
||||||
/// <returns>The instance of the role.</returns>
|
public void MindAddRoles(EntityUid mindId,
|
||||||
/// <exception cref="ArgumentException">
|
List<ProtoId<EntityPrototype>>? roles,
|
||||||
/// Thrown if we already have a role with this type.
|
MindComponent? mind = null,
|
||||||
/// </exception>
|
bool silent = false)
|
||||||
public void MindAddRole<T>(EntityUid mindId, T component, MindComponent? mind = null, bool silent = false) where T : IComponent, new()
|
|
||||||
{
|
{
|
||||||
if (!Resolve(mindId, ref mind))
|
if (roles is null || roles.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (HasComp<T>(mindId))
|
foreach (var proto in roles)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"We already have this role: {typeof(T)}");
|
MindAddRole(mindId, proto, mind, silent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a mind role to a mind
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity to add the role to</param>
|
||||||
|
/// <param name="protoId">The mind role to add</param>
|
||||||
|
/// <param name="mind">If the mind component is provided, it will be checked if it belongs to the mind entity</param>
|
||||||
|
/// <param name="silent">If true, no briefing will be generated upon receiving the mind role</param>
|
||||||
|
public void MindAddRole(EntityUid mindId,
|
||||||
|
ProtoId<EntityPrototype> protoId,
|
||||||
|
MindComponent? mind = null,
|
||||||
|
bool silent = false)
|
||||||
|
{
|
||||||
|
if (protoId == "MindRoleJob")
|
||||||
|
MindAddJobRole(mindId, mind, silent, "");
|
||||||
|
else
|
||||||
|
MindAddRoleDo(mindId, protoId, mind, silent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Job mind role with the specified job prototype
|
||||||
|
/// </summary>
|
||||||
|
/// /// <param name="mindId">The mind entity to add the job role to</param>
|
||||||
|
/// <param name="mind">If the mind component is provided, it will be checked if it belongs to the mind entity</param>
|
||||||
|
/// <param name="silent">If true, no briefing will be generated upon receiving the mind role</param>
|
||||||
|
/// <param name="jobPrototype">The Job prototype for the new role</param>
|
||||||
|
public void MindAddJobRole(EntityUid mindId,
|
||||||
|
MindComponent? mind = null,
|
||||||
|
bool silent = false,
|
||||||
|
string? jobPrototype = null)
|
||||||
|
{
|
||||||
|
// Can't have someone get paid for two jobs now, can we
|
||||||
|
if (MindHasRole<JobRoleComponent>(mindId, out var jobRole)
|
||||||
|
&& jobRole.Value.Comp.JobPrototype != jobPrototype)
|
||||||
|
{
|
||||||
|
Resolve(mindId, ref mind);
|
||||||
|
if (mind is not null)
|
||||||
|
{
|
||||||
|
_adminLogger.Add(LogType.Mind,
|
||||||
|
LogImpact.Low,
|
||||||
|
$"Job Role of {ToPrettyString(mind.OwnedEntity)} changed from '{jobRole.Value.Comp.JobPrototype}' to '{jobPrototype}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
jobRole.Value.Comp.JobPrototype = jobPrototype;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MindAddRoleDo(mindId, "MindRoleJob", mind, silent, jobPrototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Mind Role
|
||||||
|
/// </summary>
|
||||||
|
private void MindAddRoleDo(EntityUid mindId,
|
||||||
|
ProtoId<EntityPrototype> protoId,
|
||||||
|
MindComponent? mind = null,
|
||||||
|
bool silent = false,
|
||||||
|
string? jobPrototype = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(mindId, ref mind))
|
||||||
|
{
|
||||||
|
Log.Error($"Failed to add role {protoId} to mind {mindId} : Mind does not match provided mind component");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddComp(mindId, component);
|
var antagonist = false;
|
||||||
var antagonist = IsAntagonistRole<T>();
|
|
||||||
|
if (!_prototypes.TryIndex(protoId, out var protoEnt))
|
||||||
|
{
|
||||||
|
Log.Error($"Failed to add role {protoId} to mind {mindId} : Role prototype does not exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO don't let a prototype being added a second time
|
||||||
|
//If that was somehow to occur, a second mindrole for that comp would be created
|
||||||
|
//Meaning any mind role checks could return wrong results, since they just return the first match they find
|
||||||
|
|
||||||
|
var mindRoleId = Spawn(protoId, MapCoordinates.Nullspace);
|
||||||
|
EnsureComp<MindRoleComponent>(mindRoleId);
|
||||||
|
var mindRoleComp = Comp<MindRoleComponent>(mindRoleId);
|
||||||
|
|
||||||
|
mindRoleComp.Mind = (mindId,mind);
|
||||||
|
if (jobPrototype is not null)
|
||||||
|
{
|
||||||
|
mindRoleComp.JobPrototype = jobPrototype;
|
||||||
|
EnsureComp<JobRoleComponent>(mindRoleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mindRoleComp.Antag || mindRoleComp.ExclusiveAntag)
|
||||||
|
antagonist = true;
|
||||||
|
|
||||||
|
mind.MindRoles.Add(mindRoleId);
|
||||||
|
|
||||||
var mindEv = new MindRoleAddedEvent(silent);
|
var mindEv = new MindRoleAddedEvent(silent);
|
||||||
RaiseLocalEvent(mindId, ref mindEv);
|
RaiseLocalEvent(mindId, ref mindEv);
|
||||||
@@ -172,94 +162,330 @@ public abstract class SharedRoleSystem : EntitySystem
|
|||||||
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low,
|
var name = Loc.GetString(protoEnt.Name);
|
||||||
$"'Role {typeof(T).Name}' added to mind of {_minds.MindOwnerLoggingString(mind)}");
|
if (mind.OwnedEntity is not null)
|
||||||
|
{
|
||||||
|
_adminLogger.Add(LogType.Mind,
|
||||||
|
LogImpact.Low,
|
||||||
|
$"{name} added to mind of {ToPrettyString(mind.OwnedEntity)}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO: This is not tied to the player on the Admin Log filters.
|
||||||
|
//Probably only happens when Job Role is added on initial spawn, before the mind entity is put in a mob
|
||||||
|
_adminLogger.Add(LogType.Mind,
|
||||||
|
LogImpact.Low,
|
||||||
|
$"{name} added to {ToPrettyString(mindId)}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a role from this mind.
|
/// Removes all instances of a specific role from this mind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mindId">The mind to remove the role from.</param>
|
/// <param name="mindId">The mind to remove the role from.</param>
|
||||||
/// <typeparam name="T">The type of the role to remove.</typeparam>
|
/// <typeparam name="T">The type of the role to remove.</typeparam>
|
||||||
/// <exception cref="ArgumentException">
|
/// <exception cref="ArgumentException">Thrown if the mind does not exist or does not have this role.</exception>
|
||||||
/// Thrown if we do not have this role.
|
/// <returns>Returns False if there was something wrong with the mind or the removal. True if successful</returns>>
|
||||||
/// </exception>
|
public bool MindRemoveRole<T>(EntityUid mindId) where T : IComponent
|
||||||
public void MindRemoveRole<T>(EntityUid mindId) where T : IComponent
|
|
||||||
{
|
{
|
||||||
if (!RemComp<T>(mindId))
|
if (!TryComp<MindComponent>(mindId, out var mind) )
|
||||||
|
throw new ArgumentException($"{mindId} does not exist or does not have mind component");
|
||||||
|
|
||||||
|
var found = false;
|
||||||
|
var antagonist = false;
|
||||||
|
var delete = new List<EntityUid>();
|
||||||
|
foreach (var role in mind.MindRoles)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"We do not have this role: {typeof(T)}");
|
if (!HasComp<T>(role))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var roleComp = Comp<MindRoleComponent>(role);
|
||||||
|
antagonist = roleComp.Antag;
|
||||||
|
_entityManager.DeleteEntity(role);
|
||||||
|
|
||||||
|
delete.Add(role);
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var role in delete)
|
||||||
|
{
|
||||||
|
mind.MindRoles.Remove(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"{mindId} does not have this role: {typeof(T)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = Comp<MindComponent>(mindId);
|
|
||||||
var antagonist = IsAntagonistRole<T>();
|
|
||||||
var message = new RoleRemovedEvent(mindId, mind, antagonist);
|
var message = new RoleRemovedEvent(mindId, mind, antagonist);
|
||||||
|
|
||||||
if (mind.OwnedEntity != null)
|
if (mind.OwnedEntity != null)
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
||||||
}
|
}
|
||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low,
|
_adminLogger.Add(LogType.Mind,
|
||||||
$"'Role {typeof(T).Name}' removed from mind of {_minds.MindOwnerLoggingString(mind)}");
|
LogImpact.Low,
|
||||||
}
|
$"'Role {typeof(T).Name}' removed from mind of {ToPrettyString(mind.OwnedEntity)}");
|
||||||
|
|
||||||
public bool MindTryRemoveRole<T>(EntityUid mindId) where T : IComponent
|
|
||||||
{
|
|
||||||
if (!MindHasRole<T>(mindId))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
MindRemoveRole<T>(mindId);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MindHasRole<T>(EntityUid mindId) where T : IComponent
|
/// <summary>
|
||||||
|
/// Finds and removes all mind roles of a specific type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <typeparam name="T">The type of the role to remove.</typeparam>
|
||||||
|
/// <returns>True if the role existed and was removed</returns>
|
||||||
|
public bool MindTryRemoveRole<T>(EntityUid mindId) where T : IComponent
|
||||||
{
|
{
|
||||||
DebugTools.Assert(HasComp<MindComponent>(mindId));
|
if (!MindHasRole<T>(mindId))
|
||||||
return HasComp<T>(mindId);
|
{
|
||||||
}
|
Log.Warning($"Failed to remove role {typeof(T)} from {mindId} : mind does not have role ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public List<RoleInfo> MindGetAllRoles(EntityUid mindId)
|
if (typeof(T) == typeof(MindRoleComponent))
|
||||||
{
|
|
||||||
DebugTools.Assert(HasComp<MindComponent>(mindId));
|
|
||||||
var ev = new MindGetAllRolesEvent(new List<RoleInfo>());
|
|
||||||
RaiseLocalEvent(mindId, ref ev);
|
|
||||||
return ev.Roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MindIsAntagonist(EntityUid? mindId)
|
|
||||||
{
|
|
||||||
if (mindId == null)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
DebugTools.Assert(HasComp<MindComponent>(mindId));
|
return MindRemoveRole<T>(mindId);
|
||||||
var ev = new MindIsAntagonistEvent();
|
}
|
||||||
RaiseLocalEvent(mindId.Value, ref ev);
|
|
||||||
return ev.IsAntagonist;
|
/// <summary>
|
||||||
|
/// Finds the first mind role of a specific T type on a mind entity.
|
||||||
|
/// Outputs entity components for the mind role's MindRoleComponent and for T
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <typeparam name="T">The type of the role to find.</typeparam>
|
||||||
|
/// <param name="role">The Mind Role entity component</param>
|
||||||
|
/// <param name="roleT">The Mind Role's entity component for T</param>
|
||||||
|
/// <returns>True if the role is found</returns>
|
||||||
|
public bool MindHasRole<T>(EntityUid mindId,
|
||||||
|
[NotNullWhen(true)] out Entity<MindRoleComponent>? role,
|
||||||
|
[NotNullWhen(true)] out Entity<T>? roleT) where T : IComponent
|
||||||
|
{
|
||||||
|
role = null;
|
||||||
|
roleT = null;
|
||||||
|
|
||||||
|
if (!TryComp<MindComponent>(mindId, out var mind))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var found = false;
|
||||||
|
|
||||||
|
foreach (var roleEnt in mind.MindRoles)
|
||||||
|
{
|
||||||
|
if (!HasComp<T>(roleEnt))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
role = (roleEnt,Comp<MindRoleComponent>(roleEnt));
|
||||||
|
roleT = (roleEnt,Comp<T>(roleEnt));
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first mind role of a specific type on a mind entity.
|
||||||
|
/// Outputs an entity component for the mind role's MindRoleComponent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <param name="type">The Type to look for</param>
|
||||||
|
/// <param name="role">The output role</param>
|
||||||
|
/// <returns>True if the role is found</returns>
|
||||||
|
public bool MindHasRole(EntityUid mindId,
|
||||||
|
Type type,
|
||||||
|
[NotNullWhen(true)] out Entity<MindRoleComponent>? role)
|
||||||
|
{
|
||||||
|
role = null;
|
||||||
|
// All MindRoles have this component, it would just return the first one.
|
||||||
|
// Order might not be what is expected.
|
||||||
|
// Better to report null
|
||||||
|
if (type == Type.GetType("MindRoleComponent"))
|
||||||
|
{
|
||||||
|
Log.Error($"Something attempted to query mind role 'MindRoleComponent' on mind {mindId}. This component is present on every single mind role.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryComp<MindComponent>(mindId, out var mind))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var found = false;
|
||||||
|
|
||||||
|
foreach (var roleEnt in mind.MindRoles)
|
||||||
|
{
|
||||||
|
if (!HasComp(roleEnt, type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
role = (roleEnt,Comp<MindRoleComponent>(roleEnt));
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first mind role of a specific type on a mind entity.
|
||||||
|
/// Outputs an entity component for the mind role's MindRoleComponent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <param name="role">The Mind Role entity component</param>
|
||||||
|
/// <typeparam name="T">The type of the role to find.</typeparam>
|
||||||
|
/// <returns>True if the role is found</returns>
|
||||||
|
public bool MindHasRole<T>(EntityUid mindId,
|
||||||
|
[NotNullWhen(true)] out Entity<MindRoleComponent>? role) where T : IComponent
|
||||||
|
{
|
||||||
|
return MindHasRole<T>(mindId, out role, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first mind role of a specific type on a mind entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <typeparam name="T">The type of the role to find.</typeparam>
|
||||||
|
/// <returns>True if the role is found</returns>
|
||||||
|
public bool MindHasRole<T>(EntityUid mindId) where T : IComponent
|
||||||
|
{
|
||||||
|
return MindHasRole<T>(mindId, out _, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Delete this later
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the first mind role of a specific type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <returns>Entity Component of the mind role</returns>
|
||||||
|
[Obsolete("Use MindHasRole's output value")]
|
||||||
|
public Entity<MindRoleComponent>? MindGetRole<T>(EntityUid mindId) where T : IComponent
|
||||||
|
{
|
||||||
|
Entity<MindRoleComponent>? result = null;
|
||||||
|
|
||||||
|
var mind = Comp<MindComponent>(mindId);
|
||||||
|
|
||||||
|
foreach (var uid in mind.MindRoles)
|
||||||
|
{
|
||||||
|
if (HasComp<T>(uid) && TryComp<MindRoleComponent>(uid, out var comp))
|
||||||
|
result = (uid,comp);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads all Roles of a mind Entity and returns their data as RoleInfo
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <returns>RoleInfo list</returns>
|
||||||
|
public List<RoleInfo> MindGetAllRoleInfo(EntityUid mindId)
|
||||||
|
{
|
||||||
|
var roleInfo = new List<RoleInfo>();
|
||||||
|
|
||||||
|
if (!TryComp<MindComponent>(mindId, out var mind))
|
||||||
|
return roleInfo;
|
||||||
|
|
||||||
|
foreach (var role in mind.MindRoles)
|
||||||
|
{
|
||||||
|
var valid = false;
|
||||||
|
var name = "game-ticker-unknown-role";
|
||||||
|
var prototype = "";
|
||||||
|
string? playTimeTracker = null;
|
||||||
|
|
||||||
|
var comp = Comp<MindRoleComponent>(role);
|
||||||
|
if (comp.AntagPrototype is not null)
|
||||||
|
{
|
||||||
|
prototype = comp.AntagPrototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp.JobPrototype is not null && comp.AntagPrototype is null)
|
||||||
|
{
|
||||||
|
prototype = comp.JobPrototype;
|
||||||
|
if (_prototypes.TryIndex(comp.JobPrototype, out var job))
|
||||||
|
{
|
||||||
|
playTimeTracker = job.PlayTimeTracker;
|
||||||
|
name = job.Name;
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Error($" Mind Role Prototype '{role.Id}' contains invalid Job prototype: '{comp.JobPrototype}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (comp.AntagPrototype is not null && comp.JobPrototype is null)
|
||||||
|
{
|
||||||
|
prototype = comp.AntagPrototype;
|
||||||
|
if (_prototypes.TryIndex(comp.AntagPrototype, out var antag))
|
||||||
|
{
|
||||||
|
name = antag.Name;
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Error($" Mind Role Prototype '{role.Id}' contains invalid Antagonist prototype: '{comp.AntagPrototype}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (comp.JobPrototype is not null && comp.AntagPrototype is not null)
|
||||||
|
{
|
||||||
|
Log.Error($" Mind Role Prototype '{role.Id}' contains both Job and Antagonist prototypes");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid)
|
||||||
|
roleInfo.Add(new RoleInfo(name, comp.Antag || comp.ExclusiveAntag , playTimeTracker, prototype));
|
||||||
|
}
|
||||||
|
return roleInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does this mind possess an antagonist role
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mindId">The mind entity</param>
|
||||||
|
/// <returns>True if the mind possesses any antag roles</returns>
|
||||||
|
public bool MindIsAntagonist(EntityUid? mindId)
|
||||||
|
{
|
||||||
|
if (mindId is null)
|
||||||
|
{
|
||||||
|
Log.Warning($"Antagonist status of mind entity {mindId} could not be determined - mind entity not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CheckAntagonistStatus(mindId.Value).Item1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Does this mind possess an exclusive antagonist role
|
/// Does this mind possess an exclusive antagonist role
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mindId">The mind entity</param>
|
/// <param name="mindId">The mind entity</param>
|
||||||
/// <returns>True if the mind possesses an exclusive antag role</returns>
|
/// <returns>True if the mind possesses any exclusive antag roles</returns>
|
||||||
public bool MindIsExclusiveAntagonist(EntityUid? mindId)
|
public bool MindIsExclusiveAntagonist(EntityUid? mindId)
|
||||||
{
|
{
|
||||||
if (mindId == null)
|
if (mindId is null)
|
||||||
|
{
|
||||||
|
Log.Warning($"Antagonist status of mind entity {mindId} could not be determined - mind entity not found");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var ev = new MindIsAntagonistEvent();
|
return CheckAntagonistStatus(mindId.Value).Item2;
|
||||||
RaiseLocalEvent(mindId.Value, ref ev);
|
|
||||||
return ev.IsExclusiveAntagonist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAntagonistRole<T>()
|
private (bool, bool) CheckAntagonistStatus(EntityUid mindId)
|
||||||
{
|
{
|
||||||
return _antagTypes.Contains(typeof(T));
|
if (!TryComp<MindComponent>(mindId, out var mind))
|
||||||
}
|
{
|
||||||
|
Log.Warning($"Antagonist status of mind entity {mindId} could not be determined - mind component not found");
|
||||||
|
return (false, false);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsAntagonistRole(Type component)
|
var antagonist = false;
|
||||||
{
|
var exclusiveAntag = false;
|
||||||
return _antagTypes.Contains(component);
|
foreach (var role in mind.MindRoles)
|
||||||
|
{
|
||||||
|
var roleComp = Comp<MindRoleComponent>(role);
|
||||||
|
if (roleComp.Antag || exclusiveAntag)
|
||||||
|
antagonist = true;
|
||||||
|
if (roleComp.ExclusiveAntag)
|
||||||
|
exclusiveAntag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (antagonist, exclusiveAntag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ public sealed partial class EntityWhitelist
|
|||||||
[DataField] public string[]? Components;
|
[DataField] public string[]? Components;
|
||||||
// TODO yaml validation
|
// TODO yaml validation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mind Role Prototype names that are allowed in the whitelist.
|
||||||
|
/// </summary>
|
||||||
|
[DataField] public string[]? MindRoles;
|
||||||
|
// TODO yaml validation
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Item sizes that are allowed in the whitelist.
|
/// Item sizes that are allowed in the whitelist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
|
|
||||||
namespace Content.Shared.Whitelist;
|
namespace Content.Shared.Whitelist;
|
||||||
@@ -7,6 +8,7 @@ namespace Content.Shared.Whitelist;
|
|||||||
public sealed class EntityWhitelistSystem : EntitySystem
|
public sealed class EntityWhitelistSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IComponentFactory _factory = default!;
|
[Dependency] private readonly IComponentFactory _factory = default!;
|
||||||
|
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||||
[Dependency] private readonly TagSystem _tag = default!;
|
[Dependency] private readonly TagSystem _tag = default!;
|
||||||
|
|
||||||
private EntityQuery<ItemComponent> _itemQuery;
|
private EntityQuery<ItemComponent> _itemQuery;
|
||||||
@@ -46,9 +48,30 @@ public sealed class EntityWhitelistSystem : EntitySystem
|
|||||||
public bool IsValid(EntityWhitelist list, EntityUid uid)
|
public bool IsValid(EntityWhitelist list, EntityUid uid)
|
||||||
{
|
{
|
||||||
if (list.Components != null)
|
if (list.Components != null)
|
||||||
EnsureRegistrations(list);
|
{
|
||||||
|
var regs = StringsToRegs(list.Components);
|
||||||
|
|
||||||
if (list.Registrations != null)
|
list.Registrations ??= new List<ComponentRegistration>();
|
||||||
|
list.Registrations.AddRange(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.MindRoles != null)
|
||||||
|
{
|
||||||
|
var regs = StringsToRegs(list.MindRoles);
|
||||||
|
|
||||||
|
foreach (var role in regs)
|
||||||
|
{
|
||||||
|
if ( _roles.MindHasRole(uid, role.Type, out _))
|
||||||
|
{
|
||||||
|
if (!list.RequireAll)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (list.RequireAll)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.Registrations != null && list.Registrations.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var reg in list.Registrations)
|
foreach (var reg in list.Registrations)
|
||||||
{
|
{
|
||||||
@@ -153,7 +176,7 @@ public sealed class EntityWhitelistSystem : EntitySystem
|
|||||||
return IsWhitelistPassOrNull(blacklist, uid);
|
return IsWhitelistPassOrNull(blacklist, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper function to determine if Blacklist is either null or the entity is not on the list
|
/// Helper function to determine if Blacklist is either null or the entity is not on the list
|
||||||
/// Duplicate of equivalent Whitelist function
|
/// Duplicate of equivalent Whitelist function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -162,24 +185,27 @@ public sealed class EntityWhitelistSystem : EntitySystem
|
|||||||
return IsWhitelistFailOrNull(blacklist, uid);
|
return IsWhitelistFailOrNull(blacklist, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureRegistrations(EntityWhitelist list)
|
private List<ComponentRegistration> StringsToRegs(string[]? input)
|
||||||
{
|
{
|
||||||
if (list.Components == null)
|
var list = new List<ComponentRegistration>();
|
||||||
return;
|
|
||||||
|
|
||||||
list.Registrations = new List<ComponentRegistration>();
|
if (input == null || input.Length == 0)
|
||||||
foreach (var name in list.Components)
|
return list;
|
||||||
|
|
||||||
|
foreach (var name in input)
|
||||||
{
|
{
|
||||||
var availability = _factory.GetComponentAvailability(name);
|
var availability = _factory.GetComponentAvailability(name);
|
||||||
if (_factory.TryGetRegistration(name, out var registration)
|
if (_factory.TryGetRegistration(name, out var registration)
|
||||||
&& availability == ComponentAvailability.Available)
|
&& availability == ComponentAvailability.Available)
|
||||||
{
|
{
|
||||||
list.Registrations.Add(registration);
|
list.Add(registration);
|
||||||
}
|
}
|
||||||
else if (availability == ComponentAvailability.Unknown)
|
else if (availability == ComponentAvailability.Unknown)
|
||||||
{
|
{
|
||||||
Log.Warning($"Unknown component name {name} passed to EntityWhitelist!");
|
Log.Error($"StringsToRegs failed: Unknown component name {name} passed to EntityWhitelist!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ nukeops-description = Nuclear operatives have targeted the station. Try to keep
|
|||||||
nukeops-welcome =
|
nukeops-welcome =
|
||||||
You are a nuclear operative. Your goal is to blow up {$station}, and ensure that it is nothing but a pile of rubble. Your bosses, the Syndicate, have provided you with the tools you'll need for the task.
|
You are a nuclear operative. Your goal is to blow up {$station}, and ensure that it is nothing but a pile of rubble. Your bosses, the Syndicate, have provided you with the tools you'll need for the task.
|
||||||
Operation {$name} is a go ! Death to Nanotrasen!
|
Operation {$name} is a go ! Death to Nanotrasen!
|
||||||
|
nukeops-briefing = Your objectives are simple. Deliver the payload and make sure it detonates. Begin mission.
|
||||||
|
|
||||||
nukeops-opsmajor = [color=crimson]Syndicate major victory![/color]
|
nukeops-opsmajor = [color=crimson]Syndicate major victory![/color]
|
||||||
nukeops-opsminor = [color=crimson]Syndicate minor victory![/color]
|
nukeops-opsminor = [color=crimson]Syndicate minor victory![/color]
|
||||||
|
|||||||
@@ -176,9 +176,8 @@
|
|||||||
min: 1
|
min: 1
|
||||||
max: 1
|
max: 1
|
||||||
pickPlayer: false
|
pickPlayer: false
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: DragonRole
|
- MindRoleDragon
|
||||||
prototype: Dragon
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseGameRule
|
parent: BaseGameRule
|
||||||
@@ -226,9 +225,8 @@
|
|||||||
nameSegments:
|
nameSegments:
|
||||||
- names_ninja_title
|
- names_ninja_title
|
||||||
- names_ninja
|
- names_ninja
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: NinjaRole
|
- MindRoleNinja
|
||||||
prototype: SpaceNinja
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseGameRule
|
parent: BaseGameRule
|
||||||
@@ -439,9 +437,8 @@
|
|||||||
- type: ZombifyOnDeath
|
- type: ZombifyOnDeath
|
||||||
- type: IncurableZombie
|
- type: IncurableZombie
|
||||||
- type: InitialInfected
|
- type: InitialInfected
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: InitialInfectedRole
|
- MindRoleInitialInfected
|
||||||
prototype: InitialInfected
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseNukeopsRule
|
parent: BaseNukeopsRule
|
||||||
@@ -466,7 +463,6 @@
|
|||||||
startingGear: SyndicateLoneOperativeGearFull
|
startingGear: SyndicateLoneOperativeGearFull
|
||||||
roleLoadout:
|
roleLoadout:
|
||||||
- RoleSurvivalNukie
|
- RoleSurvivalNukie
|
||||||
|
|
||||||
components:
|
components:
|
||||||
- type: NukeOperative
|
- type: NukeOperative
|
||||||
- type: RandomMetadata
|
- type: RandomMetadata
|
||||||
@@ -476,9 +472,8 @@
|
|||||||
- type: NpcFactionMember
|
- type: NpcFactionMember
|
||||||
factions:
|
factions:
|
||||||
- Syndicate
|
- Syndicate
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: NukeopsRole
|
- MindRoleNukeops
|
||||||
prototype: Nukeops
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseTraitorRule
|
parent: BaseTraitorRule
|
||||||
@@ -505,9 +500,8 @@
|
|||||||
blacklist:
|
blacklist:
|
||||||
components:
|
components:
|
||||||
- AntagImmune
|
- AntagImmune
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: TraitorRole
|
- MindRoleTraitorSleeper
|
||||||
prototype: TraitorSleeper
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MassHallucinations
|
id: MassHallucinations
|
||||||
|
|||||||
@@ -26,8 +26,7 @@
|
|||||||
startingGear: ThiefGear
|
startingGear: ThiefGear
|
||||||
components:
|
components:
|
||||||
- type: Pacified
|
- type: Pacified
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: ThiefRole
|
- MindRoleThief
|
||||||
prototype: Thief
|
|
||||||
briefing:
|
briefing:
|
||||||
sound: "/Audio/Misc/thief_greeting.ogg"
|
sound: "/Audio/Misc/thief_greeting.ogg"
|
||||||
|
|||||||
@@ -114,9 +114,8 @@
|
|||||||
- type: NpcFactionMember
|
- type: NpcFactionMember
|
||||||
factions:
|
factions:
|
||||||
- Syndicate
|
- Syndicate
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: NukeopsRole
|
- MindRoleNukeopsCommander
|
||||||
prototype: NukeopsCommander
|
|
||||||
- prefRoles: [ NukeopsMedic ]
|
- prefRoles: [ NukeopsMedic ]
|
||||||
fallbackRoles: [ Nukeops, NukeopsCommander ]
|
fallbackRoles: [ Nukeops, NukeopsCommander ]
|
||||||
spawnerPrototype: SpawnPointNukeopsMedic
|
spawnerPrototype: SpawnPointNukeopsMedic
|
||||||
@@ -132,9 +131,8 @@
|
|||||||
- type: NpcFactionMember
|
- type: NpcFactionMember
|
||||||
factions:
|
factions:
|
||||||
- Syndicate
|
- Syndicate
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: NukeopsRole
|
- MindRoleNukeopsMedic
|
||||||
prototype: NukeopsMedic
|
|
||||||
- prefRoles: [ Nukeops ]
|
- prefRoles: [ Nukeops ]
|
||||||
fallbackRoles: [ NukeopsCommander, NukeopsMedic ]
|
fallbackRoles: [ NukeopsCommander, NukeopsMedic ]
|
||||||
spawnerPrototype: SpawnPointNukeopsOperative
|
spawnerPrototype: SpawnPointNukeopsOperative
|
||||||
@@ -152,9 +150,8 @@
|
|||||||
- type: NpcFactionMember
|
- type: NpcFactionMember
|
||||||
factions:
|
factions:
|
||||||
- Syndicate
|
- Syndicate
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: NukeopsRole
|
- MindRoleNukeops
|
||||||
prototype: Nukeops
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
abstract: true
|
abstract: true
|
||||||
@@ -189,9 +186,8 @@
|
|||||||
components:
|
components:
|
||||||
- AntagImmune
|
- AntagImmune
|
||||||
lateJoinAdditional: true
|
lateJoinAdditional: true
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: TraitorRole
|
- MindRoleTraitor
|
||||||
prototype: Traitor
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: Revolutionary
|
id: Revolutionary
|
||||||
@@ -213,9 +209,8 @@
|
|||||||
components:
|
components:
|
||||||
- type: Revolutionary
|
- type: Revolutionary
|
||||||
- type: HeadRevolutionary
|
- type: HeadRevolutionary
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: RevolutionaryRole
|
- MindRoleHeadRevolutionary
|
||||||
prototype: HeadRev
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: Sandbox
|
id: Sandbox
|
||||||
@@ -257,9 +252,8 @@
|
|||||||
- type: ZombifyOnDeath
|
- type: ZombifyOnDeath
|
||||||
- type: IncurableZombie
|
- type: IncurableZombie
|
||||||
- type: InitialInfected
|
- type: InitialInfected
|
||||||
mindComponents:
|
mindRoles:
|
||||||
- type: InitialInfectedRole
|
- MindRoleInitialInfected
|
||||||
prototype: InitialInfected
|
|
||||||
|
|
||||||
# event schedulers
|
# event schedulers
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
issuer: objective-issuer-dragon
|
issuer: objective-issuer-dragon
|
||||||
- type: RoleRequirement
|
- type: RoleRequirement
|
||||||
roles:
|
roles:
|
||||||
components:
|
mindRoles:
|
||||||
- DragonRole
|
- DragonRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
issuer: objective-issuer-spiderclan
|
issuer: objective-issuer-spiderclan
|
||||||
- type: RoleRequirement
|
- type: RoleRequirement
|
||||||
roles:
|
roles:
|
||||||
components:
|
mindRoles:
|
||||||
- NinjaRole
|
- NinjaRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
issuer: objective-issuer-thief
|
issuer: objective-issuer-thief
|
||||||
- type: RoleRequirement
|
- type: RoleRequirement
|
||||||
roles:
|
roles:
|
||||||
components:
|
mindRoles:
|
||||||
- ThiefRole
|
- ThiefRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
issuer: objective-issuer-syndicate
|
issuer: objective-issuer-syndicate
|
||||||
- type: RoleRequirement
|
- type: RoleRequirement
|
||||||
roles:
|
roles:
|
||||||
components:
|
mindRoles:
|
||||||
- TraitorRole
|
- TraitorRole
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
180
Resources/Prototypes/Roles/MindRoles/mind_roles.yml
Normal file
180
Resources/Prototypes/Roles/MindRoles/mind_roles.yml
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
- type: entity
|
||||||
|
id: BaseMindRole
|
||||||
|
name: Mind Role
|
||||||
|
description: Mind Role entity
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRole
|
||||||
|
id: BaseMindRoleAntag
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antag: true
|
||||||
|
|
||||||
|
#Observer
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRole
|
||||||
|
id: MindRoleObserver
|
||||||
|
name: Observer Role
|
||||||
|
components:
|
||||||
|
- type: ObserverRole
|
||||||
|
|
||||||
|
#Ghostrole Marker
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRole
|
||||||
|
id: MindRoleGhostMarker
|
||||||
|
name: Ghost Role
|
||||||
|
components:
|
||||||
|
- type: GhostRoleMarkerRole
|
||||||
|
|
||||||
|
# The Job MindRole holds the mob's Job prototype
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRole
|
||||||
|
id: MindRoleJob
|
||||||
|
name: Job Role
|
||||||
|
# description:
|
||||||
|
# MindRoleComponent.JobPrototype is filled by SharedJobSystem
|
||||||
|
|
||||||
|
# Subverted Silicon
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleSubvertedSilicon
|
||||||
|
name: Subverted Silicon Role
|
||||||
|
description:
|
||||||
|
components:
|
||||||
|
- type: SubvertedSiliconRole
|
||||||
|
|
||||||
|
# Dragon
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleDragon
|
||||||
|
name: Dragon Role
|
||||||
|
# description:
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: Dragon
|
||||||
|
exclusiveAntag: true
|
||||||
|
- type: DragonRole
|
||||||
|
- type: RoleBriefing
|
||||||
|
briefing: dragon-role-briefing
|
||||||
|
|
||||||
|
# Ninja
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleNinja
|
||||||
|
name: Space Ninja Role
|
||||||
|
# description: mind-role-ninja-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: SpaceNinja
|
||||||
|
exclusiveAntag: true
|
||||||
|
- type: NinjaRole
|
||||||
|
|
||||||
|
# Nukies
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleNukeops
|
||||||
|
name: Nukeops Operative Role
|
||||||
|
# description: mind-role-nukeops-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
exclusiveAntag: true
|
||||||
|
antagPrototype: Nukeops
|
||||||
|
- type: NukeopsRole
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: MindRoleNukeops
|
||||||
|
id: MindRoleNukeopsMedic
|
||||||
|
name: Nukeops Medic Role
|
||||||
|
# description: mind-role-nukeops-medic-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: NukeopsMedic
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: MindRoleNukeops
|
||||||
|
id: MindRoleNukeopsCommander
|
||||||
|
name: Nukeops Commander Role
|
||||||
|
# description: mind-role-nukeops-commander-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: NukeopsCommander
|
||||||
|
|
||||||
|
# Revolutionaries
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleHeadRevolutionary
|
||||||
|
name: Head Revolutionary Role
|
||||||
|
# description: mind-role-head-revolutionary-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: HeadRev
|
||||||
|
exclusiveAntag: true
|
||||||
|
- type: RevolutionaryRole
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: MindRoleHeadRevolutionary
|
||||||
|
id: MindRoleRevolutionary
|
||||||
|
name: Revolutionary Role
|
||||||
|
# description: mind-role-revolutionary-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: Rev
|
||||||
|
|
||||||
|
# Thief
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleThief
|
||||||
|
name: Thief Role
|
||||||
|
# description: mind-role-thief-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: Thief
|
||||||
|
- type: ThiefRole
|
||||||
|
|
||||||
|
# Traitors
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleTraitor
|
||||||
|
name: Traitor Role
|
||||||
|
# description: mind-role-traitor-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: Traitor
|
||||||
|
exclusiveAntag: true
|
||||||
|
- type: TraitorRole
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: MindRoleTraitor
|
||||||
|
id: MindRoleTraitorSleeper
|
||||||
|
name: Sleeper Agent Role
|
||||||
|
# description: mind-role-traitor-sleeper-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: TraitorSleeper
|
||||||
|
|
||||||
|
# Zombie Squad
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleInitialInfected
|
||||||
|
name: Initial Infected Role
|
||||||
|
# description: mind-role-initial-infected-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: InitialInfected
|
||||||
|
exclusiveAntag: true
|
||||||
|
- type: InitialInfectedRole
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMindRoleAntag
|
||||||
|
id: MindRoleZombie
|
||||||
|
name: Zombie Role
|
||||||
|
# description: mind-role-zombie-description
|
||||||
|
components:
|
||||||
|
- type: MindRole
|
||||||
|
antagPrototype: Zombie
|
||||||
|
exclusiveAntag: true
|
||||||
|
- type: ZombieRole
|
||||||
Reference in New Issue
Block a user