Remove ghost role component references (#15262)

This commit is contained in:
DrSmugleaf
2023-04-12 06:32:14 -07:00
committed by GitHub
parent 284f6b99b9
commit 9146374e39
30 changed files with 258 additions and 182 deletions

View File

@@ -609,9 +609,10 @@ namespace Content.Server.Botany.Systems
if (component.Seed.Sentient) if (component.Seed.Sentient)
{ {
var comp = EnsureComp<GhostTakeoverAvailableComponent>(uid); var ghostRole = EnsureComp<GhostRoleComponent>(uid);
comp.RoleName = MetaData(uid).EntityName; EnsureComp<GhostTakeoverAvailableComponent>(uid);
comp.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", comp.RoleName)); ghostRole.RoleName = MetaData(uid).EntityName;
ghostRole.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", ghostRole.RoleName));
} }
if (component.UpdateSpriteAfterUpdate) if (component.UpdateSpriteAfterUpdate)

View File

@@ -1,8 +1,7 @@
using Content.Server.Ghost.Roles.Components;
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.Speech.Components; using Content.Server.Speech.Components;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Server.Ghost.Roles.Components;
namespace Content.Server.Chemistry.ReagentEffects; namespace Content.Server.Chemistry.ReagentEffects;
@@ -26,16 +25,18 @@ public sealed class MakeSentient : ReagentEffect
} }
// No idea what anything past this point does // No idea what anything past this point does
if (entityManager.TryGetComponent(uid, out GhostTakeoverAvailableComponent? takeOver)) if (entityManager.TryGetComponent(uid, out GhostRoleComponent? ghostRole) ||
entityManager.TryGetComponent(uid, out GhostTakeoverAvailableComponent? takeOver))
{ {
return; return;
} }
takeOver = entityManager.AddComponent<GhostTakeoverAvailableComponent>(uid); ghostRole = entityManager.AddComponent<GhostRoleComponent>(uid);
entityManager.AddComponent<GhostTakeoverAvailableComponent>(uid);
var entityData = entityManager.GetComponent<MetaDataComponent>(uid); var entityData = entityManager.GetComponent<MetaDataComponent>(uid);
takeOver.RoleName = entityData.EntityName; ghostRole.RoleName = entityData.EntityName;
takeOver.RoleDescription = Loc.GetString("ghost-role-information-cognizine-description"); ghostRole.RoleDescription = Loc.GetString("ghost-role-information-cognizine-description");
} }
} }

View File

