Add a system for modifying entity names without causing conflicts (#27863)

This commit is contained in:
Tayrtahn
2024-06-16 15:38:53 -04:00
committed by GitHub
parent ee2769ed9f
commit 89a9f07c3a
30 changed files with 326 additions and 123 deletions

View File

@@ -14,14 +14,6 @@ namespace Content.Server.Chemistry.Components;
[RegisterComponent, Access(typeof(TransformableContainerSystem))] [RegisterComponent, Access(typeof(TransformableContainerSystem))]
public sealed partial class TransformableContainerComponent : Component public sealed partial class TransformableContainerComponent : Component
{ {
/// <summary>
/// This is the initial metadata name for the container.
/// It will revert to this when emptied.
/// It defaults to the name of the parent entity unless overwritten.
/// </summary>
[DataField("initialName")]
public string? InitialName;
/// <summary> /// <summary>
/// This is the initial metadata description for the container. /// This is the initial metadata description for the container.
/// It will revert to this when emptied. /// It will revert to this when emptied.

View File

@@ -2,6 +2,7 @@ using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Server.Chemistry.EntitySystems; namespace Content.Server.Chemistry.EntitySystems;
@@ -11,6 +12,7 @@ public sealed class TransformableContainerSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!; [Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!;
[Dependency] private readonly MetaDataSystem _metadataSystem = default!; [Dependency] private readonly MetaDataSystem _metadataSystem = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -18,15 +20,12 @@ public sealed class TransformableContainerSystem : EntitySystem
SubscribeLocalEvent<TransformableContainerComponent, MapInitEvent>(OnMapInit); SubscribeLocalEvent<TransformableContainerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<TransformableContainerComponent, SolutionContainerChangedEvent>(OnSolutionChange); SubscribeLocalEvent<TransformableContainerComponent, SolutionContainerChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<TransformableContainerComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
} }
private void OnMapInit(Entity<TransformableContainerComponent> entity, ref MapInitEvent args) private void OnMapInit(Entity<TransformableContainerComponent> entity, ref MapInitEvent args)
{ {
var meta = MetaData(entity.Owner); var meta = MetaData(entity.Owner);
if (string.IsNullOrEmpty(entity.Comp.InitialName))
{
entity.Comp.InitialName = meta.EntityName;
}
if (string.IsNullOrEmpty(entity.Comp.InitialDescription)) if (string.IsNullOrEmpty(entity.Comp.InitialDescription))
{ {
entity.Comp.InitialDescription = meta.EntityDescription; entity.Comp.InitialDescription = meta.EntityDescription;
@@ -58,12 +57,20 @@ public sealed class TransformableContainerSystem : EntitySystem
&& _prototypeManager.TryIndex(reagentId.Value.Prototype, out ReagentPrototype? proto)) && _prototypeManager.TryIndex(reagentId.Value.Prototype, out ReagentPrototype? proto))
{ {
var metadata = MetaData(entity.Owner); var metadata = MetaData(entity.Owner);
var val = Loc.GetString("transformable-container-component-glass", ("name", proto.LocalizedName));
_metadataSystem.SetEntityName(entity.Owner, val, metadata);
_metadataSystem.SetEntityDescription(entity.Owner, proto.LocalizedDescription, metadata); _metadataSystem.SetEntityDescription(entity.Owner, proto.LocalizedDescription, metadata);
entity.Comp.CurrentReagent = proto; entity.Comp.CurrentReagent = proto;
entity.Comp.Transformed = true; entity.Comp.Transformed = true;
} }
_nameMod.RefreshNameModifiers(entity.Owner);
}
private void OnRefreshNameModifiers(Entity<TransformableContainerComponent> entity, ref RefreshNameModifiersEvent args)
{
if (entity.Comp.CurrentReagent is { } currentReagent)
{
args.AddModifier("transformable-container-component-glass", priority: -1, ("reagent", currentReagent.LocalizedName));
}
} }
private void CancelTransformation(Entity<TransformableContainerComponent> entity) private void CancelTransformation(Entity<TransformableContainerComponent> entity)
@@ -73,10 +80,8 @@ public sealed class TransformableContainerSystem : EntitySystem
var metadata = MetaData(entity); var metadata = MetaData(entity);
if (!string.IsNullOrEmpty(entity.Comp.InitialName)) _nameMod.RefreshNameModifiers(entity.Owner);
{
_metadataSystem.SetEntityName(entity.Owner, entity.Comp.InitialName, metadata);
}
if (!string.IsNullOrEmpty(entity.Comp.InitialDescription)) if (!string.IsNullOrEmpty(entity.Comp.InitialDescription))
{ {
_metadataSystem.SetEntityDescription(entity.Owner, entity.Comp.InitialDescription, metadata); _metadataSystem.SetEntityDescription(entity.Owner, entity.Comp.InitialDescription, metadata);

View File

@@ -14,8 +14,8 @@ using Content.Server.Emoting.Systems;
using Content.Server.Speech.EntitySystems; using Content.Server.Speech.EntitySystems;
using Content.Shared.Cluwne; using Content.Shared.Cluwne;
using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Content.Shared.NameModifier.EntitySystems;
namespace Content.Server.Cluwne; namespace Content.Server.Cluwne;
@@ -30,6 +30,7 @@ public sealed class CluwneSystem : EntitySystem
[Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!; [Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -39,6 +40,7 @@ public sealed class CluwneSystem : EntitySystem
SubscribeLocalEvent<CluwneComponent, MobStateChangedEvent>(OnMobState); SubscribeLocalEvent<CluwneComponent, MobStateChangedEvent>(OnMobState);
SubscribeLocalEvent<CluwneComponent, EmoteEvent>(OnEmote, before: SubscribeLocalEvent<CluwneComponent, EmoteEvent>(OnEmote, before:
new[] { typeof(VocalSystem), typeof(BodyEmotesSystem) }); new[] { typeof(VocalSystem), typeof(BodyEmotesSystem) });
SubscribeLocalEvent<CluwneComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
} }
/// <summary> /// <summary>
@@ -59,7 +61,7 @@ public sealed class CluwneSystem : EntitySystem
public EmoteSoundsPrototype? EmoteSounds; public EmoteSoundsPrototype? EmoteSounds;
/// <summary> /// <summary>
/// OnStartup gives the cluwne outfit, ensures clumsy, gives name prefix and makes sure emote sounds are laugh. /// OnStartup gives the cluwne outfit, ensures clumsy, and makes sure emote sounds are laugh.
/// </summary> /// </summary>
private void OnComponentStartup(EntityUid uid, CluwneComponent component, ComponentStartup args) private void OnComponentStartup(EntityUid uid, CluwneComponent component, ComponentStartup args)
{ {
@@ -67,9 +69,6 @@ public sealed class CluwneSystem : EntitySystem
return; return;
_prototypeManager.TryIndex(component.EmoteSoundsId, out EmoteSounds); _prototypeManager.TryIndex(component.EmoteSoundsId, out EmoteSounds);
var meta = MetaData(uid);
var name = meta.EntityName;
EnsureComp<AutoEmoteComponent>(uid); EnsureComp<AutoEmoteComponent>(uid);
_autoEmote.AddEmote(uid, "CluwneGiggle"); _autoEmote.AddEmote(uid, "CluwneGiggle");
EnsureComp<ClumsyComponent>(uid); EnsureComp<ClumsyComponent>(uid);
@@ -77,7 +76,7 @@ public sealed class CluwneSystem : EntitySystem
_popupSystem.PopupEntity(Loc.GetString("cluwne-transform", ("target", uid)), uid, PopupType.LargeCaution); _popupSystem.PopupEntity(Loc.GetString("cluwne-transform", ("target", uid)), uid, PopupType.LargeCaution);
_audio.PlayPvs(component.SpawnSound, uid); _audio.PlayPvs(component.SpawnSound, uid);
_metaData.SetEntityName(uid, Loc.GetString("cluwne-name-prefix", ("target", name)), meta); _nameMod.RefreshNameModifiers(uid);
SetOutfitCommand.SetOutfit(uid, "CluwneGear", EntityManager); SetOutfitCommand.SetOutfit(uid, "CluwneGear", EntityManager);
} }
@@ -104,4 +103,12 @@ public sealed class CluwneSystem : EntitySystem
_chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, ChatTransmitRange.Normal); _chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, ChatTransmitRange.Normal);
} }
} }
/// <summary>
/// Applies "Cluwnified" prefix
/// </summary>
private void OnRefreshNameModifiers(Entity<CluwneComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("cluwne-name-prefix");
}
} }

