Refactor minds to be entities with components, make roles components (#19591)
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -211,8 +212,9 @@ public sealed partial class TestPair : IAsyncDisposable
|
|||||||
Assert.That(entMan.HasComponent<MindContainerComponent>(session.AttachedEntity));
|
Assert.That(entMan.HasComponent<MindContainerComponent>(session.AttachedEntity));
|
||||||
var mindCont = entMan.GetComponent<MindContainerComponent>(session.AttachedEntity!.Value);
|
var mindCont = entMan.GetComponent<MindContainerComponent>(session.AttachedEntity!.Value);
|
||||||
Assert.NotNull(mindCont.Mind);
|
Assert.NotNull(mindCont.Mind);
|
||||||
Assert.Null(mindCont.Mind?.VisitingEntity);
|
Assert.True(entMan.TryGetComponent(mindCont.Mind, out MindComponent? mind));
|
||||||
Assert.That(mindCont.Mind!.OwnedEntity, Is.EqualTo(session.AttachedEntity!.Value));
|
Assert.Null(mind!.VisitingEntity);
|
||||||
Assert.That(mindCont.Mind.UserId, Is.EqualTo(session.UserId));
|
Assert.That(mind.OwnedEntity, Is.EqualTo(session.AttachedEntity!.Value));
|
||||||
|
Assert.That(mind.UserId, Is.EqualTo(session.UserId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,19 +44,20 @@ public sealed class GhostRoleTests
|
|||||||
var conHost = client.ResolveDependency<IConsoleHost>();
|
var conHost = client.ResolveDependency<IConsoleHost>();
|
||||||
var mindSystem = entMan.System<MindSystem>();
|
var mindSystem = entMan.System<MindSystem>();
|
||||||
var session = sPlayerMan.ServerSessions.Single();
|
var session = sPlayerMan.ServerSessions.Single();
|
||||||
var originalMind = session.ContentData()!.Mind!;
|
var originalMindId = session.ContentData()!.Mind!.Value;
|
||||||
|
|
||||||
// Spawn player entity & attach
|
// Spawn player entity & attach
|
||||||
EntityUid originalMob = default;
|
EntityUid originalMob = default;
|
||||||
await server.WaitPost(() =>
|
await server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
originalMob = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
originalMob = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
||||||
mindSystem.TransferTo(originalMind, originalMob, true);
|
mindSystem.TransferTo(originalMindId, originalMob, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check player got attached.
|
// Check player got attached.
|
||||||
await pair.RunTicksSync(10);
|
await pair.RunTicksSync(10);
|
||||||
Assert.That(session.AttachedEntity, Is.EqualTo(originalMob));
|
Assert.That(session.AttachedEntity, Is.EqualTo(originalMob));
|
||||||
|
var originalMind = entMan.GetComponent<MindComponent>(originalMindId);
|
||||||
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
|
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
|
||||||
Assert.Null(originalMind.VisitingEntity);
|
Assert.Null(originalMind.VisitingEntity);
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ public sealed class GhostRoleTests
|
|||||||
var ghost = session.AttachedEntity;
|
var ghost = session.AttachedEntity;
|
||||||
Assert.That(entMan.HasComponent<GhostComponent>(ghost));
|
Assert.That(entMan.HasComponent<GhostComponent>(ghost));
|
||||||
Assert.That(ghost, Is.Not.EqualTo(originalMob));
|
Assert.That(ghost, Is.Not.EqualTo(originalMob));
|
||||||
Assert.That(session.ContentData()?.Mind, Is.EqualTo(originalMind));
|
Assert.That(session.ContentData()?.Mind, Is.EqualTo(originalMindId));
|
||||||
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
|
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
|
||||||
Assert.That(originalMind.VisitingEntity, Is.EqualTo(ghost));
|
Assert.That(originalMind.VisitingEntity, Is.EqualTo(ghost));
|
||||||
|
|
||||||
@@ -83,8 +84,9 @@ public sealed class GhostRoleTests
|
|||||||
|
|
||||||
// Check player got attached to ghost role.
|
// Check player got attached to ghost role.
|
||||||
await pair.RunTicksSync(10);
|
await pair.RunTicksSync(10);
|
||||||
var newMind = session.ContentData()!.Mind!;
|
var newMindId = session.ContentData()!.Mind!.Value;
|
||||||
Assert.That(newMind, Is.Not.EqualTo(originalMind));
|
var newMind = entMan.GetComponent<MindComponent>(newMindId);
|
||||||
|
Assert.That(newMindId, Is.Not.EqualTo(originalMindId));
|
||||||
Assert.That(session.AttachedEntity, Is.EqualTo(ghostRole));
|
Assert.That(session.AttachedEntity, Is.EqualTo(ghostRole));
|
||||||
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
|
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
|
||||||
Assert.Null(newMind.VisitingEntity);
|
Assert.Null(newMind.VisitingEntity);
|
||||||
@@ -101,12 +103,12 @@ public sealed class GhostRoleTests
|
|||||||
Assert.That(entMan.HasComponent<GhostComponent>(otherGhost));
|
Assert.That(entMan.HasComponent<GhostComponent>(otherGhost));
|
||||||
Assert.That(otherGhost, Is.Not.EqualTo(originalMob));
|
Assert.That(otherGhost, Is.Not.EqualTo(originalMob));
|
||||||
Assert.That(otherGhost, Is.Not.EqualTo(ghostRole));
|
Assert.That(otherGhost, Is.Not.EqualTo(ghostRole));
|
||||||
Assert.That(session.ContentData()?.Mind, Is.EqualTo(newMind));
|
Assert.That(session.ContentData()?.Mind, Is.EqualTo(newMindId));
|
||||||
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
|
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
|
||||||
Assert.That(newMind.VisitingEntity, Is.EqualTo(session.AttachedEntity));
|
Assert.That(newMind.VisitingEntity, Is.EqualTo(session.AttachedEntity));
|
||||||
|
|
||||||
// Next, control the original entity again:
|
// Next, control the original entity again:
|
||||||
await server.WaitPost(() => mindSystem.SetUserId(originalMind, session.UserId));
|
await server.WaitPost(() => mindSystem.SetUserId(originalMindId, session.UserId));
|
||||||
await pair.RunTicksSync(10);
|
await pair.RunTicksSync(10);
|
||||||
Assert.That(session.AttachedEntity, Is.EqualTo(originalMob));
|
Assert.That(session.AttachedEntity, Is.EqualTo(originalMob));
|
||||||
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
|
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ public sealed partial class MindTests
|
|||||||
|
|
||||||
EntityUid playerEnt = default;
|
EntityUid playerEnt = default;
|
||||||
EntityUid visitEnt = default;
|
EntityUid visitEnt = default;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
@@ -39,9 +40,10 @@ public sealed partial class MindTests
|
|||||||
playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
||||||
visitEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
visitEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
||||||
|
|
||||||
mind = mindSystem.CreateMind(player.UserId);
|
mindId = mindSystem.CreateMind(player.UserId);
|
||||||
mindSystem.TransferTo(mind, playerEnt);
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
mindSystem.Visit(mind, visitEnt);
|
mindSystem.TransferTo(mindId, playerEnt);
|
||||||
|
mindSystem.Visit(mindId, visitEnt);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
@@ -84,12 +86,14 @@ public sealed partial class MindTests
|
|||||||
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
||||||
|
|
||||||
EntityUid playerEnt = default;
|
EntityUid playerEnt = default;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
playerEnt = entMan.SpawnEntity(null, coordinates);
|
playerEnt = entMan.SpawnEntity(null, coordinates);
|
||||||
mind = player.ContentData()!.Mind!;
|
mindId = player.ContentData()!.Mind!.Value;
|
||||||
mindSystem.TransferTo(mind, playerEnt);
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
mindSystem.TransferTo(mindId, playerEnt);
|
||||||
|
|
||||||
Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt));
|
Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt));
|
||||||
});
|
});
|
||||||
@@ -169,15 +173,15 @@ public sealed partial class MindTests
|
|||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
ghost = entMan.SpawnEntity("MobObserver", MapCoordinates.Nullspace);
|
ghost = entMan.SpawnEntity("MobObserver", MapCoordinates.Nullspace);
|
||||||
mindSystem.Visit(mind, ghost);
|
mindSystem.Visit(mind.Id, ghost);
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(player.AttachedEntity, Is.EqualTo(ghost));
|
Assert.That(player.AttachedEntity, Is.EqualTo(ghost));
|
||||||
Assert.That(entMan.HasComponent<GhostComponent>(player.AttachedEntity), "player is not a ghost");
|
Assert.That(entMan.HasComponent<GhostComponent>(player.AttachedEntity), "player is not a ghost");
|
||||||
Assert.That(mind.VisitingEntity, Is.EqualTo(player.AttachedEntity));
|
Assert.That(mind.Comp.VisitingEntity, Is.EqualTo(player.AttachedEntity));
|
||||||
Assert.That(mind.OwnedEntity, Is.EqualTo(originalEntity));
|
Assert.That(mind.Comp.OwnedEntity, Is.EqualTo(originalEntity));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
@@ -192,8 +196,8 @@ public sealed partial class MindTests
|
|||||||
{
|
{
|
||||||
Assert.That(player.AttachedEntity, Is.EqualTo(ghost));
|
Assert.That(player.AttachedEntity, Is.EqualTo(ghost));
|
||||||
Assert.That(entMan.HasComponent<GhostComponent>(player.AttachedEntity));
|
Assert.That(entMan.HasComponent<GhostComponent>(player.AttachedEntity));
|
||||||
Assert.That(mind.VisitingEntity, Is.Null);
|
Assert.That(mind.Comp.VisitingEntity, Is.Null);
|
||||||
Assert.That(mind.OwnedEntity, Is.EqualTo(ghost));
|
Assert.That(mind.Comp.OwnedEntity, Is.EqualTo(ghost));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.CleanReturnAsync();
|
await pair.CleanReturnAsync();
|
||||||
@@ -233,8 +237,10 @@ public sealed partial class MindTests
|
|||||||
Assert.That(entMan.GetComponent<MetaDataComponent>(player.AttachedEntity!.Value).EntityPrototype?.ID, Is.EqualTo("AdminObserver"));
|
Assert.That(entMan.GetComponent<MetaDataComponent>(player.AttachedEntity!.Value).EntityPrototype?.ID, Is.EqualTo("AdminObserver"));
|
||||||
});
|
});
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
var mindId = player.ContentData()?.Mind;
|
||||||
Assert.That(mind, Is.Not.Null);
|
Assert.That(mindId, Is.Not.Null);
|
||||||
|
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId.Value);
|
||||||
Assert.That(mind.VisitingEntity, Is.Null);
|
Assert.That(mind.VisitingEntity, Is.Null);
|
||||||
|
|
||||||
await pair.CleanReturnAsync();
|
await pair.CleanReturnAsync();
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ using Robust.Shared.Enums;
|
|||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using IPlayerManager = Robust.Server.Player.IPlayerManager;
|
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.Minds;
|
namespace Content.IntegrationTests.Tests.Minds;
|
||||||
|
|
||||||
@@ -40,19 +39,21 @@ public sealed partial class MindTests
|
|||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
|
|
||||||
EntityUid entity = default;
|
EntityUid entity = default;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
await pair.Server.WaitPost(() =>
|
await pair.Server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
entity = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
entity = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
||||||
mind = mindSys.CreateMind(player.UserId);
|
mindId = mindSys.CreateMind(player.UserId);
|
||||||
mindSys.TransferTo(mind, entity);
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
mindSys.TransferTo(mindId, entity);
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(player.ContentData()?.Mind, Is.EqualTo(mind));
|
Assert.That(player.ContentData()?.Mind, Is.EqualTo(mindId));
|
||||||
Assert.That(player.AttachedEntity, Is.EqualTo(entity));
|
Assert.That(player.AttachedEntity, Is.EqualTo(entity));
|
||||||
Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity.");
|
Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity.");
|
||||||
Assert.That(entMan.EntityExists(mind.OwnedEntity), "The mind's current entity does not exist");
|
Assert.That(entMan.EntityExists(mind.OwnedEntity), "The mind's current entity does not exist");
|
||||||
@@ -67,23 +68,25 @@ public sealed partial class MindTests
|
|||||||
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
|
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
|
||||||
var mindSys = entMan.System<MindSystem>();
|
var mindSys = entMan.System<MindSystem>();
|
||||||
EntityUid ghostUid = default;
|
EntityUid ghostUid = default;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
|
|
||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
await pair.Server.WaitAssertion(() =>
|
await pair.Server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var oldUid = player.AttachedEntity;
|
var oldUid = player.AttachedEntity;
|
||||||
ghostUid = entMan.SpawnEntity("MobObserver", MapCoordinates.Nullspace);
|
ghostUid = entMan.SpawnEntity("MobObserver", MapCoordinates.Nullspace);
|
||||||
mind = mindSys.GetMind(player.UserId);
|
mindId = mindSys.GetMind(player.UserId)!.Value;
|
||||||
Assert.That(mind, Is.Not.Null);
|
Assert.That(mindId, Is.Not.EqualTo(default(EntityUid)));
|
||||||
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
|
||||||
if (visit)
|
if (visit)
|
||||||
{
|
{
|
||||||
mindSys.Visit(mind, ghostUid);
|
mindSys.Visit(mindId, ghostUid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mindSys.TransferTo(mind, ghostUid);
|
mindSys.TransferTo(mindId, ghostUid);
|
||||||
if (oldUid != null)
|
if (oldUid != null)
|
||||||
entMan.DeleteEntity(oldUid.Value);
|
entMan.DeleteEntity(oldUid.Value);
|
||||||
|
|
||||||
@@ -111,15 +114,16 @@ public sealed partial class MindTests
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the player's current mind and check that the entities exists.
|
/// Get the player's current mind and check that the entities exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Mind GetMind(Pair.TestPair pair)
|
private static (EntityUid Id, MindComponent Comp) GetMind(Pair.TestPair pair)
|
||||||
{
|
{
|
||||||
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
|
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
|
||||||
var entMan = pair.Server.ResolveDependency<IEntityManager>();
|
var entMan = pair.Server.ResolveDependency<IEntityManager>();
|
||||||
var player = playerMan.ServerSessions.SingleOrDefault();
|
var player = playerMan.ServerSessions.SingleOrDefault();
|
||||||
Assert.That(player, Is.Not.Null);
|
Assert.That(player, Is.Not.Null);
|
||||||
|
|
||||||
var mind = player.ContentData()!.Mind;
|
var mindId = player.ContentData()!.Mind!.Value;
|
||||||
Assert.That(mind, Is.Not.Null);
|
Assert.That(mindId, Is.Not.EqualTo(default(EntityUid)));
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity.");
|
Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity.");
|
||||||
@@ -127,15 +131,17 @@ public sealed partial class MindTests
|
|||||||
Assert.That(mind.VisitingEntity == null || entMan.EntityExists(mind.VisitingEntity), "The minds visited entity does not exist.");
|
Assert.That(mind.VisitingEntity == null || entMan.EntityExists(mind.VisitingEntity), "The minds visited entity does not exist.");
|
||||||
});
|
});
|
||||||
|
|
||||||
return mind;
|
return (mindId, mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task Disconnect(Pair.TestPair pair)
|
private static async Task Disconnect(Pair.TestPair pair)
|
||||||
{
|
{
|
||||||
var netManager = pair.Client.ResolveDependency<IClientNetManager>();
|
var netManager = pair.Client.ResolveDependency<IClientNetManager>();
|
||||||
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
|
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
|
||||||
|
var entMan = pair.Server.ResolveDependency<IEntityManager>();
|
||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
var mind = player.ContentData()!.Mind;
|
var mindId = player.ContentData()!.Mind!.Value;
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
|
||||||
await pair.Client.WaitAssertion(() =>
|
await pair.Client.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public sealed partial class MindTests
|
|||||||
{
|
{
|
||||||
Assert.That(GetMind(pair), Is.EqualTo(mind));
|
Assert.That(GetMind(pair), Is.EqualTo(mind));
|
||||||
Assert.That(entMan.Deleted(ghost));
|
Assert.That(entMan.Deleted(ghost));
|
||||||
Assert.That(entMan.HasComponent<GhostComponent>(mind.OwnedEntity));
|
Assert.That(entMan.HasComponent<GhostComponent>(mind.Comp.OwnedEntity));
|
||||||
Assert.That(mind.VisitingEntity, Is.Null);
|
Assert.That(mind.Comp.VisitingEntity, Is.Null);
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.CleanReturnAsync();
|
await pair.CleanReturnAsync();
|
||||||
@@ -52,11 +52,11 @@ public sealed partial class MindTests
|
|||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
var name = player.Name;
|
var name = player.Name;
|
||||||
var user = player.UserId;
|
var user = player.UserId;
|
||||||
Assert.That(mind.OwnedEntity, Is.Not.Null);
|
Assert.That(mind.Comp.OwnedEntity, Is.Not.Null);
|
||||||
var entity = mind.OwnedEntity.Value;
|
var entity = mind.Comp.OwnedEntity.Value;
|
||||||
|
|
||||||
// Player is not a ghost
|
// Player is not a ghost
|
||||||
Assert.That(!entMan.HasComponent<GhostComponent>(mind.CurrentEntity));
|
Assert.That(!entMan.HasComponent<GhostComponent>(mind.Comp.CurrentEntity));
|
||||||
|
|
||||||
// Disconnect
|
// Disconnect
|
||||||
await Disconnect(pair);
|
await Disconnect(pair);
|
||||||
@@ -67,7 +67,7 @@ public sealed partial class MindTests
|
|||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(entMan.Deleted(entity));
|
Assert.That(entMan.Deleted(entity));
|
||||||
Assert.That(mind.OwnedEntity, Is.Null);
|
Assert.That(mind.Comp.OwnedEntity, Is.Null);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reconnect
|
// Reconnect
|
||||||
@@ -79,8 +79,8 @@ public sealed partial class MindTests
|
|||||||
|
|
||||||
// Player is now a new ghost entity
|
// Player is now a new ghost entity
|
||||||
Assert.That(GetMind(pair), Is.EqualTo(mind));
|
Assert.That(GetMind(pair), Is.EqualTo(mind));
|
||||||
Assert.That(mind.OwnedEntity, Is.Not.EqualTo(entity));
|
Assert.That(mind.Comp.OwnedEntity, Is.Not.EqualTo(entity));
|
||||||
Assert.That(entMan.HasComponent<GhostComponent>(mind.OwnedEntity));
|
Assert.That(entMan.HasComponent<GhostComponent>(mind.Comp.OwnedEntity));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.CleanReturnAsync();
|
await pair.CleanReturnAsync();
|
||||||
@@ -98,7 +98,7 @@ public sealed partial class MindTests
|
|||||||
var entMan = pair.Server.ResolveDependency<IEntityManager>();
|
var entMan = pair.Server.ResolveDependency<IEntityManager>();
|
||||||
var mind = GetMind(pair);
|
var mind = GetMind(pair);
|
||||||
|
|
||||||
var original = mind.CurrentEntity;
|
var original = mind.Comp.CurrentEntity;
|
||||||
var ghost = await VisitGhost(pair);
|
var ghost = await VisitGhost(pair);
|
||||||
await DisconnectReconnect(pair);
|
await DisconnectReconnect(pair);
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ public sealed partial class MindTests
|
|||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mind, Is.EqualTo(GetMind(pair)));
|
Assert.That(mind, Is.EqualTo(GetMind(pair)));
|
||||||
Assert.That(mind.CurrentEntity, Is.EqualTo(original));
|
Assert.That(mind.Comp.CurrentEntity, Is.EqualTo(original));
|
||||||
Assert.That(entMan.Deleted(original), Is.False);
|
Assert.That(entMan.Deleted(original), Is.False);
|
||||||
Assert.That(entMan.Deleted(ghost));
|
Assert.That(entMan.Deleted(ghost));
|
||||||
});
|
});
|
||||||
@@ -128,12 +128,12 @@ public sealed partial class MindTests
|
|||||||
var mind = GetMind(pair);
|
var mind = GetMind(pair);
|
||||||
|
|
||||||
// Make player visit a new mob
|
// Make player visit a new mob
|
||||||
var original = mind.CurrentEntity;
|
var original = mind.Comp.CurrentEntity;
|
||||||
EntityUid visiting = default;
|
EntityUid visiting = default;
|
||||||
await pair.Server.WaitAssertion(() =>
|
await pair.Server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
visiting = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
visiting = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
|
||||||
mindSys.Visit(mind, visiting);
|
mindSys.Visit(mind.Id, visiting);
|
||||||
});
|
});
|
||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ public sealed partial class MindTests
|
|||||||
Assert.That(GetMind(pair), Is.EqualTo(mind));
|
Assert.That(GetMind(pair), Is.EqualTo(mind));
|
||||||
Assert.That(entMan.Deleted(original), Is.False);
|
Assert.That(entMan.Deleted(original), Is.False);
|
||||||
Assert.That(entMan.Deleted(visiting), Is.False);
|
Assert.That(entMan.Deleted(visiting), Is.False);
|
||||||
Assert.That(mind.CurrentEntity, Is.EqualTo(visiting));
|
Assert.That(mind.Comp.CurrentEntity, Is.EqualTo(visiting));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.CleanReturnAsync();
|
await pair.CleanReturnAsync();
|
||||||
|
|||||||
@@ -8,17 +8,17 @@ using Content.Server.Mind.Commands;
|
|||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Roles;
|
|
||||||
using Robust.Server.Console;
|
using Robust.Server.Console;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using IPlayerManager = Robust.Server.Player.IPlayerManager;
|
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.Minds;
|
namespace Content.IntegrationTests.Tests.Minds;
|
||||||
|
|
||||||
@@ -66,12 +66,13 @@ public sealed partial class MindTests
|
|||||||
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
||||||
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
||||||
|
|
||||||
var mind = mindSystem.CreateMind(null);
|
var mindId = mindSystem.CreateMind(null);
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
|
||||||
Assert.That(mind.UserId, Is.EqualTo(null));
|
Assert.That(mind.UserId, Is.EqualTo(null));
|
||||||
|
|
||||||
mindSystem.TransferTo(mind, entity);
|
mindSystem.TransferTo(mindId, entity, mind: mind);
|
||||||
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.CleanReturnAsync();
|
await pair.CleanReturnAsync();
|
||||||
@@ -92,15 +93,16 @@ public sealed partial class MindTests
|
|||||||
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
||||||
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
||||||
|
|
||||||
var mind = mindSystem.CreateMind(null);
|
var mindId = mindSystem.CreateMind(null);
|
||||||
mindSystem.TransferTo(mind, entity);
|
mindSystem.TransferTo(mindId, entity);
|
||||||
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
|
||||||
|
|
||||||
var mind2 = mindSystem.CreateMind(null);
|
var mind2 = mindSystem.CreateMind(null);
|
||||||
mindSystem.TransferTo(mind2, entity);
|
mindSystem.TransferTo(mind2, entity);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind2));
|
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind2));
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
Assert.That(mind.OwnedEntity, Is.Not.EqualTo(entity));
|
Assert.That(mind.OwnedEntity, Is.Not.EqualTo(entity));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -119,7 +121,7 @@ public sealed partial class MindTests
|
|||||||
|
|
||||||
EntityUid entity = default!;
|
EntityUid entity = default!;
|
||||||
MindContainerComponent mindContainerComp = default!;
|
MindContainerComponent mindContainerComp = default!;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
||||||
var damageableSystem = entMan.EntitySysManager.GetEntitySystem<DamageableSystem>();
|
var damageableSystem = entMan.EntitySysManager.GetEntitySystem<DamageableSystem>();
|
||||||
|
|
||||||
@@ -128,12 +130,13 @@ public sealed partial class MindTests
|
|||||||
entity = entMan.SpawnEntity("MindTestEntityDamageable", new MapCoordinates());
|
entity = entMan.SpawnEntity("MindTestEntityDamageable", new MapCoordinates());
|
||||||
mindContainerComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
mindContainerComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
||||||
|
|
||||||
mind = mindSystem.CreateMind(null);
|
mindId = mindSystem.CreateMind(null);
|
||||||
|
|
||||||
mindSystem.TransferTo(mind, entity);
|
mindSystem.TransferTo(mindId, entity);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId));
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
Assert.That(!mindSystem.IsCharacterDeadPhysically(mind));
|
Assert.That(!mindSystem.IsCharacterDeadPhysically(mind));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -149,13 +152,14 @@ public sealed partial class MindTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
damageableSystem.SetDamage(entity, damageable, new DamageSpecifier(prototype, FixedPoint2.New(401)));
|
damageableSystem.SetDamage(entity, damageable, new DamageSpecifier(prototype, FixedPoint2.New(401)));
|
||||||
Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
|
var mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
Assert.That(mindSystem.IsCharacterDeadPhysically(mind));
|
Assert.That(mindSystem.IsCharacterDeadPhysically(mind));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -211,20 +215,22 @@ public sealed partial class MindTests
|
|||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
||||||
var originalMind = GetMind(pair);
|
var originalMind = GetMind(pair);
|
||||||
var userId = originalMind.UserId;
|
var userId = originalMind.Comp.UserId;
|
||||||
|
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
||||||
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
||||||
entMan.DirtyEntity(entity);
|
entMan.DirtyEntity(entity);
|
||||||
|
|
||||||
mind = mindSystem.CreateMind(null);
|
mindId = mindSystem.CreateMind(null);
|
||||||
mindSystem.TransferTo(mind, entity);
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
mindSystem.TransferTo(mindId, entity);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
|
||||||
Assert.That(mindComp.HasMind);
|
Assert.That(mindComp.HasMind);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -233,18 +239,18 @@ public sealed partial class MindTests
|
|||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
mindSystem.SetUserId(mind, userId);
|
mindSystem.SetUserId(mindId, userId);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mind.UserId, Is.EqualTo(userId));
|
Assert.That(mind.UserId, Is.EqualTo(userId));
|
||||||
Assert.That(originalMind.UserId, Is.EqualTo(null));
|
Assert.That(originalMind.Comp.UserId, Is.EqualTo(null));
|
||||||
});
|
});
|
||||||
|
|
||||||
mindSystem.SetUserId(originalMind, userId);
|
mindSystem.SetUserId(originalMind.Id, userId);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mind.UserId, Is.EqualTo(null));
|
Assert.That(mind.UserId, Is.EqualTo(null));
|
||||||
Assert.That(originalMind.UserId, Is.EqualTo(userId));
|
Assert.That(originalMind.Comp.UserId, Is.EqualTo(userId));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -264,57 +270,59 @@ public sealed partial class MindTests
|
|||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
|
||||||
|
var roleSystem = entMan.EntitySysManager.GetEntitySystem<RoleSystem>();
|
||||||
|
|
||||||
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
var entity = entMan.SpawnEntity(null, new MapCoordinates());
|
||||||
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
||||||
|
|
||||||
var mind = mindSystem.CreateMind(null);
|
var mindId = mindSystem.CreateMind(null);
|
||||||
|
var mind = entMan.EnsureComponent<MindComponent>(mindId);
|
||||||
|
|
||||||
Assert.That(mind.UserId, Is.EqualTo(null));
|
Assert.That(mind.UserId, Is.EqualTo(null));
|
||||||
|
|
||||||
mindSystem.TransferTo(mind, entity);
|
mindSystem.TransferTo(mindId, entity);
|
||||||
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.HasRole<TraitorRole>(mind), Is.False);
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
||||||
Assert.That(mindSystem.HasRole<Job>(mind), Is.False);
|
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId), Is.False);
|
||||||
});
|
});
|
||||||
|
|
||||||
var traitorRole = new TraitorRole(mind, new AntagPrototype());
|
var traitorRole = new TraitorRoleComponent();
|
||||||
|
|
||||||
mindSystem.AddRole(mind, traitorRole);
|
roleSystem.MindAddRole(mindId, traitorRole);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.HasRole<TraitorRole>(mind));
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
|
||||||
Assert.That(mindSystem.HasRole<Job>(mind), Is.False);
|
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId), Is.False);
|
||||||
});
|
});
|
||||||
|
|
||||||
var jobRole = new Job(mind, new JobPrototype());
|
var jobRole = new JobComponent();
|
||||||
|
|
||||||
mindSystem.AddRole(mind, jobRole);
|
roleSystem.MindAddRole(mindId, jobRole);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.HasRole<TraitorRole>(mind));
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
|
||||||
Assert.That(mindSystem.HasRole<Job>(mind));
|
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
mindSystem.RemoveRole(mind, traitorRole);
|
roleSystem.MindRemoveRole<TraitorRoleComponent>(mindId);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.HasRole<TraitorRole>(mind), Is.False);
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
||||||
Assert.That(mindSystem.HasRole<Job>(mind));
|
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
mindSystem.RemoveRole(mind, jobRole);
|
roleSystem.MindRemoveRole<JobComponent>(mindId);
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(mindSystem.HasRole<TraitorRole>(mind), Is.False);
|
Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
|
||||||
Assert.That(mindSystem.HasRole<Job>(mind), Is.False);
|
Assert.That(roleSystem.MindHasRole<JobComponent>(mindId), Is.False);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -335,7 +343,8 @@ public sealed partial class MindTests
|
|||||||
var ghostSystem = entMan.EntitySysManager.GetEntitySystem<GhostSystem>();
|
var ghostSystem = entMan.EntitySysManager.GetEntitySystem<GhostSystem>();
|
||||||
|
|
||||||
EntityUid entity = default!;
|
EntityUid entity = default!;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
@@ -343,12 +352,13 @@ public sealed partial class MindTests
|
|||||||
entity = entMan.SpawnEntity(null, new MapCoordinates());
|
entity = entMan.SpawnEntity(null, new MapCoordinates());
|
||||||
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
|
||||||
|
|
||||||
mind = mindSystem.CreateMind(player.UserId, "Mindy McThinker");
|
mindId = mindSystem.CreateMind(player.UserId, "Mindy McThinker");
|
||||||
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
|
||||||
Assert.That(mind.UserId, Is.EqualTo(player.UserId));
|
Assert.That(mind.UserId, Is.EqualTo(player.UserId));
|
||||||
|
|
||||||
mindSystem.TransferTo(mind, entity);
|
mindSystem.TransferTo(mindId, entity);
|
||||||
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
|
Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
@@ -361,7 +371,8 @@ public sealed partial class MindTests
|
|||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
|
|
||||||
EntityUid mob = default!;
|
EntityUid mob = default!;
|
||||||
Mind mobMind = default!;
|
EntityUid mobMindId = default!;
|
||||||
|
MindComponent mobMind = default!;
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
@@ -370,22 +381,25 @@ public sealed partial class MindTests
|
|||||||
mob = entMan.SpawnEntity(null, new MapCoordinates());
|
mob = entMan.SpawnEntity(null, new MapCoordinates());
|
||||||
|
|
||||||
MakeSentientCommand.MakeSentient(mob, IoCManager.Resolve<IEntityManager>());
|
MakeSentientCommand.MakeSentient(mob, IoCManager.Resolve<IEntityManager>());
|
||||||
mobMind = mindSystem.CreateMind(player.UserId, "Mindy McThinker the Second");
|
mobMindId = mindSystem.CreateMind(player.UserId, "Mindy McThinker the Second");
|
||||||
|
mobMind = entMan.GetComponent<MindComponent>(mobMindId);
|
||||||
|
|
||||||
mindSystem.SetUserId(mobMind, player.UserId);
|
mindSystem.SetUserId(mobMindId, player.UserId);
|
||||||
mindSystem.TransferTo(mobMind, mob);
|
mindSystem.TransferTo(mobMindId, mob);
|
||||||
});
|
});
|
||||||
|
|
||||||
await pair.RunTicksSync(5);
|
await pair.RunTicksSync(5);
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var m = player.ContentData()?.Mind;
|
var mId = player.ContentData()?.Mind!.Value;
|
||||||
Assert.That(m, Is.Not.Null);
|
Assert.That(mId, Is.Not.Null);
|
||||||
|
Assert.That(mId, Is.Not.EqualTo(default(EntityUid)));
|
||||||
|
var m = entMan.GetComponent<MindComponent>(mId!.Value);
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
{
|
{
|
||||||
Assert.That(m!.OwnedEntity, Is.EqualTo(mob));
|
Assert.That(m!.OwnedEntity, Is.EqualTo(mob));
|
||||||
Assert.That(m, Is.Not.EqualTo(mind));
|
Assert.That(mId, Is.Not.EqualTo(mindId));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -416,7 +430,8 @@ public sealed partial class MindTests
|
|||||||
//EntityUid entity = default!;
|
//EntityUid entity = default!;
|
||||||
EntityUid ghostRole = default!;
|
EntityUid ghostRole = default!;
|
||||||
EntityUid ghost = default!;
|
EntityUid ghost = default!;
|
||||||
Mind mind = default!;
|
EntityUid mindId = default!;
|
||||||
|
MindComponent mind = default!;
|
||||||
var player = playerMan.ServerSessions.Single();
|
var player = playerMan.ServerSessions.Single();
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
@@ -434,7 +449,8 @@ public sealed partial class MindTests
|
|||||||
var data = player.ContentData();
|
var data = player.ContentData();
|
||||||
|
|
||||||
Assert.That(data?.Mind, Is.Not.EqualTo(null));
|
Assert.That(data?.Mind, Is.Not.EqualTo(null));
|
||||||
mind = data!.Mind!;
|
mindId = data!.Mind!.Value;
|
||||||
|
mind = entMan.GetComponent<MindComponent>(mindId);
|
||||||
|
|
||||||
Assert.That(mind.OwnedEntity, Is.Not.Null);
|
Assert.That(mind.OwnedEntity, Is.Not.Null);
|
||||||
|
|
||||||
@@ -460,8 +476,8 @@ public sealed partial class MindTests
|
|||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
var data = player.ContentData()!;
|
var data = entMan.GetComponent<MindComponent>(player.ContentData()!.Mind!.Value);
|
||||||
Assert.That(data.Mind!.OwnedEntity, Is.EqualTo(ghostRole));
|
Assert.That(data.OwnedEntity, Is.EqualTo(ghostRole));
|
||||||
|
|
||||||
serverConsole.ExecuteCommand(player, "aghost");
|
serverConsole.ExecuteCommand(player, "aghost");
|
||||||
Assert.That(player.AttachedEntity, Is.Not.Null);
|
Assert.That(player.AttachedEntity, Is.Not.Null);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
@@ -26,20 +25,18 @@ namespace Content.Server.Administration.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
var mindSystem = _entities.System<MindSystem>();
|
||||||
|
if (!mindSystem.TryGetMind(player, out var mindId, out var mind))
|
||||||
if (mind == null)
|
|
||||||
{
|
{
|
||||||
shell.WriteLine("You can't ghost here!");
|
shell.WriteLine("You can't ghost here!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mindSystem = _entities.System<MindSystem>();
|
|
||||||
var metaDataSystem = _entities.System<MetaDataSystem>();
|
var metaDataSystem = _entities.System<MetaDataSystem>();
|
||||||
|
|
||||||
if (mind.VisitingEntity != default && _entities.TryGetComponent<GhostComponent>(mind.VisitingEntity, out var oldGhostComponent))
|
if (mind.VisitingEntity != default && _entities.TryGetComponent<GhostComponent>(mind.VisitingEntity, out var oldGhostComponent))
|
||||||
{
|
{
|
||||||
mindSystem.UnVisit(mind);
|
mindSystem.UnVisit(mindId, mind);
|
||||||
// If already an admin ghost, then return to body.
|
// If already an admin ghost, then return to body.
|
||||||
if (oldGhostComponent.CanGhostInteract)
|
if (oldGhostComponent.CanGhostInteract)
|
||||||
return;
|
return;
|
||||||
@@ -61,12 +58,12 @@ namespace Content.Server.Administration.Commands
|
|||||||
else if (!string.IsNullOrWhiteSpace(mind.Session?.Name))
|
else if (!string.IsNullOrWhiteSpace(mind.Session?.Name))
|
||||||
metaDataSystem.SetEntityName(ghost, mind.Session.Name);
|
metaDataSystem.SetEntityName(ghost, mind.Session.Name);
|
||||||
|
|
||||||
mindSystem.Visit(mind, ghost);
|
mindSystem.Visit(mindId, ghost, mind);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
metaDataSystem.SetEntityName(ghost, player.Name);
|
metaDataSystem.SetEntityName(ghost, player.Name);
|
||||||
mindSystem.TransferTo(mind, ghost);
|
mindSystem.TransferTo(mindId, ghost, mind: mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
var comp = _entities.GetComponent<GhostComponent>(ghost);
|
var comp = _entities.GetComponent<GhostComponent>(ghost);
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
namespace Content.Server.Administration.Commands
|
||||||
{
|
{
|
||||||
@@ -45,18 +42,14 @@ namespace Content.Server.Administration.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_entities.HasComponent<MindContainerComponent>(target))
|
var mindSystem = _entities.System<MindSystem>();
|
||||||
|
if (!mindSystem.TryGetMind(target, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
shell.WriteLine(Loc.GetString("shell-entity-is-not-mob"));
|
shell.WriteLine(Loc.GetString("shell-entity-is-not-mob"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
mindSystem.TransferTo(mindId, target, mind: mind);
|
||||||
|
|
||||||
DebugTools.AssertNotNull(mind);
|
|
||||||
|
|
||||||
var mindSystem = _entities.System<MindSystem>();
|
|
||||||
mindSystem.TransferTo(mind!, target);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,13 +68,9 @@ namespace Content.Server.Administration.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mindSystem = entityManager.System<MindSystem>();
|
var mindSystem = entityManager.System<MindSystem>();
|
||||||
|
var metadata = entityManager.GetComponent<MetaDataComponent>(eUid);
|
||||||
|
|
||||||
var mind = playerCData.Mind;
|
var mind = playerCData.Mind ?? mindSystem.CreateMind(session.UserId, metadata.EntityName);
|
||||||
if (mind == null)
|
|
||||||
{
|
|
||||||
mind = mindSystem.CreateMind(session.UserId);
|
|
||||||
mind.CharacterName = entityManager.GetComponent<MetaDataComponent>(eUid).EntityName;
|
|
||||||
}
|
|
||||||
|
|
||||||
mindSystem.TransferTo(mind, eUid, ghostOverride);
|
mindSystem.TransferTo(mind, eUid, ghostOverride);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.GameTicking.Events;
|
|
||||||
using Content.Server.IdentityManagement;
|
using Content.Server.IdentityManagement;
|
||||||
using Content.Server.Players;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Administration.Events;
|
using Content.Shared.Administration.Events;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -20,6 +19,9 @@ namespace Content.Server.Administration.Systems
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||||
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _role = default!;
|
||||||
|
|
||||||
private readonly Dictionary<NetUserId, PlayerInfo> _playerList = new();
|
private readonly Dictionary<NetUserId, PlayerInfo> _playerList = new();
|
||||||
|
|
||||||
@@ -102,10 +104,10 @@ namespace Content.Server.Administration.Systems
|
|||||||
|
|
||||||
private void OnRoleEvent(RoleEvent ev)
|
private void OnRoleEvent(RoleEvent ev)
|
||||||
{
|
{
|
||||||
if (!ev.Role.Antagonist || ev.Role.Mind.Session == null)
|
if (!ev.Antagonist || ev.Mind.Session == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdatePlayerList(ev.Role.Mind.Session);
|
UpdatePlayerList(ev.Mind.Session);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAdminPermsChanged(AdminPermsChangedEventArgs obj)
|
private void OnAdminPermsChanged(AdminPermsChangedEventArgs obj)
|
||||||
@@ -169,12 +171,13 @@ namespace Content.Server.Administration.Systems
|
|||||||
identityName = Identity.Name(session.AttachedEntity.Value, EntityManager);
|
identityName = Identity.Name(session.AttachedEntity.Value, EntityManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = data.ContentData()?.Mind;
|
var antag = false;
|
||||||
|
var startingRole = string.Empty;
|
||||||
var job = mind?.AllRoles.FirstOrDefault(role => role is Job);
|
if (_minds.TryGetMind(session, out var mindId, out _))
|
||||||
var startingRole = job != null ? CultureInfo.CurrentCulture.TextInfo.ToTitleCase(job.Name) : string.Empty;
|
{
|
||||||
|
antag = _role.MindIsAntagonist(mindId);
|
||||||
var antag = mind?.AllRoles.Any(r => r.Antagonist) ?? false;
|
startingRole = _jobs.MindTryGetJobName(mindId);
|
||||||
|
}
|
||||||
|
|
||||||
var connected = session != null && session.Status is SessionStatus.Connected or SessionStatus.InGame;
|
var connected = session != null && session.Status is SessionStatus.Connected or SessionStatus.InGame;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.GameTicking.Rules;
|
using Content.Server.GameTicking.Rules;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Zombies;
|
using Content.Server.Zombies;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
@@ -15,6 +16,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
[Dependency] private readonly TraitorRuleSystem _traitorRule = default!;
|
[Dependency] private readonly TraitorRuleSystem _traitorRule = default!;
|
||||||
[Dependency] private readonly NukeopsRuleSystem _nukeopsRule = default!;
|
[Dependency] private readonly NukeopsRuleSystem _nukeopsRule = default!;
|
||||||
[Dependency] private readonly PiratesRuleSystem _piratesRule = default!;
|
[Dependency] private readonly PiratesRuleSystem _piratesRule = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
|
||||||
// All antag verbs have names so invokeverb works.
|
// All antag verbs have names so invokeverb works.
|
||||||
private void AddAntagVerbs(GetVerbsEvent<Verb> args)
|
private void AddAntagVerbs(GetVerbsEvent<Verb> args)
|
||||||
@@ -38,10 +40,10 @@ public sealed partial class AdminVerbSystem
|
|||||||
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Structures/Wallmounts/posters.rsi"), "poster5_contraband"),
|
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Structures/Wallmounts/posters.rsi"), "poster5_contraband"),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
if (targetMindComp.Mind == null || targetMindComp.Mind.Session == null)
|
if (!_minds.TryGetSession(targetMindComp.Mind, out var session))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_traitorRule.MakeTraitor(targetMindComp.Mind.Session);
|
_traitorRule.MakeTraitor(session);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.High,
|
Impact = LogImpact.High,
|
||||||
Message = Loc.GetString("admin-verb-make-traitor"),
|
Message = Loc.GetString("admin-verb-make-traitor"),
|
||||||
@@ -70,10 +72,10 @@ public sealed partial class AdminVerbSystem
|
|||||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Structures/Wallmounts/signs.rsi"), "radiation"),
|
Icon = new SpriteSpecifier.Rsi(new("/Textures/Structures/Wallmounts/signs.rsi"), "radiation"),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
if (targetMindComp.Mind == null || targetMindComp.Mind.Session == null)
|
if (!_minds.TryGetMind(args.Target, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_nukeopsRule.MakeLoneNukie(targetMindComp.Mind);
|
_nukeopsRule.MakeLoneNukie(mindId, mind);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.High,
|
Impact = LogImpact.High,
|
||||||
Message = Loc.GetString("admin-verb-make-nuclear-operative"),
|
Message = Loc.GetString("admin-verb-make-nuclear-operative"),
|
||||||
@@ -87,10 +89,10 @@ public sealed partial class AdminVerbSystem
|
|||||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Clothing/Head/Hats/pirate.rsi"), "icon"),
|
Icon = new SpriteSpecifier.Rsi(new("/Textures/Clothing/Head/Hats/pirate.rsi"), "icon"),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
if (targetMindComp.Mind == null || targetMindComp.Mind.Session == null)
|
if (!_minds.TryGetMind(args.Target, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_piratesRule.MakePirate(targetMindComp.Mind);
|
_piratesRule.MakePirate(mindId, mind);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.High,
|
Impact = LogImpact.High,
|
||||||
Message = Loc.GetString("admin-verb-make-pirate"),
|
Message = Loc.GetString("admin-verb-make-pirate"),
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using Content.Server.Ghost.Roles;
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Commands;
|
using Content.Server.Mind.Commands;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Server.Prayer;
|
using Content.Server.Prayer;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||||
@@ -262,11 +261,10 @@ namespace Content.Server.Administration.Systems
|
|||||||
{
|
{
|
||||||
MakeSentientCommand.MakeSentient(args.Target, EntityManager);
|
MakeSentientCommand.MakeSentient(args.Target, EntityManager);
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
if (!_minds.TryGetMind(player, out var mindId, out var mind))
|
||||||
if (mind == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_mindSystem.TransferTo(mind, args.Target, ghostCheckOverride: true);
|
_mindSystem.TransferTo(mindId, args.Target, ghostCheckOverride: true, mind: mind);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.High,
|
Impact = LogImpact.High,
|
||||||
ConfirmationPopup = true
|
ConfirmationPopup = true
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
|||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Discord;
|
using Content.Server.Discord;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Players;
|
using Content.Server.Mind;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -31,6 +31,7 @@ namespace Content.Server.Administration.Systems
|
|||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IPlayerLocator _playerLocator = default!;
|
[Dependency] private readonly IPlayerLocator _playerLocator = default!;
|
||||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
private readonly HttpClient _httpClient = new();
|
private readonly HttpClient _httpClient = new();
|
||||||
@@ -221,8 +222,6 @@ namespace Content.Server.Administration.Systems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var characterName = _playerManager.GetPlayerData(userId).ContentData()?.Mind?.CharacterName;
|
|
||||||
|
|
||||||
var linkToPrevious = string.Empty;
|
var linkToPrevious = string.Empty;
|
||||||
|
|
||||||
// If we have all the data required, we can link to the embed of the previous round or embed that was too long
|
// If we have all the data required, we can link to the embed of the previous round or embed that was too long
|
||||||
@@ -238,6 +237,7 @@ namespace Content.Server.Administration.Systems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var characterName = _minds.GetCharacterName(userId);
|
||||||
existingEmbed = (null, lookup.Username, linkToPrevious, characterName, _gameTicker.RunLevel);
|
existingEmbed = (null, lookup.Username, linkToPrevious, characterName, _gameTicker.RunLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Ame.Components;
|
using Content.Server.Ame.Components;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
@@ -15,8 +17,6 @@ using Robust.Server.GameObjects;
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Content.Server.Ame.EntitySystems;
|
namespace Content.Server.Ame.EntitySystems;
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ public sealed class AmeControllerSystem : EntitySystem
|
|||||||
safeLimit = group.CoreCount * 2;
|
safeLimit = group.CoreCount * 2;
|
||||||
|
|
||||||
if (oldValue <= safeLimit && value > safeLimit)
|
if (oldValue <= safeLimit && value > safeLimit)
|
||||||
_chatManager.SendAdminAlert(user.Value, $"increased AME over safe limit to {controller.InjectionAmount}", mindContainer);
|
_chatManager.SendAdminAlert(user.Value, $"increased AME over safe limit to {controller.InjectionAmount}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AdjustInjectionAmount(EntityUid uid, int delta, int min = 0, int max = int.MaxValue, EntityUid? user = null, AmeControllerComponent? controller = null)
|
public void AdjustInjectionAmount(EntityUid uid, int delta, int min = 0, int max = int.MaxValue, EntityUid? user = null, AmeControllerComponent? controller = null)
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ using Content.Server.Mind;
|
|||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Body.Organ;
|
using Content.Shared.Body.Organ;
|
||||||
using Content.Shared.Body.Part;
|
using Content.Shared.Body.Part;
|
||||||
using Content.Shared.Body.Prototypes;
|
|
||||||
using Content.Shared.Body.Systems;
|
using Content.Shared.Body.Systems;
|
||||||
using Content.Shared.Coordinates;
|
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
@@ -106,14 +104,10 @@ public sealed class BodySystem : SharedBodySystem
|
|||||||
|
|
||||||
private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args)
|
private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args)
|
||||||
{
|
{
|
||||||
if (_mobState.IsDead(uid) && _mindSystem.TryGetMind(uid, out var mind))
|
if (_mobState.IsDead(uid) && _mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
if (!mind.TimeOfDeath.HasValue)
|
mind.TimeOfDeath ??= _gameTiming.RealTime;
|
||||||
{
|
_ticker.OnGhostAttempt(mindId, true, mind: mind);
|
||||||
mind.TimeOfDeath = _gameTiming.RealTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ticker.OnGhostAttempt(mind, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Content.Server.Mind.Components;
|
|||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Body.Events;
|
using Content.Shared.Body.Events;
|
||||||
using Content.Shared.Body.Organ;
|
using Content.Shared.Body.Organ;
|
||||||
using Content.Shared.Body.Part;
|
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
|
|
||||||
@@ -57,10 +56,10 @@ namespace Content.Server.Body.Systems
|
|||||||
_movementSpeed.ChangeBaseSpeed(newEntity, 0, 0 , 0, move);
|
_movementSpeed.ChangeBaseSpeed(newEntity, 0, 0 , 0, move);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_mindSystem.TryGetMind(oldEntity, out var mind, oldMind))
|
if (!_mindSystem.TryGetMind(oldEntity, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_mindSystem.TransferTo(mind, newEntity);
|
_mindSystem.TransferTo(mindId, newEntity, mind: mind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Shared.CharacterInfo;
|
using Content.Shared.CharacterInfo;
|
||||||
using Content.Shared.Objectives;
|
using Content.Shared.Objectives;
|
||||||
|
|
||||||
@@ -7,6 +8,10 @@ namespace Content.Server.CharacterInfo;
|
|||||||
|
|
||||||
public sealed class CharacterInfoSystem : EntitySystem
|
public sealed class CharacterInfoSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roles = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -25,10 +30,8 @@ public sealed class CharacterInfoSystem : EntitySystem
|
|||||||
var conditions = new Dictionary<string, List<ConditionInfo>>();
|
var conditions = new Dictionary<string, List<ConditionInfo>>();
|
||||||
var jobTitle = "No Profession";
|
var jobTitle = "No Profession";
|
||||||
var briefing = "!!ERROR: No Briefing!!"; //should never show on the UI unless there's an issue
|
var briefing = "!!ERROR: No Briefing!!"; //should never show on the UI unless there's an issue
|
||||||
if (TryComp<MindContainerComponent>(entity, out var mindContainerComponent) && mindContainerComponent.Mind != null)
|
if (_minds.TryGetMind(entity, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
var mind = mindContainerComponent.Mind;
|
|
||||||
|
|
||||||
// Get objectives
|
// Get objectives
|
||||||
foreach (var objective in mind.AllObjectives)
|
foreach (var objective in mind.AllObjectives)
|
||||||
{
|
{
|
||||||
@@ -41,17 +44,11 @@ public sealed class CharacterInfoSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get job title
|
if (_jobs.MindTryGetJobName(mindId, out var jobName))
|
||||||
foreach (var role in mind.AllRoles)
|
jobTitle = jobName;
|
||||||
{
|
|
||||||
if (role.GetType() != typeof(Job)) continue;
|
|
||||||
|
|
||||||
jobTitle = role.Name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get briefing
|
// Get briefing
|
||||||
briefing = mind.Briefing;
|
briefing = _roles.MindGetBriefing(mindId) ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
RaiseNetworkEvent(new CharacterInfoEvent(entity, jobTitle, conditions, briefing), args.SenderSession);
|
RaiseNetworkEvent(new CharacterInfoEvent(entity, jobTitle, conditions, briefing), args.SenderSession);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Players;
|
using Content.Server.Mind;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -26,25 +26,27 @@ namespace Content.Server.Chat.Commands
|
|||||||
|
|
||||||
if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
|
if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
|
||||||
return;
|
return;
|
||||||
var mind = player.ContentData()?.Mind;
|
|
||||||
|
|
||||||
|
var minds = IoCManager.Resolve<IEntityManager>().System<MindSystem>();
|
||||||
// This check also proves mind not-null for at the end when the mob is ghosted.
|
// This check also proves mind not-null for at the end when the mob is ghosted.
|
||||||
if (mind?.OwnedEntity is not { Valid: true } victim)
|
if (!minds.TryGetMind(player, out var mindId, out var mind) ||
|
||||||
|
mind.OwnedEntity is not { Valid: true } victim)
|
||||||
{
|
{
|
||||||
shell.WriteLine("You don't have a mind!");
|
shell.WriteLine("You don't have a mind!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gameTicker = EntitySystem.Get<GameTicker>();
|
var gameTicker = EntitySystem.Get<GameTicker>();
|
||||||
var suicideSystem = EntitySystem.Get<SuicideSystem>();
|
var suicideSystem = EntitySystem.Get<SuicideSystem>();
|
||||||
if (suicideSystem.Suicide(victim))
|
if (suicideSystem.Suicide(victim))
|
||||||
{
|
{
|
||||||
// Prevent the player from returning to the body.
|
// Prevent the player from returning to the body.
|
||||||
// Note that mind cannot be null because otherwise victim would be null.
|
// Note that mind cannot be null because otherwise victim would be null.
|
||||||
gameTicker.OnGhostAttempt(mind, false);
|
gameTicker.OnGhostAttempt(mindId, false, mind: mind);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameTicker.OnGhostAttempt(mind, true))
|
if (gameTicker.OnGhostAttempt(mindId, true, mind: mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
shell.WriteLine("You can't ghost right now.");
|
shell.WriteLine("You can't ghost right now.");
|
||||||
|
|||||||
@@ -2,17 +2,15 @@ using System.Linq;
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Administration.Systems;
|
using Content.Server.Administration.Systems;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind;
|
||||||
using Content.Server.MoMMI;
|
using Content.Server.MoMMI;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Map;
|
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Replays;
|
using Robust.Shared.Replays;
|
||||||
@@ -116,19 +114,19 @@ namespace Content.Server.Chat.Managers
|
|||||||
ChatMessageToMany(ChatChannel.AdminAlert, message, wrappedMessage, default, false, true, clients);
|
ChatMessageToMany(ChatChannel.AdminAlert, message, wrappedMessage, default, false, true, clients);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAdminAlert(EntityUid player, string message, MindContainerComponent? mindContainerComponent = null)
|
public void SendAdminAlert(EntityUid player, string message)
|
||||||
{
|
{
|
||||||
if ((mindContainerComponent == null && !_entityManager.TryGetComponent(player, out mindContainerComponent)) || !mindContainerComponent.HasMind)
|
var mindSystem = _entityManager.System<MindSystem>();
|
||||||
|
if (!mindSystem.TryGetMind(player, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
SendAdminAlert(message);
|
SendAdminAlert(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminSystem = _entityManager.System<AdminSystem>();
|
var adminSystem = _entityManager.System<AdminSystem>();
|
||||||
var antag = mindContainerComponent.Mind!.UserId != null
|
var antag = mind.UserId != null && (adminSystem.GetCachedPlayerInfo(mind.UserId.Value)?.Antag ?? false);
|
||||||
&& (adminSystem.GetCachedPlayerInfo(mindContainerComponent.Mind!.UserId.Value)?.Antag ?? false);
|
|
||||||
|
|
||||||
SendAdminAlert($"{mindContainerComponent.Mind!.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}");
|
SendAdminAlert($"{mind.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendHookOOC(string sender, string message)
|
public void SendHookOOC(string sender, string message)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
@@ -24,7 +23,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
void SendHookOOC(string sender, string message);
|
void SendHookOOC(string sender, string message);
|
||||||
void SendAdminAnnouncement(string message);
|
void SendAdminAnnouncement(string message);
|
||||||
void SendAdminAlert(string message);
|
void SendAdminAlert(string message);
|
||||||
void SendAdminAlert(EntityUid player, string message, MindContainerComponent? mindContainerComponent = null);
|
void SendAdminAlert(EntityUid player, string message);
|
||||||
|
|
||||||
void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat,
|
void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat,
|
||||||
INetChannel client, Color? colorOverride = null, bool recordReplay = false, string? audioPath = null, float audioVolume = 0);
|
INetChannel client, Color? colorOverride = null, bool recordReplay = false, string? audioPath = null, float audioVolume = 0);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Shared.Cloning;
|
using Content.Shared.Cloning;
|
||||||
using Content.Shared.Eui;
|
using Content.Shared.Eui;
|
||||||
|
|
||||||
@@ -6,11 +7,13 @@ namespace Content.Server.Cloning
|
|||||||
{
|
{
|
||||||
public sealed class AcceptCloningEui : BaseEui
|
public sealed class AcceptCloningEui : BaseEui
|
||||||
{
|
{
|
||||||
|
private readonly EntityUid _mindId;
|
||||||
|
private readonly MindComponent _mind;
|
||||||
private readonly CloningSystem _cloningSystem;
|
private readonly CloningSystem _cloningSystem;
|
||||||
private readonly Mind.Mind _mind;
|
|
||||||
|
|
||||||
public AcceptCloningEui(Mind.Mind mind, CloningSystem cloningSys)
|
public AcceptCloningEui(EntityUid mindId, MindComponent mind, CloningSystem cloningSys)
|
||||||
{
|
{
|
||||||
|
_mindId = mindId;
|
||||||
_mind = mind;
|
_mind = mind;
|
||||||
_cloningSystem = cloningSys;
|
_cloningSystem = cloningSys;
|
||||||
}
|
}
|
||||||
@@ -26,7 +29,7 @@ namespace Content.Server.Cloning
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cloningSystem.TransferMindToClone(_mind);
|
_cloningSystem.TransferMindToClone(_mindId, _mind);
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Medical.Components;
|
|
||||||
using Content.Server.Cloning.Components;
|
using Content.Server.Cloning.Components;
|
||||||
using Content.Server.DeviceLinking.Systems;
|
using Content.Server.DeviceLinking.Systems;
|
||||||
|
using Content.Server.Medical.Components;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.UserInterface;
|
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Robust.Server.GameObjects;
|
using Content.Server.UserInterface;
|
||||||
using Robust.Server.Player;
|
|
||||||
using Content.Shared.Cloning.CloningConsole;
|
|
||||||
using Content.Shared.Cloning;
|
using Content.Shared.Cloning;
|
||||||
|
using Content.Shared.Cloning.CloningConsole;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.DeviceLinking;
|
using Content.Shared.DeviceLinking;
|
||||||
using Content.Shared.DeviceLinking.Events;
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
|
||||||
namespace Content.Server.Cloning
|
namespace Content.Server.Cloning
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,8 @@ namespace Content.Server.Cloning
|
|||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
[Dependency] private readonly PowerReceiverSystem _powerReceiverSystem = default!;
|
[Dependency] private readonly PowerReceiverSystem _powerReceiverSystem = default!;
|
||||||
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -162,12 +164,10 @@ namespace Content.Server.Cloning
|
|||||||
if (body is null)
|
if (body is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!TryComp<MindContainerComponent>(body, out var mindComp))
|
if (!_mindSystem.TryGetMind(body.Value, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var mind = mindComp.Mind;
|
if (mind.UserId.HasValue == false || mind.Session == null)
|
||||||
|
|
||||||
if (mind == null || mind.UserId.HasValue == false || mind.Session == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_cloningSystem.TryCloning(cloningPodUid, body.Value, mind, cloningPod, scannerComp.CloningFailChanceMultiplier))
|
if (_cloningSystem.TryCloning(cloningPodUid, body.Value, mind, cloningPod, scannerComp.CloningFailChanceMultiplier))
|
||||||
@@ -212,15 +212,15 @@ namespace Content.Server.Cloning
|
|||||||
{
|
{
|
||||||
scanBodyInfo = MetaData(scanBody.Value).EntityName;
|
scanBodyInfo = MetaData(scanBody.Value).EntityName;
|
||||||
|
|
||||||
TryComp<MindContainerComponent>(scanBody, out var mindComp);
|
|
||||||
|
|
||||||
if (!_mobStateSystem.IsDead(scanBody.Value))
|
if (!_mobStateSystem.IsDead(scanBody.Value))
|
||||||
{
|
{
|
||||||
clonerStatus = ClonerStatus.ScannerOccupantAlive;
|
clonerStatus = ClonerStatus.ScannerOccupantAlive;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mindComp == null || mindComp.Mind == null || mindComp.Mind.UserId == null || !_playerManager.TryGetSessionById(mindComp.Mind.UserId.Value, out _))
|
if (!_mindSystem.TryGetMind(scanBody.Value, out _, out var mind) ||
|
||||||
|
mind.UserId == null ||
|
||||||
|
!_playerManager.TryGetSessionById(mind.UserId.Value, out _))
|
||||||
{
|
{
|
||||||
clonerStatus = ClonerStatus.NoMindDetected;
|
clonerStatus = ClonerStatus.NoMindDetected;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,40 @@
|
|||||||
using Content.Shared.GameTicking;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Shared.Damage;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Shared.Examine;
|
using Content.Server.Cloning.Components;
|
||||||
using Content.Shared.Cloning;
|
using Content.Server.Construction;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
|
using Content.Server.EUI;
|
||||||
|
using Content.Server.Fluids.EntitySystems;
|
||||||
|
using Content.Server.Humanoid;
|
||||||
|
using Content.Server.Jobs;
|
||||||
|
using Content.Server.Materials;
|
||||||
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Mind.Components;
|
||||||
|
using Content.Server.Popups;
|
||||||
|
using Content.Server.Power.EntitySystems;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
|
using Content.Server.Traits.Assorted;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Server.Cloning.Components;
|
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Power.EntitySystems;
|
|
||||||
using Content.Server.Atmos.EntitySystems;
|
|
||||||
using Content.Server.EUI;
|
|
||||||
using Content.Server.Humanoid;
|
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Server.Fluids.EntitySystems;
|
using Content.Shared.Cloning;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Shared.Damage;
|
||||||
using Content.Server.Construction;
|
|
||||||
using Content.Server.DeviceLinking.Events;
|
|
||||||
using Content.Server.DeviceLinking.Systems;
|
|
||||||
using Content.Server.Materials;
|
|
||||||
using Content.Server.Jobs;
|
|
||||||
using Content.Shared.DeviceLinking.Events;
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Shared.Emag.Components;
|
using Content.Shared.Emag.Components;
|
||||||
using Content.Server.Mind;
|
using Content.Shared.Emag.Systems;
|
||||||
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
using Content.Shared.Zombies;
|
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Content.Shared.Emag.Systems;
|
using Robust.Shared.Prototypes;
|
||||||
using Content.Server.Popups;
|
using Robust.Shared.Random;
|
||||||
using Content.Server.Traits.Assorted;
|
|
||||||
|
|
||||||
namespace Content.Server.Cloning
|
namespace Content.Server.Cloning
|
||||||
{
|
{
|
||||||
@@ -62,8 +61,9 @@ namespace Content.Server.Cloning
|
|||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
|
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
|
||||||
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
|
|
||||||
public readonly Dictionary<Mind.Mind, EntityUid> ClonesWaitingForMind = new();
|
public readonly Dictionary<MindComponent, EntityUid> ClonesWaitingForMind = new();
|
||||||
public const float EasyModeCloningCost = 0.7f;
|
public const float EasyModeCloningCost = 0.7f;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -102,7 +102,7 @@ namespace Content.Server.Cloning
|
|||||||
args.AddPercentageUpgrade("cloning-pod-component-upgrade-biomass-requirement", component.BiomassRequirementMultiplier);
|
args.AddPercentageUpgrade("cloning-pod-component-upgrade-biomass-requirement", component.BiomassRequirementMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void TransferMindToClone(Mind.Mind mind)
|
internal void TransferMindToClone(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) ||
|
if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) ||
|
||||||
!EntityManager.EntityExists(entity) ||
|
!EntityManager.EntityExists(entity) ||
|
||||||
@@ -110,8 +110,8 @@ namespace Content.Server.Cloning
|
|||||||
mindComp.Mind != null)
|
mindComp.Mind != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_mindSystem.TransferTo(mind, entity, ghostCheckOverride: true);
|
_mindSystem.TransferTo(mindId, entity, ghostCheckOverride: true, mind: mind);
|
||||||
_mindSystem.UnVisit(mind);
|
_mindSystem.UnVisit(mindId, mind);
|
||||||
ClonesWaitingForMind.Remove(mind);
|
ClonesWaitingForMind.Remove(mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ namespace Content.Server.Cloning
|
|||||||
args.PushMarkup(Loc.GetString("cloning-pod-biomass", ("number", _material.GetMaterialAmount(uid, component.RequiredMaterial))));
|
args.PushMarkup(Loc.GetString("cloning-pod-biomass", ("number", _material.GetMaterialAmount(uid, component.RequiredMaterial))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Mind.Mind mind, CloningPodComponent? clonePod, float failChanceModifier = 1)
|
public bool TryCloning(EntityUid uid, EntityUid bodyToClone, MindComponent mind, CloningPodComponent? clonePod, float failChanceModifier = 1)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref clonePod))
|
if (!Resolve(uid, ref clonePod))
|
||||||
return false;
|
return false;
|
||||||
@@ -167,7 +167,7 @@ namespace Content.Server.Cloning
|
|||||||
if (EntityManager.EntityExists(clone) &&
|
if (EntityManager.EntityExists(clone) &&
|
||||||
!_mobStateSystem.IsDead(clone) &&
|
!_mobStateSystem.IsDead(clone) &&
|
||||||
TryComp<MindContainerComponent>(clone, out var cloneMindComp) &&
|
TryComp<MindContainerComponent>(clone, out var cloneMindComp) &&
|
||||||
(cloneMindComp.Mind == null || cloneMindComp.Mind == mind))
|
(cloneMindComp.Mind == null || cloneMindComp.Mind == mind.Owner))
|
||||||
return false; // Mind already has clone
|
return false; // Mind already has clone
|
||||||
|
|
||||||
ClonesWaitingForMind.Remove(mind);
|
ClonesWaitingForMind.Remove(mind);
|
||||||
@@ -253,16 +253,16 @@ namespace Content.Server.Cloning
|
|||||||
clonePod.BodyContainer.Insert(mob);
|
clonePod.BodyContainer.Insert(mob);
|
||||||
ClonesWaitingForMind.Add(mind, mob);
|
ClonesWaitingForMind.Add(mind, mob);
|
||||||
UpdateStatus(uid, CloningPodStatus.NoMind, clonePod);
|
UpdateStatus(uid, CloningPodStatus.NoMind, clonePod);
|
||||||
_euiManager.OpenEui(new AcceptCloningEui(mind, this), client);
|
var mindId = mind.Owner;
|
||||||
|
_euiManager.OpenEui(new AcceptCloningEui(mindId, mind, this), client);
|
||||||
|
|
||||||
AddComp<ActiveCloningPodComponent>(uid);
|
AddComp<ActiveCloningPodComponent>(uid);
|
||||||
|
|
||||||
// TODO: Ideally, components like this should be on a mind entity so this isn't neccesary.
|
// TODO: Ideally, components like this should be components on the mind entity so this isn't necessary.
|
||||||
// Remove this when 'mind entities' are added.
|
|
||||||
// Add on special job components to the mob.
|
// Add on special job components to the mob.
|
||||||
if (mind.CurrentJob != null)
|
if (_jobs.MindTryGetJob(mindId, out _, out var prototype))
|
||||||
{
|
{
|
||||||
foreach (var special in mind.CurrentJob.Prototype.Special)
|
foreach (var special in prototype.Special)
|
||||||
{
|
{
|
||||||
if (special is AddComponentSpecial)
|
if (special is AddComponentSpecial)
|
||||||
special.AfterEquip(mob);
|
special.AfterEquip(mob);
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
using Content.Server.Mind;
|
||||||
|
|
||||||
namespace Content.Server.Cloning.Components
|
namespace Content.Server.Cloning.Components
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class BeingClonedComponent : Component
|
public sealed partial class BeingClonedComponent : Component
|
||||||
{
|
{
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public Mind.Mind? Mind = default;
|
public MindComponent? Mind = default;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public EntityUid Parent;
|
public EntityUid Parent;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.GameTicking.Presets;
|
using Content.Server.GameTicking.Presets;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
@@ -192,8 +193,11 @@ namespace Content.Server.GameTicking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnGhostAttempt(Mind.Mind mind, bool canReturnGlobal, bool viaCommand = false)
|
public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaCommand = false, MindComponent? mind = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(mindId, ref mind))
|
||||||
|
return false;
|
||||||
|
|
||||||
var playerEntity = mind.CurrentEntity;
|
var playerEntity = mind.CurrentEntity;
|
||||||
|
|
||||||
if (playerEntity != null && viaCommand)
|
if (playerEntity != null && viaCommand)
|
||||||
@@ -222,7 +226,7 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
if (mind.VisitingEntity != default)
|
if (mind.VisitingEntity != default)
|
||||||
{
|
{
|
||||||
_mind.UnVisit(mind);
|
_mind.UnVisit(mindId, mind: mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
var position = Exists(playerEntity)
|
var position = Exists(playerEntity)
|
||||||
@@ -281,9 +285,9 @@ namespace Content.Server.GameTicking
|
|||||||
_ghost.SetCanReturnToBody(ghostComponent, canReturn);
|
_ghost.SetCanReturnToBody(ghostComponent, canReturn);
|
||||||
|
|
||||||
if (canReturn)
|
if (canReturn)
|
||||||
_mind.Visit(mind, ghost);
|
_mind.Visit(mindId, ghost, mind);
|
||||||
else
|
else
|
||||||
_mind.TransferTo(mind, ghost);
|
_mind.TransferTo(mindId, ghost, mind: mind);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,11 +312,11 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
public sealed class GhostAttemptHandleEvent : HandledEntityEventArgs
|
public sealed class GhostAttemptHandleEvent : HandledEntityEventArgs
|
||||||
{
|
{
|
||||||
public Mind.Mind Mind { get; }
|
public MindComponent Mind { get; }
|
||||||
public bool CanReturnGlobal { get; }
|
public bool CanReturnGlobal { get; }
|
||||||
public bool Result { get; set; }
|
public bool Result { get; set; }
|
||||||
|
|
||||||
public GhostAttemptHandleEvent(Mind.Mind mind, bool canReturnGlobal)
|
public GhostAttemptHandleEvent(MindComponent mind, bool canReturnGlobal)
|
||||||
{
|
{
|
||||||
Mind = mind;
|
Mind = mind;
|
||||||
CanReturnGlobal = canReturnGlobal;
|
CanReturnGlobal = canReturnGlobal;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using Robust.Server.Player;
|
|||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using PlayerData = Content.Server.Players.PlayerData;
|
|
||||||
|
|
||||||
namespace Content.Server.GameTicking
|
namespace Content.Server.GameTicking
|
||||||
{
|
{
|
||||||
@@ -27,7 +26,7 @@ namespace Content.Server.GameTicking
|
|||||||
{
|
{
|
||||||
var session = args.Session;
|
var session = args.Session;
|
||||||
|
|
||||||
if (_mind.TryGetMind(session.UserId, out var mind))
|
if (_mind.TryGetMind(session.UserId, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
if (args.OldStatus == SessionStatus.Connecting && args.NewStatus == SessionStatus.Connected)
|
if (args.OldStatus == SessionStatus.Connecting && args.NewStatus == SessionStatus.Connected)
|
||||||
mind.Session = session;
|
mind.Session = session;
|
||||||
@@ -35,7 +34,7 @@ namespace Content.Server.GameTicking
|
|||||||
DebugTools.Assert(mind.Session == session);
|
DebugTools.Assert(mind.Session == session);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugTools.Assert(session.GetMind() == mind);
|
DebugTools.Assert(session.GetMind() == mindId);
|
||||||
|
|
||||||
switch (args.NewStatus)
|
switch (args.NewStatus)
|
||||||
{
|
{
|
||||||
@@ -47,7 +46,7 @@ namespace Content.Server.GameTicking
|
|||||||
if (session.Data.ContentDataUncast == null)
|
if (session.Data.ContentDataUncast == null)
|
||||||
{
|
{
|
||||||
var data = new PlayerData(session.UserId, args.Session.Name);
|
var data = new PlayerData(session.UserId, args.Session.Name);
|
||||||
data.Mind = mind;
|
data.Mind = mindId;
|
||||||
session.Data.ContentDataUncast = data;
|
session.Data.ContentDataUncast = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
|
using System.Linq;
|
||||||
using Content.Server.Announcements;
|
using Content.Server.Announcements;
|
||||||
|
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.Mind;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Shared.Database;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Prometheus;
|
using Prometheus;
|
||||||
using Robust.Server.Maps;
|
using Robust.Server.Maps;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Asynchronous;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.Discord;
|
|
||||||
using Content.Shared.Database;
|
|
||||||
using Robust.Shared.Asynchronous;
|
|
||||||
using PlayerData = Content.Server.Players.PlayerData;
|
|
||||||
|
|
||||||
namespace Content.Server.GameTicking
|
namespace Content.Server.GameTicking
|
||||||
{
|
{
|
||||||
@@ -329,8 +329,8 @@ namespace Content.Server.GameTicking
|
|||||||
//Generate a list of basic player info to display in the end round summary.
|
//Generate a list of basic player info to display in the end round summary.
|
||||||
var listOfPlayerInfo = new List<RoundEndMessageEvent.RoundEndPlayerInfo>();
|
var listOfPlayerInfo = new List<RoundEndMessageEvent.RoundEndPlayerInfo>();
|
||||||
// Grab the great big book of all the Minds, we'll need them for this.
|
// Grab the great big book of all the Minds, we'll need them for this.
|
||||||
var allMinds = _mindTracker.AllMinds;
|
var allMinds = EntityQueryEnumerator<MindComponent>();
|
||||||
foreach (var mind in allMinds)
|
while (allMinds.MoveNext(out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
// TODO don't list redundant observer roles?
|
// TODO don't list redundant observer roles?
|
||||||
// I.e., if a player was an observer ghost, then a hamster ghost role, maybe just list hamster and not
|
// I.e., if a player was an observer ghost, then a hamster ghost role, maybe just list hamster and not
|
||||||
@@ -338,7 +338,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 = mind.AllRoles.Any(role => role is ObserverRole);
|
var observer = HasComp<ObserverRoleComponent>(mindId);
|
||||||
// Continuing
|
// Continuing
|
||||||
if (userId != null && _playerManager.ValidSessionId(userId.Value))
|
if (userId != null && _playerManager.ValidSessionId(userId.Value))
|
||||||
{
|
{
|
||||||
@@ -350,7 +350,8 @@ namespace Content.Server.GameTicking
|
|||||||
contentPlayerData = playerData.ContentData();
|
contentPlayerData = playerData.ContentData();
|
||||||
}
|
}
|
||||||
// Finish
|
// Finish
|
||||||
var antag = mind.AllRoles.Any(role => role.Antagonist);
|
|
||||||
|
var antag = _roles.MindIsAntagonist(mindId);
|
||||||
|
|
||||||
var playerIcName = "Unknown";
|
var playerIcName = "Unknown";
|
||||||
|
|
||||||
@@ -363,6 +364,8 @@ namespace Content.Server.GameTicking
|
|||||||
if (Exists(entity))
|
if (Exists(entity))
|
||||||
_pvsOverride.AddGlobalOverride(entity.Value, recursive: true);
|
_pvsOverride.AddGlobalOverride(entity.Value, recursive: true);
|
||||||
|
|
||||||
|
var roles = _roles.MindGetAllRoles(mindId);
|
||||||
|
|
||||||
var playerEndRoundInfo = new RoundEndMessageEvent.RoundEndPlayerInfo()
|
var playerEndRoundInfo = new RoundEndMessageEvent.RoundEndPlayerInfo()
|
||||||
{
|
{
|
||||||
// Note that contentPlayerData?.Name sticks around after the player is disconnected.
|
// Note that contentPlayerData?.Name sticks around after the player is disconnected.
|
||||||
@@ -372,8 +375,8 @@ namespace Content.Server.GameTicking
|
|||||||
PlayerICName = playerIcName,
|
PlayerICName = playerIcName,
|
||||||
PlayerEntityUid = entity,
|
PlayerEntityUid = entity,
|
||||||
Role = antag
|
Role = antag
|
||||||
? mind.AllRoles.First(role => role.Antagonist).Name
|
? roles.First(role => role.Antagonist).Name
|
||||||
: mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("game-ticker-unknown-role"),
|
: roles.FirstOrDefault().Name ?? Loc.GetString("game-ticker-unknown-role"),
|
||||||
Antag = antag,
|
Antag = antag,
|
||||||
Observer = observer,
|
Observer = observer,
|
||||||
Connected = connected
|
Connected = connected
|
||||||
@@ -496,6 +499,13 @@ namespace Content.Server.GameTicking
|
|||||||
PlayerJoinLobby(player);
|
PlayerJoinLobby(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Round restart cleanup event, so entity systems can reset.
|
||||||
|
var ev = new RoundRestartCleanupEvent();
|
||||||
|
RaiseLocalEvent(ev);
|
||||||
|
|
||||||
|
// So clients' entity systems can clean up too...
|
||||||
|
RaiseNetworkEvent(ev, Filter.Broadcast());
|
||||||
|
|
||||||
// Delete all entities.
|
// Delete all entities.
|
||||||
foreach (var entity in EntityManager.GetEntities().ToArray())
|
foreach (var entity in EntityManager.GetEntities().ToArray())
|
||||||
{
|
{
|
||||||
@@ -530,13 +540,6 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
_allPreviousGameRules.Clear();
|
_allPreviousGameRules.Clear();
|
||||||
|
|
||||||
// Round restart cleanup event, so entity systems can reset.
|
|
||||||
var ev = new RoundRestartCleanupEvent();
|
|
||||||
RaiseLocalEvent(ev);
|
|
||||||
|
|
||||||
// So clients' entity systems can clean up too...
|
|
||||||
RaiseNetworkEvent(ev, Filter.Broadcast());
|
|
||||||
|
|
||||||
DisallowLateJoin = false;
|
DisallowLateJoin = false;
|
||||||
_playerGameStatuses.Clear();
|
_playerGameStatuses.Clear();
|
||||||
foreach (var session in _playerManager.ServerSessions)
|
foreach (var session in _playerManager.ServerSessions)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Numerics;
|
|||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
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;
|
||||||
@@ -18,13 +19,13 @@ using Robust.Shared.Network;
|
|||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Job = Content.Server.Roles.Job;
|
|
||||||
|
|
||||||
namespace Content.Server.GameTicking
|
namespace Content.Server.GameTicking
|
||||||
{
|
{
|
||||||
public sealed partial class GameTicker
|
public sealed partial class GameTicker
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||||
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
|
|
||||||
[ValidatePrototypeId<EntityPrototype>]
|
[ValidatePrototypeId<EntityPrototype>]
|
||||||
private const string ObserverPrototypeName = "MobObserver";
|
private const string ObserverPrototypeName = "MobObserver";
|
||||||
@@ -186,12 +187,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 Job(newMind, jobPrototype);
|
var job = new JobComponent { PrototypeId = jobId };
|
||||||
_mind.AddRole(newMind, job);
|
_roles.MindAddRole(newMind, job);
|
||||||
|
var jobName = _jobs.MindTryGetJobName(newMind);
|
||||||
|
|
||||||
_playTimeTrackings.PlayerRolesChanged(player);
|
_playTimeTrackings.PlayerRolesChanged(player);
|
||||||
|
|
||||||
|
|
||||||
var mobMaybe = _stationSpawning.SpawnPlayerCharacterOnStation(station, job, character);
|
var mobMaybe = _stationSpawning.SpawnPlayerCharacterOnStation(station, job, character);
|
||||||
DebugTools.AssertNotNull(mobMaybe);
|
DebugTools.AssertNotNull(mobMaybe);
|
||||||
var mob = mobMaybe!.Value;
|
var mob = mobMaybe!.Value;
|
||||||
@@ -204,7 +205,7 @@ namespace Content.Server.GameTicking
|
|||||||
Loc.GetString(
|
Loc.GetString(
|
||||||
"latejoin-arrival-announcement",
|
"latejoin-arrival-announcement",
|
||||||
("character", MetaData(mob).EntityName),
|
("character", MetaData(mob).EntityName),
|
||||||
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(job.Name))
|
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))
|
||||||
), Loc.GetString("latejoin-arrival-sender"),
|
), Loc.GetString("latejoin-arrival-sender"),
|
||||||
playDefaultSound: false);
|
playDefaultSound: false);
|
||||||
}
|
}
|
||||||
@@ -217,9 +218,9 @@ namespace Content.Server.GameTicking
|
|||||||
_stationJobs.TryAssignJob(station, jobPrototype);
|
_stationJobs.TryAssignJob(station, jobPrototype);
|
||||||
|
|
||||||
if (lateJoin)
|
if (lateJoin)
|
||||||
_adminLogger.Add(LogType.LateJoin, LogImpact.Medium, $"Player {player.Name} late joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {job.Name:jobName}.");
|
_adminLogger.Add(LogType.LateJoin, LogImpact.Medium, $"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, LogImpact.Medium, $"Player {player.Name} joined as {character.Name:characterName} on station {Name(station):stationName} with {ToPrettyString(mob):entity} as a {job.Name:jobName}.");
|
_adminLogger.Add(LogType.RoundStartJoin, LogImpact.Medium, $"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
|
||||||
@@ -305,15 +306,15 @@ namespace Content.Server.GameTicking
|
|||||||
if (mind == null)
|
if (mind == null)
|
||||||
{
|
{
|
||||||
mind = _mind.CreateMind(player.UserId);
|
mind = _mind.CreateMind(player.UserId);
|
||||||
_mind.SetUserId(mind, player.UserId);
|
_mind.SetUserId(mind.Value, player.UserId);
|
||||||
_mind.AddRole(mind, new ObserverRole(mind));
|
_roles.MindAddRole(mind.Value, new ObserverRoleComponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = GetPlayerProfile(player).Name;
|
var name = GetPlayerProfile(player).Name;
|
||||||
var ghost = SpawnObserverMob();
|
var ghost = SpawnObserverMob();
|
||||||
_metaData.SetEntityName(ghost, name);
|
_metaData.SetEntityName(ghost, name);
|
||||||
_ghost.SetCanReturnToBody(ghost, false);
|
_ghost.SetCanReturnToBody(ghost, false);
|
||||||
_mind.TransferTo(mind, ghost);
|
_mind.TransferTo(mind.Value, ghost);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Mob Spawning Helpers
|
#region Mob Spawning Helpers
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Server.Maps;
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Players.PlayTimeTracking;
|
using Content.Server.Players.PlayTimeTracking;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
|
using Content.Server.Roles;
|
||||||
using Content.Server.ServerUpdates;
|
using Content.Server.ServerUpdates;
|
||||||
using Content.Server.Shuttles.Systems;
|
using Content.Server.Shuttles.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
@@ -21,14 +22,14 @@ using Robust.Server.GameObjects;
|
|||||||
using Robust.Server.GameStates;
|
using Robust.Server.GameStates;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
#if EXCEPTION_TOLERANCE
|
|
||||||
using Robust.Shared.Exceptions;
|
|
||||||
#endif
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
#if EXCEPTION_TOLERANCE
|
||||||
|
using Robust.Shared.Exceptions;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Content.Server.GameTicking
|
namespace Content.Server.GameTicking
|
||||||
{
|
{
|
||||||
@@ -57,7 +58,6 @@ namespace Content.Server.GameTicking
|
|||||||
[Dependency] private readonly MapLoaderSystem _map = default!;
|
[Dependency] private readonly MapLoaderSystem _map = default!;
|
||||||
[Dependency] private readonly GhostSystem _ghost = default!;
|
[Dependency] private readonly GhostSystem _ghost = default!;
|
||||||
[Dependency] private readonly MindSystem _mind = default!;
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
[Dependency] private readonly MindTrackerSystem _mindTracker = default!;
|
|
||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly PlayTimeTrackingSystem _playTimeTrackings = default!;
|
[Dependency] private readonly PlayTimeTrackingSystem _playTimeTrackings = default!;
|
||||||
[Dependency] private readonly PvsOverrideSystem _pvsOverride = default!;
|
[Dependency] private readonly PvsOverrideSystem _pvsOverride = default!;
|
||||||
@@ -67,6 +67,7 @@ namespace Content.Server.GameTicking
|
|||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
[Dependency] private readonly UserDbDataManager _userDb = default!;
|
[Dependency] private readonly UserDbDataManager _userDb = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roles = default!;
|
||||||
|
|
||||||
[ViewVariables] private bool _initialized;
|
[ViewVariables] private bool _initialized;
|
||||||
[ViewVariables] private bool _postInitialized;
|
[ViewVariables] private bool _postInitialized;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Content.Server.GameTicking.Rules.Components;
|
|||||||
public sealed partial class PiratesRuleComponent : Component
|
public sealed partial class PiratesRuleComponent : Component
|
||||||
{
|
{
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public List<Mind.Mind> Pirates = new();
|
public List<EntityUid> Pirates = new();
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public EntityUid PirateShip = EntityUid.Invalid;
|
public EntityUid PirateShip = EntityUid.Invalid;
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Roles;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Preferences;
|
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -10,12 +9,12 @@ namespace Content.Server.GameTicking.Rules.Components;
|
|||||||
[RegisterComponent, Access(typeof(TraitorRuleSystem))]
|
[RegisterComponent, Access(typeof(TraitorRuleSystem))]
|
||||||
public sealed partial class TraitorRuleComponent : Component
|
public sealed partial class TraitorRuleComponent : Component
|
||||||
{
|
{
|
||||||
public List<TraitorRole> Traitors = new();
|
public readonly List<EntityUid> TraitorMinds = new();
|
||||||
|
|
||||||
[DataField("traitorPrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
[DataField("traitorPrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
||||||
public string TraitorPrototypeId = "Traitor";
|
public string TraitorPrototypeId = "Traitor";
|
||||||
|
|
||||||
public int TotalTraitors => Traitors.Count;
|
public int TotalTraitors => TraitorMinds.Count;
|
||||||
public string[] Codewords = new string[3];
|
public string[] Codewords = new string[3];
|
||||||
|
|
||||||
public enum SelectionState
|
public enum SelectionState
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using Content.Server.GameTicking.Rules.Components;
|
|||||||
using Content.Server.Ghost.Roles.Components;
|
using Content.Server.Ghost.Roles.Components;
|
||||||
using Content.Server.Ghost.Roles.Events;
|
using Content.Server.Ghost.Roles.Events;
|
||||||
using Content.Server.Humanoid;
|
using Content.Server.Humanoid;
|
||||||
using Content.Server.Humanoid.Systems;
|
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.NPC.Components;
|
using Content.Server.NPC.Components;
|
||||||
@@ -20,7 +19,6 @@ using Content.Server.Shuttles.Systems;
|
|||||||
using Content.Server.Spawners.Components;
|
using Content.Server.Spawners.Components;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Server.Traitor;
|
|
||||||
using Content.Shared.Dataset;
|
using Content.Shared.Dataset;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
@@ -58,8 +56,12 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
[Dependency] private readonly MapLoaderSystem _map = default!;
|
[Dependency] private readonly MapLoaderSystem _map = default!;
|
||||||
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roles = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
|
|
||||||
|
[ValidatePrototypeId<AntagPrototype>]
|
||||||
|
public const string NukeopsId = "Nukeops";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -87,10 +89,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If entity has a prior mind attached, add them to the players list.
|
// If entity has a prior mind attached, add them to the players list.
|
||||||
if (!TryComp<MindContainerComponent>(uid, out var mindComponent))
|
if (!_mindSystem.TryGetMind(uid, out _, out var mind))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var session = mindComponent.Mind?.Session;
|
var session = mind?.Session;
|
||||||
var name = MetaData(uid).EntityName;
|
var name = MetaData(uid).EntityName;
|
||||||
if (session != null)
|
if (session != null)
|
||||||
nukeops.OperativePlayers.Add(name, session);
|
nukeops.OperativePlayers.Add(name, session);
|
||||||
@@ -592,22 +594,21 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
|
|
||||||
private void OnMindAdded(EntityUid uid, NukeOperativeComponent component, MindAddedMessage args)
|
private void OnMindAdded(EntityUid uid, NukeOperativeComponent component, MindAddedMessage args)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindContainerComponent>(uid, out var mindContainerComponent) || mindContainerComponent.Mind == null)
|
if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var mind = mindContainerComponent.Mind;
|
|
||||||
|
|
||||||
foreach (var nukeops in EntityQuery<NukeopsRuleComponent>())
|
foreach (var nukeops in EntityQuery<NukeopsRuleComponent>())
|
||||||
{
|
{
|
||||||
if (nukeops.OperativeMindPendingData.TryGetValue(uid, out var role) || !nukeops.SpawnOutpost || !nukeops.EndsRound)
|
if (nukeops.OperativeMindPendingData.TryGetValue(uid, out var role) || !nukeops.SpawnOutpost || !nukeops.EndsRound)
|
||||||
{
|
{
|
||||||
role ??= nukeops.OperativeRoleProto;
|
role ??= nukeops.OperativeRoleProto;
|
||||||
_mindSystem.AddRole(mind, new NukeopsRole(mind, _prototypeManager.Index<AntagPrototype>(role)));
|
_roles.MindAddRole(mindId, new NukeopsRoleComponent { PrototypeId = role });
|
||||||
nukeops.OperativeMindPendingData.Remove(uid);
|
nukeops.OperativeMindPendingData.Remove(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_mindSystem.TryGetSession(mind, out var playerSession))
|
if (mind.Session is not { } playerSession)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (nukeops.OperativePlayers.ContainsValue(playerSession))
|
if (nukeops.OperativePlayers.ContainsValue(playerSession))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -778,7 +779,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
SetupOperativeEntity(mob, spawnDetails.Name, spawnDetails.Gear, profile, component);
|
SetupOperativeEntity(mob, spawnDetails.Name, spawnDetails.Gear, profile, component);
|
||||||
var newMind = _mindSystem.CreateMind(session.UserId, spawnDetails.Name);
|
var newMind = _mindSystem.CreateMind(session.UserId, spawnDetails.Name);
|
||||||
_mindSystem.SetUserId(newMind, session.UserId);
|
_mindSystem.SetUserId(newMind, session.UserId);
|
||||||
_mindSystem.AddRole(newMind, new NukeopsRole(newMind, nukeOpsAntag));
|
_roles.MindAddRole(newMind, new NukeopsRoleComponent { PrototypeId = spawnDetails.Role });
|
||||||
|
|
||||||
_mindSystem.TransferTo(newMind, mob);
|
_mindSystem.TransferTo(newMind, mob);
|
||||||
}
|
}
|
||||||
@@ -820,13 +821,13 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
//For admins forcing someone to nukeOps.
|
//For admins forcing someone to nukeOps.
|
||||||
public void MakeLoneNukie(Mind.Mind mind)
|
public void MakeLoneNukie(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
if (!mind.OwnedEntity.HasValue)
|
if (!mind.OwnedEntity.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//ok hardcoded value bad but so is everything else here
|
//ok hardcoded value bad but so is everything else here
|
||||||
_mindSystem.AddRole(mind, new NukeopsRole(mind, _prototypeManager.Index<AntagPrototype>("Nukeops")));
|
_roles.MindAddRole(mindId, new NukeopsRoleComponent { PrototypeId = NukeopsId }, mind);
|
||||||
SetOutfitCommand.SetOutfit(mind.OwnedEntity.Value, "SyndicateOperativeGearFull", EntityManager);
|
SetOutfitCommand.SetOutfit(mind.OwnedEntity.Value, "SyndicateOperativeGearFull", EntityManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,7 +879,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
var query = EntityQuery<NukeOperativeComponent, MindContainerComponent, MetaDataComponent>(true);
|
var query = EntityQuery<NukeOperativeComponent, MindContainerComponent, MetaDataComponent>(true);
|
||||||
foreach (var (_, mindComp, metaData) in query)
|
foreach (var (_, mindComp, metaData) in query)
|
||||||
{
|
{
|
||||||
if (!mindComp.HasMind || !_mindSystem.TryGetSession(mindComp.Mind, out var session))
|
if (!mindComp.HasMind || !_mindSystem.TryGetSession(mindComp.Mind.Value, out var session))
|
||||||
continue;
|
continue;
|
||||||
component.OperativePlayers.Add(metaData.EntityName, session);
|
component.OperativePlayers.Add(metaData.EntityName, session);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,12 @@ using Content.Shared.Roles;
|
|||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Maps;
|
using Robust.Server.Maps;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.Enums;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
|
|
||||||
namespace Content.Server.GameTicking.Rules;
|
namespace Content.Server.GameTicking.Rules;
|
||||||
|
|
||||||
@@ -68,15 +66,14 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
List<(double, EntityUid)> mostValuableThefts = new();
|
List<(double, EntityUid)> mostValuableThefts = new();
|
||||||
|
|
||||||
var comp1 = pirates;
|
var comp1 = pirates;
|
||||||
var finalValue = _pricingSystem.AppraiseGrid(pirates.PirateShip, uid =>
|
var finalValue = _pricingSystem.AppraiseGrid(pirates.PirateShip, uid =>
|
||||||
{
|
{
|
||||||
foreach (var mind in comp1.Pirates)
|
foreach (var mindId in comp1.Pirates)
|
||||||
{
|
{
|
||||||
if (mind.CurrentEntity == uid)
|
if (TryComp(mindId, out MindComponent? mind) && mind.CurrentEntity == uid)
|
||||||
return false; // Don't appraise the pirates twice, we count them in separately.
|
return false; // Don't appraise the pirates twice, we count them in separately.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,9 +89,9 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
|||||||
mostValuableThefts.Pop();
|
mostValuableThefts.Pop();
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var mind in pirates.Pirates)
|
foreach (var mindId in pirates.Pirates)
|
||||||
{
|
{
|
||||||
if (mind.CurrentEntity is not null)
|
if (TryComp(mindId, out MindComponent? mind) && mind.CurrentEntity is not null)
|
||||||
finalValue += _pricingSystem.GetPrice(mind.CurrentEntity.Value);
|
finalValue += _pricingSystem.GetPrice(mind.CurrentEntity.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +116,10 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
|||||||
ev.AddLine(Loc.GetString("pirates-list-start"));
|
ev.AddLine(Loc.GetString("pirates-list-start"));
|
||||||
foreach (var pirate in pirates.Pirates)
|
foreach (var pirate in pirates.Pirates)
|
||||||
{
|
{
|
||||||
ev.AddLine($"- {pirate.CharacterName} ({pirate.Session?.Name})");
|
if (TryComp(pirate, out MindComponent? mind))
|
||||||
|
{
|
||||||
|
ev.AddLine($"- {mind.CharacterName} ({mind.Session?.Name})");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Forcing one player to be a pirate.
|
//Forcing one player to be a pirate.
|
||||||
public void MakePirate(Mind.Mind mind)
|
public void MakePirate(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
if (!mind.OwnedEntity.HasValue)
|
if (!mind.OwnedEntity.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
using Content.Server.GameTicking.Rules.Components;
|
using Content.Server.GameTicking.Rules.Components;
|
||||||
using Content.Server.NPC.Systems;
|
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.NPC.Systems;
|
||||||
|
using Content.Server.Objectives;
|
||||||
using Content.Server.PDA.Ringer;
|
using Content.Server.PDA.Ringer;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
using Content.Server.Traitor.Uplink;
|
using Content.Server.Traitor.Uplink;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Dataset;
|
using Content.Shared.Dataset;
|
||||||
using Content.Shared.Preferences;
|
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -28,16 +28,17 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
[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 IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
[Dependency] private readonly IObjectivesManager _objectivesManager = default!;
|
|
||||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
[Dependency] private readonly IComponentFactory _component = default!;
|
||||||
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
|
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
[Dependency] private readonly UplinkSystem _uplink = default!;
|
[Dependency] private readonly UplinkSystem _uplink = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roleSystem = default!;
|
||||||
private ISawmill _sawmill = default!;
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
|
[Dependency] private readonly ObjectivesSystem _objectives = default!;
|
||||||
|
|
||||||
private int PlayersPerTraitor => _cfg.GetCVar(CCVars.TraitorPlayersPerTraitor);
|
private int PlayersPerTraitor => _cfg.GetCVar(CCVars.TraitorPlayersPerTraitor);
|
||||||
private int MaxTraitors => _cfg.GetCVar(CCVars.TraitorMaxTraitors);
|
private int MaxTraitors => _cfg.GetCVar(CCVars.TraitorMaxTraitors);
|
||||||
@@ -46,8 +47,6 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
_sawmill = Logger.GetSawmill("preset");
|
|
||||||
|
|
||||||
SubscribeLocalEvent<RoundStartAttemptEvent>(OnStartAttempt);
|
SubscribeLocalEvent<RoundStartAttemptEvent>(OnStartAttempt);
|
||||||
SubscribeLocalEvent<RulePlayerJobsAssignedEvent>(OnPlayersSpawned);
|
SubscribeLocalEvent<RulePlayerJobsAssignedEvent>(OnPlayersSpawned);
|
||||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLatejoin);
|
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLatejoin);
|
||||||
@@ -107,7 +106,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
{
|
{
|
||||||
if (!component.StartCandidates.Any())
|
if (!component.StartCandidates.Any())
|
||||||
{
|
{
|
||||||
_sawmill.Error("Tried to start Traitor mode without any candidates.");
|
Log.Error("Tried to start Traitor mode without any candidates.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +155,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
foreach (var player in candidates.Keys)
|
foreach (var player in candidates.Keys)
|
||||||
{
|
{
|
||||||
// Role prevents antag.
|
// Role prevents antag.
|
||||||
if (!(player.Data.ContentData()?.Mind?.AllRoles.All(role => role is not Job { CanBeAntag: false }) ?? false))
|
if (!_jobs.CanBeAntag(player))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -180,7 +179,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
}
|
}
|
||||||
if (prefList.Count == 0)
|
if (prefList.Count == 0)
|
||||||
{
|
{
|
||||||
_sawmill.Info("Insufficient preferred traitors, picking at random.");
|
Log.Info("Insufficient preferred traitors, picking at random.");
|
||||||
prefList = list;
|
prefList = list;
|
||||||
}
|
}
|
||||||
return prefList;
|
return prefList;
|
||||||
@@ -191,14 +190,14 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
var results = new List<IPlayerSession>(traitorCount);
|
var results = new List<IPlayerSession>(traitorCount);
|
||||||
if (prefList.Count == 0)
|
if (prefList.Count == 0)
|
||||||
{
|
{
|
||||||
_sawmill.Info("Insufficient ready players to fill up with traitors, stopping the selection.");
|
Log.Info("Insufficient ready players to fill up with traitors, stopping the selection.");
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < traitorCount; i++)
|
for (var i = 0; i < traitorCount; i++)
|
||||||
{
|
{
|
||||||
results.Add(_random.PickAndTake(prefList));
|
results.Add(_random.PickAndTake(prefList));
|
||||||
_sawmill.Info("Selected a preferred traitor.");
|
Log.Info("Selected a preferred traitor.");
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@@ -215,22 +214,28 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
MakeCodewords(traitorRule);
|
MakeCodewords(traitorRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = traitor.Data.ContentData()?.Mind;
|
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
|
||||||
if (mind == null)
|
|
||||||
{
|
{
|
||||||
_sawmill.Info("Failed getting mind for picked traitor.");
|
Log.Info("Failed getting mind for picked traitor.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasComp<TraitorRoleComponent>(mindId))
|
||||||
|
{
|
||||||
|
Log.Error($"Player {traitor.Name} is already a traitor.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mind.OwnedEntity is not { } entity)
|
if (mind.OwnedEntity is not { } entity)
|
||||||
{
|
{
|
||||||
Logger.ErrorS("preset", "Mind picked for traitor did not have an attached entity.");
|
Log.Error("Mind picked for traitor did not have an attached entity.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the amount of currency on the uplink.
|
// Calculate the amount of currency on the uplink.
|
||||||
var startingBalance = _cfg.GetCVar(CCVars.TraitorStartingBalance);
|
var startingBalance = _cfg.GetCVar(CCVars.TraitorStartingBalance);
|
||||||
if (mind.CurrentJob != null)
|
if (_jobs.MindTryGetJob(mindId, out _, out var prototype))
|
||||||
startingBalance = Math.Max(startingBalance - mind.CurrentJob.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.
|
||||||
// PDA should be in place already
|
// PDA should be in place already
|
||||||
@@ -241,22 +246,22 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
// Add the ringtone uplink and get its code for greeting
|
// Add the ringtone uplink and get its code for greeting
|
||||||
var code = EnsureComp<RingerUplinkComponent>(pda.Value).Code;
|
var code = EnsureComp<RingerUplinkComponent>(pda.Value).Code;
|
||||||
|
|
||||||
// Prepare antagonist role
|
// Prepare traitor role
|
||||||
var antagPrototype = _prototypeManager.Index<AntagPrototype>(traitorRule.TraitorPrototypeId);
|
|
||||||
var traitorRole = new TraitorRole(mind, antagPrototype);
|
|
||||||
|
|
||||||
// Give traitors their codewords and uplink code to keep in their character info menu
|
// Give traitors their codewords and uplink code to keep in their character info menu
|
||||||
traitorRole.Mind.Briefing = string.Format(
|
var briefing =
|
||||||
"{0}\n{1}",
|
$"{Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords)))}\n{Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", code).Replace("sharp", "#")))}";
|
||||||
Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords))),
|
var traitorRole = new TraitorRoleComponent
|
||||||
Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", code).Replace("sharp","#"))));
|
{
|
||||||
|
PrototypeId = traitorRule.TraitorPrototypeId,
|
||||||
|
Briefing = briefing
|
||||||
|
};
|
||||||
|
|
||||||
// Assign traitor roles
|
// Assign traitor roles
|
||||||
_mindSystem.AddRole(mind, traitorRole);
|
_roleSystem.MindAddRole(mindId, traitorRole);
|
||||||
SendTraitorBriefing(mind, traitorRule.Codewords, code);
|
SendTraitorBriefing(mindId, traitorRule.Codewords, code);
|
||||||
traitorRule.Traitors.Add(traitorRole);
|
traitorRule.TraitorMinds.Add(mindId);
|
||||||
|
|
||||||
if (_mindSystem.TryGetSession(mind, out var session))
|
if (_mindSystem.TryGetSession(mindId, out var session))
|
||||||
{
|
{
|
||||||
// Notificate player about new role assignment
|
// Notificate player about new role assignment
|
||||||
_audioSystem.PlayGlobal(traitorRule.GreetSoundNotification, session);
|
_audioSystem.PlayGlobal(traitorRule.GreetSoundNotification, session);
|
||||||
@@ -272,11 +277,11 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
var difficulty = 0f;
|
var difficulty = 0f;
|
||||||
for (var pick = 0; pick < maxPicks && maxDifficulty > difficulty; pick++)
|
for (var pick = 0; pick < maxPicks && maxDifficulty > difficulty; pick++)
|
||||||
{
|
{
|
||||||
var objective = _objectivesManager.GetRandomObjective(traitorRole.Mind, "TraitorObjectiveGroups");
|
var objective = _objectives.GetRandomObjective(mindId, mind, "TraitorObjectiveGroups");
|
||||||
|
|
||||||
if (objective == null)
|
if (objective == null)
|
||||||
continue;
|
continue;
|
||||||
if (_mindSystem.TryAddObjective(traitorRole.Mind, objective))
|
if (_mindSystem.TryAddObjective(mindId, mind, objective))
|
||||||
difficulty += objective.Difficulty;
|
difficulty += objective.Difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +294,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
/// <param name="mind">A mind (player)</param>
|
/// <param name="mind">A mind (player)</param>
|
||||||
/// <param name="codewords">Codewords</param>
|
/// <param name="codewords">Codewords</param>
|
||||||
/// <param name="code">Uplink codes</param>
|
/// <param name="code">Uplink codes</param>
|
||||||
private void SendTraitorBriefing(Mind.Mind mind, string[] codewords, Note[] code)
|
private void SendTraitorBriefing(EntityUid mind, string[] codewords, Note[] code)
|
||||||
{
|
{
|
||||||
if (_mindSystem.TryGetSession(mind, out var session))
|
if (_mindSystem.TryGetSession(mind, out var session))
|
||||||
{
|
{
|
||||||
@@ -362,18 +367,21 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var result = Loc.GetString("traitor-round-end-result", ("traitorCount", traitor.Traitors.Count));
|
var result = Loc.GetString("traitor-round-end-result", ("traitorCount", traitor.TraitorMinds.Count));
|
||||||
|
|
||||||
result += "\n" + Loc.GetString("traitor-round-end-codewords", ("codewords", string.Join(", ", traitor.Codewords))) +
|
result += "\n" + Loc.GetString("traitor-round-end-codewords", ("codewords", string.Join(", ", traitor.Codewords))) +
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
foreach (var t in traitor.Traitors)
|
foreach (var mindId in traitor.TraitorMinds)
|
||||||
{
|
{
|
||||||
var name = t.Mind.CharacterName;
|
if (!TryComp(mindId, out MindComponent? mind))
|
||||||
_mindSystem.TryGetSession(t.Mind, out var session);
|
continue;
|
||||||
|
|
||||||
|
var name = mind.CharacterName;
|
||||||
|
_mindSystem.TryGetSession(mindId, out var session);
|
||||||
var username = session?.Name;
|
var username = session?.Name;
|
||||||
|
|
||||||
var objectives = t.Mind.AllObjectives.ToArray();
|
var objectives = mind.AllObjectives.ToArray();
|
||||||
if (objectives.Length == 0)
|
if (objectives.Length == 0)
|
||||||
{
|
{
|
||||||
if (username != null)
|
if (username != null)
|
||||||
@@ -437,12 +445,12 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TraitorRole> GetOtherTraitorsAliveAndConnected(Mind.Mind ourMind)
|
public List<(EntityUid Id, MindComponent Mind)> GetOtherTraitorMindsAliveAndConnected(MindComponent ourMind)
|
||||||
{
|
{
|
||||||
List<TraitorRole> allTraitors = new();
|
List<(EntityUid Id, MindComponent Mind)> allTraitors = new();
|
||||||
foreach (var traitor in EntityQuery<TraitorRuleComponent>())
|
foreach (var traitor in EntityQuery<TraitorRuleComponent>())
|
||||||
{
|
{
|
||||||
foreach (var role in GetOtherTraitorsAliveAndConnected(ourMind, traitor))
|
foreach (var role in GetOtherTraitorMindsAliveAndConnected(ourMind, traitor))
|
||||||
{
|
{
|
||||||
if (!allTraitors.Contains(role))
|
if (!allTraitors.Contains(role))
|
||||||
allTraitors.Add(role);
|
allTraitors.Add(role);
|
||||||
@@ -452,13 +460,22 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
return allTraitors;
|
return allTraitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TraitorRole> GetOtherTraitorsAliveAndConnected(Mind.Mind ourMind, TraitorRuleComponent component)
|
private List<(EntityUid Id, MindComponent Mind)> GetOtherTraitorMindsAliveAndConnected(MindComponent ourMind, TraitorRuleComponent component)
|
||||||
{
|
{
|
||||||
return component.Traitors // don't want
|
var traitors = new List<(EntityUid Id, MindComponent Mind)>();
|
||||||
.Where(t => t.Mind.OwnedEntity is not null) // no entity
|
foreach (var traitor in component.TraitorMinds)
|
||||||
.Where(t => t.Mind.Session is not null) // player disconnected
|
{
|
||||||
.Where(t => t.Mind != ourMind) // ourselves
|
if (TryComp(traitor, out MindComponent? mind) &&
|
||||||
.Where(t => _mobStateSystem.IsAlive((EntityUid) t.Mind.OwnedEntity!)) // dead
|
mind.OwnedEntity != null &&
|
||||||
.Where(t => t.Mind.CurrentEntity == t.Mind.OwnedEntity).ToList(); // not in original body
|
mind.Session != null &&
|
||||||
|
mind != ourMind &&
|
||||||
|
_mobStateSystem.IsAlive(mind.OwnedEntity.Value) &&
|
||||||
|
mind.CurrentEntity == mind.OwnedEntity)
|
||||||
|
{
|
||||||
|
traitors.Add((traitor, mind));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return traitors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ using Content.Server.Chat.Managers;
|
|||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.GameTicking.Rules.Components;
|
using Content.Server.GameTicking.Rules.Components;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
@@ -21,7 +19,6 @@ 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.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles;
|
|
||||||
using Content.Shared.Zombies;
|
using Content.Shared.Zombies;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
@@ -48,6 +45,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly ZombieSystem _zombie = default!;
|
[Dependency] private readonly ZombieSystem _zombie = default!;
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roles = default!;
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
@@ -97,10 +95,9 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
{
|
{
|
||||||
var meta = MetaData(survivor);
|
var meta = MetaData(survivor);
|
||||||
var username = string.Empty;
|
var username = string.Empty;
|
||||||
if (TryComp<MindContainerComponent>(survivor, out var mindcomp))
|
if (_mindSystem.TryGetMind(survivor, out _, out var mind) && mind.Session != null)
|
||||||
{
|
{
|
||||||
if (mindcomp.Mind != null && mindcomp.Mind.Session != null)
|
username = mind.Session.Name;
|
||||||
username = mindcomp.Mind.Session.Name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ev.AddLine(Loc.GetString("zombie-round-end-user-was-survivor",
|
ev.AddLine(Loc.GetString("zombie-round-end-user-was-survivor",
|
||||||
@@ -312,12 +309,15 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
|
|||||||
|
|
||||||
prefList.Remove(zombie);
|
prefList.Remove(zombie);
|
||||||
playerList.Remove(zombie);
|
playerList.Remove(zombie);
|
||||||
if (zombie.Data.ContentData()?.Mind is not { } mind || mind.OwnedEntity is not { } ownedEntity)
|
if (!_mindSystem.TryGetMind(zombie, out var mindId, out var mind) ||
|
||||||
|
mind.OwnedEntity is not { } ownedEntity)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
totalInfected++;
|
totalInfected++;
|
||||||
|
|
||||||
_mindSystem.AddRole(mind, new ZombieRole(mind, _prototypeManager.Index<AntagPrototype>(component.PatientZeroPrototypeId)));
|
_roles.MindAddRole(mindId, new ZombieRoleComponent { PrototypeId = component.PatientZeroPrototypeId });
|
||||||
|
|
||||||
var pending = EnsureComp<PendingZombieComponent>(ownedEntity);
|
var pending = EnsureComp<PendingZombieComponent>(ownedEntity);
|
||||||
pending.GracePeriod = _random.Next(component.MinInitialInfectedGrace, component.MaxInitialInfectedGrace);
|
pending.GracePeriod = _random.Next(component.MinInitialInfectedGrace, component.MaxInitialInfectedGrace);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Players;
|
using Content.Server.Mind;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -9,6 +9,8 @@ namespace Content.Server.Ghost
|
|||||||
[AnyCommand]
|
[AnyCommand]
|
||||||
public sealed class Ghost : IConsoleCommand
|
public sealed class Ghost : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entities = default!;
|
||||||
|
|
||||||
public string Command => "ghost";
|
public string Command => "ghost";
|
||||||
public string Description => "Give up on life and become a ghost.";
|
public string Description => "Give up on life and become a ghost.";
|
||||||
public string Help => "ghost";
|
public string Help => "ghost";
|
||||||
@@ -22,14 +24,14 @@ namespace Content.Server.Ghost
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
var minds = _entities.System<MindSystem>();
|
||||||
if (mind == null)
|
if (!minds.TryGetMind(player, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
shell.WriteLine("You have no Mind, you can't ghost.");
|
shell.WriteLine("You have no Mind, you can't ghost.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitySystem.Get<GameTicker>().OnGhostAttempt(mind, true, viaCommand:true))
|
if (!EntitySystem.Get<GameTicker>().OnGhostAttempt(mindId, true, true, mind))
|
||||||
{
|
{
|
||||||
shell.WriteLine("You can't ghost right now.");
|
shell.WriteLine("You can't ghost right now.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Content.Server.GameTicking;
|
|||||||
using Content.Server.Ghost.Components;
|
using Content.Server.Ghost.Components;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Players;
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Server.Visible;
|
using Content.Server.Visible;
|
||||||
using Content.Server.Warps;
|
using Content.Server.Warps;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
@@ -16,7 +16,6 @@ using Content.Shared.Mobs.Components;
|
|||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Storage.Components;
|
using Content.Shared.Storage.Components;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -38,6 +37,8 @@ namespace Content.Server.Ghost
|
|||||||
[Dependency] private readonly FollowerSystem _followerSystem = default!;
|
[Dependency] private readonly FollowerSystem _followerSystem = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
[Dependency] private readonly JobSystem _jobs = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -92,13 +93,13 @@ namespace Content.Server.Ghost
|
|||||||
if (EntityManager.HasComponent<VisitingMindComponent>(uid))
|
if (EntityManager.HasComponent<VisitingMindComponent>(uid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent<MindContainerComponent>(uid, out var mind) || !mind.HasMind || mind.Mind.IsVisitingEntity)
|
if (!_minds.TryGetMind(uid, out var mindId, out var mind) || mind.IsVisitingEntity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.MustBeDead && (_mobState.IsAlive(uid) || _mobState.IsCritical(uid)))
|
if (component.MustBeDead && (_mobState.IsAlive(uid) || _mobState.IsCritical(uid)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_ticker.OnGhostAttempt(mind.Mind, component.CanReturn);
|
_ticker.OnGhostAttempt(mindId, component.CanReturn, mind: mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGhostStartup(EntityUid uid, GhostComponent component, ComponentStartup args)
|
private void OnGhostStartup(EntityUid uid, GhostComponent component, ComponentStartup args)
|
||||||
@@ -199,7 +200,7 @@ namespace Content.Server.Ghost
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_mindSystem.UnVisit(actor.PlayerSession.ContentData()!.Mind);
|
_mindSystem.UnVisit(actor.PlayerSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGhostWarpToTargetRequest(GhostWarpToTargetRequestEvent msg, EntitySessionEventArgs args)
|
private void OnGhostWarpToTargetRequest(GhostWarpToTargetRequestEvent msg, EntitySessionEventArgs args)
|
||||||
@@ -260,7 +261,8 @@ namespace Content.Server.Ghost
|
|||||||
|
|
||||||
TryComp<MindContainerComponent>(attached, out var mind);
|
TryComp<MindContainerComponent>(attached, out var mind);
|
||||||
|
|
||||||
string playerInfo = $"{EntityManager.GetComponent<MetaDataComponent>(attached).EntityName} ({mind?.Mind?.CurrentJob?.Name ?? "Unknown"})";
|
var jobName = _jobs.MindTryGetJobName(mind?.Mind);
|
||||||
|
var playerInfo = $"{EntityManager.GetComponent<MetaDataComponent>(attached).EntityName} ({jobName})";
|
||||||
|
|
||||||
if (_mobState.IsAlive(attached) || _mobState.IsCritical(attached))
|
if (_mobState.IsAlive(attached) || _mobState.IsCritical(attached))
|
||||||
yield return new GhostWarp(attached, playerInfo, false);
|
yield return new GhostWarp(attached, playerInfo, false);
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using Content.Server.Roles;
|
|
||||||
|
|
||||||
namespace Content.Server.Ghost
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This is used to mark Observers properly, as they get Minds
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ObserverRole : Role
|
|
||||||
{
|
|
||||||
public override string Name => Loc.GetString("observer-role-name");
|
|
||||||
public override bool Antagonist => false;
|
|
||||||
|
|
||||||
public ObserverRole(Mind.Mind mind) : base(mind)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
Content.Server/Ghost/ObserverRoleComponent.cs
Normal file
11
Content.Server/Ghost/ObserverRoleComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Content.Server.Ghost
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is used to mark Observers properly, as they get Minds
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class ObserverRoleComponent : Component
|
||||||
|
{
|
||||||
|
public string Name => Loc.GetString("observer-role-name");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Shared.Eui;
|
using Content.Shared.Eui;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
|
|
||||||
@@ -10,9 +9,9 @@ public sealed class ReturnToBodyEui : BaseEui
|
|||||||
{
|
{
|
||||||
private readonly MindSystem _mindSystem;
|
private readonly MindSystem _mindSystem;
|
||||||
|
|
||||||
private readonly Mind.Mind _mind;
|
private readonly MindComponent _mind;
|
||||||
|
|
||||||
public ReturnToBodyEui(Mind.Mind mind, MindSystem mindSystem)
|
public ReturnToBodyEui(MindComponent mind, MindSystem mindSystem)
|
||||||
{
|
{
|
||||||
_mind = mind;
|
_mind = mind;
|
||||||
_mindSystem = mindSystem;
|
_mindSystem = mindSystem;
|
||||||
@@ -29,8 +28,8 @@ public sealed class ReturnToBodyEui : BaseEui
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mindSystem.TryGetSession(_mind, out var session))
|
_mindSystem.UnVisit(_mind.Session);
|
||||||
_mindSystem.UnVisit(session.ContentData()!.Mind);
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
using Content.Server.Roles;
|
|
||||||
|
|
||||||
namespace Content.Server.Ghost.Roles
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class GhostRoleMarkerRole : Role
|
|
||||||
{
|
|
||||||
private readonly string _name;
|
|
||||||
public override string Name => _name;
|
|
||||||
public override bool Antagonist => false;
|
|
||||||
|
|
||||||
public GhostRoleMarkerRole(Mind.Mind mind, string name) : base(mind)
|
|
||||||
{
|
|
||||||
_name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
Content.Server/Ghost/Roles/GhostRoleMarkerRoleComponent.cs
Normal file
11
Content.Server/Ghost/Roles/GhostRoleMarkerRoleComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Content.Server.Ghost.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class GhostRoleMarkerRoleComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("name")] public string? Name;
|
||||||
|
}
|
||||||
@@ -3,10 +3,11 @@ using Content.Server.EUI;
|
|||||||
using Content.Server.Ghost.Roles.Components;
|
using Content.Server.Ghost.Roles.Components;
|
||||||
using Content.Server.Ghost.Roles.Events;
|
using Content.Server.Ghost.Roles.Events;
|
||||||
using Content.Server.Ghost.Roles.UI;
|
using Content.Server.Ghost.Roles.UI;
|
||||||
using Content.Server.Mind.Commands;
|
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Mind.Commands;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Server.Roles;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Follower;
|
using Content.Shared.Follower;
|
||||||
@@ -34,6 +35,7 @@ namespace Content.Server.Ghost.Roles
|
|||||||
[Dependency] private readonly FollowerSystem _followerSystem = default!;
|
[Dependency] private readonly FollowerSystem _followerSystem = default!;
|
||||||
[Dependency] private readonly TransformSystem _transform = default!;
|
[Dependency] private readonly TransformSystem _transform = default!;
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roleSystem = default!;
|
||||||
|
|
||||||
private uint _nextRoleIdentifier;
|
private uint _nextRoleIdentifier;
|
||||||
private bool _needsUpdateGhostRoleCount = true;
|
private bool _needsUpdateGhostRoleCount = true;
|
||||||
@@ -219,7 +221,7 @@ namespace Content.Server.Ghost.Roles
|
|||||||
|
|
||||||
var newMind = _mindSystem.CreateMind(player.UserId,
|
var newMind = _mindSystem.CreateMind(player.UserId,
|
||||||
EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
|
EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
|
||||||
_mindSystem.AddRole(newMind, new GhostRoleMarkerRole(newMind, role.RoleName));
|
_roleSystem.MindAddRole(newMind, new GhostRoleMarkerRoleComponent { Name = role.RoleName });
|
||||||
|
|
||||||
_mindSystem.SetUserId(newMind, player.UserId);
|
_mindSystem.SetUserId(newMind, player.UserId);
|
||||||
_mindSystem.TransferTo(newMind, mob);
|
_mindSystem.TransferTo(newMind, mob);
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ public sealed class ToggleableGhostRoleSystem : EntitySystem
|
|||||||
Text = Loc.GetString(component.WipeVerbText),
|
Text = Loc.GetString(component.WipeVerbText),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
if (!TryComp<MindContainerComponent>(uid, out var mindComp) || mindComp.Mind == null)
|
if (!_mind.TryGetMind(uid, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
// Wiping device :(
|
// Wiping device :(
|
||||||
// The shutdown of the Mind should cause automatic reset of the pAI during OnMindRemoved
|
// The shutdown of the Mind should cause automatic reset of the pAI during OnMindRemoved
|
||||||
// EDIT: But it doesn't!!!! Wtf? Do stuff manually
|
// EDIT: But it doesn't!!!! Wtf? Do stuff manually
|
||||||
_mind.TransferTo(mindComp.Mind, null);
|
_mind.TransferTo(mindId, null, mind: mind);
|
||||||
_popup.PopupEntity(Loc.GetString(component.WipeVerbPopup), uid, args.User, PopupType.Large);
|
_popup.PopupEntity(Loc.GetString(component.WipeVerbPopup), uid, args.User, PopupType.Large);
|
||||||
UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
|
UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
|
||||||
_pai.PAITurningOff(uid);
|
_pai.PAITurningOff(uid);
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ using Content.Server.Info;
|
|||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
using Content.Server.MoMMI;
|
using Content.Server.MoMMI;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
using Content.Server.Objectives;
|
|
||||||
using Content.Server.Objectives.Interfaces;
|
|
||||||
using Content.Server.Players.PlayTimeTracking;
|
using Content.Server.Players.PlayTimeTracking;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
using Content.Server.ServerInfo;
|
using Content.Server.ServerInfo;
|
||||||
@@ -40,7 +38,6 @@ namespace Content.Server.IoC
|
|||||||
IoCManager.Register<INodeGroupFactory, NodeGroupFactory>();
|
IoCManager.Register<INodeGroupFactory, NodeGroupFactory>();
|
||||||
IoCManager.Register<IConnectionManager, ConnectionManager>();
|
IoCManager.Register<IConnectionManager, ConnectionManager>();
|
||||||
IoCManager.Register<ServerUpdateManager>();
|
IoCManager.Register<ServerUpdateManager>();
|
||||||
IoCManager.Register<IObjectivesManager, ObjectivesManager>();
|
|
||||||
IoCManager.Register<IAdminManager, AdminManager>();
|
IoCManager.Register<IAdminManager, AdminManager>();
|
||||||
IoCManager.Register<ISharedAdminManager, AdminManager>();
|
IoCManager.Register<ISharedAdminManager, AdminManager>();
|
||||||
IoCManager.Register<EuiManager, EuiManager>();
|
IoCManager.Register<EuiManager, EuiManager>();
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using Content.Server.Chemistry.EntitySystems;
|
|||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
using Content.Server.Fluids.EntitySystems;
|
using Content.Server.Fluids.EntitySystems;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Nutrition.Components;
|
using Content.Server.Nutrition.Components;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Stack;
|
using Content.Server.Stack;
|
||||||
@@ -34,6 +34,7 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
|
|||||||
[Dependency] private readonly SharedBodySystem _body = default!; //bobby
|
[Dependency] private readonly SharedBodySystem _body = default!; //bobby
|
||||||
[Dependency] private readonly PuddleSystem _puddle = default!;
|
[Dependency] private readonly PuddleSystem _puddle = default!;
|
||||||
[Dependency] private readonly StackSystem _stack = default!;
|
[Dependency] private readonly StackSystem _stack = default!;
|
||||||
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -105,9 +106,9 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
|
|||||||
args.SetHandled(SuicideKind.Bloodloss);
|
args.SetHandled(SuicideKind.Bloodloss);
|
||||||
var victim = args.Victim;
|
var victim = args.Victim;
|
||||||
if (TryComp(victim, out ActorComponent? actor) &&
|
if (TryComp(victim, out ActorComponent? actor) &&
|
||||||
actor.PlayerSession.ContentData()?.Mind is { } mind)
|
_mind.TryGetMind(actor.PlayerSession, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
_ticker.OnGhostAttempt(mind, false);
|
_ticker.OnGhostAttempt(mindId, false, mind: mind);
|
||||||
if (mind.OwnedEntity is { Valid: true } entity)
|
if (mind.OwnedEntity is { Valid: true } entity)
|
||||||
{
|
{
|
||||||
_popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), entity);
|
_popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), entity);
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Content.Shared.Interaction;
|
|
||||||
using Content.Shared.Audio;
|
|
||||||
using Content.Shared.Jittering;
|
|
||||||
using Content.Shared.Chemistry.Components;
|
|
||||||
using Content.Shared.Throwing;
|
|
||||||
using Content.Shared.Construction.Components;
|
|
||||||
using Content.Shared.Nutrition.Components;
|
|
||||||
using Content.Shared.Administration.Logs;
|
|
||||||
using Content.Shared.CCVar;
|
|
||||||
using Content.Shared.Database;
|
|
||||||
using Content.Server.Power.Components;
|
|
||||||
using Content.Server.Fluids.EntitySystems;
|
|
||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Climbing;
|
using Content.Server.Climbing;
|
||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
|
using Content.Server.Fluids.EntitySystems;
|
||||||
using Content.Server.Materials;
|
using Content.Server.Materials;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Power.Components;
|
||||||
|
using Content.Shared.Administration.Logs;
|
||||||
|
using Content.Shared.Audio;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Content.Shared.Construction.Components;
|
||||||
|
using Content.Shared.Database;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
|
using Content.Shared.Jittering;
|
||||||
|
using Content.Shared.Medical;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Content.Shared.Nutrition.Components;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Shared.Random;
|
using Content.Shared.Throwing;
|
||||||
using Robust.Shared.Configuration;
|
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Content.Shared.Medical;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Medical.BiomassReclaimer
|
namespace Content.Server.Medical.BiomassReclaimer
|
||||||
{
|
{
|
||||||
@@ -45,6 +45,7 @@ namespace Content.Server.Medical.BiomassReclaimer
|
|||||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly MaterialStorageSystem _material = default!;
|
[Dependency] private readonly MaterialStorageSystem _material = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
@@ -244,9 +245,9 @@ namespace Content.Server.Medical.BiomassReclaimer
|
|||||||
// Reject souled bodies in easy mode.
|
// Reject souled bodies in easy mode.
|
||||||
if (_configManager.GetCVar(CCVars.BiomassEasyMode) &&
|
if (_configManager.GetCVar(CCVars.BiomassEasyMode) &&
|
||||||
HasComp<HumanoidAppearanceComponent>(dragged) &&
|
HasComp<HumanoidAppearanceComponent>(dragged) &&
|
||||||
TryComp<MindContainerComponent>(dragged, out var mindComp))
|
_minds.TryGetMind(dragged, out _, out var mind))
|
||||||
{
|
{
|
||||||
if (mindComp.Mind?.UserId != null && _playerManager.TryGetSessionById(mindComp.Mind.UserId.Value, out _))
|
if (mind.UserId != null && _playerManager.TryGetSessionById(mind.UserId.Value, out _))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Content.Server.Electrocution;
|
|||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.PowerCell;
|
using Content.Server.PowerCell;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
@@ -224,16 +223,16 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||||||
_mobState.ChangeMobState(target, MobState.Critical, mob, uid);
|
_mobState.ChangeMobState(target, MobState.Critical, mob, uid);
|
||||||
_mobThreshold.SetAllowRevives(target, false, thresholds);
|
_mobThreshold.SetAllowRevives(target, false, thresholds);
|
||||||
|
|
||||||
if (TryComp<MindContainerComponent>(target, out var mindComp) &&
|
if (_mind.TryGetMind(target, out var mindId, out var mind) &&
|
||||||
mindComp.Mind?.Session is { } playerSession)
|
mind.Session is { } playerSession)
|
||||||
{
|
{
|
||||||
session = playerSession;
|
session = playerSession;
|
||||||
// notify them they're being revived.
|
// notify them they're being revived.
|
||||||
if (mindComp.Mind.CurrentEntity != target)
|
if (mind.CurrentEntity != target)
|
||||||
{
|
{
|
||||||
_chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-ghosted"),
|
_chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-ghosted"),
|
||||||
InGameICChatType.Speak, true);
|
InGameICChatType.Speak, true);
|
||||||
_euiManager.OpenEui(new ReturnToBodyEui(mindComp.Mind, _mind), session);
|
_euiManager.OpenEui(new ReturnToBodyEui(mind, _mind), session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Players;
|
using Content.Server.Roles;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -10,10 +10,10 @@ namespace Content.Server.Mind.Commands
|
|||||||
[AdminCommand(AdminFlags.Admin)]
|
[AdminCommand(AdminFlags.Admin)]
|
||||||
public sealed class MindInfoCommand : IConsoleCommand
|
public sealed class MindInfoCommand : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entities = default!;
|
||||||
|
|
||||||
public string Command => "mindinfo";
|
public string Command => "mindinfo";
|
||||||
|
|
||||||
public string Description => "Lists info for the mind of a specific player.";
|
public string Description => "Lists info for the mind of a specific player.";
|
||||||
|
|
||||||
public string Help => "mindinfo <session ID>";
|
public string Help => "mindinfo <session ID>";
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
@@ -25,15 +25,14 @@ namespace Content.Server.Mind.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mgr = IoCManager.Resolve<IPlayerManager>();
|
var mgr = IoCManager.Resolve<IPlayerManager>();
|
||||||
if (!mgr.TryGetSessionByUsername(args[0], out var data))
|
if (!mgr.TryGetSessionByUsername(args[0], out var session))
|
||||||
{
|
{
|
||||||
shell.WriteLine("Can't find that mind");
|
shell.WriteLine("Can't find that mind");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = data.ContentData()?.Mind;
|
var minds = _entities.System<MindSystem>();
|
||||||
|
if (!minds.TryGetMind(session, out var mindId, out var mind))
|
||||||
if (mind == null)
|
|
||||||
{
|
{
|
||||||
shell.WriteLine("Can't find that mind");
|
shell.WriteLine("Can't find that mind");
|
||||||
return;
|
return;
|
||||||
@@ -41,7 +40,9 @@ namespace Content.Server.Mind.Commands
|
|||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedEntity);
|
builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedEntity);
|
||||||
foreach (var role in mind.AllRoles)
|
|
||||||
|
var roles = _entities.System<RoleSystem>();
|
||||||
|
foreach (var role in roles.MindGetAllRoles(mindId))
|
||||||
{
|
{
|
||||||
builder.AppendFormat("{0} ", role.Name);
|
builder.AppendFormat("{0} ", role.Name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Content.Server.Access.Systems;
|
using Content.Server.Access.Systems;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Administration.Systems;
|
using Content.Server.Administration.Systems;
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.PDA;
|
using Content.Server.PDA;
|
||||||
using Content.Server.StationRecords.Systems;
|
using Content.Server.StationRecords.Systems;
|
||||||
using Content.Shared.Access.Components;
|
using Content.Shared.Access.Components;
|
||||||
@@ -46,16 +45,16 @@ public sealed class RenameCommand : IConsoleCommand
|
|||||||
var oldName = metadata.EntityName;
|
var oldName = metadata.EntityName;
|
||||||
entMan.System<MetaDataSystem>().SetEntityName(entityUid, name, metadata);
|
entMan.System<MetaDataSystem>().SetEntityName(entityUid, name, metadata);
|
||||||
|
|
||||||
var entSysMan = IoCManager.Resolve<IEntitySystemManager>();
|
var minds = entMan.System<MindSystem>();
|
||||||
|
|
||||||
if (entMan.TryGetComponent(entityUid, out MindContainerComponent? mind) && mind.Mind != null)
|
if (minds.TryGetMind(entityUid, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
// Mind
|
// Mind
|
||||||
mind.Mind.CharacterName = name;
|
mind.CharacterName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Id Cards
|
// Id Cards
|
||||||
if (entSysMan.TryGetEntitySystem<IdCardSystem>(out var idCardSystem))
|
if (entMan.TrySystem<IdCardSystem>(out var idCardSystem))
|
||||||
{
|
{
|
||||||
if (idCardSystem.TryFindIdCard(entityUid, out var idCard))
|
if (idCardSystem.TryFindIdCard(entityUid, out var idCard))
|
||||||
{
|
{
|
||||||
@@ -63,7 +62,7 @@ public sealed class RenameCommand : IConsoleCommand
|
|||||||
|
|
||||||
// Records
|
// Records
|
||||||
// This is done here because ID cards are linked to station records
|
// This is done here because ID cards are linked to station records
|
||||||
if (entSysMan.TryGetEntitySystem<StationRecordsSystem>(out var recordsSystem)
|
if (entMan.TrySystem<StationRecordsSystem>(out var recordsSystem)
|
||||||
&& entMan.TryGetComponent(idCard.Owner, out StationRecordKeyStorageComponent? keyStorage)
|
&& entMan.TryGetComponent(idCard.Owner, out StationRecordKeyStorageComponent? keyStorage)
|
||||||
&& keyStorage.Key != null)
|
&& keyStorage.Key != null)
|
||||||
{
|
{
|
||||||
@@ -80,7 +79,7 @@ public sealed class RenameCommand : IConsoleCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PDAs
|
// PDAs
|
||||||
if (entSysMan.TryGetEntitySystem<PdaSystem>(out var pdaSystem))
|
if (entMan.TrySystem<PdaSystem>(out var pdaSystem))
|
||||||
{
|
{
|
||||||
var query = entMan.EntityQueryEnumerator<PdaComponent>();
|
var query = entMan.EntityQueryEnumerator<PdaComponent>();
|
||||||
while (query.MoveNext(out var uid, out var pda))
|
while (query.MoveNext(out var uid, out var pda))
|
||||||
@@ -93,7 +92,7 @@ public sealed class RenameCommand : IConsoleCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Admin Overlay
|
// Admin Overlay
|
||||||
if (entSysMan.TryGetEntitySystem<AdminSystem>(out var adminSystem)
|
if (entMan.TrySystem<AdminSystem>(out var adminSystem)
|
||||||
&& entMan.TryGetComponent<ActorComponent>(entityUid, out var actorComp))
|
&& entMan.TryGetComponent<ActorComponent>(entityUid, out var actorComp))
|
||||||
{
|
{
|
||||||
adminSystem.UpdatePlayerList(actorComp.PlayerSession);
|
adminSystem.UpdatePlayerList(actorComp.PlayerSession);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
namespace Content.Server.Mind.Components
|
namespace Content.Server.Mind.Components
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stores a <see cref="Server.Mind.Mind"/> on a mob.
|
/// Stores a <see cref="MindComponent"/> on a mob.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, Access(typeof(MindSystem))]
|
[RegisterComponent, Access(typeof(MindSystem))]
|
||||||
public sealed partial class MindContainerComponent : Component
|
public sealed partial class MindContainerComponent : Component
|
||||||
@@ -13,7 +13,7 @@ namespace Content.Server.Mind.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
[Access(typeof(MindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
|
[Access(typeof(MindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
|
||||||
public Mind? Mind { get; set; }
|
public EntityUid? Mind { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if we have a mind, false otherwise.
|
/// True if we have a mind, false otherwise.
|
||||||
@@ -40,10 +40,12 @@ namespace Content.Server.Mind.Components
|
|||||||
|
|
||||||
public sealed class MindRemovedMessage : EntityEventArgs
|
public sealed class MindRemovedMessage : EntityEventArgs
|
||||||
{
|
{
|
||||||
public Mind OldMind;
|
public EntityUid OldMindId;
|
||||||
|
public MindComponent OldMind;
|
||||||
|
|
||||||
public MindRemovedMessage(Mind oldMind)
|
public MindRemovedMessage(EntityUid oldMindId, MindComponent oldMind)
|
||||||
{
|
{
|
||||||
|
OldMindId = oldMindId;
|
||||||
OldMind = oldMind;
|
OldMind = oldMind;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ namespace Content.Server.Mind.Components
|
|||||||
public sealed partial class VisitingMindComponent : Component
|
public sealed partial class VisitingMindComponent : Component
|
||||||
{
|
{
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public Mind? Mind;
|
public EntityUid? MindId;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public MindComponent? Mind;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MindUnvisitedMessage : EntityEventArgs
|
public sealed class MindUnvisitedMessage : EntityEventArgs
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
using System.Linq;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.GameTicking;
|
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Objectives;
|
using Content.Server.Objectives;
|
||||||
using Content.Server.Roles;
|
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
|
||||||
namespace Content.Server.Mind
|
namespace Content.Server.Mind
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A mind represents the IC "mind" of a player. Stores roles currently.
|
/// A mind represents the IC "mind" of a player.
|
||||||
|
/// Roles are attached as components to its owning entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Think of it like this: if a player is supposed to have their memories,
|
/// Think of it like this: if a player is supposed to have their memories,
|
||||||
@@ -18,23 +17,11 @@ namespace Content.Server.Mind
|
|||||||
/// Things such as respawning do not follow, because you're a new character.
|
/// Things such as respawning do not follow, because you're a new character.
|
||||||
/// Getting borged, cloned, turned into a catbeast, etc... will keep it following you.
|
/// Getting borged, cloned, turned into a catbeast, etc... will keep it following you.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public sealed class Mind
|
[RegisterComponent]
|
||||||
|
public sealed partial class MindComponent : Component
|
||||||
{
|
{
|
||||||
internal readonly ISet<Role> Roles = new HashSet<Role>();
|
|
||||||
|
|
||||||
internal readonly List<Objective> Objectives = new();
|
internal readonly List<Objective> Objectives = new();
|
||||||
|
|
||||||
public string Briefing = String.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates the new mind.
|
|
||||||
/// Note: the Mind is NOT initially attached!
|
|
||||||
/// The provided UserId is solely for tracking of intended owner.
|
|
||||||
/// </summary>
|
|
||||||
public Mind()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The session ID of the player owning this mind.
|
/// The session ID of the player owning this mind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -87,12 +74,7 @@ namespace Content.Server.Mind
|
|||||||
[ViewVariables, Access(typeof(MindSystem))]
|
[ViewVariables, Access(typeof(MindSystem))]
|
||||||
public EntityUid? OwnedEntity { get; set; }
|
public EntityUid? OwnedEntity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
// TODO move objectives out of mind component
|
||||||
/// An enumerable over all the roles this mind has.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public IEnumerable<Role> AllRoles => Roles;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An enumerable over all the objectives this mind has.
|
/// An enumerable over all the objectives this mind has.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -119,10 +101,5 @@ namespace Content.Server.Mind
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables, Access(typeof(MindSystem), typeof(GameTicker))]
|
[ViewVariables, Access(typeof(MindSystem), typeof(GameTicker))]
|
||||||
public IPlayerSession? Session { get; internal set; }
|
public IPlayerSession? Session { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current job
|
|
||||||
/// </summary>
|
|
||||||
public Job? CurrentJob => Roles.OfType<Job>().SingleOrDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,17 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Objectives;
|
using Content.Server.Objectives;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Content.Server.Roles;
|
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
using Content.Shared.Mobs.Systems;
|
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
|
using Content.Shared.Mobs.Systems;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
@@ -36,7 +34,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
|
|
||||||
// This is dictionary is required to track the minds of disconnected players that may have had their entity deleted.
|
// This is dictionary is required to track the minds of disconnected players that may have had their entity deleted.
|
||||||
private readonly Dictionary<NetUserId, Mind> _userMinds = new();
|
private readonly Dictionary<NetUserId, EntityUid> _userMinds = new();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -55,14 +53,6 @@ public sealed class MindSystem : EntitySystem
|
|||||||
WipeAllMinds();
|
WipeAllMinds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetGhostOnShutdown(EntityUid uid, bool value, MindContainerComponent? mind = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref mind))
|
|
||||||
return;
|
|
||||||
|
|
||||||
mind.GhostOnShutdown = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnReset(RoundRestartCleanupEvent ev)
|
private void OnReset(RoundRestartCleanupEvent ev)
|
||||||
{
|
{
|
||||||
WipeAllMinds();
|
WipeAllMinds();
|
||||||
@@ -86,59 +76,35 @@ public sealed class MindSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mind? GetMind(NetUserId user)
|
public EntityUid? GetMind(NetUserId user)
|
||||||
{
|
{
|
||||||
TryGetMind(user, out var mind);
|
TryGetMind(user, out var mind, out _);
|
||||||
return mind;
|
return mind;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetMind(NetUserId user, [NotNullWhen(true)] out Mind? mind)
|
public bool TryGetMind(NetUserId user, [NotNullWhen(true)] out EntityUid? mindId, [NotNullWhen(true)] out MindComponent? mind)
|
||||||
{
|
{
|
||||||
if (_userMinds.TryGetValue(user, out mind))
|
if (_userMinds.TryGetValue(user, out var mindIdValue) &&
|
||||||
|
TryComp(mindIdValue, out mind))
|
||||||
{
|
{
|
||||||
DebugTools.Assert(mind.UserId == user);
|
DebugTools.Assert(mind.UserId == user);
|
||||||
DebugTools.Assert(_playerManager.GetPlayerData(user).ContentData() is not {} data
|
DebugTools.Assert(_playerManager.GetPlayerData(user).ContentData() is not {} data
|
||||||
|| data.Mind == mind);
|
|| data.Mind == mindIdValue);
|
||||||
|
|
||||||
|
mindId = mindIdValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugTools.Assert(_playerManager.GetPlayerData(user).ContentData()?.Mind == null);
|
DebugTools.Assert(_playerManager.GetPlayerData(user).ContentData()?.Mind == null);
|
||||||
|
mindId = null;
|
||||||
|
mind = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Don't call this unless you know what the hell you're doing.
|
|
||||||
/// Use <see cref="MindSystem.TransferTo(Mind,System.Nullable{Robust.Shared.GameObjects.EntityUid},bool)"/> instead.
|
|
||||||
/// If that doesn't cover it, make something to cover it.
|
|
||||||
/// </summary>
|
|
||||||
private void InternalAssignMind(EntityUid uid, Mind value, MindContainerComponent? mind = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref mind))
|
|
||||||
return;
|
|
||||||
|
|
||||||
mind.Mind = value;
|
|
||||||
RaiseLocalEvent(uid, new MindAddedMessage(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Don't call this unless you know what the hell you're doing.
|
|
||||||
/// Use <see cref="MindSystem.TransferTo(Mind,System.Nullable{Robust.Shared.GameObjects.EntityUid},bool)"/> instead.
|
|
||||||
/// If that doesn't cover it, make something to cover it.
|
|
||||||
/// </summary>
|
|
||||||
private void InternalEjectMind(EntityUid uid, MindContainerComponent? mind = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref mind, false) || mind.Mind == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var oldMind = mind.Mind;
|
|
||||||
mind.Mind = null;
|
|
||||||
RaiseLocalEvent(uid, new MindRemovedMessage(oldMind), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnVisitingTerminating(EntityUid uid, VisitingMindComponent component, ref EntityTerminatingEvent args)
|
private void OnVisitingTerminating(EntityUid uid, VisitingMindComponent component, ref EntityTerminatingEvent args)
|
||||||
{
|
{
|
||||||
if (component.Mind != null)
|
if (component.MindId != null)
|
||||||
UnVisit(component.Mind);
|
UnVisit(component.MindId.Value, component.Mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMindContainerTerminating(EntityUid uid, MindContainerComponent component, ref EntityTerminatingEvent args)
|
private void OnMindContainerTerminating(EntityUid uid, MindContainerComponent component, ref EntityTerminatingEvent args)
|
||||||
@@ -147,7 +113,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby)
|
if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.Mind is not { } mind)
|
if (!TryGetMind(uid, out var mindId, out var mind, component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the player is currently visiting some other entity, simply attach to that entity.
|
// If the player is currently visiting some other entity, simply attach to that entity.
|
||||||
@@ -156,13 +122,13 @@ public sealed class MindSystem : EntitySystem
|
|||||||
&& !Deleted(visiting)
|
&& !Deleted(visiting)
|
||||||
&& !Terminating(visiting))
|
&& !Terminating(visiting))
|
||||||
{
|
{
|
||||||
TransferTo(mind, visiting);
|
TransferTo(mindId, visiting, mind: mind);
|
||||||
if (TryComp(visiting, out GhostComponent? ghost))
|
if (TryComp(visiting, out GhostComponent? ghost))
|
||||||
_ghostSystem.SetCanReturnToBody(ghost, false);
|
_ghostSystem.SetCanReturnToBody(ghost, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransferTo(mind, null, createGhost: false);
|
TransferTo(mindId, null, createGhost: false, mind: mind);
|
||||||
|
|
||||||
if (component.GhostOnShutdown && mind.Session != null)
|
if (component.GhostOnShutdown && mind.Session != null)
|
||||||
{
|
{
|
||||||
@@ -187,7 +153,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
// This should be an error, if it didn't cause tests to start erroring when they delete a player.
|
// This should be an error, if it didn't cause tests to start erroring when they delete a player.
|
||||||
Log.Warning($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available.");
|
Log.Warning($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available.");
|
||||||
TransferTo(mind, null, createGhost: false);
|
TransferTo(mindId, null, createGhost: false, mind: mind);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +166,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
|
|
||||||
var val = mind.CharacterName ?? string.Empty;
|
var val = mind.CharacterName ?? string.Empty;
|
||||||
_metaData.SetEntityName(ghost, val);
|
_metaData.SetEntityName(ghost, val);
|
||||||
TransferTo(mind, ghost);
|
TransferTo(mindId, ghost, mind: mind);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +177,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var dead = _mobStateSystem.IsDead(uid);
|
var dead = _mobStateSystem.IsDead(uid);
|
||||||
var hasSession = mindContainer.Mind?.Session;
|
var hasSession = CompOrNull<MindComponent>(mindContainer.Mind)?.Session;
|
||||||
|
|
||||||
if (dead && !mindContainer.HasMind)
|
if (dead && !mindContainer.HasMind)
|
||||||
args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-dead-and-irrecoverable", ("ent", uid))}[/color]");
|
args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-dead-and-irrecoverable", ("ent", uid))}[/color]");
|
||||||
@@ -230,36 +196,40 @@ public sealed class MindSystem : EntitySystem
|
|||||||
if (args.Handled)
|
if (args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.HasMind && component.Mind.PreventSuicide)
|
if (TryComp(component.Mind, out MindComponent? mind) && mind.PreventSuicide)
|
||||||
{
|
{
|
||||||
args.BlockSuicideAttempt(true);
|
args.BlockSuicideAttempt(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mind? GetMind(EntityUid uid, MindContainerComponent? mind = null)
|
public EntityUid? GetMind(EntityUid uid, MindContainerComponent? mind = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref mind))
|
if (!Resolve(uid, ref mind))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (mind.HasMind)
|
if (mind.HasMind)
|
||||||
return mind.Mind;
|
return mind.Mind;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mind CreateMind(NetUserId? userId, string? name = null)
|
public EntityUid CreateMind(NetUserId? userId, string? name = null)
|
||||||
{
|
{
|
||||||
var mind = new Mind();
|
var mindId = Spawn(null, MapCoordinates.Nullspace);
|
||||||
|
var mind = EnsureComp<MindComponent>(mindId);
|
||||||
mind.CharacterName = name;
|
mind.CharacterName = name;
|
||||||
SetUserId(mind, userId);
|
SetUserId(mindId, userId, mind);
|
||||||
|
|
||||||
return mind;
|
Dirty(mindId, MetaData(mindId));
|
||||||
|
|
||||||
|
return mindId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the OwnedEntity of this mind is physically dead.
|
/// True if the OwnedEntity of this mind is physically dead.
|
||||||
/// This specific definition, as opposed to CharacterDeadIC, is used to determine if ghosting should allow return.
|
/// This specific definition, as opposed to CharacterDeadIC, is used to determine if ghosting should allow return.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsCharacterDeadPhysically(Mind mind)
|
public bool IsCharacterDeadPhysically(MindComponent mind)
|
||||||
{
|
{
|
||||||
// This is written explicitly so that the logic can be understood.
|
// This is written explicitly so that the logic can be understood.
|
||||||
// But it's also weird and potentially situational.
|
// But it's also weird and potentially situational.
|
||||||
@@ -285,8 +255,11 @@ public sealed class MindSystem : EntitySystem
|
|||||||
return _mobStateSystem.IsDead(mind.OwnedEntity.Value, targetMobState);
|
return _mobStateSystem.IsDead(mind.OwnedEntity.Value, targetMobState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Visit(Mind mind, EntityUid entity)
|
public void Visit(EntityUid mindId, EntityUid entity, MindComponent? mind = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(mindId, ref mind))
|
||||||
|
return;
|
||||||
|
|
||||||
if (mind.VisitingEntity != null)
|
if (mind.VisitingEntity != null)
|
||||||
{
|
{
|
||||||
Log.Error($"Attempted to visit an entity ({ToPrettyString(entity)}) while already visiting another ({ToPrettyString(mind.VisitingEntity.Value)}).");
|
Log.Error($"Attempted to visit an entity ({ToPrettyString(entity)}) while already visiting another ({ToPrettyString(mind.VisitingEntity.Value)}).");
|
||||||
@@ -304,6 +277,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
|
|
||||||
// EnsureComp instead of AddComp to deal with deferred deletions.
|
// EnsureComp instead of AddComp to deal with deferred deletions.
|
||||||
var comp = EnsureComp<VisitingMindComponent>(entity);
|
var comp = EnsureComp<VisitingMindComponent>(entity);
|
||||||
|
comp.MindId = mindId;
|
||||||
comp.Mind = mind;
|
comp.Mind = mind;
|
||||||
Log.Info($"Session {mind.Session?.Name} visiting entity {entity}.");
|
Log.Info($"Session {mind.Session?.Name} visiting entity {entity}.");
|
||||||
}
|
}
|
||||||
@@ -311,9 +285,12 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the mind to its original entity.
|
/// Returns the mind to its original entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UnVisit(Mind? mind)
|
public void UnVisit(EntityUid mindId, MindComponent? mind = null)
|
||||||
{
|
{
|
||||||
if (mind == null || mind.VisitingEntity == null)
|
if (!Resolve(mindId, ref mind))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mind.VisitingEntity == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RemoveVisitingEntity(mind);
|
RemoveVisitingEntity(mind);
|
||||||
@@ -331,11 +308,22 @@ public sealed class MindSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the mind to its original entity.
|
||||||
|
/// </summary>
|
||||||
|
public void UnVisit(IPlayerSession? player)
|
||||||
|
{
|
||||||
|
if (player == null || !TryGetMind(player, out var mindId, out var mind))
|
||||||
|
return;
|
||||||
|
|
||||||
|
UnVisit(mindId, mind);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cleans up the VisitingEntity.
|
/// Cleans up the VisitingEntity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mind"></param>
|
/// <param name="mind"></param>
|
||||||
private void RemoveVisitingEntity(Mind mind)
|
private void RemoveVisitingEntity(MindComponent mind)
|
||||||
{
|
{
|
||||||
if (mind.VisitingEntity == null)
|
if (mind.VisitingEntity == null)
|
||||||
return;
|
return;
|
||||||
@@ -363,19 +351,19 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Detaches a mind from all entities and clears the user ID.
|
/// Detaches a mind from all entities and clears the user ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void WipeMind(Mind? mind)
|
public void WipeMind(EntityUid? mindId, MindComponent? mind = null)
|
||||||
{
|
{
|
||||||
if (mind == null)
|
if (mindId == null || !Resolve(mindId.Value, ref mind, false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TransferTo(mind, null);
|
TransferTo(mindId.Value, null, mind: mind);
|
||||||
SetUserId(mind, null);
|
SetUserId(mindId.Value, null, mind: mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transfer this mind's control over to a new entity.
|
/// Transfer this mind's control over to a new entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mind">The mind to transfer</param>
|
/// <param name="mindId">The mind to transfer</param>
|
||||||
/// <param name="entity">
|
/// <param name="entity">
|
||||||
/// The entity to control.
|
/// The entity to control.
|
||||||
/// Can be null, in which case it will simply detach the mind from any entity.
|
/// Can be null, in which case it will simply detach the mind from any entity.
|
||||||
@@ -384,10 +372,13 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// If true, skips ghost check for Visiting Entity
|
/// If true, skips ghost check for Visiting Entity
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="ArgumentException">
|
/// <exception cref="ArgumentException">
|
||||||
/// Thrown if <paramref name="entity"/> is already owned by another mind.
|
/// Thrown if <paramref name="entity"/> is already controlled by another player.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
public void TransferTo(Mind mind, EntityUid? entity, bool ghostCheckOverride = false, bool createGhost = true)
|
public void TransferTo(EntityUid mindId, EntityUid? entity, bool ghostCheckOverride = false, bool createGhost = true, MindComponent? mind = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(mindId, ref mind))
|
||||||
|
return;
|
||||||
|
|
||||||
if (entity == mind.OwnedEntity)
|
if (entity == mind.OwnedEntity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -399,7 +390,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
component = EnsureComp<MindContainerComponent>(entity.Value);
|
component = EnsureComp<MindContainerComponent>(entity.Value);
|
||||||
|
|
||||||
if (component.HasMind)
|
if (component.HasMind)
|
||||||
_gameTicker.OnGhostAttempt(component.Mind, false);
|
_gameTicker.OnGhostAttempt(component.Mind.Value, false);
|
||||||
|
|
||||||
if (TryComp<ActorComponent>(entity.Value, out var actor))
|
if (TryComp<ActorComponent>(entity.Value, out var actor))
|
||||||
{
|
{
|
||||||
@@ -425,8 +416,11 @@ public sealed class MindSystem : EntitySystem
|
|||||||
|
|
||||||
var oldComp = mind.OwnedComponent;
|
var oldComp = mind.OwnedComponent;
|
||||||
var oldEntity = mind.OwnedEntity;
|
var oldEntity = mind.OwnedEntity;
|
||||||
if(oldComp != null && oldEntity != null)
|
if (oldComp != null && oldEntity != null)
|
||||||
InternalEjectMind(oldEntity.Value, oldComp);
|
{
|
||||||
|
oldComp.Mind = null;
|
||||||
|
RaiseLocalEvent(oldEntity.Value, new MindRemovedMessage(oldEntity.Value, mind), true);
|
||||||
|
}
|
||||||
|
|
||||||
SetOwnedEntity(mind, entity, component);
|
SetOwnedEntity(mind, entity, component);
|
||||||
|
|
||||||
@@ -455,7 +449,8 @@ public sealed class MindSystem : EntitySystem
|
|||||||
|
|
||||||
if (mind.OwnedComponent != null)
|
if (mind.OwnedComponent != null)
|
||||||
{
|
{
|
||||||
InternalAssignMind(mind.OwnedEntity!.Value, mind, mind.OwnedComponent);
|
mind.OwnedComponent.Mind = mindId;
|
||||||
|
RaiseLocalEvent(mind.OwnedEntity!.Value, new MindAddedMessage(), true);
|
||||||
mind.OriginalOwnedEntity ??= mind.OwnedEntity;
|
mind.OriginalOwnedEntity ??= mind.OwnedEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,11 +458,11 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an objective to this mind.
|
/// Adds an objective to this mind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryAddObjective(Mind mind, ObjectivePrototype objectivePrototype)
|
public bool TryAddObjective(EntityUid mindId, MindComponent mind, ObjectivePrototype objectivePrototype)
|
||||||
{
|
{
|
||||||
if (!objectivePrototype.CanBeAssigned(mind))
|
if (!objectivePrototype.CanBeAssigned(mindId, mind))
|
||||||
return false;
|
return false;
|
||||||
var objective = objectivePrototype.GetObjective(mind);
|
var objective = objectivePrototype.GetObjective(mindId, mind);
|
||||||
if (mind.Objectives.Contains(objective))
|
if (mind.Objectives.Contains(objective))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -476,7 +471,6 @@ public sealed class MindSystem : EntitySystem
|
|||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low, $"'{condition.Title}' added to mind of {MindOwnerLoggingString(mind)}");
|
_adminLogger.Add(LogType.Mind, LogImpact.Low, $"'{condition.Title}' added to mind of {MindOwnerLoggingString(mind)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mind.Objectives.Add(objective);
|
mind.Objectives.Add(objective);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -485,9 +479,10 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// Removes an objective to this mind.
|
/// Removes an objective to this mind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns true if the removal succeeded.</returns>
|
/// <returns>Returns true if the removal succeeded.</returns>
|
||||||
public bool TryRemoveObjective(Mind mind, int index)
|
public bool TryRemoveObjective(MindComponent mind, int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= mind.Objectives.Count) return false;
|
if (index < 0 || index >= mind.Objectives.Count)
|
||||||
|
return false;
|
||||||
|
|
||||||
var objective = mind.Objectives[index];
|
var objective = mind.Objectives[index];
|
||||||
|
|
||||||
@@ -500,90 +495,56 @@ public sealed class MindSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out IPlayerSession? session)
|
||||||
/// Gives this mind a new role.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mind">The mind to add the role to.</param>
|
|
||||||
/// <param name="role">The type of the role to give.</param>
|
|
||||||
/// <returns>The instance of the role.</returns>
|
|
||||||
/// <exception cref="ArgumentException">
|
|
||||||
/// Thrown if we already have a role with this type.
|
|
||||||
/// </exception>
|
|
||||||
public void AddRole(Mind mind, Role role)
|
|
||||||
{
|
{
|
||||||
if (mind.Roles.Contains(role))
|
session = null;
|
||||||
{
|
return TryComp(mindId, out MindComponent? mind) && (session = mind.Session) != null;
|
||||||
throw new ArgumentException($"We already have this role: {role}");
|
|
||||||
}
|
|
||||||
|
|
||||||
mind.Roles.Add(role);
|
|
||||||
role.Greet();
|
|
||||||
|
|
||||||
var message = new RoleAddedEvent(mind, role);
|
|
||||||
if (mind.OwnedEntity != null)
|
|
||||||
{
|
|
||||||
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low,
|
|
||||||
$"'{role.Name}' added to mind of {MindOwnerLoggingString(mind)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a role from this mind.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mind">The mind to remove the role from.</param>
|
|
||||||
/// <param name="role">The type of the role to remove.</param>
|
|
||||||
/// <exception cref="ArgumentException">
|
|
||||||
/// Thrown if we do not have this role.
|
|
||||||
/// </exception>
|
|
||||||
public void RemoveRole(Mind mind, Role role)
|
|
||||||
{
|
|
||||||
if (!mind.Roles.Contains(role))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"We do not have this role: {role}");
|
|
||||||
}
|
|
||||||
|
|
||||||
mind.Roles.Remove(role);
|
|
||||||
|
|
||||||
var message = new RoleRemovedEvent(mind, role);
|
|
||||||
|
|
||||||
if (mind.OwnedEntity != null)
|
|
||||||
{
|
|
||||||
RaiseLocalEvent(mind.OwnedEntity.Value, message, true);
|
|
||||||
}
|
|
||||||
_adminLogger.Add(LogType.Mind, LogImpact.Low,
|
|
||||||
$"'{role.Name}' removed from mind of {MindOwnerLoggingString(mind)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasRole<T>(Mind mind) where T : Role
|
|
||||||
{
|
|
||||||
return mind.Roles.Any(role => role is T);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetSession(Mind mind, [NotNullWhen(true)] out IPlayerSession? session)
|
|
||||||
{
|
|
||||||
return (session = mind.Session) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a mind from uid and/or MindContainerComponent. Used for null checks.
|
/// Gets a mind from uid and/or MindContainerComponent. Used for null checks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uid">Entity UID that owns the mind.</param>
|
/// <param name="uid">Entity UID that owns the mind.</param>
|
||||||
|
/// <param name="mindId">The mind id.</param>
|
||||||
/// <param name="mind">The returned mind.</param>
|
/// <param name="mind">The returned mind.</param>
|
||||||
/// <param name="mindContainerComponent">Mind component on <paramref name="uid"/> to get the mind from.</param>
|
/// <param name="container">Mind component on <paramref name="uid"/> to get the mind from.</param>
|
||||||
/// <returns>True if mind found. False if not.</returns>
|
/// <returns>True if mind found. False if not.</returns>
|
||||||
public bool TryGetMind(EntityUid uid, [NotNullWhen(true)] out Mind? mind, MindContainerComponent? mindContainerComponent = null)
|
public bool TryGetMind(
|
||||||
|
EntityUid uid,
|
||||||
|
out EntityUid mindId,
|
||||||
|
[NotNullWhen(true)] out MindComponent? mind,
|
||||||
|
MindContainerComponent? container = null)
|
||||||
{
|
{
|
||||||
|
mindId = default;
|
||||||
mind = null;
|
mind = null;
|
||||||
if (!Resolve(uid, ref mindContainerComponent, false))
|
|
||||||
|
if (!Resolve(uid, ref container, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!mindContainerComponent.HasMind)
|
if (!container.HasMind)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mind = mindContainerComponent.Mind;
|
mindId = container.Mind ?? default;
|
||||||
return true;
|
return TryComp(mindId, out mind);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetMind(
|
||||||
|
PlayerData player,
|
||||||
|
out EntityUid mindId,
|
||||||
|
[NotNullWhen(true)] out MindComponent? mind)
|
||||||
|
{
|
||||||
|
mindId = player.Mind ?? default;
|
||||||
|
return TryComp(mindId, out mind);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetMind(
|
||||||
|
IPlayerSession? player,
|
||||||
|
out EntityUid mindId,
|
||||||
|
[NotNullWhen(true)] out MindComponent? mind)
|
||||||
|
{
|
||||||
|
mindId = default;
|
||||||
|
mind = null;
|
||||||
|
return player?.ContentData() is { } data && TryGetMind(data, out mindId, out mind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -592,7 +553,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// <param name="mind">Mind to set OwnedComponent and OwnedEntity on</param>
|
/// <param name="mind">Mind to set OwnedComponent and OwnedEntity on</param>
|
||||||
/// <param name="uid">Entity owned by <paramref name="mind"/></param>
|
/// <param name="uid">Entity owned by <paramref name="mind"/></param>
|
||||||
/// <param name="mindContainerComponent">MindContainerComponent owned by <paramref name="mind"/></param>
|
/// <param name="mindContainerComponent">MindContainerComponent owned by <paramref name="mind"/></param>
|
||||||
private void SetOwnedEntity(Mind mind, EntityUid? uid, MindContainerComponent? mindContainerComponent)
|
private void SetOwnedEntity(MindComponent mind, EntityUid? uid, MindContainerComponent? mindContainerComponent)
|
||||||
{
|
{
|
||||||
if (uid != null)
|
if (uid != null)
|
||||||
Resolve(uid.Value, ref mindContainerComponent);
|
Resolve(uid.Value, ref mindContainerComponent);
|
||||||
@@ -606,8 +567,11 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// entity that any mind is connected to, except as a side effect of the fact that it may change a player's
|
/// entity that any mind is connected to, except as a side effect of the fact that it may change a player's
|
||||||
/// attached entity. E.g., ghosts get deleted.
|
/// attached entity. E.g., ghosts get deleted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetUserId(Mind mind, NetUserId? userId)
|
public void SetUserId(EntityUid mindId, NetUserId? userId, MindComponent? mind = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(mindId, ref mind))
|
||||||
|
return;
|
||||||
|
|
||||||
if (mind.UserId == userId)
|
if (mind.UserId == userId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -637,12 +601,15 @@ public sealed class MindSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_userMinds.TryGetValue(userId.Value, out var oldMind))
|
if (_userMinds.TryGetValue(userId.Value, out var oldMindId) &&
|
||||||
SetUserId(oldMind, null);
|
TryComp(oldMindId, out MindComponent? oldMind))
|
||||||
|
{
|
||||||
|
SetUserId(oldMindId, null, oldMind);
|
||||||
|
}
|
||||||
|
|
||||||
DebugTools.AssertNull(_playerManager.GetPlayerData(userId.Value).ContentData()?.Mind);
|
DebugTools.AssertNull(_playerManager.GetPlayerData(userId.Value).ContentData()?.Mind);
|
||||||
|
|
||||||
_userMinds[userId.Value] = mind;
|
_userMinds[userId.Value] = mindId;
|
||||||
mind.UserId = userId;
|
mind.UserId = userId;
|
||||||
mind.OriginalOwnerUserId ??= userId;
|
mind.OriginalOwnerUserId ??= userId;
|
||||||
|
|
||||||
@@ -654,7 +621,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
|
|
||||||
// session may be null, but user data may still exist for disconnected players.
|
// session may be null, but user data may still exist for disconnected players.
|
||||||
if (_playerManager.GetPlayerData(userId.Value).ContentData() is { } data)
|
if (_playerManager.GetPlayerData(userId.Value).ContentData() is { } data)
|
||||||
data.Mind = mind;
|
data.Mind = mindId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -663,7 +630,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// "If administrators decide that zombies are dead, this returns true for zombies."
|
/// "If administrators decide that zombies are dead, this returns true for zombies."
|
||||||
/// (Maybe you were looking for the action blocker system?)
|
/// (Maybe you were looking for the action blocker system?)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsCharacterDeadIc(Mind mind)
|
public bool IsCharacterDeadIc(MindComponent mind)
|
||||||
{
|
{
|
||||||
if (mind.OwnedEntity is { } owned)
|
if (mind.OwnedEntity is { } owned)
|
||||||
{
|
{
|
||||||
@@ -680,7 +647,7 @@ public sealed class MindSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A string to represent the mind for logging
|
/// A string to represent the mind for logging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string MindOwnerLoggingString(Mind mind)
|
public string MindOwnerLoggingString(MindComponent mind)
|
||||||
{
|
{
|
||||||
if (mind.OwnedEntity != null)
|
if (mind.OwnedEntity != null)
|
||||||
return ToPrettyString(mind.OwnedEntity.Value);
|
return ToPrettyString(mind.OwnedEntity.Value);
|
||||||
@@ -688,6 +655,11 @@ public sealed class MindSystem : EntitySystem
|
|||||||
return mind.UserId.Value.ToString();
|
return mind.UserId.Value.ToString();
|
||||||
return "(originally " + mind.OriginalOwnerUserId + ")";
|
return "(originally " + mind.OriginalOwnerUserId + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? GetCharacterName(NetUserId userId)
|
||||||
|
{
|
||||||
|
return TryGetMind(userId, out _, out var mind) ? mind.CharacterName : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Shared.GameTicking;
|
|
||||||
|
|
||||||
namespace Content.Server.Mind
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This is absolutely evil.
|
|
||||||
/// It tracks all mind changes and logs all the Mind objects.
|
|
||||||
/// This is so that when round end comes around, there's a coherent list of all Minds that were in play during the round.
|
|
||||||
/// The Minds themselves contain metadata about their owners.
|
|
||||||
/// Anyway, this is because disconnected people and ghost roles have been breaking round end statistics for way too long.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class MindTrackerSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[ViewVariables]
|
|
||||||
public readonly HashSet<Mind> AllMinds = new();
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
|
|
||||||
SubscribeLocalEvent<MindContainerComponent, MindAddedMessage>(OnMindAdded);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset(RoundRestartCleanupEvent ev)
|
|
||||||
{
|
|
||||||
AllMinds.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnMindAdded(EntityUid uid, MindContainerComponent mc, MindAddedMessage args)
|
|
||||||
{
|
|
||||||
var mind = mc.Mind;
|
|
||||||
if (mind != null)
|
|
||||||
AllMinds.Add(mind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,7 +1,4 @@
|
|||||||
using Content.Server.Mind.Components;
|
using Robust.Server.Player;
|
||||||
using Content.Server.Players;
|
|
||||||
using Robust.Server.Player;
|
|
||||||
using Robust.Shared.Players;
|
|
||||||
using Robust.Shared.Toolshed;
|
using Robust.Shared.Toolshed;
|
||||||
using Robust.Shared.Toolshed.Errors;
|
using Robust.Shared.Toolshed.Errors;
|
||||||
using Robust.Shared.Toolshed.Syntax;
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
@@ -17,20 +14,17 @@ public sealed class MindCommand : ToolshedCommand
|
|||||||
private MindSystem? _mind;
|
private MindSystem? _mind;
|
||||||
|
|
||||||
[CommandImplementation("get")]
|
[CommandImplementation("get")]
|
||||||
public Mind? Get([PipedArgument] IPlayerSession session)
|
public MindComponent? Get([PipedArgument] IPlayerSession session)
|
||||||
{
|
{
|
||||||
return session.ContentData()?.Mind;
|
_mind ??= GetSys<MindSystem>();
|
||||||
|
return _mind.TryGetMind(session, out _, out var mind) ? mind : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandImplementation("get")]
|
[CommandImplementation("get")]
|
||||||
public Mind? Get([PipedArgument] EntityUid ent)
|
public MindComponent? Get([PipedArgument] EntityUid ent)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindContainerComponent>(ent, out var container))
|
_mind ??= GetSys<MindSystem>();
|
||||||
{
|
return _mind.TryGetMind(ent, out _, out var mind) ? mind : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return container.Mind;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandImplementation("control")]
|
[CommandImplementation("control")]
|
||||||
@@ -48,15 +42,13 @@ public sealed class MindCommand : ToolshedCommand
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
if (!_mind.TryGetMind(player, out var mindId, out var mind))
|
||||||
|
|
||||||
if (mind is null)
|
|
||||||
{
|
{
|
||||||
ctx.ReportError(new SessionHasNoEntityError(player));
|
ctx.ReportError(new SessionHasNoEntityError(player));
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
_mind.TransferTo(mind, target);
|
_mind.TransferTo(mindId, target, mind: mind);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public sealed class TransferMindOnGibSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnGib(EntityUid uid, TransferMindOnGibComponent component, BeingGibbedEvent args)
|
private void OnGib(EntityUid uid, TransferMindOnGibComponent component, BeingGibbedEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<MindContainerComponent>(uid, out var mindcomp) || mindcomp.Mind == null)
|
if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var validParts = args.GibbedParts.Where(p => _tag.HasTag(p, component.TargetTag)).ToHashSet();
|
var validParts = args.GibbedParts.Where(p => _tag.HasTag(p, component.TargetTag)).ToHashSet();
|
||||||
@@ -33,6 +33,6 @@ public sealed class TransferMindOnGibSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var ent = _random.Pick(validParts);
|
var ent = _random.Pick(validParts);
|
||||||
_mindSystem.TransferTo(mindcomp.Mind, ent);
|
_mindSystem.TransferTo(mindId, ent, mind: mind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
using Content.Server.Morgue.Components;
|
|
||||||
using Content.Shared.Morgue;
|
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
using Content.Server.Storage.Components;
|
|
||||||
using Content.Shared.Verbs;
|
|
||||||
using Content.Shared.Database;
|
|
||||||
using Content.Shared.Interaction.Events;
|
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Shared.Popups;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Morgue.Components;
|
||||||
|
using Content.Server.Storage.Components;
|
||||||
using Content.Server.Storage.EntitySystems;
|
using Content.Server.Storage.EntitySystems;
|
||||||
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.IdentityManagement;
|
||||||
|
using Content.Shared.Interaction.Events;
|
||||||
|
using Content.Shared.Morgue;
|
||||||
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Standing;
|
using Content.Shared.Standing;
|
||||||
using Content.Shared.Storage;
|
using Content.Shared.Storage;
|
||||||
using Content.Shared.IdentityManagement;
|
|
||||||
using Content.Shared.Storage.Components;
|
using Content.Shared.Storage.Components;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
namespace Content.Server.Morgue;
|
namespace Content.Server.Morgue;
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ public sealed class CrematoriumSystem : EntitySystem
|
|||||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
[Dependency] private readonly StandingStateSystem _standing = default!;
|
[Dependency] private readonly StandingStateSystem _standing = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -141,9 +142,9 @@ public sealed class CrematoriumSystem : EntitySystem
|
|||||||
args.SetHandled(SuicideKind.Heat);
|
args.SetHandled(SuicideKind.Heat);
|
||||||
|
|
||||||
var victim = args.Victim;
|
var victim = args.Victim;
|
||||||
if (TryComp(victim, out ActorComponent? actor) && actor.PlayerSession.ContentData()?.Mind is { } mind)
|
if (TryComp(victim, out ActorComponent? actor) && _minds.TryGetMind(victim, out var mindId, out var mind))
|
||||||
{
|
{
|
||||||
_ticker.OnGhostAttempt(mind, false);
|
_ticker.OnGhostAttempt(mindId, false, mind: mind);
|
||||||
|
|
||||||
if (mind.OwnedEntity is { Valid: true } entity)
|
if (mind.OwnedEntity is { Valid: true } entity)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -25,15 +24,14 @@ namespace Content.Server.Objectives.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mgr = IoCManager.Resolve<IPlayerManager>();
|
var mgr = IoCManager.Resolve<IPlayerManager>();
|
||||||
if (!mgr.TryGetPlayerDataByUsername(args[0], out var data))
|
if (!mgr.TryGetSessionByUsername(args[0], out var data))
|
||||||
{
|
{
|
||||||
shell.WriteLine("Can't find the playerdata.");
|
shell.WriteLine("Can't find the playerdata.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var minds = _entityManager.System<MindSystem>();
|
||||||
var mind = data.ContentData()?.Mind;
|
if (!minds.TryGetMind(data, out var mindId, out var mind))
|
||||||
if (mind == null)
|
|
||||||
{
|
{
|
||||||
shell.WriteLine("Can't find the mind.");
|
shell.WriteLine("Can't find the mind.");
|
||||||
return;
|
return;
|
||||||
@@ -47,12 +45,10 @@ namespace Content.Server.Objectives.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mindSystem = _entityManager.System<MindSystem>();
|
var mindSystem = _entityManager.System<MindSystem>();
|
||||||
|
if (!mindSystem.TryAddObjective(mindId, mind, objectivePrototype))
|
||||||
if (!mindSystem.TryAddObjective(mind, objectivePrototype))
|
|
||||||
{
|
{
|
||||||
shell.WriteLine("Objective requirements dont allow that objective to be added.");
|
shell.WriteLine("Objective requirements dont allow that objective to be added.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Players;
|
using Content.Server.Mind;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -10,39 +10,38 @@ namespace Content.Server.Objectives.Commands
|
|||||||
[AdminCommand(AdminFlags.Logs)]
|
[AdminCommand(AdminFlags.Logs)]
|
||||||
public sealed class ListObjectivesCommand : LocalizedCommands
|
public sealed class ListObjectivesCommand : LocalizedCommands
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entities = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _players = default!;
|
||||||
|
|
||||||
public override string Command => "lsobjectives";
|
public override string Command => "lsobjectives";
|
||||||
|
|
||||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var player = shell.Player as IPlayerSession;
|
var player = shell.Player as IPlayerSession;
|
||||||
IPlayerData? data;
|
if (player == null || !_players.TryGetSessionByUsername(args[0], out player))
|
||||||
if (args.Length == 0 && player != null)
|
|
||||||
{
|
|
||||||
data = player.Data;
|
|
||||||
}
|
|
||||||
else if (player == null || !IoCManager.Resolve<IPlayerManager>().TryGetPlayerDataByUsername(args[0], out data))
|
|
||||||
{
|
{
|
||||||
shell.WriteError(LocalizationManager.GetString("shell-target-player-does-not-exist"));
|
shell.WriteError(LocalizationManager.GetString("shell-target-player-does-not-exist"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mind = data.ContentData()?.Mind;
|
var minds = _entities.System<MindSystem>();
|
||||||
if (mind == null)
|
if (!minds.TryGetMind(player, out _, out var mind))
|
||||||
{
|
{
|
||||||
shell.WriteError(LocalizationManager.GetString("shell-target-entity-does-not-have-message", ("missing", "mind")));
|
shell.WriteError(LocalizationManager.GetString("shell-target-entity-does-not-have-message", ("missing", "mind")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
shell.WriteLine($"Objectives for player {data.UserId}:");
|
shell.WriteLine($"Objectives for player {player.UserId}:");
|
||||||
var objectives = mind.AllObjectives.ToList();
|
var objectives = mind.AllObjectives.ToList();
|
||||||
if (objectives.Count == 0)
|
if (objectives.Count == 0)
|
||||||
{
|
{
|
||||||
shell.WriteLine("None.");
|
shell.WriteLine("None.");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < objectives.Count; i++)
|
for (var i = 0; i < objectives.Count; i++)
|
||||||
{
|
{
|
||||||
shell.WriteLine($"- [{i}] {objectives[i].Conditions[0].Title}");
|
shell.WriteLine($"- [{i}] {objectives[i].Conditions[0].Title}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Players;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -24,30 +23,29 @@ namespace Content.Server.Objectives.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mgr = IoCManager.Resolve<IPlayerManager>();
|
var mgr = IoCManager.Resolve<IPlayerManager>();
|
||||||
if (mgr.TryGetPlayerDataByUsername(args[0], out var data))
|
var minds = _entityManager.System<MindSystem>();
|
||||||
|
if (!mgr.TryGetSessionByUsername(args[0], out var session))
|
||||||
{
|
{
|
||||||
var mind = data.ContentData()?.Mind;
|
shell.WriteLine("Can't find the playerdata.");
|
||||||
if (mind == null)
|
return;
|
||||||
{
|
}
|
||||||
shell.WriteLine("Can't find the mind.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (int.TryParse(args[1], out var i))
|
if (!minds.TryGetMind(session, out _, out var mind))
|
||||||
{
|
{
|
||||||
var mindSystem = _entityManager.System<MindSystem>();
|
shell.WriteLine("Can't find the mind.");
|
||||||
shell.WriteLine(mindSystem.TryRemoveObjective(mind, i)
|
return;
|
||||||
? "Objective successfully removed!"
|
}
|
||||||
: "Objective removing failed. Maybe the index is out of bounds? Check lsobjectives!");
|
|
||||||
}
|
if (int.TryParse(args[1], out var i))
|
||||||
else
|
{
|
||||||
{
|
var mindSystem = _entityManager.System<MindSystem>();
|
||||||
shell.WriteLine($"Invalid index {args[1]}!");
|
shell.WriteLine(mindSystem.TryRemoveObjective(mind, i)
|
||||||
}
|
? "Objective successfully removed!"
|
||||||
|
: "Objective removing failed. Maybe the index is out of bounds? Check lsobjectives!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
shell.WriteLine("Can't find the playerdata.");
|
shell.WriteLine($"Invalid index {args[1]}!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class DieCondition : IObjectiveCondition
|
public sealed partial class DieCondition : IObjectiveCondition
|
||||||
{
|
{
|
||||||
private Mind.Mind? _mind;
|
private MindComponent? _mind;
|
||||||
|
|
||||||
public IObjectiveCondition GetAssigned(Mind.Mind mind)
|
public IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
return new DieCondition {_mind = mind};
|
return new DieCondition { _mind = mind };
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title => Loc.GetString("objective-condition-die-title");
|
public string Title => Loc.GetString("objective-condition-die-title");
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class EscapeShuttleCondition : IObjectiveCondition
|
public sealed partial class EscapeShuttleCondition : IObjectiveCondition
|
||||||
{
|
{
|
||||||
private Mind.Mind? _mind;
|
// TODO refactor all of this to be ecs
|
||||||
|
private MindComponent? _mind;
|
||||||
|
|
||||||
public IObjectiveCondition GetAssigned(Mind.Mind mind)
|
public IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
return new EscapeShuttleCondition {
|
return new EscapeShuttleCondition
|
||||||
|
{
|
||||||
_mind = mind,
|
_mind = mind,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Server.Shuttles.Systems;
|
using Content.Server.Shuttles.Systems;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
@@ -10,10 +11,14 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
public abstract class KillPersonCondition : IObjectiveCondition
|
public abstract class KillPersonCondition : IObjectiveCondition
|
||||||
{
|
{
|
||||||
|
// TODO refactor all of this to be ecs
|
||||||
protected IEntityManager EntityManager => IoCManager.Resolve<IEntityManager>();
|
protected IEntityManager EntityManager => IoCManager.Resolve<IEntityManager>();
|
||||||
protected MobStateSystem MobStateSystem => EntityManager.EntitySysManager.GetEntitySystem<MobStateSystem>();
|
protected MindSystem Minds => EntityManager.System<MindSystem>();
|
||||||
protected Mind.Mind? Target;
|
protected JobSystem Jobs => EntityManager.System<JobSystem>();
|
||||||
public abstract IObjectiveCondition GetAssigned(Mind.Mind mind);
|
protected MobStateSystem MobStateSystem => EntityManager.System<MobStateSystem>();
|
||||||
|
protected EntityUid? TargetMindId;
|
||||||
|
protected MindComponent? TargetMind => EntityManager.GetComponentOrNull<MindComponent>(TargetMindId);
|
||||||
|
public abstract IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the target must be truly dead, ignores missing evac.
|
/// Whether the target must be truly dead, ignores missing evac.
|
||||||
@@ -24,10 +29,11 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var targetName = Target?.CharacterName ?? "Unknown";
|
var mind = TargetMind;
|
||||||
var jobName = Target?.CurrentJob?.Name ?? "Unknown";
|
var targetName = mind?.CharacterName ?? "Unknown";
|
||||||
|
var jobName = Jobs.MindTryGetJobName(TargetMindId);
|
||||||
|
|
||||||
if (Target == null)
|
if (TargetMind == null)
|
||||||
return Loc.GetString("objective-condition-kill-person-title", ("targetName", targetName), ("job", jobName));
|
return Loc.GetString("objective-condition-kill-person-title", ("targetName", targetName), ("job", jobName));
|
||||||
|
|
||||||
return Loc.GetString("objective-condition-kill-person-title", ("targetName", targetName), ("job", jobName));
|
return Loc.GetString("objective-condition-kill-person-title", ("targetName", targetName), ("job", jobName));
|
||||||
@@ -42,12 +48,12 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Target == null || Target.OwnedEntity == null)
|
if (TargetMindId == null || TargetMind?.OwnedEntity == null)
|
||||||
return 1f;
|
return 1f;
|
||||||
|
|
||||||
var entMan = IoCManager.Resolve<EntityManager>();
|
var entMan = IoCManager.Resolve<EntityManager>();
|
||||||
var mindSystem = entMan.System<MindSystem>();
|
var mindSystem = entMan.System<MindSystem>();
|
||||||
if (mindSystem.IsCharacterDeadIc(Target))
|
if (mindSystem.IsCharacterDeadIc(TargetMind))
|
||||||
return 1f;
|
return 1f;
|
||||||
|
|
||||||
if (RequireDead)
|
if (RequireDead)
|
||||||
@@ -60,7 +66,7 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|
|
||||||
// target is escaping so you fail
|
// target is escaping so you fail
|
||||||
var emergencyShuttle = entMan.System<EmergencyShuttleSystem>();
|
var emergencyShuttle = entMan.System<EmergencyShuttleSystem>();
|
||||||
if (emergencyShuttle.IsTargetEscaping(Target.OwnedEntity.Value))
|
if (emergencyShuttle.IsTargetEscaping(TargetMind.OwnedEntity.Value))
|
||||||
return 0f;
|
return 0f;
|
||||||
|
|
||||||
// evac has left without the target, greentext since the target is afk in space with a full oxygen tank and coordinates off.
|
// evac has left without the target, greentext since the target is afk in space with a full oxygen tank and coordinates off.
|
||||||
@@ -76,7 +82,7 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|
|
||||||
public bool Equals(IObjectiveCondition? other)
|
public bool Equals(IObjectiveCondition? other)
|
||||||
{
|
{
|
||||||
return other is KillPersonCondition kpc && Equals(Target, kpc.Target);
|
return other is KillPersonCondition kpc && Equals(TargetMindId, kpc.TargetMindId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
@@ -89,7 +95,7 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return Target?.GetHashCode() ?? 0;
|
return TargetMindId?.GetHashCode() ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,43 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
using Content.Server.Roles;
|
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Conditions;
|
namespace Content.Server.Objectives.Conditions;
|
||||||
|
|
||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class KillRandomHeadCondition : KillPersonCondition
|
public sealed partial class KillRandomHeadCondition : KillPersonCondition
|
||||||
{
|
{
|
||||||
public override IObjectiveCondition GetAssigned(Mind.Mind mind)
|
// TODO refactor all of this to be ecs
|
||||||
|
public override IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
RequireDead = true;
|
RequireDead = true;
|
||||||
|
|
||||||
var allHumans = EntityManager.EntityQuery<MindContainerComponent>(true).Where(mc =>
|
var allHumans = EntityManager.EntityQuery<MindContainerComponent>(true).Where(mc =>
|
||||||
{
|
{
|
||||||
var entity = mc.Mind?.OwnedEntity;
|
var entity = EntityManager.GetComponentOrNull<MindComponent>(mc.Mind)?.OwnedEntity;
|
||||||
|
|
||||||
if (entity == default)
|
if (entity == default)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return EntityManager.TryGetComponent(entity, out MobStateComponent? mobState) &&
|
return EntityManager.TryGetComponent(entity, out MobStateComponent? mobState) &&
|
||||||
MobStateSystem.IsAlive(entity.Value, mobState) &&
|
MobStateSystem.IsAlive(entity.Value, mobState) &&
|
||||||
mc.Mind != mind;
|
mc.Mind != mindId;
|
||||||
}).Select(mc => mc.Mind).ToList();
|
}).Select(mc => mc.Mind).ToList();
|
||||||
|
|
||||||
if (allHumans.Count == 0)
|
if (allHumans.Count == 0)
|
||||||
return new DieCondition(); // I guess I'll die
|
return new DieCondition(); // I guess I'll die
|
||||||
|
|
||||||
var allHeads = allHumans.Where(mind => mind?.AllRoles.Any(role => {
|
var allHeads = allHumans
|
||||||
if (role is not Job job)
|
.Where(mind => Jobs.MindTryGetJob(mind, out _, out var prototype) && prototype.RequireAdminNotify)
|
||||||
return false;
|
.ToList();
|
||||||
|
|
||||||
// basically a command department check, pretty sussy but whatever
|
|
||||||
return job.Prototype.RequireAdminNotify;
|
|
||||||
}) ?? false).ToList();
|
|
||||||
|
|
||||||
if (allHeads.Count == 0)
|
if (allHeads.Count == 0)
|
||||||
allHeads = allHumans; // fallback to non-head target
|
allHeads = allHumans; // fallback to non-head target
|
||||||
|
|
||||||
return new KillRandomHeadCondition {Target = IoCManager.Resolve<IRobustRandom>().Pick(allHeads)};
|
return new KillRandomHeadCondition { TargetMindId = IoCManager.Resolve<IRobustRandom>().Pick(allHeads) };
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Description => Loc.GetString("objective-condition-kill-head-description");
|
public string Description => Loc.GetString("objective-condition-kill-head-description");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
@@ -9,27 +10,27 @@ namespace Content.Server.Objectives.Conditions;
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class KillRandomPersonCondition : KillPersonCondition
|
public sealed partial class KillRandomPersonCondition : KillPersonCondition
|
||||||
{
|
{
|
||||||
public override IObjectiveCondition GetAssigned(Mind.Mind mind)
|
public override IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
var allHumans = new List<Mind.Mind>();
|
var allHumans = new List<EntityUid>();
|
||||||
var query = EntityManager.EntityQuery<MindContainerComponent, HumanoidAppearanceComponent>(true);
|
var query = EntityManager.EntityQuery<MindContainerComponent, HumanoidAppearanceComponent>(true);
|
||||||
foreach (var (mc, _) in query)
|
foreach (var (mc, _) in query)
|
||||||
{
|
{
|
||||||
var entity = mc.Mind?.OwnedEntity;
|
var entity = EntityManager.GetComponentOrNull<MindComponent>(mc.Mind)?.OwnedEntity;
|
||||||
if (entity == default)
|
if (entity == default)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent(entity, out MobStateComponent? mobState) &&
|
if (EntityManager.TryGetComponent(entity, out MobStateComponent? mobState) &&
|
||||||
MobStateSystem.IsAlive(entity.Value, mobState) &&
|
MobStateSystem.IsAlive(entity.Value, mobState) &&
|
||||||
mc.Mind != mind && mc.Mind != null)
|
mc.Mind != mindId && mc.Mind != null)
|
||||||
{
|
{
|
||||||
allHumans.Add(mc.Mind);
|
allHumans.Add(mc.Mind.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allHumans.Count == 0)
|
if (allHumans.Count == 0)
|
||||||
return new DieCondition(); // I guess I'll die
|
return new DieCondition(); // I guess I'll die
|
||||||
|
|
||||||
return new KillRandomPersonCondition {Target = IoCManager.Resolve<IRobustRandom>().Pick(allHumans)};
|
return new KillRandomPersonCondition {TargetMindId = IoCManager.Resolve<IRobustRandom>().Pick(allHumans)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Objectives.Interfaces;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using Content.Server.GameTicking.Rules;
|
using Content.Server.GameTicking.Rules;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Conditions
|
namespace Content.Server.Objectives.Conditions
|
||||||
{
|
{
|
||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class RandomTraitorAliveCondition : IObjectiveCondition
|
public sealed partial class RandomTraitorAliveCondition : IObjectiveCondition
|
||||||
{
|
{
|
||||||
private Mind.Mind? _target;
|
private EntityUid? _target;
|
||||||
|
|
||||||
public IObjectiveCondition GetAssigned(Mind.Mind mind)
|
public IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
var entityMgr = IoCManager.Resolve<IEntityManager>();
|
var entityMgr = IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
var traitors = entityMgr.EntitySysManager.GetEntitySystem<TraitorRuleSystem>().GetOtherTraitorsAliveAndConnected(mind).ToList();
|
var traitors = entityMgr.System<TraitorRuleSystem>().GetOtherTraitorMindsAliveAndConnected(mind).ToList();
|
||||||
|
|
||||||
if (traitors.Count == 0)
|
if (traitors.Count == 0)
|
||||||
return new EscapeShuttleCondition(); //You were made a traitor by admins, and are the first/only.
|
return new EscapeShuttleCondition(); //You were made a traitor by admins, and are the first/only.
|
||||||
return new RandomTraitorAliveCondition { _target = IoCManager.Resolve<IRobustRandom>().Pick(traitors).Mind };
|
return new RandomTraitorAliveCondition { _target = IoCManager.Resolve<IRobustRandom>().Pick(traitors).Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title
|
public string Title
|
||||||
@@ -27,13 +29,19 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
var targetName = string.Empty;
|
var targetName = string.Empty;
|
||||||
var jobName = _target?.CurrentJob?.Name ?? "Unknown";
|
var ents = IoCManager.Resolve<IEntityManager>();
|
||||||
|
var jobs = ents.System<JobSystem>();
|
||||||
|
var jobName = jobs.MindTryGetJobName(_target);
|
||||||
|
|
||||||
if (_target == null)
|
if (_target == null)
|
||||||
return Loc.GetString("objective-condition-other-traitor-alive-title", ("targetName", targetName), ("job", jobName));
|
return Loc.GetString("objective-condition-other-traitor-alive-title", ("targetName", targetName), ("job", jobName));
|
||||||
|
|
||||||
if (_target.OwnedEntity is {Valid: true} owned)
|
var minds = ents.System<MindSystem>();
|
||||||
targetName = IoCManager.Resolve<IEntityManager>().GetComponent<MetaDataComponent>(owned).EntityName;
|
if (minds.TryGetMind(_target.Value, out _, out var mind) &&
|
||||||
|
mind.OwnedEntity is { Valid: true } owned)
|
||||||
|
{
|
||||||
|
targetName = ents.GetComponent<MetaDataComponent>(owned).EntityName;
|
||||||
|
}
|
||||||
|
|
||||||
return Loc.GetString("objective-condition-other-traitor-alive-title", ("targetName", targetName), ("job", jobName));
|
return Loc.GetString("objective-condition-other-traitor-alive-title", ("targetName", targetName), ("job", jobName));
|
||||||
}
|
}
|
||||||
@@ -49,7 +57,11 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
var entityManager = IoCManager.Resolve<EntityManager>();
|
var entityManager = IoCManager.Resolve<EntityManager>();
|
||||||
var mindSystem = entityManager.System<MindSystem>();
|
var mindSystem = entityManager.System<MindSystem>();
|
||||||
return _target == null || !mindSystem.IsCharacterDeadIc(_target) ? 1f : 0f;
|
return _target == null ||
|
||||||
|
!mindSystem.TryGetMind(_target.Value, out _, out var mind) ||
|
||||||
|
!mindSystem.IsCharacterDeadIc(mind)
|
||||||
|
? 1f
|
||||||
|
: 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.GameTicking.Rules;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Content.Server.GameTicking.Rules;
|
|
||||||
using Content.Server.Roles;
|
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Conditions
|
namespace Content.Server.Objectives.Conditions
|
||||||
{
|
{
|
||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class RandomTraitorProgressCondition : IObjectiveCondition
|
public sealed partial class RandomTraitorProgressCondition : IObjectiveCondition
|
||||||
{
|
{
|
||||||
private Mind.Mind? _target;
|
// TODO ecs all of this
|
||||||
|
private EntityUid? _target;
|
||||||
|
|
||||||
public IObjectiveCondition GetAssigned(Mind.Mind mind)
|
public IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
//todo shit of a fuck
|
//todo shit of a fuck
|
||||||
var entityMgr = IoCManager.Resolve<IEntityManager>();
|
var entityMgr = IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
var traitors = entityMgr.EntitySysManager.GetEntitySystem<TraitorRuleSystem>().GetOtherTraitorsAliveAndConnected(mind).ToList();
|
var traitors = entityMgr.System<TraitorRuleSystem>().GetOtherTraitorMindsAliveAndConnected(mind).ToList();
|
||||||
List<TraitorRole> removeList = new();
|
List<EntityUid> removeList = new();
|
||||||
|
|
||||||
foreach (var traitor in traitors)
|
foreach (var traitor in traitors)
|
||||||
{
|
{
|
||||||
@@ -28,7 +30,7 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
if (condition is RandomTraitorProgressCondition)
|
if (condition is RandomTraitorProgressCondition)
|
||||||
{
|
{
|
||||||
removeList.Add(traitor);
|
removeList.Add(traitor.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,11 +38,11 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|
|
||||||
foreach (var traitor in removeList)
|
foreach (var traitor in removeList)
|
||||||
{
|
{
|
||||||
traitors.Remove(traitor);
|
traitors.RemoveAll(t => t.Id == traitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traitors.Count == 0) return new EscapeShuttleCondition{}; //You were made a traitor by admins, and are the first/only.
|
if (traitors.Count == 0) return new EscapeShuttleCondition{}; //You were made a traitor by admins, and are the first/only.
|
||||||
return new RandomTraitorProgressCondition { _target = IoCManager.Resolve<IRobustRandom>().Pick(traitors).Mind };
|
return new RandomTraitorProgressCondition { _target = IoCManager.Resolve<IRobustRandom>().Pick(traitors).Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title
|
public string Title
|
||||||
@@ -48,13 +50,18 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
var targetName = string.Empty;
|
var targetName = string.Empty;
|
||||||
var jobName = _target?.CurrentJob?.Name ?? "Unknown";
|
var entities = IoCManager.Resolve<IEntityManager>();
|
||||||
|
var jobs = entities.System<JobSystem>();
|
||||||
|
var jobName = jobs.MindTryGetJobName(_target);
|
||||||
|
|
||||||
if (_target == null)
|
if (_target == null)
|
||||||
return Loc.GetString("objective-condition-other-traitor-progress-title", ("targetName", targetName), ("job", jobName));
|
return Loc.GetString("objective-condition-other-traitor-progress-title", ("targetName", targetName), ("job", jobName));
|
||||||
|
|
||||||
if (_target.OwnedEntity is {Valid: true} owned)
|
if (entities.TryGetComponent(_target, out MindComponent? mind) &&
|
||||||
targetName = IoCManager.Resolve<IEntityManager>().GetComponent<MetaDataComponent>(owned).EntityName;
|
mind.OwnedEntity is {Valid: true} owned)
|
||||||
|
{
|
||||||
|
targetName = entities.GetComponent<MetaDataComponent>(owned).EntityName;
|
||||||
|
}
|
||||||
|
|
||||||
return Loc.GetString("objective-condition-other-traitor-progress-title", ("targetName", targetName), ("job", jobName));
|
return Loc.GetString("objective-condition-other-traitor-progress-title", ("targetName", targetName), ("job", jobName));
|
||||||
}
|
}
|
||||||
@@ -66,9 +73,8 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|
|
||||||
public float Progress
|
public float Progress
|
||||||
{
|
{
|
||||||
get {
|
get
|
||||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
{
|
||||||
|
|
||||||
float total = 0f; // how much progress they have
|
float total = 0f; // how much progress they have
|
||||||
float max = 0f; // how much progress is needed for 100%
|
float max = 0f; // how much progress is needed for 100%
|
||||||
|
|
||||||
@@ -78,12 +84,16 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
return 1f;
|
return 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var objective in _target.AllObjectives)
|
var entities = IoCManager.Resolve<IEntityManager>();
|
||||||
|
if (entities.TryGetComponent(_target, out MindComponent? mind))
|
||||||
{
|
{
|
||||||
foreach (var condition in objective.Conditions)
|
foreach (var objective in mind.AllObjectives)
|
||||||
{
|
{
|
||||||
max++; // things can only be up to 100% complete yeah
|
foreach (var condition in objective.Conditions)
|
||||||
total += condition.Progress;
|
{
|
||||||
|
max++; // things can only be up to 100% complete yeah
|
||||||
|
total += condition.Progress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
@@ -12,7 +13,7 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class StealCondition : IObjectiveCondition, ISerializationHooks
|
public sealed partial class StealCondition : IObjectiveCondition, ISerializationHooks
|
||||||
{
|
{
|
||||||
private Mind.Mind? _mind;
|
private EntityUid? _mind;
|
||||||
[DataField("prototype")] private string _prototypeId = string.Empty;
|
[DataField("prototype")] private string _prototypeId = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -21,11 +22,11 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("owner")] private string? _owner = null;
|
[DataField("owner")] private string? _owner = null;
|
||||||
|
|
||||||
public IObjectiveCondition GetAssigned(Mind.Mind mind)
|
public IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
return new StealCondition
|
return new StealCondition
|
||||||
{
|
{
|
||||||
_mind = mind,
|
_mind = mindId,
|
||||||
_prototypeId = _prototypeId,
|
_prototypeId = _prototypeId,
|
||||||
_owner = _owner
|
_owner = _owner
|
||||||
};
|
};
|
||||||
@@ -49,7 +50,6 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var uid = _mind?.OwnedEntity;
|
|
||||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
// TODO make this a container system function
|
// TODO make this a container system function
|
||||||
@@ -59,13 +59,16 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
var managerQuery = entMan.GetEntityQuery<ContainerManagerComponent>();
|
var managerQuery = entMan.GetEntityQuery<ContainerManagerComponent>();
|
||||||
var stack = new Stack<ContainerManagerComponent>();
|
var stack = new Stack<ContainerManagerComponent>();
|
||||||
|
|
||||||
if (!metaQuery.TryGetComponent(_mind?.OwnedEntity, out var meta))
|
if (!entMan.TryGetComponent(_mind, out MindComponent? mind))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!metaQuery.TryGetComponent(mind.OwnedEntity, out var meta))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (meta.EntityPrototype?.ID == _prototypeId)
|
if (meta.EntityPrototype?.ID == _prototypeId)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!managerQuery.TryGetComponent(uid, out var currentManager))
|
if (!managerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
using Robust.Shared.Utility;
|
using Content.Server.Mind;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Interfaces
|
namespace Content.Server.Objectives.Interfaces
|
||||||
{
|
{
|
||||||
|
// TODO refactor all of this to be ecs
|
||||||
public interface IObjectiveCondition : IEquatable<IObjectiveCondition>
|
public interface IObjectiveCondition : IEquatable<IObjectiveCondition>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a copy of the IObjectiveCondition which is assigned to the mind.
|
/// Returns a copy of the IObjectiveCondition which is assigned to the mind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="mindId">Mind id to assign to.</param>
|
||||||
/// <param name="mind">Mind to assign to.</param>
|
/// <param name="mind">Mind to assign to.</param>
|
||||||
/// <returns>The new IObjectiveCondition.</returns>
|
/// <returns>The new IObjectiveCondition.</returns>
|
||||||
IObjectiveCondition GetAssigned(Mind.Mind mind);
|
IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the title of the condition.
|
/// Returns the title of the condition.
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
namespace Content.Server.Objectives.Interfaces
|
using Content.Server.Mind;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives.Interfaces
|
||||||
{
|
{
|
||||||
|
// TODO refactor all of this to be ecs
|
||||||
public interface IObjectiveRequirement
|
public interface IObjectiveRequirement
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks whether or not the entity & its surroundings are valid to be given the objective.
|
/// Checks whether or not the entity & its surroundings are valid to be given the objective.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns true if objective can be given.</returns>
|
/// <returns>Returns true if objective can be given.</returns>
|
||||||
bool CanBeAssigned(Mind.Mind mind);
|
bool CanBeAssigned(EntityUid mindId, MindComponent mind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Content.Server.Objectives.Interfaces
|
|
||||||
{
|
|
||||||
public interface IObjectivesManager
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a randomly picked objective the provided mind is valid for.
|
|
||||||
/// </summary>
|
|
||||||
ObjectivePrototype? GetRandomObjective(Mind.Mind mind, string objectiveGroupProto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +1,28 @@
|
|||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
|
||||||
namespace Content.Server.Objectives
|
namespace Content.Server.Objectives
|
||||||
{
|
{
|
||||||
public sealed class Objective : IEquatable<Objective>
|
public sealed class Objective : IEquatable<Objective>
|
||||||
{
|
{
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public readonly Mind.Mind Mind;
|
public readonly EntityUid MindId;
|
||||||
|
[ViewVariables]
|
||||||
|
public readonly MindComponent Mind;
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public readonly ObjectivePrototype Prototype;
|
public readonly ObjectivePrototype Prototype;
|
||||||
private readonly List<IObjectiveCondition> _conditions = new();
|
private readonly List<IObjectiveCondition> _conditions = new();
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IReadOnlyList<IObjectiveCondition> Conditions => _conditions;
|
public IReadOnlyList<IObjectiveCondition> Conditions => _conditions;
|
||||||
|
|
||||||
public Objective(ObjectivePrototype prototype, Mind.Mind mind)
|
public Objective(ObjectivePrototype prototype, EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
Prototype = prototype;
|
Prototype = prototype;
|
||||||
|
MindId = mindId;
|
||||||
Mind = mind;
|
Mind = mind;
|
||||||
foreach (var condition in prototype.Conditions)
|
foreach (var condition in prototype.Conditions)
|
||||||
{
|
{
|
||||||
_conditions.Add(condition.GetAssigned(mind));
|
_conditions.Add(condition.GetAssigned(mindId, mind));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
@@ -34,27 +35,29 @@ namespace Content.Server.Objectives
|
|||||||
[DataField("difficultyOverride")]
|
[DataField("difficultyOverride")]
|
||||||
private float? _difficultyOverride = null;
|
private float? _difficultyOverride = null;
|
||||||
|
|
||||||
public bool CanBeAssigned(Mind.Mind mind)
|
public bool CanBeAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
foreach (var requirement in _requirements)
|
foreach (var requirement in _requirements)
|
||||||
{
|
{
|
||||||
if (!requirement.CanBeAssigned(mind)) return false;
|
if (!requirement.CanBeAssigned(mindId, mind))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanBeDuplicateAssignment)
|
if (!CanBeDuplicateAssignment)
|
||||||
{
|
{
|
||||||
foreach (var objective in mind.AllObjectives)
|
foreach (var objective in mind.AllObjectives)
|
||||||
{
|
{
|
||||||
if (objective.Prototype.ID == ID) return false;
|
if (objective.Prototype.ID == ID)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Objective GetObjective(Mind.Mind mind)
|
public Objective GetObjective(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
return new(this, mind);
|
return new Objective(this, mindId, mind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
using Content.Server.Objectives.Interfaces;
|
|
||||||
using Content.Shared.Random.Helpers;
|
|
||||||
using Content.Shared.Random;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Server.Objectives
|
|
||||||
{
|
|
||||||
public sealed class ObjectivesManager : IObjectivesManager
|
|
||||||
{
|
|
||||||
[Dependency] private IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private IRobustRandom _random = default!;
|
|
||||||
|
|
||||||
public ObjectivePrototype? GetRandomObjective(Mind.Mind mind, string objectiveGroupProto)
|
|
||||||
{
|
|
||||||
if (!_prototypeManager.TryIndex<WeightedRandomPrototype>(objectiveGroupProto, out var groups))
|
|
||||||
{
|
|
||||||
Logger.Error("Tried to get a random objective, but can't index WeightedRandomPrototype " + objectiveGroupProto);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// yeah the old 'preventing infinite loops' thing wasn't super elegant either and it mislead people on what exactly it did
|
|
||||||
var tries = 0;
|
|
||||||
while (tries < 20)
|
|
||||||
{
|
|
||||||
var groupName = groups.Pick(_random);
|
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex<WeightedRandomPrototype>(groupName, out var group))
|
|
||||||
{
|
|
||||||
Logger.Error("Couldn't index objective group prototype" + groupName);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_prototypeManager.TryIndex<ObjectivePrototype>(group.Pick(_random), out var objective)
|
|
||||||
&& objective.CanBeAssigned(mind))
|
|
||||||
return objective;
|
|
||||||
else
|
|
||||||
tries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
44
Content.Server/Objectives/ObjectivesSystem.cs
Normal file
44
Content.Server/Objectives/ObjectivesSystem.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using Content.Server.Mind;
|
||||||
|
using Content.Shared.Random;
|
||||||
|
using Content.Shared.Random.Helpers;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives;
|
||||||
|
|
||||||
|
public sealed class ObjectivesSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
public ObjectivePrototype? GetRandomObjective(EntityUid mindId, MindComponent mind, string objectiveGroupProto)
|
||||||
|
{
|
||||||
|
if (!_prototypeManager.TryIndex<WeightedRandomPrototype>(objectiveGroupProto, out var groups))
|
||||||
|
{
|
||||||
|
Log.Error("Tried to get a random objective, but can't index WeightedRandomPrototype " + objectiveGroupProto);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO replace whatever the fuck this is with a proper objective selection system
|
||||||
|
// yeah the old 'preventing infinite loops' thing wasn't super elegant either and it mislead people on what exactly it did
|
||||||
|
var tries = 0;
|
||||||
|
while (tries < 20)
|
||||||
|
{
|
||||||
|
var groupName = groups.Pick(_random);
|
||||||
|
|
||||||
|
if (!_prototypeManager.TryIndex<WeightedRandomPrototype>(groupName, out var group))
|
||||||
|
{
|
||||||
|
Log.Error("Couldn't index objective group prototype" + groupName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_prototypeManager.TryIndex<ObjectivePrototype>(group.Pick(_random), out var objective)
|
||||||
|
&& objective.CanBeAssigned(mindId, mind))
|
||||||
|
return objective;
|
||||||
|
else
|
||||||
|
tries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Requirements
|
namespace Content.Server.Objectives.Requirements
|
||||||
{
|
{
|
||||||
@@ -8,7 +9,7 @@ namespace Content.Server.Objectives.Requirements
|
|||||||
[DataField("conditions")]
|
[DataField("conditions")]
|
||||||
private List<string> _incompatibleConditions = new();
|
private List<string> _incompatibleConditions = new();
|
||||||
|
|
||||||
public bool CanBeAssigned(Mind.Mind mind)
|
public bool CanBeAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
foreach (var objective in mind.AllObjectives)
|
foreach (var objective in mind.AllObjectives)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Requirements
|
namespace Content.Server.Objectives.Requirements
|
||||||
{
|
{
|
||||||
@@ -8,7 +9,7 @@ namespace Content.Server.Objectives.Requirements
|
|||||||
[DataField("objectives")]
|
[DataField("objectives")]
|
||||||
private List<string> _incompatibleObjectives = new();
|
private List<string> _incompatibleObjectives = new();
|
||||||
|
|
||||||
public bool CanBeAssigned(Mind.Mind mind)
|
public bool CanBeAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
foreach (var objective in mind.AllObjectives)
|
foreach (var objective in mind.AllObjectives)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Objectives.Interfaces;
|
|
||||||
using Content.Server.GameTicking.Rules;
|
using Content.Server.GameTicking.Rules;
|
||||||
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Requirements
|
namespace Content.Server.Objectives.Requirements
|
||||||
{
|
{
|
||||||
@@ -9,9 +10,9 @@ namespace Content.Server.Objectives.Requirements
|
|||||||
[DataField("traitors")]
|
[DataField("traitors")]
|
||||||
private int _requiredTraitors = 2;
|
private int _requiredTraitors = 2;
|
||||||
|
|
||||||
public bool CanBeAssigned(Mind.Mind mind)
|
public bool CanBeAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
return EntitySystem.Get<TraitorRuleSystem>().GetOtherTraitorsAliveAndConnected(mind).Count >= _requiredTraitors;
|
return EntitySystem.Get<TraitorRuleSystem>().GetOtherTraitorMindsAliveAndConnected(mind).Count >= _requiredTraitors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using Content.Shared.Roles;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
|
using Content.Shared.Roles;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Requirements
|
namespace Content.Server.Objectives.Requirements
|
||||||
{
|
{
|
||||||
|
|
||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class NotRoleRequirement : IObjectiveRequirement
|
public sealed partial class NotRoleRequirement : IObjectiveRequirement
|
||||||
{
|
{
|
||||||
@@ -14,12 +15,14 @@ namespace Content.Server.Objectives.Requirements
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This requirement is met if the traitor is NOT the roleId, and fails if they are.
|
/// This requirement is met if the traitor is NOT the roleId, and fails if they are.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanBeAssigned(Mind.Mind mind)
|
public bool CanBeAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
if (mind.CurrentJob == null) // no job no problems
|
// TODO ECS this shit i keep seeing shitcode everywhere
|
||||||
|
var entities = IoCManager.Resolve<IEntityManager>();
|
||||||
|
if (!entities.TryGetComponent(mindId, out JobComponent? job))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return (mind.CurrentJob.Prototype.ID != _roleId);
|
return job.PrototypeId != _roleId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Content.Server.Roles;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using TraitorRole = Content.Server.Roles.TraitorRole;
|
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Requirements
|
namespace Content.Server.Objectives.Requirements
|
||||||
{
|
{
|
||||||
@@ -9,11 +9,10 @@ namespace Content.Server.Objectives.Requirements
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public sealed partial class TraitorRequirement : IObjectiveRequirement
|
public sealed partial class TraitorRequirement : IObjectiveRequirement
|
||||||
{
|
{
|
||||||
public bool CanBeAssigned(Mind.Mind mind)
|
public bool CanBeAssigned(EntityUid mindId, MindComponent mind)
|
||||||
{
|
{
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
var roleSystem = IoCManager.Resolve<IEntityManager>().System<RoleSystem>();
|
||||||
var mindSystem = entityManager.System<MindSystem>();
|
return roleSystem.MindHasRole<TraitorRoleComponent>(mindId);
|
||||||
return mindSystem.HasRole<TraitorRole>(mind);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,14 +77,17 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
|
|||||||
return state.CurrentState is MobState.Alive or MobState.Critical;
|
return state.CurrentState is MobState.Alive or MobState.Critical;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> GetTimedRoles(Mind.Mind mind)
|
public IEnumerable<string> GetTimedRoles(EntityUid mindId)
|
||||||
{
|
{
|
||||||
foreach (var role in mind.AllRoles)
|
var ev = new MindGetAllRolesEvent(new List<RoleInfo>());
|
||||||
|
RaiseLocalEvent(ref ev);
|
||||||
|
|
||||||
|
foreach (var role in ev.Roles)
|
||||||
{
|
{
|
||||||
if (role is not IRoleTimer timer)
|
if (string.IsNullOrWhiteSpace(role.PlayTimeTrackerId))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
yield return _prototypes.Index<PlayTimeTrackerPrototype>(timer.Timer).ID;
|
yield return _prototypes.Index<PlayTimeTrackerPrototype>(role.PlayTimeTrackerId).ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +98,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
|
|||||||
if (contentData?.Mind == null)
|
if (contentData?.Mind == null)
|
||||||
return Enumerable.Empty<string>();
|
return Enumerable.Empty<string>();
|
||||||
|
|
||||||
return GetTimedRoles(contentData.Mind);
|
return GetTimedRoles(contentData.Mind.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRoleRemove(RoleRemovedEvent ev)
|
private void OnRoleRemove(RoleRemovedEvent ev)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Content.Server.Players
|
|||||||
/// DO NOT DIRECTLY SET THIS UNLESS YOU KNOW WHAT YOU'RE DOING.
|
/// DO NOT DIRECTLY SET THIS UNLESS YOU KNOW WHAT YOU'RE DOING.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables, Access(typeof(MindSystem), typeof(GameTicker))]
|
[ViewVariables, Access(typeof(MindSystem), typeof(GameTicker))]
|
||||||
public Mind.Mind? Mind { get; set; }
|
public EntityUid? Mind { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, the player is an admin and they explicitly de-adminned mid-game,
|
/// If true, the player is an admin and they explicitly de-adminned mid-game,
|
||||||
@@ -65,7 +65,7 @@ namespace Content.Server.Players
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the mind that is associated with this player.
|
/// Gets the mind that is associated with this player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Mind.Mind? GetMind(this IPlayerSession session)
|
public static EntityUid? GetMind(this IPlayerSession session)
|
||||||
{
|
{
|
||||||
return session.Data.ContentData()?.Mind;
|
return session.Data.ContentData()?.Mind;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Players;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Pointing.Components;
|
using Content.Server.Pointing.Components;
|
||||||
using Content.Server.Visible;
|
using Content.Server.Visible;
|
||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
@@ -38,6 +38,7 @@ namespace Content.Server.Pointing.EntitySystems
|
|||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
[Dependency] private readonly VisibilitySystem _visibilitySystem = default!;
|
[Dependency] private readonly VisibilitySystem _visibilitySystem = default!;
|
||||||
|
[Dependency] private readonly MindSystem _minds = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
|
|
||||||
private static readonly TimeSpan PointDelay = TimeSpan.FromSeconds(0.5f);
|
private static readonly TimeSpan PointDelay = TimeSpan.FromSeconds(0.5f);
|
||||||
@@ -169,7 +170,8 @@ namespace Content.Server.Pointing.EntitySystems
|
|||||||
// Get players that are in range and whose visibility layer matches the arrow's.
|
// Get players that are in range and whose visibility layer matches the arrow's.
|
||||||
bool ViewerPredicate(IPlayerSession playerSession)
|
bool ViewerPredicate(IPlayerSession playerSession)
|
||||||
{
|
{
|
||||||
if (playerSession.ContentData()?.Mind?.CurrentEntity is not {Valid: true} ent ||
|
if (!_minds.TryGetMind(playerSession, out _, out var mind) ||
|
||||||
|
mind.CurrentEntity is not { Valid: true } ent ||
|
||||||
!TryComp(ent, out EyeComponent? eyeComp) ||
|
!TryComp(ent, out EyeComponent? eyeComp) ||
|
||||||
(eyeComp.VisibilityMask & layer) == 0)
|
(eyeComp.VisibilityMask & layer) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Content.Server.Humanoid;
|
|||||||
using Content.Server.Inventory;
|
using Content.Server.Inventory;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Mind.Commands;
|
using Content.Server.Mind.Commands;
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Nutrition;
|
using Content.Server.Nutrition;
|
||||||
using Content.Server.Polymorph.Components;
|
using Content.Server.Polymorph.Components;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
@@ -229,8 +228,8 @@ namespace Content.Server.Polymorph.Systems
|
|||||||
_humanoid.CloneAppearance(uid, child);
|
_humanoid.CloneAppearance(uid, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mindSystem.TryGetMind(uid, out var mind))
|
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||||
_mindSystem.TransferTo(mind, child);
|
_mindSystem.TransferTo(mindId, child, mind: mind);
|
||||||
|
|
||||||
//Ensures a map to banish the entity to
|
//Ensures a map to banish the entity to
|
||||||
EnsurePausesdMap();
|
EnsurePausesdMap();
|
||||||
@@ -303,8 +302,8 @@ namespace Content.Server.Polymorph.Systems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mindSystem.TryGetMind(uid, out var mind))
|
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||||
_mindSystem.TransferTo(mind, parent);
|
_mindSystem.TransferTo(mindId, parent, mind: mind);
|
||||||
|
|
||||||
// if an item polymorph was picked up, put it back down after reverting
|
// if an item polymorph was picked up, put it back down after reverting
|
||||||
Transform(parent).AttachToGridOrMap();
|
Transform(parent).AttachToGridOrMap();
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.Mind;
|
|
||||||
|
|
||||||
namespace Content.Server.Roles
|
namespace Content.Server.Roles
|
||||||
{
|
{
|
||||||
@@ -50,15 +49,14 @@ namespace Content.Server.Roles
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mind.AllRoles.Any(r => r.Name == jobPrototype.Name))
|
var jobs = _entityManager.System<JobSystem>();
|
||||||
|
if (jobs.MindHasJobWithId(mind, jobPrototype.Name))
|
||||||
{
|
{
|
||||||
shell.WriteLine("Mind already has that role");
|
shell.WriteLine("Mind already has that role");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var role = new Job(mind, jobPrototype);
|
jobs.MindAddJob(mind.Value, args[1]);
|
||||||
var mindSystem = _entityManager.System<MindSystem>();
|
|
||||||
mindSystem.AddRole(mind, role);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using Content.Shared.Roles;
|
|
||||||
|
|
||||||
namespace Content.Server.Roles;
|
|
||||||
|
|
||||||
public abstract class AntagonistRole : Role
|
|
||||||
{
|
|
||||||
public AntagPrototype Prototype { get; }
|
|
||||||
|
|
||||||
public override string Name { get; }
|
|
||||||
|
|
||||||
public override bool Antagonist { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// .ctor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mind">A mind (player)</param>
|
|
||||||
/// <param name="antagPrototype">Antagonist prototype</param>
|
|
||||||
protected AntagonistRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind)
|
|
||||||
{
|
|
||||||
Prototype = antagPrototype;
|
|
||||||
Name = Loc.GetString(antagPrototype.Name);
|
|
||||||
Antagonist = antagPrototype.Antagonist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
10
Content.Server/Roles/AntagonistRoleComponent.cs
Normal file
10
Content.Server/Roles/AntagonistRoleComponent.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
|
public abstract partial class AntagonistRoleComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
||||||
|
public string? PrototypeId;
|
||||||
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using Content.Server.Chat.Managers;
|
|
||||||
using Content.Server.Chat.Systems;
|
|
||||||
using Content.Shared.Roles;
|
|
||||||
using System.Globalization;
|
|
||||||
using Content.Server.Mind;
|
|
||||||
|
|
||||||
namespace Content.Server.Roles
|
|
||||||
{
|
|
||||||
public sealed class Job : Role, IRoleTimer
|
|
||||||
{
|
|
||||||
[ViewVariables] public string Timer => Prototype.PlayTimeTracker;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public JobPrototype Prototype { get; }
|
|
||||||
|
|
||||||
public override string Name { get; }
|
|
||||||
|
|
||||||
public override bool Antagonist => false;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public string? StartingGear => Prototype.StartingGear;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public string? JobEntity => Prototype.JobEntity;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public bool CanBeAntag;
|
|
||||||
|
|
||||||
public Job(Mind.Mind mind, JobPrototype jobPrototype) : base(mind)
|
|
||||||
{
|
|
||||||
Prototype = jobPrototype;
|
|
||||||
Name = jobPrototype.LocalizedName;
|
|
||||||
CanBeAntag = jobPrototype.CanBeAntag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Greet()
|
|
||||||
{
|
|
||||||
base.Greet();
|
|
||||||
|
|
||||||
var entityManager = IoCManager.Resolve<EntityManager>();
|
|
||||||
var mindSystem = entityManager.System<MindSystem>();
|
|
||||||
|
|
||||||
if (mindSystem.TryGetSession(Mind, out var session))
|
|
||||||
{
|
|
||||||
var chatMgr = IoCManager.Resolve<IChatManager>();
|
|
||||||
chatMgr.DispatchServerMessage(session, Loc.GetString("job-greet-introduce-job-name",
|
|
||||||
("jobName", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Name))));
|
|
||||||
|
|
||||||
if(Prototype.RequireAdminNotify)
|
|
||||||
chatMgr.DispatchServerMessage(session, Loc.GetString("job-greet-important-disconnect-admin-notify"));
|
|
||||||
|
|
||||||
chatMgr.DispatchServerMessage(session, Loc.GetString("job-greet-supervisors-warning", ("jobName", Name), ("supervisors", Loc.GetString(Prototype.Supervisors))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
Content.Server/Roles/Jobs/JobComponent.cs
Normal file
14
Content.Server/Roles/Jobs/JobComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Server.Roles.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to mind entities to hold the data for the player's current job.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class JobComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<JobPrototype>))]
|
||||||
|
public string? PrototypeId;
|
||||||
|
}
|
||||||
108
Content.Server/Roles/Jobs/JobSystem.cs
Normal file
108
Content.Server/Roles/Jobs/JobSystem.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Globalization;
|
||||||
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Players;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Roles.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the job data on mind entities.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class JobSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IChatManager _chat = default!;
|
||||||
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
|
[Dependency] private readonly RoleSystem _roles = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypes = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<JobComponent, RoleAddedEvent>(MindOnDoGreeting);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MindOnDoGreeting(EntityUid mindId, JobComponent component, RoleAddedEvent args)
|
||||||
|
{
|
||||||
|
if (!_mind.TryGetSession(mindId, out var session))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!MindTryGetJob(mindId, out _, out var prototype))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_chat.DispatchServerMessage(session, Loc.GetString("job-greet-introduce-job-name",
|
||||||
|
("jobName", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(prototype.LocalizedName))));
|
||||||
|
|
||||||
|
if (prototype.RequireAdminNotify)
|
||||||
|
_chat.DispatchServerMessage(session, Loc.GetString("job-greet-important-disconnect-admin-notify"));
|
||||||
|
|
||||||
|
_chat.DispatchServerMessage(session, Loc.GetString("job-greet-supervisors-warning",
|
||||||
|
("jobName", Name),
|
||||||
|
("supervisors", Loc.GetString(prototype.Supervisors))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MindAddJob(EntityUid mindId, string jobPrototypeId)
|
||||||
|
{
|
||||||
|
if (MindHasJobWithId(mindId, jobPrototypeId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_roles.MindAddRole(mindId, new JobComponent { PrototypeId = jobPrototypeId });
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
|
||||||
|
{
|
||||||
|
return CompOrNull<JobComponent>(mindId)?.PrototypeId == prototypeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MindTryGetJob(
|
||||||
|
[NotNullWhen(true)] EntityUid? mindId,
|
||||||
|
[NotNullWhen(true)] out JobComponent? comp,
|
||||||
|
[NotNullWhen(true)] out JobPrototype? prototype)
|
||||||
|
{
|
||||||
|
comp = null;
|
||||||
|
prototype = null;
|
||||||
|
|
||||||
|
return TryComp(mindId, out comp) &&
|
||||||
|
comp.PrototypeId != null &&
|
||||||
|
_prototypes.TryIndex(comp.PrototypeId, out prototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to get the job name for this mind.
|
||||||
|
/// Returns unknown if not found.
|
||||||
|
/// </summary>
|
||||||
|
public bool MindTryGetJobName([NotNullWhen(true)] EntityUid? mindId, out string name)
|
||||||
|
{
|
||||||
|
if (MindTryGetJob(mindId, out _, out var prototype))
|
||||||
|
{
|
||||||
|
name = prototype.LocalizedName;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = Loc.GetString("generic-unknown-title");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to get the job name for this mind.
|
||||||
|
/// Returns unknown if not found.
|
||||||
|
/// </summary>
|
||||||
|
public string MindTryGetJobName([NotNullWhen(true)] EntityUid? mindId)
|
||||||
|
{
|
||||||
|
MindTryGetJobName(mindId, out var name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanBeAntag(IPlayerSession player)
|
||||||
|
{
|
||||||
|
if (player.ContentData() is not { Mind: { } mindId })
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!MindTryGetJob(mindId, out _, out var prototype))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return prototype.CanBeAntag;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Content.Server/Roles/MindGetAllRolesEvent.cs
Normal file
19
Content.Server/Roles/MindGetAllRolesEvent.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Content.Shared.Players.PlayTimeTracking;
|
||||||
|
|
||||||
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised on a mind entity to get all roles that a player has.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Roles">The list of roles on the player.</param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct MindGetAllRolesEvent(List<RoleInfo> Roles);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returned by <see cref="MindGetAllRolesEvent"/> to give some information about a player's role.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Component">Role component associated with the mind entity id.</param>
|
||||||
|
/// <param name="Name">Name of the role.</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>
|
||||||
|
public readonly record struct RoleInfo(Component Component, string Name, bool Antagonist, string? PlayTimeTrackerId = null);
|
||||||
9
Content.Server/Roles/MindIsAntagonistEvent.cs
Normal file
9
Content.Server/Roles/MindIsAntagonistEvent.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised on a mind entity id to get whether or not the player is considered an antagonist,
|
||||||
|
/// depending on their roles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="IsAntagonist">Whether or not the player is an antagonist.</param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct MindIsAntagonistEvent(bool IsAntagonist);
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
using Content.Shared.Roles;
|
|
||||||
|
|
||||||
namespace Content.Server.Roles;
|
|
||||||
|
|
||||||
public sealed class NukeopsRole : AntagonistRole
|
|
||||||
{
|
|
||||||
public NukeopsRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind, antagPrototype) { }
|
|
||||||
}
|
|
||||||
9
Content.Server/Roles/NukeopsRoleComponent.cs
Normal file
9
Content.Server/Roles/NukeopsRoleComponent.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Content.Server.Roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to mind entities to tag that they are a nuke operative.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class NukeopsRoleComponent : AntagonistRoleComponent
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Mind;
|
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Server.Roles.Jobs;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Roles;
|
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -44,9 +43,10 @@ namespace Content.Server.Roles
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var role = new Job(mind, _prototypeManager.Index<JobPrototype>(args[1]));
|
var roles = _entityManager.System<RoleSystem>();
|
||||||
var mindSystem = _entityManager.System<MindSystem>();
|
var jobs = _entityManager.System<JobSystem>();
|
||||||
mindSystem.RemoveRole(mind, role);
|
if (jobs.MindHasJobWithId(mind, args[1]))
|
||||||
|
roles.MindRemoveRole<JobComponent>(mind.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
// Hey look,
|
|
||||||
// Antag Datums.
|
|
||||||
|
|
||||||
namespace Content.Server.Roles
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The Role is a basic building block for,
|
|
||||||
/// well, IC roles.
|
|
||||||
/// This can be anything and is not necessarily limited to antagonists.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class Role
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The mind owning this role instance.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public Mind.Mind Mind { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A friendly name for this role type.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public abstract string Name { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether this role should be considered antagonistic or not.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public abstract bool Antagonist { get; }
|
|
||||||
|
|
||||||
protected Role(Mind.Mind mind)
|
|
||||||
{
|
|
||||||
Mind = mind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when a mind (player) first gets this role, to greet them.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void Greet()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
namespace Content.Server.Roles
|
using Content.Server.Mind;
|
||||||
{
|
|
||||||
public sealed class RoleAddedEvent : RoleEvent
|
namespace Content.Server.Roles;
|
||||||
{
|
|
||||||
public RoleAddedEvent(Mind.Mind mind, Role role) : base(mind, role) { }
|
/// <summary>
|
||||||
}
|
/// Event raised on player entities to indicate that a role was added to their mind.
|
||||||
}
|
/// </summary>
|
||||||
|
/// <param name="MindId">The mind id associated with the player.</param>
|
||||||
|
/// <param name="Mind">The mind component associated with the mind id.</param>
|
||||||
|
/// <param name="Antagonist">Whether or not the role makes the player an antagonist.</param>
|
||||||
|
public sealed record RoleAddedEvent(EntityUid MindId, MindComponent Mind, bool Antagonist) : RoleEvent(MindId, Mind, Antagonist);
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
namespace Content.Server.Roles
|
using Content.Server.Mind;
|
||||||
{
|
|
||||||
public abstract class RoleEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly Mind.Mind Mind;
|
|
||||||
public readonly Role Role;
|
|
||||||
|
|
||||||
public RoleEvent(Mind.Mind mind, Role role)
|
namespace Content.Server.Roles;
|
||||||
{
|
|
||||||
Mind = mind;
|
/// <summary>
|
||||||
Role = role;
|
/// Base event raised on player entities to indicate that something changed about one of their roles.
|
||||||
}
|
/// </summary>
|
||||||
}
|
/// <param name="MindId">The mind id associated with the player.</param>
|
||||||
}
|
/// <param name="Mind">The mind component associated with the mind id.</param>
|
||||||
|
/// <param name="Antagonist">Whether or not the role makes the player an antagonist.</param>
|
||||||
|
public abstract record RoleEvent(EntityUid MindId, MindComponent Mind, bool Antagonist);
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
namespace Content.Server.Roles
|
using Content.Server.Mind;
|
||||||
{
|
|
||||||
public sealed class RoleRemovedEvent : RoleEvent
|
namespace Content.Server.Roles;
|
||||||
{
|
|
||||||
public RoleRemovedEvent(Mind.Mind mind, Role role) : base(mind, role) { }
|
/// <summary>
|
||||||
}
|
/// Event raised on player entities to indicate that a role was removed from their mind.
|
||||||
}
|
/// </summary>
|
||||||
|
/// <param name="MindId">The mind id associated with the player.</param>
|
||||||
|
/// <param name="Mind">The mind component associated with the mind id.</param>
|
||||||
|
/// <param name="Antagonist">
|
||||||
|
/// Whether or not the role made the player an antagonist.
|
||||||
|
/// They may still be one due to one of their other roles.
|
||||||
|
/// </param>
|
||||||
|
public sealed record RoleRemovedEvent(EntityUid MindId, MindComponent Mind, bool Antagonist) : RoleEvent(MindId, Mind, Antagonist);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user