@@ -18,6 +18,7 @@ using Content.Server.Station.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Server.Traitor; using Content.Server.Traitor;
using Content.Shared.Dataset; using Content.Shared.Dataset;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Mobs; using Content.Shared.Mobs;
using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Components;
using Content.Shared.Nuke; using Content.Shared.Nuke;
@@ -31,7 +32,6 @@ using Robust.Shared.Player;
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 Content.Shared.Humanoid.Prototypes;
namespace Content.Server.GameTicking.Rules; namespace Content.Server.GameTicking.Rules;
@@ -770,9 +770,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
else if (addSpawnPoints) else if (addSpawnPoints)
{ {
var spawnPoint = EntityManager.SpawnEntity(_nukeopsRuleConfig.GhostSpawnPointProto, _random.Pick(spawns)); var spawnPoint = EntityManager.SpawnEntity(_nukeopsRuleConfig.GhostSpawnPointProto, _random.Pick(spawns));
var spawner = EnsureComp<GhostRoleMobSpawnerComponent>(spawnPoint); var ghostRole = EnsureComp<GhostRoleComponent>(spawnPoint);
spawner.RoleName = Loc.GetString(nukeOpsAntag.Name); EnsureComp<GhostRoleMobSpawnerComponent>(spawnPoint);
spawner.RoleDescription = Loc.GetString(nukeOpsAntag.Objective); ghostRole.RoleName = Loc.GetString(nukeOpsAntag.Name);
ghostRole.RoleDescription = Loc.GetString(nukeOpsAntag.Objective);
var nukeOpSpawner = EnsureComp<NukeOperativeSpawnerComponent>(spawnPoint); var nukeOpSpawner = EnsureComp<NukeOperativeSpawnerComponent>(spawnPoint);
nukeOpSpawner.OperativeName = spawnDetails.Name; nukeOpSpawner.OperativeName = spawnDetails.Name;

View File

@@ -1,10 +1,10 @@
using Content.Server.Mind.Commands; using Content.Server.Mind.Commands;
using Robust.Server.Player;
namespace Content.Server.Ghost.Roles.Components namespace Content.Server.Ghost.Roles.Components
{ {
[RegisterComponent]
[Access(typeof(GhostRoleSystem))] [Access(typeof(GhostRoleSystem))]
public abstract class GhostRoleComponent : Component public sealed class GhostRoleComponent : Component
{ {
[DataField("name")] public string _roleName = "Unknown"; [DataField("name")] public string _roleName = "Unknown";
@@ -16,7 +16,7 @@ namespace Content.Server.Ghost.Roles.Components
/// Whether the <see cref="MakeSentientCommand"/> should run on the mob. /// Whether the <see cref="MakeSentientCommand"/> should run on the mob.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [DataField("makeSentient")] [ViewVariables(VVAccess.ReadWrite)] [DataField("makeSentient")]
protected bool MakeSentient = true; public bool MakeSentient = true;
/// <summary> /// <summary>
/// The probability that this ghost role will be available after init. /// The probability that this ghost role will be available after init.
@@ -83,7 +83,5 @@ namespace Content.Server.Ghost.Roles.Components
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("reregister")] [DataField("reregister")]
public bool ReregisterOnGhost { get; set; } = true; public bool ReregisterOnGhost { get; set; } = true;
public abstract bool Take(IPlayerSession session);
} }
} }

View File

@@ -1,67 +1,26 @@
using Content.Server.Mind.Commands; using Robust.Shared.Prototypes;
using Content.Server.Mind.Components;
using JetBrains.Annotations;
using Robust.Server.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Content.Server.Ghost.Roles.Events;
namespace Content.Server.Ghost.Roles.Components namespace Content.Server.Ghost.Roles.Components
{ {
/// <summary> /// <summary>
/// Allows a ghost to take this role, spawning a new entity. /// Allows a ghost to take this role, spawning a new entity.
/// </summary> /// </summary>
[RegisterComponent, ComponentReference(typeof(GhostRoleComponent))] [RegisterComponent]
public sealed class GhostRoleMobSpawnerComponent : GhostRoleComponent [Access(typeof(GhostRoleSystem))]
public sealed class GhostRoleMobSpawnerComponent : Component
{ {
[Dependency] private readonly IEntityManager _entMan = default!;
[ViewVariables(VVAccess.ReadWrite)] [DataField("deleteOnSpawn")] [ViewVariables(VVAccess.ReadWrite)] [DataField("deleteOnSpawn")]
private bool _deleteOnSpawn = true; public bool DeleteOnSpawn = true;
[ViewVariables(VVAccess.ReadWrite)] [DataField("availableTakeovers")] [ViewVariables(VVAccess.ReadWrite)] [DataField("availableTakeovers")]
private int _availableTakeovers = 1; public int AvailableTakeovers = 1;
[ViewVariables] [ViewVariables]
private int _currentTakeovers = 0; public int CurrentTakeovers = 0;
[CanBeNull]
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("prototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] [DataField("prototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? Prototype { get; private set; } public string? Prototype { get; private set; }
public override bool Take(IPlayerSession session)
{
if (Taken)
return false;
if (string.IsNullOrEmpty(Prototype))
throw new NullReferenceException("Prototype string cannot be null or empty!");
var mob = _entMan.SpawnEntity(Prototype, _entMan.GetComponent<TransformComponent>(Owner).Coordinates);
var xform = _entMan.GetComponent<TransformComponent>(mob);
xform.AttachToGridOrMap();
var spawnedEvent = new GhostRoleSpawnerUsedEvent(Owner, mob);
_entMan.EventBus.RaiseLocalEvent(mob, spawnedEvent, false);
if (MakeSentient)
MakeSentientCommand.MakeSentient(mob, _entMan, AllowMovement, AllowSpeech);
mob.EnsureComponent<MindComponent>();
var ghostRoleSystem = EntitySystem.Get<GhostRoleSystem>();
ghostRoleSystem.GhostRoleInternalCreateMindAndTransfer(session, Owner, mob, this);
if (++_currentTakeovers < _availableTakeovers)
return true;
Taken = true;
if (_deleteOnSpawn)
_entMan.QueueDeleteEntity(Owner);
return true;
}
} }
} }

View File

@@ -1,36 +1,11 @@
using Content.Server.Mind.Commands;
using Content.Server.Mind.Components;
using Robust.Server.Player;
namespace Content.Server.Ghost.Roles.Components namespace Content.Server.Ghost.Roles.Components
{ {
/// <summary> /// <summary>
/// Allows a ghost to take over the Owner entity. /// Allows a ghost to take over the Owner entity.
/// </summary> /// </summary>
[RegisterComponent, ComponentReference(typeof(GhostRoleComponent))] [RegisterComponent]
public sealed class GhostTakeoverAvailableComponent : GhostRoleComponent [Access(typeof(GhostRoleSystem))]
public sealed class GhostTakeoverAvailableComponent : Component
{ {
public override bool Take(IPlayerSession session)
{
if (Taken)
return false;
Taken = true;
var mind = Owner.EnsureComponent<MindComponent>();
if (mind.HasMind)
return false;
if (MakeSentient)
MakeSentientCommand.MakeSentient(Owner, IoCManager.Resolve<IEntityManager>(), AllowMovement, AllowSpeech);
var ghostRoleSystem = EntitySystem.Get<GhostRoleSystem>();
ghostRoleSystem.GhostRoleInternalCreateMindAndTransfer(session, Owner, Owner, this);
ghostRoleSystem.UnregisterGhostRole(this);
return true;
}
} }
} }

View File

@@ -0,0 +1,9 @@
using Robust.Server.Player;
namespace Content.Server.Ghost.Roles.Components;
[ByRefEvent]
public record struct TakeGhostRoleEvent(IPlayerSession Player)
{
public bool TookRole { get; set; }
}

View File

@@ -2,7 +2,9 @@ using Content.Server.Administration.Logs;
using Content.Server.EUI; using Content.Server.EUI;
using Content.Server.Ghost.Components; using Content.Server.Ghost.Components;
using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Components;
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.Components; using Content.Server.Mind.Components;
using Content.Server.Players; using Content.Server.Players;
using Content.Shared.Administration; using Content.Shared.Administration;
@@ -30,6 +32,7 @@ namespace Content.Server.Ghost.Roles
[Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly FollowerSystem _followerSystem = default!; [Dependency] private readonly FollowerSystem _followerSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
private uint _nextRoleIdentifier; private uint _nextRoleIdentifier;
private bool _needsUpdateGhostRoleCount = true; private bool _needsUpdateGhostRoleCount = true;
@@ -51,22 +54,27 @@ namespace Content.Server.Ghost.Roles
SubscribeLocalEvent<GhostTakeoverAvailableComponent, MobStateChangedEvent>(OnMobStateChanged); SubscribeLocalEvent<GhostTakeoverAvailableComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<GhostRoleComponent, ComponentInit>(OnInit); SubscribeLocalEvent<GhostRoleComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<GhostRoleComponent, ComponentShutdown>(OnShutdown); SubscribeLocalEvent<GhostRoleComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
_playerManager.PlayerStatusChanged += PlayerStatusChanged; _playerManager.PlayerStatusChanged += PlayerStatusChanged;
} }
private void OnMobStateChanged(EntityUid uid, GhostRoleComponent component, MobStateChangedEvent args) private void OnMobStateChanged(EntityUid uid, GhostTakeoverAvailableComponent component, MobStateChangedEvent args)
{ {
if (!TryComp(uid, out GhostRoleComponent? ghostRole))
return;
switch (args.NewMobState) switch (args.NewMobState)
{ {
case MobState.Alive: case MobState.Alive:
{ {
if (!component.Taken) if (!ghostRole.Taken)
RegisterGhostRole(component); RegisterGhostRole(ghostRole);
break; break;
} }
case MobState.Critical: case MobState.Critical:
case MobState.Dead: case MobState.Dead:
UnregisterGhostRole(component); UnregisterGhostRole(ghostRole);
break; break;
} }
} }
@@ -180,7 +188,11 @@ namespace Content.Server.Ghost.Roles
public void Takeover(IPlayerSession player, uint identifier) public void Takeover(IPlayerSession player, uint identifier)
{ {
if (!_ghostRoles.TryGetValue(identifier, out var role)) return; if (!_ghostRoles.TryGetValue(identifier, out var role)) return;
if (!role.Take(player)) return;
var ev = new TakeGhostRoleEvent(player);
RaiseLocalEvent(role.Owner, ref ev);
if (!ev.TookRole) return;
if (player.AttachedEntity != null) if (player.AttachedEntity != null)
_adminLogger.Add(LogType.GhostRoleTaken, LogImpact.Low, $"{player:player} took the {role.RoleName:roleName} ghost role {ToPrettyString(player.AttachedEntity.Value):entity}"); _adminLogger.Add(LogType.GhostRoleTaken, LogImpact.Low, $"{player:player} took the {role.RoleName:roleName} ghost role {ToPrettyString(player.AttachedEntity.Value):entity}");
@@ -239,18 +251,24 @@ namespace Content.Server.Ghost.Roles
private void OnMindAdded(EntityUid uid, GhostTakeoverAvailableComponent component, MindAddedMessage args) private void OnMindAdded(EntityUid uid, GhostTakeoverAvailableComponent component, MindAddedMessage args)
{ {
component.Taken = true; if (!TryComp(uid, out GhostRoleComponent? ghostRole))
UnregisterGhostRole(component);
}
private void OnMindRemoved(EntityUid uid, GhostRoleComponent component, MindRemovedMessage args)
{
// Avoid re-registering it for duplicate entries and potential exceptions.
if (!component.ReregisterOnGhost || component.LifeStage > ComponentLifeStage.Running)
return; return;
component.Taken = false; ghostRole.Taken = true;
RegisterGhostRole(component); UnregisterGhostRole(ghostRole);
}
private void OnMindRemoved(EntityUid uid, GhostTakeoverAvailableComponent component, MindRemovedMessage args)
{
if (!TryComp(uid, out GhostRoleComponent? ghostRole))
return;
// Avoid re-registering it for duplicate entries and potential exceptions.
if (!ghostRole.ReregisterOnGhost || component.LifeStage > ComponentLifeStage.Running)
return;
ghostRole.Taken = false;
RegisterGhostRole(ghostRole);
} }
public void Reset(RoundRestartCleanupEvent ev) public void Reset(RoundRestartCleanupEvent ev)
@@ -282,6 +300,73 @@ namespace Content.Server.Ghost.Roles
{ {
UnregisterGhostRole(role); UnregisterGhostRole(role);
} }
private void OnSpawnerTakeRole(EntityUid uid, GhostRoleMobSpawnerComponent component, ref TakeGhostRoleEvent args)
{
if (!TryComp(uid, out GhostRoleComponent? ghostRole) ||
ghostRole.Taken)
{
args.TookRole = false;
return;
}
if (string.IsNullOrEmpty(component.Prototype))
throw new NullReferenceException("Prototype string cannot be null or empty!");
var mob = Spawn(component.Prototype, Transform(uid).Coordinates);
_transform.AttachToGridOrMap(mob);
var spawnedEvent = new GhostRoleSpawnerUsedEvent(uid, mob);
RaiseLocalEvent(mob, spawnedEvent);
if (ghostRole.MakeSentient)
MakeSentientCommand.MakeSentient(mob, EntityManager, ghostRole.AllowMovement, ghostRole.AllowSpeech);
mob.EnsureComponent<MindComponent>();
GhostRoleInternalCreateMindAndTransfer(args.Player, uid, mob, ghostRole);
if (++component.CurrentTakeovers < component.AvailableTakeovers)
{
args.TookRole = true;
return;
}
ghostRole.Taken = true;
if (component.DeleteOnSpawn)
QueueDel(uid);
args.TookRole = true;
}
private void OnTakeoverTakeRole(EntityUid uid, GhostTakeoverAvailableComponent component, ref TakeGhostRoleEvent args)
{
if (!TryComp(uid, out GhostRoleComponent? ghostRole) ||
ghostRole.Taken)
{
args.TookRole = false;
return;
}
ghostRole.Taken = true;
var mind = EnsureComp<MindComponent>(uid);
if (mind.HasMind)
{
args.TookRole = false;
return;
}
if (ghostRole.MakeSentient)
MakeSentientCommand.MakeSentient(uid, EntityManager, ghostRole.AllowMovement, ghostRole.AllowSpeech);
GhostRoleInternalCreateMindAndTransfer(args.Player, uid, uid, ghostRole);
UnregisterGhostRole(ghostRole);
args.TookRole = true;
}
} }
[AnyCommand] [AnyCommand]

View File

@@ -46,16 +46,23 @@ namespace Content.Server.Ghost.Roles
var description = args[2]; var description = args[2];
var rules = args.Length >= 4 ? args[3] : Loc.GetString("ghost-role-component-default-rules"); var rules = args.Length >= 4 ? args[3] : Loc.GetString("ghost-role-component-default-rules");
if (entityManager.TryGetComponent(uid, out GhostRoleComponent? ghostRole))
{
shell.WriteLine($"Entity {metaData.EntityName} with id {uid} already has a {nameof(GhostRoleComponent)}");
return;
}
if (entityManager.TryGetComponent(uid, out GhostTakeoverAvailableComponent? takeOver)) if (entityManager.TryGetComponent(uid, out GhostTakeoverAvailableComponent? takeOver))
{ {
shell.WriteLine($"Entity {metaData.EntityName} with id {uid} already has a {nameof(GhostTakeoverAvailableComponent)}"); shell.WriteLine($"Entity {metaData.EntityName} with id {uid} already has a {nameof(GhostTakeoverAvailableComponent)}");
return; return;
} }
takeOver = entityManager.AddComponent<GhostTakeoverAvailableComponent>(uid); ghostRole = entityManager.AddComponent<GhostRoleComponent>(uid);
takeOver.RoleName = name; entityManager.AddComponent<GhostTakeoverAvailableComponent>(uid);
takeOver.RoleDescription = description; ghostRole.RoleName = name;
takeOver.RoleRules = rules; ghostRole.RoleDescription = description;
ghostRole.RoleRules = rules;
shell.WriteLine($"Made entity {metaData.EntityName} a ghost role."); shell.WriteLine($"Made entity {metaData.EntityName} a ghost role.");
} }