View File

@@ -29,6 +29,7 @@ using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Content.Shared.NameModifier.Components;
namespace Content.Server.Fax; namespace Content.Server.Fax;
@@ -464,10 +465,11 @@ public sealed class FaxSystem : EntitySystem
return; return;
TryComp<LabelComponent>(sendEntity, out var labelComponent); TryComp<LabelComponent>(sendEntity, out var labelComponent);
TryComp<NameModifierComponent>(sendEntity, out var nameMod);
// TODO: See comment in 'Send()' about not being able to copy whole entities // TODO: See comment in 'Send()' about not being able to copy whole entities
var printout = new FaxPrintout(paper.Content, var printout = new FaxPrintout(paper.Content,
labelComponent?.OriginalName ?? metadata.EntityName, nameMod?.BaseName ?? metadata.EntityName,
labelComponent?.CurrentLabel, labelComponent?.CurrentLabel,
metadata.EntityPrototype?.ID ?? DefaultPaperPrototypeId, metadata.EntityPrototype?.ID ?? DefaultPaperPrototypeId,
paper.StampState, paper.StampState,
@@ -510,12 +512,14 @@ public sealed class FaxSystem : EntitySystem
!TryComp<PaperComponent>(sendEntity, out var paper)) !TryComp<PaperComponent>(sendEntity, out var paper))
return; return;
TryComp<NameModifierComponent>(sendEntity, out var nameMod);
TryComp<LabelComponent>(sendEntity, out var labelComponent); TryComp<LabelComponent>(sendEntity, out var labelComponent);
var payload = new NetworkPayload() var payload = new NetworkPayload()
{ {
{ DeviceNetworkConstants.Command, FaxConstants.FaxPrintCommand }, { DeviceNetworkConstants.Command, FaxConstants.FaxPrintCommand },
{ FaxConstants.FaxPaperNameData, labelComponent?.OriginalName ?? metadata.EntityName }, { FaxConstants.FaxPaperNameData, nameMod?.BaseName ?? metadata.EntityName },
{ FaxConstants.FaxPaperLabelData, labelComponent?.CurrentLabel }, { FaxConstants.FaxPaperLabelData, labelComponent?.CurrentLabel },
{ FaxConstants.FaxPaperContentData, paper.Content }, { FaxConstants.FaxPaperContentData, paper.Content },
}; };

View File

@@ -6,6 +6,7 @@ using Content.Shared.Hands;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Components;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Verbs; using Content.Shared.Verbs;
@@ -20,9 +21,9 @@ public sealed class GlueSystem : SharedGlueSystem
[Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly OpenableSystem _openable = default!; [Dependency] private readonly OpenableSystem _openable = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -32,6 +33,7 @@ public sealed class GlueSystem : SharedGlueSystem
SubscribeLocalEvent<GluedComponent, ComponentInit>(OnGluedInit); SubscribeLocalEvent<GluedComponent, ComponentInit>(OnGluedInit);
SubscribeLocalEvent<GlueComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb); SubscribeLocalEvent<GlueComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
SubscribeLocalEvent<GluedComponent, GotEquippedHandEvent>(OnHandPickUp); SubscribeLocalEvent<GluedComponent, GotEquippedHandEvent>(OnHandPickUp);
SubscribeLocalEvent<GluedComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
} }
// When glue bottle is used on item it will apply the glued and unremoveable components. // When glue bottle is used on item it will apply the glued and unremoveable components.
@@ -95,27 +97,22 @@ public sealed class GlueSystem : SharedGlueSystem
{ {
base.Update(frameTime); base.Update(frameTime);
var query = EntityQueryEnumerator<GluedComponent, UnremoveableComponent, MetaDataComponent>(); var query = EntityQueryEnumerator<GluedComponent, UnremoveableComponent>();
while (query.MoveNext(out var uid, out var glue, out var _, out var meta)) while (query.MoveNext(out var uid, out var glue, out var _))
{ {
if (_timing.CurTime < glue.Until) if (_timing.CurTime < glue.Until)
continue; continue;
// Instead of string matching, just reconstruct the expected name and compare
if (meta.EntityName == Loc.GetString("glued-name-prefix", ("target", glue.BeforeGluedEntityName)))
_metaData.SetEntityName(uid, glue.BeforeGluedEntityName);
RemComp<UnremoveableComponent>(uid); RemComp<UnremoveableComponent>(uid);
RemComp<GluedComponent>(uid); RemComp<GluedComponent>(uid);
_nameMod.RefreshNameModifiers(uid);
} }
} }
private void OnGluedInit(Entity<GluedComponent> entity, ref ComponentInit args) private void OnGluedInit(Entity<GluedComponent> entity, ref ComponentInit args)
{ {
var meta = MetaData(entity); _nameMod.RefreshNameModifiers(entity.Owner);
var name = meta.EntityName;
entity.Comp.BeforeGluedEntityName = meta.EntityName;
_metaData.SetEntityName(entity.Owner, Loc.GetString("glued-name-prefix", ("target", name)));
} }
private void OnHandPickUp(Entity<GluedComponent> entity, ref GotEquippedHandEvent args) private void OnHandPickUp(Entity<GluedComponent> entity, ref GotEquippedHandEvent args)
@@ -124,4 +121,9 @@ public sealed class GlueSystem : SharedGlueSystem
comp.DeleteOnDrop = false; comp.DeleteOnDrop = false;
entity.Comp.Until = _timing.CurTime + entity.Comp.Duration; entity.Comp.Until = _timing.CurTime + entity.Comp.Duration;
} }
private void OnRefreshNameModifiers(Entity<GluedComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("glued-name-prefix");
}
} }

View File

@@ -5,6 +5,7 @@ using Content.Shared.Examine;
using Content.Shared.Labels; using Content.Shared.Labels;
using Content.Shared.Labels.Components; using Content.Shared.Labels.Components;
using Content.Shared.Labels.EntitySystems; using Content.Shared.Labels.EntitySystems;
using Content.Shared.NameModifier.EntitySystems;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -18,7 +19,7 @@ namespace Content.Server.Labels
{ {
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly NameModifierSystem _nameMod = default!;
public const string ContainerName = "paper_label"; public const string ContainerName = "paper_label";
@@ -41,6 +42,8 @@ namespace Content.Server.Labels
component.CurrentLabel = Loc.GetString(component.CurrentLabel); component.CurrentLabel = Loc.GetString(component.CurrentLabel);
Dirty(uid, component); Dirty(uid, component);
} }
_nameMod.RefreshNameModifiers(uid);
} }
/// <summary> /// <summary>
@@ -52,30 +55,11 @@ namespace Content.Server.Labels
/// <param name="metadata">metadata component for resolve</param> /// <param name="metadata">metadata component for resolve</param>
public override void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null) public override void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null)
{ {
if (!Resolve(uid, ref metadata))
return;
if (!Resolve(uid, ref label, false)) if (!Resolve(uid, ref label, false))
label = EnsureComp<LabelComponent>(uid); label = EnsureComp<LabelComponent>(uid);
if (string.IsNullOrEmpty(text))
{
if (label.OriginalName is null)
return;
// Remove label
_metaData.SetEntityName(uid, label.OriginalName, metadata);
label.CurrentLabel = null;
label.OriginalName = null;
Dirty(uid, label);
return;
}
// Update label
label.OriginalName ??= metadata.EntityName;
label.CurrentLabel = text; label.CurrentLabel = text;
_metaData.SetEntityName(uid, $"{label.OriginalName} ({text})", metadata); _nameMod.RefreshNameModifiers(uid);
Dirty(uid, label); Dirty(uid, label);
} }