View File

@@ -1,14 +1,13 @@
using Content.Shared.Examine;
using Content.Shared.PAI;
using Content.Shared.Verbs;
using Content.Server.Popups;
using Content.Server.Instruments;
using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Components;
using Content.Server.Instruments;
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Robust.Server.GameObjects; using Content.Server.Popups;
using Robust.Shared.Player; using Content.Shared.Examine;
using Content.Shared.Interaction.Events; using Content.Shared.Interaction.Events;
using Content.Shared.PAI;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Verbs;
using Robust.Server.GameObjects;
namespace Content.Server.PAI namespace Content.Server.PAI
{ {
@@ -79,10 +78,11 @@ namespace Content.Server.PAI
EntityManager.GetComponent<MetaDataComponent>(component.Owner).EntityName = val; EntityManager.GetComponent<MetaDataComponent>(component.Owner).EntityName = val;
var ghostFinder = EntityManager.EnsureComponent<GhostTakeoverAvailableComponent>(uid); var ghostRole = AddComp<GhostRoleComponent>(uid);
EnsureComp<GhostTakeoverAvailableComponent>(uid);
ghostFinder.RoleName = Loc.GetString("pai-system-role-name"); ghostRole.RoleName = Loc.GetString("pai-system-role-name");
ghostFinder.RoleDescription = Loc.GetString("pai-system-role-description"); ghostRole.RoleDescription = Loc.GetString("pai-system-role-description");
_popupSystem.PopupEntity(Loc.GetString("pai-system-searching"), uid, args.User); _popupSystem.PopupEntity(Loc.GetString("pai-system-searching"), uid, args.User);
UpdatePAIAppearance(uid, PAIStatus.Searching); UpdatePAIAppearance(uid, PAIStatus.Searching);

View File

@@ -1,11 +1,8 @@
using System.Linq; using System.Linq;
using Content.Server.Chat;
using Content.Server.Chat.Systems; using Content.Server.Chat.Systems;
using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Components;
using Content.Server.Mind.Commands;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Server.StationEvents.Components; using Content.Server.StationEvents.Components;
using Robust.Shared.Random;
namespace Content.Server.StationEvents.Events; namespace Content.Server.StationEvents.Events;
@@ -31,9 +28,10 @@ public sealed class RandomSentience : StationEventSystem
break; break;
EntityManager.RemoveComponent<SentienceTargetComponent>(target.Owner); EntityManager.RemoveComponent<SentienceTargetComponent>(target.Owner);
var comp = EntityManager.AddComponent<GhostTakeoverAvailableComponent>(target.Owner); var ghostRole = AddComp<GhostRoleComponent>(target.Owner);
comp.RoleName = EntityManager.GetComponent<MetaDataComponent>(target.Owner).EntityName; AddComp<GhostTakeoverAvailableComponent>(target.Owner);
comp.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", comp.RoleName)); ghostRole.RoleName = EntityManager.GetComponent<MetaDataComponent>(target.Owner).EntityName;
ghostRole.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", ghostRole.RoleName));
groups.Add(Loc.GetString(target.FlavorKind)); groups.Add(Loc.GetString(target.FlavorKind));
} }