View File

@@ -1,5 +1,6 @@
using Content.Shared.IdentityManagement; using Content.Shared.IdentityManagement;
using Content.Shared.Lube; using Content.Shared.Lube;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Throwing; using Content.Shared.Throwing;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -9,11 +10,11 @@ namespace Content.Server.Lube;
public sealed class LubedSystem : EntitySystem public sealed class LubedSystem : EntitySystem
{ {
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -21,14 +22,12 @@ public sealed class LubedSystem : EntitySystem
SubscribeLocalEvent<LubedComponent, ComponentInit>(OnInit); SubscribeLocalEvent<LubedComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<LubedComponent, ContainerGettingInsertedAttemptEvent>(OnHandPickUp); SubscribeLocalEvent<LubedComponent, ContainerGettingInsertedAttemptEvent>(OnHandPickUp);
SubscribeLocalEvent<LubedComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
} }
private void OnInit(EntityUid uid, LubedComponent component, ComponentInit args) private void OnInit(EntityUid uid, LubedComponent component, ComponentInit args)
{ {
var meta = MetaData(uid); _nameMod.RefreshNameModifiers(uid);
var name = meta.EntityName;
component.BeforeLubedEntityName = meta.EntityName;
_metaData.SetEntityName(uid, Loc.GetString("lubed-name-prefix", ("target", name)));
} }
private void OnHandPickUp(EntityUid uid, LubedComponent component, ContainerGettingInsertedAttemptEvent args) private void OnHandPickUp(EntityUid uid, LubedComponent component, ContainerGettingInsertedAttemptEvent args)
@@ -36,7 +35,7 @@ public sealed class LubedSystem : EntitySystem
if (component.SlipsLeft <= 0) if (component.SlipsLeft <= 0)
{ {
RemComp<LubedComponent>(uid); RemComp<LubedComponent>(uid);
_metaData.SetEntityName(uid, component.BeforeLubedEntityName); _nameMod.RefreshNameModifiers(uid);
return; return;
} }
component.SlipsLeft--; component.SlipsLeft--;
@@ -47,4 +46,9 @@ public sealed class LubedSystem : EntitySystem
_throwing.TryThrow(uid, _random.NextVector2(), strength: component.SlipStrength); _throwing.TryThrow(uid, _random.NextVector2(), strength: component.SlipStrength);
_popup.PopupEntity(Loc.GetString("lube-slip", ("target", Identity.Entity(uid, EntityManager))), user, user, PopupType.MediumCaution); _popup.PopupEntity(Loc.GetString("lube-slip", ("target", Identity.Entity(uid, EntityManager))), user, user, PopupType.MediumCaution);
} }
private void OnRefreshNameModifiers(Entity<LubedComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("lubed-name-prefix");
}
} }

View File

@@ -5,13 +5,12 @@ using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Components;
using Content.Shared.Mind.Components; using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Systems; using Content.Shared.Mobs.Systems;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Nutrition.AnimalHusbandry; using Content.Shared.Nutrition.AnimalHusbandry;
using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Storage; using Content.Shared.Storage;
using Content.Shared.Whitelist; using Content.Shared.Whitelist;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Random; using Robust.Shared.Random;
@@ -29,12 +28,12 @@ public sealed class AnimalHusbandrySystem : EntitySystem
[Dependency] private readonly IAdminLogManager _adminLog = default!; [Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
private readonly HashSet<EntityUid> _failedAttempts = new(); private readonly HashSet<EntityUid> _failedAttempts = new();
private readonly HashSet<EntityUid> _birthQueue = new(); private readonly HashSet<EntityUid> _birthQueue = new();
@@ -43,8 +42,7 @@ public sealed class AnimalHusbandrySystem : EntitySystem
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<ReproductiveComponent, MindAddedMessage>(OnMindAdded); SubscribeLocalEvent<ReproductiveComponent, MindAddedMessage>(OnMindAdded);
SubscribeLocalEvent<InfantComponent, ComponentStartup>(OnInfantStartup); SubscribeLocalEvent<InfantComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
SubscribeLocalEvent<InfantComponent, ComponentShutdown>(OnInfantShutdown);
} }
// we express EZ-pass terminate the pregnancy if a player takes the role // we express EZ-pass terminate the pregnancy if a player takes the role
@@ -54,16 +52,11 @@ public sealed class AnimalHusbandrySystem : EntitySystem
component.GestationEndTime = null; component.GestationEndTime = null;
} }
private void OnInfantStartup(EntityUid uid, InfantComponent component, ComponentStartup args) private void OnRefreshNameModifiers(Entity<InfantComponent> entity, ref RefreshNameModifiersEvent args)
{ {
var meta = MetaData(uid); // This check may seem redundant, but it makes sure that the prefix is removed before the component is removed
component.OriginalName = meta.EntityName; if (_timing.CurTime < entity.Comp.InfantEndTime)
_metaData.SetEntityName(uid, Loc.GetString("infant-name-prefix", ("name", meta.EntityName)), meta); args.AddModifier("infant-name-prefix");
}
private void OnInfantShutdown(EntityUid uid, InfantComponent component, ComponentShutdown args)
{
_metaData.SetEntityName(uid, component.OriginalName);
} }
/// <summary> /// <summary>
@@ -202,6 +195,8 @@ public sealed class AnimalHusbandrySystem : EntitySystem
{ {
var infant = AddComp<InfantComponent>(offspring); var infant = AddComp<InfantComponent>(offspring);
infant.InfantEndTime = _timing.CurTime + infant.InfantDuration; infant.InfantEndTime = _timing.CurTime + infant.InfantDuration;
// Make sure the name prefix is applied
_nameMod.RefreshNameModifiers(offspring);
} }
_adminLog.Add(LogType.Action, $"{ToPrettyString(uid)} gave birth to {ToPrettyString(offspring)}."); _adminLog.Add(LogType.Action, $"{ToPrettyString(uid)} gave birth to {ToPrettyString(offspring)}.");
} }
@@ -249,6 +244,8 @@ public sealed class AnimalHusbandrySystem : EntitySystem
if (_timing.CurTime < infant.InfantEndTime) if (_timing.CurTime < infant.InfantEndTime)
continue; continue;
RemCompDeferred(uid, infant); RemCompDeferred(uid, infant);
// Make sure the name prefix gets removed
_nameMod.RefreshNameModifiers(uid);
} }
} }
} }