View File

@@ -210,10 +210,11 @@ namespace Content.Server.Zombies
if (!HasComp<GhostRoleMobSpawnerComponent>(target) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig if (!HasComp<GhostRoleMobSpawnerComponent>(target) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig
{ {
//yet more hardcoding. Visit zombie.ftl for more information. //yet more hardcoding. Visit zombie.ftl for more information.
EntityManager.EnsureComponent<GhostTakeoverAvailableComponent>(target, out var ghostcomp); var ghostRole = EnsureComp<GhostRoleComponent>(target);
ghostcomp.RoleName = Loc.GetString("zombie-generic"); EnsureComp<GhostTakeoverAvailableComponent>(target);
ghostcomp.RoleDescription = Loc.GetString("zombie-role-desc"); ghostRole.RoleName = Loc.GetString("zombie-generic");
ghostcomp.RoleRules = Loc.GetString("zombie-role-rules"); ghostRole.RoleDescription = Loc.GetString("zombie-role-desc");
ghostRole.RoleRules = Loc.GetString("zombie-role-rules");
} }
//Goes through every hand, drops the items in it, then removes the hand //Goes through every hand, drops the items in it, then removes the hand

View File

@@ -4,7 +4,7 @@
suffix: rat king suffix: rat king
parent: MarkerBase parent: MarkerBase
components: components:
- type: GhostRoleMobSpawner - type: GhostRole
prototype: MobRatKing prototype: MobRatKing
name: Rat King name: Rat King
description: You are the Rat King, scavenge food in order to produce rat minions to do your bidding. description: You are the Rat King, scavenge food in order to produce rat minions to do your bidding.
@@ -22,11 +22,12 @@
suffix: Remilia suffix: Remilia
parent: MarkerBase parent: MarkerBase
components: components:
- type: GhostRoleMobSpawner - type: GhostRole
prototype: MobBatRemilia
name: Remilia, the chaplain's familiar name: Remilia, the chaplain's familiar
description: Obey your master. Eat fruit. description: Obey your master. Eat fruit.
rules: You are an intelligent fruit bat. Follow the chaplain around. Don't cause any trouble unless the chaplain tells you to. rules: You are an intelligent fruit bat. Follow the chaplain around. Don't cause any trouble unless the chaplain tells you to.
- type: GhostRoleMobSpawner
prototype: MobBatRemilia
- type: Sprite - type: Sprite
sprite: Markers/jobs.rsi sprite: Markers/jobs.rsi
layers: layers:
@@ -40,11 +41,12 @@
suffix: cerberus suffix: cerberus
parent: MarkerBase parent: MarkerBase
components: components:
- type: GhostRoleMobSpawner - type: GhostRole
prototype: MobCorgiCerberus
name: Cerberus, Evil Familiar name: Cerberus, Evil Familiar
description: Obey your master. Spread chaos. description: Obey your master. Spread chaos.
rules: You are an intelligent, demonic dog. Try to help the chaplain and any of his flock. As an antagonist, you're otherwise unrestrained. rules: You are an intelligent, demonic dog. Try to help the chaplain and any of his flock. As an antagonist, you're otherwise unrestrained.
- type: GhostRoleMobSpawner
prototype: MobCorgiCerberus
- type: Sprite - type: Sprite
sprite: Markers/jobs.rsi sprite: Markers/jobs.rsi
layers: layers:
@@ -59,9 +61,10 @@
suffix: nukeops suffix: nukeops
parent: MarkerBase parent: MarkerBase
components: components:
- type: GhostRole
rules: You are a syndicate operative tasked with the destruction of the station. As an antagonist, do whatever is required to complete this task.
- type: GhostRoleMobSpawner - type: GhostRoleMobSpawner
prototype: MobHumanNukeOp prototype: MobHumanNukeOp
rules: You are a syndicate operative tasked with the destruction of the station. As an antagonist, do whatever is required to complete this task.
- type: NukeOperativeSpawner - type: NukeOperativeSpawner
- type: Sprite - type: Sprite
sprite: Markers/jobs.rsi sprite: Markers/jobs.rsi
@@ -69,5 +72,3 @@
- state: green - state: green
- sprite: Structures/Wallmounts/signs.rsi - sprite: Structures/Wallmounts/signs.rsi
state: radiation state: radiation

View File

@@ -751,12 +751,13 @@
id: MobMouse id: MobMouse
description: Squeak! description: Squeak!
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
allowSpeech: true allowSpeech: true
allowMovement: true allowMovement: true
name: ghost-role-information-mouse-name name: ghost-role-information-mouse-name
description: ghost-role-information-mouse-description description: ghost-role-information-mouse-description
- type: GhostTakeoverAvailable
- type: Speech - type: Speech
speechSounds: Squeak speechSounds: Squeak
- type: Sprite - type: Sprite
@@ -1353,10 +1354,11 @@
- type: MobMover - type: MobMover
- type: HTN - type: HTN
rootTask: SimpleHostileCompound rootTask: SimpleHostileCompound
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
name: ghost-role-information-giant-spider-name name: ghost-role-information-giant-spider-name
description: ghost-role-information-giant-spider-description description: ghost-role-information-giant-spider-description
- type: GhostTakeoverAvailable
- type: entity - type: entity
name: possum name: possum
@@ -1937,12 +1939,13 @@
id: MobHamster id: MobHamster
description: A cute, fluffy, robust hamster. description: A cute, fluffy, robust hamster.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
allowSpeech: true allowSpeech: true
allowMovement: true allowMovement: true
name: ghost-role-information-hamster-name name: ghost-role-information-hamster-name
description: ghost-role-information-hamster-description description: ghost-role-information-hamster-description
- type: GhostTakeoverAvailable
- type: Speech - type: Speech
speechSounds: Squeak speechSounds: Squeak
- type: Sprite - type: Sprite

View File

@@ -90,20 +90,22 @@
radius: 1.2 radius: 1.2
energy: 2 energy: 2
color: "#4faffb" color: "#4faffb"
- type: GhostTakeoverAvailable - type: GhostRole
prob: 0.25 prob: 0.25
name: space bear name: space bear
description: | description: |
You're a bear! Do bear things. You're a bear! Do bear things.
- type: GhostTakeoverAvailable
- type: entity - type: entity
id: MobBearSpaceSalvage id: MobBearSpaceSalvage
parent: MobBearSpace parent: MobBearSpace
suffix: "Salvage Ruleset" suffix: "Salvage Ruleset"
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
prob: 0.25 prob: 0.25
name: space bear on salvage wreck name: space bear on salvage wreck
description: | description: |
Defend the loot inside the salvage wreck! Defend the loot inside the salvage wreck!
- type: GhostTakeoverAvailable
- type: SalvageMobRestrictions - type: SalvageMobRestrictions

View File

@@ -129,13 +129,14 @@
parent: MobCarp parent: MobCarp
suffix: "Salvage Ruleset" suffix: "Salvage Ruleset"
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
prob: 0.33 prob: 0.33
name: space carp on salvage wreck name: space carp on salvage wreck
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
description: | description: |
Defend the loot inside the salvage wreck! Defend the loot inside the salvage wreck!
- type: GhostTakeoverAvailable
- type: SalvageMobRestrictions - type: SalvageMobRestrictions
- type: entity - type: entity
@@ -144,11 +145,12 @@
suffix: DragonBrood suffix: DragonBrood
parent: BaseMobCarp parent: BaseMobCarp
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
name: Sentient Carp name: Sentient Carp
description: Help the dragon flood the station with carps! description: Help the dragon flood the station with carps!
- type: GhostTakeoverAvailable
- type: HTN - type: HTN
rootTask: DragonCarpCompound rootTask: DragonCarpCompound

View File

@@ -445,12 +445,13 @@
id: MobHamsterHamlet id: MobHamsterHamlet
description: A grumpy, cute and fluffy hamster. description: A grumpy, cute and fluffy hamster.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
allowSpeech: true allowSpeech: true
allowMovement: true allowMovement: true
name: ghost-role-information-hamlet-name name: ghost-role-information-hamlet-name
description: ghost-role-information-hamlet-description description: ghost-role-information-hamlet-description
- type: GhostTakeoverAvailable
- type: InteractionPopup - type: InteractionPopup
successChance: 1 successChance: 1
- type: Butcherable - type: Butcherable

View File

@@ -82,11 +82,12 @@
Base: dead Base: dead
Dead: Dead:
Base: dead Base: dead
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
name: Rat King name: Rat King
description: You are the Rat King, scavenge food in order to produce rat minions to do your bidding. description: You are the Rat King, scavenge food in order to produce rat minions to do your bidding.
rules: You are an antagonist, scavenge, attack, and grow your hoard! rules: You are an antagonist, scavenge, attack, and grow your hoard!
- type: GhostTakeoverAvailable
- type: Tag - type: Tag
tags: tags:
- CannotSuicide - CannotSuicide
@@ -283,11 +284,12 @@
Female: Mouse Female: Mouse
Unsexed: Mouse Unsexed: Mouse
wilhelmProbability: 0.001 wilhelmProbability: 0.001
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
name: Rat Servant name: Rat Servant
description: You are a Rat Servant. You must follow your king's orders. description: You are a Rat Servant. You must follow your king's orders.
rules: You are an antagonist, scavenge, attack, and serve your king! rules: You are an antagonist, scavenge, attack, and serve your king!
- type: GhostTakeoverAvailable
- type: Tag - type: Tag
tags: tags:
- CannotSuicide - CannotSuicide

View File

@@ -48,11 +48,12 @@
- type: Alerts - type: Alerts
- type: NameIdentifier - type: NameIdentifier
group: GenericNumber group: GenericNumber
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
name: Revenant name: Revenant
description: You are a Revenant. Use your powers to harvest souls and unleash chaos upon the crew. Unlock new abilities with the essence you harvest. description: You are a Revenant. Use your powers to harvest souls and unleash chaos upon the crew. Unlock new abilities with the essence you harvest.
rules: You are an antagonist, harvest, defile, and drive the crew insane. rules: You are an antagonist, harvest, defile, and drive the crew insane.
- type: GhostTakeoverAvailable
- type: Revenant - type: Revenant
- type: PointLight - type: PointLight
color: MediumPurple color: MediumPurple

View File

@@ -132,10 +132,11 @@
- type: Construction - type: Construction
graph: HonkBot graph: HonkBot
node: bot node: bot
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
name: honkbot name: honkbot
description: An artificial being of pure evil. description: An artificial being of pure evil.
- type: GhostTakeoverAvailable
- type: InteractionPopup - type: InteractionPopup
interactSuccessString: petting-success-honkbot interactSuccessString: petting-success-honkbot
interactFailureString: petting-failure-honkbot interactFailureString: petting-failure-honkbot

View File

@@ -74,12 +74,13 @@
Quantity: 5 Quantity: 5
- type: MeleeChemicalInjector - type: MeleeChemicalInjector
solution: melee solution: melee
- type: GhostTakeoverAvailable - type: GhostRole
prob: 0.33 prob: 0.33
makeSentient: true makeSentient: true
name: space tick name: space tick
description: | description: |
Wreak havoc on the station! Wreak havoc on the station!
- type: GhostTakeoverAvailable
- type: ReplacementAccent - type: ReplacementAccent
accent: genericAggressive accent: genericAggressive
@@ -88,9 +89,10 @@
parent: MobTick parent: MobTick
suffix: "Salvage Ruleset" suffix: "Salvage Ruleset"
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: space tick on salvage wreck name: space tick on salvage wreck
description: | description: |
Defend the loot inside the salvage wreck! Defend the loot inside the salvage wreck!
- type: GhostTakeoverAvailable
- type: SalvageMobRestrictions - type: SalvageMobRestrictions

View File

@@ -89,13 +89,14 @@
spawned: spawned:
- id: FoodMeatXeno - id: FoodMeatXeno
amount: 5 amount: 5
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
name: xeno name: xeno
description: You are a xeno, co-operate with your hive to kill all crewmembers! description: You are a xeno, co-operate with your hive to kill all crewmembers!
rules: You are an antagonist, smack, slash, and wack! rules: You are an antagonist, smack, slash, and wack!
- type: GhostTakeoverAvailable
- type: TypingIndicator - type: TypingIndicator
proto: alien proto: alien
- type: Temperature - type: Temperature

View File

@@ -5,12 +5,13 @@
suffix: "" suffix: ""
description: A flying leviathan, loosely related to space carps. description: A flying leviathan, loosely related to space carps.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
name: Space dragon name: Space dragon
description: Call in 3 carp rifts and take over this quadrant! You have only 5 minutes in between each rift before you will disappear. description: Call in 3 carp rifts and take over this quadrant! You have only 5 minutes in between each rift before you will disappear.
- type: GhostTakeoverAvailable
- type: HTN - type: HTN
rootTask: XenoCompound rootTask: XenoCompound
- type: Faction - type: Faction

View File

@@ -4,13 +4,14 @@
id: MobBatRemilia id: MobBatRemilia
description: The chaplain's familiar. Likes fruit. description: The chaplain's familiar. Likes fruit.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
name: Remilia, the chaplain's familiar name: Remilia, the chaplain's familiar
description: Obey your master. Eat fruit. description: Obey your master. Eat fruit.
rules: You are an intelligent fruit bat. Follow the chaplain around. Don't cause any trouble unless the chaplain tells you to. rules: You are an intelligent fruit bat. Follow the chaplain around. Don't cause any trouble unless the chaplain tells you to.
- type: GhostTakeoverAvailable
- type: Grammar - type: Grammar
attributes: attributes:
gender: female gender: female
@@ -32,13 +33,14 @@
id: MobCorgiCerberus id: MobCorgiCerberus
description: This pupper is not wholesome. description: This pupper is not wholesome.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
name: Cerberus, Evil Familiar name: Cerberus, Evil Familiar
description: Obey your master. Spread chaos. description: Obey your master. Spread chaos.
rules: You are an intelligent, demonic dog. Try to help the chaplain and any of his flock. As an antagonist, you're otherwise unrestrained. rules: You are an intelligent, demonic dog. Try to help the chaplain and any of his flock. As an antagonist, you're otherwise unrestrained.
- type: GhostTakeoverAvailable
- type: MeleeWeapon - type: MeleeWeapon
hidden: true hidden: true
angle: 0 angle: 0

View File

@@ -7,12 +7,13 @@
save: false save: false
components: components:
- type: LagCompensation - type: LagCompensation
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
name: Guardian name: Guardian
description: Listen to your owner. Don't tank damage. Punch people hard. description: Listen to your owner. Don't tank damage. Punch people hard.
- type: GhostTakeoverAvailable
- type: Input - type: Input
context: "human" context: "human"
- type: MobMover - type: MobMover
@@ -104,12 +105,13 @@
parent: MobGuardianBase parent: MobGuardianBase
description: A mesmerising whirl of hard-light patterns weaves a marvelous, yet oddly familiar visage. It stands proud, tuning into its owner's life to sustain itself. description: A mesmerising whirl of hard-light patterns weaves a marvelous, yet oddly familiar visage. It stands proud, tuning into its owner's life to sustain itself.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
name: Holoparasite name: Holoparasite
description: Listen to your owner. Don't tank damage. Punch people hard. description: Listen to your owner. Don't tank damage. Punch people hard.
- type: GhostTakeoverAvailable
- type: NameIdentifier - type: NameIdentifier
group: Holoparasite group: Holoparasite
- type: TypingIndicator - type: TypingIndicator
@@ -130,12 +132,13 @@
id: MobIfritGuardian id: MobIfritGuardian
description: A corrupted jinn, ripped from fitra to serve the wizard's petty needs. It stands wicked, tuning into it's owner's life to sustain itself. description: A corrupted jinn, ripped from fitra to serve the wizard's petty needs. It stands wicked, tuning into it's owner's life to sustain itself.
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
name: Ifrit name: Ifrit
description: Listen to your owner. Don't tank damage. Punch people hard. description: Listen to your owner. Don't tank damage. Punch people hard.
- type: GhostTakeoverAvailable
- type: RandomSprite - type: RandomSprite
available: available:
- enum.DamageStateVisualLayers.BaseUnshaded: - enum.DamageStateVisualLayers.BaseUnshaded:

View File

@@ -21,9 +21,10 @@
id: ERTLeader id: ERTLeader
randomizeName: false randomizeName: false
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Leader name: ERT Leader
description: Lead a team of specialists to resolve the stations issues. description: Lead a team of specialists to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ ERTLeaderGear ] prototypes: [ ERTLeaderGear ]
- type: RandomMetadata - type: RandomMetadata
@@ -48,9 +49,10 @@
id: ERTLeaderEVA id: ERTLeaderEVA
parent: ERTLeader parent: ERTLeader
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Leader name: ERT Leader
description: Lead a team of specialists to resolve the stations issues. description: Lead a team of specialists to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ ERTLeaderGearEVA ] prototypes: [ ERTLeaderGearEVA ]
@@ -76,9 +78,10 @@
id: ERTJanitor id: ERTJanitor
parent: ERTLeader parent: ERTLeader
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Janitor name: ERT Janitor
description: Assist with custodial efforts to resolve the stations issues. description: Assist with custodial efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: RandomMetadata - type: RandomMetadata
nameSegments: nameSegments:
- NamesFirstMilitary - NamesFirstMilitary
@@ -103,9 +106,10 @@
id: ERTJanitorEVA id: ERTJanitorEVA
parent: ERTJanitor parent: ERTJanitor
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Janitor name: ERT Janitor
description: Assist with custodial efforts to resolve the stations issues. description: Assist with custodial efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ ERTJanitorGearEVA ] prototypes: [ ERTJanitorGearEVA ]
@@ -131,9 +135,10 @@
id: ERTEngineer id: ERTEngineer
parent: ERTLeader parent: ERTLeader
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Engineer name: ERT Engineer
description: Assist with engineering efforts to resolve the stations issues. description: Assist with engineering efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: RandomMetadata - type: RandomMetadata
nameSegments: nameSegments:
- NamesFirstMilitary - NamesFirstMilitary
@@ -158,9 +163,10 @@
id: ERTEngineerEVA id: ERTEngineerEVA
parent: ERTEngineer parent: ERTEngineer
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Engineer name: ERT Engineer
description: Assist with engineering efforts to resolve the stations issues. description: Assist with engineering efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ ERTEngineerGearEVA ] prototypes: [ ERTEngineerGearEVA ]
@@ -186,9 +192,10 @@
id: ERTSecurity id: ERTSecurity
parent: ERTLeader parent: ERTLeader
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Security name: ERT Security
description: Assist with security efforts to resolve the stations issues. description: Assist with security efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: RandomMetadata - type: RandomMetadata
nameSegments: nameSegments:
- NamesFirstMilitary - NamesFirstMilitary
@@ -213,9 +220,10 @@
id: ERTSecurityEVA id: ERTSecurityEVA
parent: ERTSecurity parent: ERTSecurity
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Security name: ERT Security
description: Assist with security efforts to resolve the stations issues. description: Assist with security efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ ERTSecurityGearEVA ] prototypes: [ ERTSecurityGearEVA ]
@@ -241,9 +249,10 @@
id: ERTMedical id: ERTMedical
parent: ERTLeader parent: ERTLeader
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Medical name: ERT Medical
description: Assist with medicaling efforts to resolve the stations issues. description: Assist with medicaling efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: RandomMetadata - type: RandomMetadata
nameSegments: nameSegments:
- NamesFirstMilitary - NamesFirstMilitary
@@ -268,9 +277,10 @@
id: ERTMedicalEVA id: ERTMedicalEVA
parent: ERTMedical parent: ERTMedical
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: ERT Medical name: ERT Medical
description: Assist with medicaling efforts to resolve the stations issues. description: Assist with medicaling efforts to resolve the stations issues.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ ERTMedicalGearEVA ] prototypes: [ ERTMedicalGearEVA ]
@@ -292,9 +302,10 @@
components: components:
- type: Loadout - type: Loadout
prototypes: [CBURNGear] prototypes: [CBURNGear]
- type: GhostTakeoverAvailable - type: GhostRole
name: CBURN Agent name: CBURN Agent
description: A highly trained CentCom agent, capable of dealing with various threats. description: A highly trained CentCom agent, capable of dealing with various threats.
- type: GhostTakeoverAvailable
- type: RandomMetadata - type: RandomMetadata
nameSegments: nameSegments:
- NamesFirstMilitary - NamesFirstMilitary
@@ -315,9 +326,10 @@
- type: randomHumanoidSettings - type: randomHumanoidSettings
id: CentcomOfficial id: CentcomOfficial
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: CentCom official name: CentCom official
description: Inspect the station, jot down performance reviews for heads of staff, bug the Captain. description: Inspect the station, jot down performance reviews for heads of staff, bug the Captain.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [ CentcomGear ] prototypes: [ CentcomGear ]
@@ -379,7 +391,8 @@
id: Cluwne id: Cluwne
randomizeName: false randomizeName: false
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: Cluwne name: Cluwne
description: Become a pitiful cluwne, your only goal in life is to find a sweet release from your suffering (usually by being beaten to death). A cluwne is not an antagonist but may defend itself. Crewmembers may murder cluwnes freely. description: Become a pitiful cluwne, your only goal in life is to find a sweet release from your suffering (usually by being beaten to death). A cluwne is not an antagonist but may defend itself. Crewmembers may murder cluwnes freely.
- type: GhostTakeoverAvailable
- type: Cluwne - type: Cluwne