View File

@@ -222,9 +222,7 @@ namespace Content.Server.Zombies
_faction.AddFaction(target, "Zombie"); _faction.AddFaction(target, "Zombie");
//gives it the funny "Zombie ___" name. //gives it the funny "Zombie ___" name.
var meta = MetaData(target); _nameMod.RefreshNameModifiers(target);
zombiecomp.BeforeZombifiedEntityName = meta.EntityName;
_metaData.SetEntityName(target, Loc.GetString("zombie-name-prefix", ("target", meta.EntityName)), meta);
_identity.QueueIdentityUpdate(target); _identity.QueueIdentityUpdate(target);

View File

@@ -14,6 +14,7 @@ using Content.Shared.Mind;
using Content.Shared.Mobs; using Content.Shared.Mobs;
using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems; using Content.Shared.Mobs.Systems;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Weapons.Melee.Events; using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Zombies; using Content.Shared.Zombies;
@@ -34,9 +35,9 @@ namespace Content.Server.Zombies
[Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!; [Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
[Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!; [Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[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 NameModifierSystem _nameMod = default!;
public const SlotFlags ProtectiveSlots = public const SlotFlags ProtectiveSlots =
SlotFlags.FEET | SlotFlags.FEET |
@@ -281,7 +282,7 @@ namespace Content.Server.Zombies
_humanoidAppearance.SetSkinColor(target, zombiecomp.BeforeZombifiedSkinColor, false); _humanoidAppearance.SetSkinColor(target, zombiecomp.BeforeZombifiedSkinColor, false);
_bloodstream.ChangeBloodReagent(target, zombiecomp.BeforeZombifiedBloodReagent); _bloodstream.ChangeBloodReagent(target, zombiecomp.BeforeZombifiedBloodReagent);
_metaData.SetEntityName(target, zombiecomp.BeforeZombifiedEntityName); _nameMod.RefreshNameModifiers(target);
return true; return true;
} }

View File

@@ -6,11 +6,6 @@ namespace Content.Shared.Glue;
[Access(typeof(SharedGlueSystem))] [Access(typeof(SharedGlueSystem))]
public sealed partial class GluedComponent : Component public sealed partial class GluedComponent : Component
{ {
/// <summary>
/// Reverts name to before prefix event (essentially removes prefix).
/// </summary>
[DataField("beforeGluedEntityName"), ViewVariables(VVAccess.ReadOnly)]
public string BeforeGluedEntityName = string.Empty;
[DataField("until", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] [DataField("until", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Until; public TimeSpan Until;

View File

@@ -7,6 +7,7 @@ using Content.Shared.Gravity;
using Content.Shared.IdentityManagement.Components; using Content.Shared.IdentityManagement.Components;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Content.Shared.Movement.Systems; using Content.Shared.Movement.Systems;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Overlays; using Content.Shared.Overlays;
using Content.Shared.Radio; using Content.Shared.Radio;
using Content.Shared.Slippery; using Content.Shared.Slippery;
@@ -28,6 +29,7 @@ public partial class InventorySystem
SubscribeLocalEvent<InventoryComponent, SeeIdentityAttemptEvent>(RelayInventoryEvent); SubscribeLocalEvent<InventoryComponent, SeeIdentityAttemptEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(RelayInventoryEvent); SubscribeLocalEvent<InventoryComponent, ModifyChangedTemperatureEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, GetDefaultRadioChannelEvent>(RelayInventoryEvent); SubscribeLocalEvent<InventoryComponent, GetDefaultRadioChannelEvent>(RelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, RefreshNameModifiersEvent>(RelayInventoryEvent);
// by-ref events // by-ref events
SubscribeLocalEvent<InventoryComponent, GetExplosionResistanceEvent>(RefRelayInventoryEvent); SubscribeLocalEvent<InventoryComponent, GetExplosionResistanceEvent>(RefRelayInventoryEvent);

View File

@@ -14,11 +14,4 @@ public sealed partial class LabelComponent : Component
/// </summary> /// </summary>
[DataField, AutoNetworkedField] [DataField, AutoNetworkedField]
public string? CurrentLabel { get; set; } public string? CurrentLabel { get; set; }
/// <summary>
/// The original name of the entity
/// Used for reverting the modified entity name when the label is removed
/// </summary>
[DataField, AutoNetworkedField]
public string? OriginalName { get; set; }
} }

View File

@@ -1,5 +1,6 @@
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Labels.Components; using Content.Shared.Labels.Components;
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Shared.Labels.EntitySystems; namespace Content.Shared.Labels.EntitySystems;
@@ -11,6 +12,7 @@ public abstract partial class SharedLabelSystem : EntitySystem
base.Initialize(); base.Initialize();
SubscribeLocalEvent<LabelComponent, ExaminedEvent>(OnExamine); SubscribeLocalEvent<LabelComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<LabelComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
} }
public virtual void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null){} public virtual void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null){}
@@ -27,4 +29,10 @@ public abstract partial class SharedLabelSystem : EntitySystem
message.AddText(Loc.GetString("hand-labeler-has-label", ("label", label.CurrentLabel))); message.AddText(Loc.GetString("hand-labeler-has-label", ("label", label.CurrentLabel)));
args.PushMessage(message); args.PushMessage(message);
} }
private void OnRefreshNameModifiers(Entity<LabelComponent> entity, ref RefreshNameModifiersEvent args)
{
if (!string.IsNullOrEmpty(entity.Comp.CurrentLabel))
args.AddModifier("comp-label-format", extraArgs: ("label", entity.Comp.CurrentLabel));
}
} }

View File

@@ -3,12 +3,6 @@ namespace Content.Shared.Lube;
[RegisterComponent] [RegisterComponent]
public sealed partial class LubedComponent : Component public sealed partial class LubedComponent : Component
{ {
/// <summary>
/// Reverts name to before prefix event (essentially removes prefix).
/// </summary>
[DataField("beforeLubedEntityName")]
public string BeforeLubedEntityName = string.Empty;
[DataField("slipsLeft"), ViewVariables(VVAccess.ReadWrite)] [DataField("slipsLeft"), ViewVariables(VVAccess.ReadWrite)]
public int SlipsLeft; public int SlipsLeft;

View File

@@ -0,0 +1,25 @@
using Robust.Shared.GameStates;
namespace Content.Shared.NameModifier.Components;
/// <summary>
/// Adds a modifier to the wearer's name when this item is equipped,
/// and removes it when it is unequipped.
/// </summary>
[RegisterComponent, NetworkedComponent]
[AutoGenerateComponentState]
public sealed partial class ModifyWearerNameComponent : Component
{
/// <summary>
/// The localization ID of the text to be used as the modifier.
/// The base name will be passed in as <c>$baseName</c>
/// </summary>
[DataField, AutoNetworkedField]
public LocId LocId = string.Empty;
/// <summary>
/// Priority of the modifier. See <see cref="EntitySystems.RefreshNameModifiersEvent"/> for more information.
/// </summary>
[DataField, AutoNetworkedField]
public int Priority;
}

View File

@@ -0,0 +1,20 @@
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.GameStates;
namespace Content.Shared.NameModifier.Components;
/// <summary>
/// Used to manage modifiers on an entity's name and handle renaming in a way
/// that survives being renamed by multiple systems.
/// </summary>
[RegisterComponent]
[NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(NameModifierSystem))]
public sealed partial class NameModifierComponent : Component
{
/// <summary>
/// The entity's name without any modifiers applied.
/// </summary>
[DataField, AutoNetworkedField]
public string BaseName = string.Empty;
}

View File

@@ -0,0 +1,34 @@
using Content.Shared.Clothing;
using Content.Shared.Inventory;
using Content.Shared.NameModifier.Components;
namespace Content.Shared.NameModifier.EntitySystems;
public sealed partial class ModifyWearerNameSystem : EntitySystem
{
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ModifyWearerNameComponent, InventoryRelayedEvent<RefreshNameModifiersEvent>>(OnRefreshNameModifiers);
SubscribeLocalEvent<ModifyWearerNameComponent, ClothingGotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<ModifyWearerNameComponent, ClothingGotUnequippedEvent>(OnGotUnequipped);
}
private void OnGotEquipped(Entity<ModifyWearerNameComponent> entity, ref ClothingGotEquippedEvent args)
{
_nameMod.RefreshNameModifiers(args.Wearer);
}
private void OnGotUnequipped(Entity<ModifyWearerNameComponent> entity, ref ClothingGotUnequippedEvent args)
{
_nameMod.RefreshNameModifiers(args.Wearer);
}
private void OnRefreshNameModifiers(Entity<ModifyWearerNameComponent> entity, ref InventoryRelayedEvent<RefreshNameModifiersEvent> args)
{
args.Args.AddModifier(entity.Comp.LocId, entity.Comp.Priority);
}
}