View File

@@ -84,7 +84,7 @@
interfaces: interfaces:
- key: enum.StrippingUiKey.Key - key: enum.StrippingUiKey.Key
type: StrippableBoundUserInterface type: StrippableBoundUserInterface
#- type: GhostTakeoverAvailable #- type: GhostRole
# makeSentient: true # makeSentient: true
# name: Maintenance Drone # name: Maintenance Drone
# description: Maintain the station. Ignore other beings except drones. # description: Maintain the station. Ignore other beings except drones.
@@ -93,6 +93,7 @@
# 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. # 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone.
# 2. You may not harm any being, regardless of intent or circumstance. # 2. You may not harm any being, regardless of intent or circumstance.
# 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. # 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals.
#- type: GhostTakeoverAvailable
- type: MovementSpeedModifier - type: MovementSpeedModifier
baseWalkSpeed : 5 baseWalkSpeed : 5
baseSprintSpeed : 5 baseSprintSpeed : 5
@@ -186,11 +187,12 @@
interfaces: interfaces:
- key: enum.StrippingUiKey.Key - key: enum.StrippingUiKey.Key
type: StrippableBoundUserInterface type: StrippableBoundUserInterface
- type: GhostTakeoverAvailable - type: GhostRole
makeSentient: true makeSentient: true
name: Onestar Mecha name: Onestar Mecha
description: You are an experimental mecha created by who-knows-what, all you know is that you have weapons and you detect fleshy moving targets nearby... description: You are an experimental mecha created by who-knows-what, all you know is that you have weapons and you detect fleshy moving targets nearby...
rules: Use your weapons to cause havoc. You are an antagonist. rules: Use your weapons to cause havoc. You are an antagonist.
- type: GhostTakeoverAvailable
- type: MovementSpeedModifier - type: MovementSpeedModifier
baseWalkSpeed : 3 baseWalkSpeed : 3
baseSprintSpeed : 2 baseSprintSpeed : 2