View File

@@ -0,0 +1,143 @@
using System.Linq;
using Content.Shared.Inventory;
using Content.Shared.NameModifier.Components;
namespace Content.Shared.NameModifier.EntitySystems;
/// <inheritdoc cref="NameModifierComponent"/>
public sealed partial class NameModifierSystem : EntitySystem
{
[Dependency] private readonly MetaDataSystem _metaData = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<NameModifierComponent, EntityRenamedEvent>(OnEntityRenamed);
}
private void OnEntityRenamed(Entity<NameModifierComponent> entity, ref EntityRenamedEvent args)
{
SetBaseName((entity, entity.Comp), args.NewName);
RefreshNameModifiers((entity, entity.Comp));
}
private void SetBaseName(Entity<NameModifierComponent> entity, string name)
{
if (name == entity.Comp.BaseName)
return;
// Set the base name to the new name
entity.Comp.BaseName = name;
Dirty(entity);
}
/// <summary>
/// Raises a <see cref="RefreshNameModifiersEvent"/> to gather modifiers and
/// updates the entity's name to its base name with modifiers applied.
/// This will add a <see cref="NameModifierComponent"/> if any modifiers are added.
/// </summary>
/// <remarks>
/// Call this to update the entity's name when adding or removing a modifier.
/// </remarks>
public void RefreshNameModifiers(Entity<NameModifierComponent?> entity)
{
var meta = MetaData(entity);
var baseName = meta.EntityName;
if (Resolve(entity, ref entity.Comp, logMissing: false))
baseName = entity.Comp.BaseName;
// Raise an event to get any modifiers
// If the entity already has the component, use its BaseName, otherwise use the entity's name from metadata
var modifierEvent = new RefreshNameModifiersEvent(baseName);
RaiseLocalEvent(entity, ref modifierEvent);
// Nothing added a modifier, so we can just use the base name
if (modifierEvent.ModifierCount == 0)
{
// If the entity doesn't have the component, we're done
if (entity.Comp == null)
return;
// Restore the base name
_metaData.SetEntityName(entity, entity.Comp.BaseName, meta, raiseEvents: false);
// The component isn't doing anything anymore, so remove it
RemComp<NameModifierComponent>(entity);
return;
}
// We have at least one modifier, so we need to apply it to the entity.
// Get the final name with modifiers applied
var modifiedName = modifierEvent.GetModifiedName();
// Add the component if needed, and initialize it with the base name
if (!EnsureComp<NameModifierComponent>(entity, out var comp))
SetBaseName((entity, comp), meta.EntityName);
// Set the entity's name with modifiers applied
_metaData.SetEntityName(entity, modifiedName, meta, raiseEvents: false);
}
}
/// <summary>
/// Raised on an entity when <see cref="NameModifierSystem.RefreshNameModifiers"/> is called.
/// Subscribe to this event and use its methods to add modifiers to the entity's name.
/// </summary>
[ByRefEvent]
public sealed class RefreshNameModifiersEvent : IInventoryRelayEvent
{
/// <summary>
/// The entity's name without any modifiers applied.
/// If you want to base a modifier on the entity's name, use
/// this so you don't include other modifiers.
/// </summary>
public readonly string BaseName;
private readonly List<(LocId LocId, int Priority, (string, object)[] ExtraArgs)> _modifiers = [];
/// <inheritdoc/>
public SlotFlags TargetSlots => ~SlotFlags.POCKET;
/// <summary>
/// How many modifiers have been added to this event.
/// </summary>
public int ModifierCount => _modifiers.Count;
public RefreshNameModifiersEvent(string baseName)
{
BaseName = baseName;
}
/// <summary>
/// Adds a modifier to the entity's name.
/// The original name will be passed to Fluent as <c>$baseName</c> along with any <paramref name="extraArgs"/>.
/// Modifiers with a higher <paramref name="priority"/> will be applied later.
/// </summary>
public void AddModifier(LocId locId, int priority = 0, params (string, object)[] extraArgs)
{
_modifiers.Add((locId, priority, extraArgs));
}
/// <summary>
/// Returns the final name with all modifiers applied.
/// </summary>
public string GetModifiedName()
{
// Start out with the entity's name name
var name = BaseName;
// Iterate through all the modifiers in priority order
foreach (var modifier in _modifiers.OrderBy(n => n.Priority))
{
// Grab any extra args needed by the Loc string
var args = modifier.ExtraArgs;
// Add the current version of the entity name as an arg
Array.Resize(ref args, args.Length + 1);
args[^1] = ("baseName", name);
// Resolve the Loc string and use the result as the base in the next iteration.
name = Loc.GetString(modifier.LocId, args);
}
return name;
}
}

View File

@@ -35,10 +35,4 @@ public sealed partial class InfantComponent : Component
[DataField("infantEndTime", customTypeSerializer: typeof(TimeOffsetSerializer))] [DataField("infantEndTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoPausedField] [AutoPausedField]
public TimeSpan InfantEndTime; public TimeSpan InfantEndTime;
/// <summary>
/// The entity's name before the "baby" prefix is added.
/// </summary>
[DataField("originalName")]
public string OriginalName = string.Empty;
} }

View File