View File

@@ -29,9 +29,10 @@
parent: MobSkeletonPerson parent: MobSkeletonPerson
id: MobSkeletonPirate id: MobSkeletonPirate
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: Skeleton Pirate name: Skeleton Pirate
description: Cause chaos and loot the station for treasure. description: Cause chaos and loot the station for treasure.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [PirateGear] prototypes: [PirateGear]
- type: RandomHumanoidAppearance - type: RandomHumanoidAppearance
@@ -42,9 +43,10 @@
parent: MobSkeletonPerson parent: MobSkeletonPerson
id: MobSkeletonBiker id: MobSkeletonBiker
components: components:
- type: GhostTakeoverAvailable - type: GhostRole
name: Skeleton Biker name: Skeleton Biker
description: Ride around on your sweet ride. description: Ride around on your sweet ride.
- type: GhostTakeoverAvailable
- type: Loadout - type: Loadout
prototypes: [SkeletonBiker] prototypes: [SkeletonBiker]
- type: RandomHumanoidAppearance - type: RandomHumanoidAppearance

View File

@@ -9,11 +9,12 @@
layers: layers:
- state: old-radio - state: old-radio
netsync: false netsync: false
- type: GhostRoleMobSpawner - type: GhostRole
prototype: MobHumanSyndicateAgent
name: Syndicate Agent name: Syndicate Agent
description: Someone needs reinforcements. You, the first person the syndicate could find, will help them. description: Someone needs reinforcements. You, the first person the syndicate could find, will help them.
rules: Normal syndicate antagonist rules apply. Work with whoever called you in, and don't harm them. rules: Normal syndicate antagonist rules apply. Work with whoever called you in, and don't harm them.
- type: GhostRoleMobSpawner
prototype: MobHumanSyndicateAgent
- type: EmitSoundOnUse - type: EmitSoundOnUse
sound: /Audio/Misc/emergency_meeting.ogg sound: /Audio/Misc/emergency_meeting.ogg
- type: ItemCooldown - type: ItemCooldown

View File

@@ -172,7 +172,7 @@
targetDepth: 3 targetDepth: 3
effectHint: artifact-effect-hint-sentience effectHint: artifact-effect-hint-sentience
permanentComponents: permanentComponents:
- type: GhostTakeoverAvailable - type: GhostRole
allowMovement: true allowMovement: true
allowSpeech: true allowSpeech: true
makeSentient: true makeSentient: true
@@ -180,6 +180,7 @@
description: | description: |
Enact your eldritch whims. Enact your eldritch whims.
Forcibly activate your nodes for good or for evil. Forcibly activate your nodes for good or for evil.
- type: GhostTakeoverAvailable
- type: MovementSpeedModifier - type: MovementSpeedModifier
baseWalkSpeed: 0.25 baseWalkSpeed: 0.25
baseSprintSpeed: 0.5 baseSprintSpeed: 0.5