@@ -1,4 +1,5 @@
using Content.Shared.Movement.Systems; using Content.Shared.Movement.Systems;
using Content.Shared.NameModifier.EntitySystems;
namespace Content.Shared.Zombies; namespace Content.Shared.Zombies;
@@ -10,6 +11,7 @@ public abstract class SharedZombieSystem : EntitySystem
base.Initialize(); base.Initialize();
SubscribeLocalEvent<ZombieComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshSpeed); SubscribeLocalEvent<ZombieComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshSpeed);
SubscribeLocalEvent<ZombieComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
} }
private void OnRefreshSpeed(EntityUid uid, ZombieComponent component, RefreshMovementSpeedModifiersEvent args) private void OnRefreshSpeed(EntityUid uid, ZombieComponent component, RefreshMovementSpeedModifiersEvent args)
@@ -17,4 +19,9 @@ public abstract class SharedZombieSystem : EntitySystem
var mod = component.ZombieMovementSpeedDebuff; var mod = component.ZombieMovementSpeedDebuff;
args.ModifySpeed(mod, mod); args.ModifySpeed(mod, mod);
} }
private void OnRefreshNameModifiers(Entity<ZombieComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("zombie-name-prefix");
}
} }

View File

@@ -62,12 +62,6 @@ public sealed partial class ZombieComponent : Component
[DataField("zombieRoleId", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))] [DataField("zombieRoleId", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
public string ZombieRoleId = "Zombie"; public string ZombieRoleId = "Zombie";
/// <summary>
/// The EntityName of the humanoid to restore in case of cloning
/// </summary>
[DataField("beforeZombifiedEntityName"), ViewVariables(VVAccess.ReadOnly)]
public string BeforeZombifiedEntityName = string.Empty;
/// <summary> /// <summary>
/// The CustomBaseLayers of the humanoid to restore in case of cloning /// The CustomBaseLayers of the humanoid to restore in case of cloning
/// </summary> /// </summary>

View File

@@ -1 +1 @@
transformable-container-component-glass = {$name} glass transformable-container-component-glass = {$reagent} glass

View File

@@ -1,2 +1,2 @@
cluwne-transform = {CAPITALIZE(THE($target))} turned into a cluwne! cluwne-transform = {CAPITALIZE(THE($target))} turned into a cluwne!
cluwne-name-prefix = Cluwnified {$target} cluwne-name-prefix = cluwnified {$baseName}

View File

@@ -1,5 +1,5 @@
glue-success = {THE($target)} has been covered in glue! glue-success = {THE($target)} has been covered in glue!
glued-name-prefix = Glued {$target} glued-name-prefix = glued {$baseName}
glue-failure = Can't cover {THE($target)} in glue! glue-failure = Can't cover {THE($target)} in glue!
glue-verb-text = Apply Glue glue-verb-text = Apply Glue
glue-verb-message = Glue an object glue-verb-message = Glue an object

View File

@@ -0,0 +1 @@
comp-label-format = {$baseName} ({$label})

View File

@@ -1,5 +1,5 @@
lube-success = {THE($target)} has been covered in lube! lube-success = {THE($target)} has been covered in lube!
lubed-name-prefix = Lubed {$target} lubed-name-prefix = lubed {$baseName}
lube-failure = Can't cover {THE($target)} in lube! lube-failure = Can't cover {THE($target)} in lube!
lube-slip = {THE($target)} slips out of your hands! lube-slip = {THE($target)} slips out of your hands!
lube-verb-text = Apply Lube lube-verb-text = Apply Lube

View File

@@ -1,3 +1,3 @@
infant-name-prefix = baby {$name} infant-name-prefix = baby {$baseName}
reproductive-birth-popup = {CAPITALIZE(THE($parent))} gave birth! reproductive-birth-popup = {CAPITALIZE(THE($parent))} gave birth!
reproductive-laid-egg-popup = {CAPITALIZE(THE($parent))} lays an egg! reproductive-laid-egg-popup = {CAPITALIZE(THE($parent))} lays an egg!

View File

@@ -2,7 +2,7 @@ zombie-transform = {CAPITALIZE(THE($target))} turned into a zombie!
zombie-infection-greeting = You have become a zombie. Your goal is to seek out the living and to try to infect them. Work together with the other zombies to overtake the station. zombie-infection-greeting = You have become a zombie. Your goal is to seek out the living and to try to infect them. Work together with the other zombies to overtake the station.
zombie-generic = zombie zombie-generic = zombie
zombie-name-prefix = Zombified {$target} zombie-name-prefix = zombified {$baseName}
zombie-role-desc = A malevolent creature of the dead. zombie-role-desc = A malevolent creature of the dead.
zombie-role-rules = You are an antagonist. Search out the living and bite them in order to infect them and turn them into zombies. Work together with the other zombies to overtake the station. zombie-role-rules = You are an antagonist. Search out the living and bite them in order to infect them and turn them into zombies. Work together with the other zombies to overtake the station.

View File

@@ -79,7 +79,6 @@
- !type:DoActsBehavior - !type:DoActsBehavior
acts: [ "Destruction" ] acts: [ "Destruction" ]
- type: Label - type: Label
originalName: jug
- type: Tag - type: Tag
tags: tags:
- ChemDispensable - ChemDispensable