diff --git a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs
index ed129dc9f6d..d3210c920a4 100644
--- a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs
+++ b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs
@@ -24,6 +24,6 @@ public override void UpdateState(BoundUserInterfaceState state)
if (state is not CrewManifestUiState crewManifestState)
return;
- _fragment?.UpdateState(crewManifestState.StationName, crewManifestState.Entries);
+ _fragment?.UpdateState(crewManifestState.Entries); // coyote: remove name
}
}
diff --git a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs
index 27ddd51815e..9752f698adb 100644
--- a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs
+++ b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs
@@ -19,13 +19,13 @@ public CrewManifestUiFragment()
VerticalExpand = true;
}
- public void UpdateState(string stationName, CrewManifestEntries? entries)
+ public void UpdateState(CrewManifestEntries? entries) // coyote: remove name
{
CrewManifestListing.DisposeAllChildren();
CrewManifestListing.RemoveAllChildren();
StationNameContainer.Visible = entries != null;
- StationName.Text = stationName;
+ StationName.Text = "Crew Manifest"; // coyote: remove name
if (entries == null)
return;
diff --git a/Content.Client/CrewManifest/CrewManifestEui.cs b/Content.Client/CrewManifest/CrewManifestEui.cs
index 500f91019d6..64418cf1c7f 100644
--- a/Content.Client/CrewManifest/CrewManifestEui.cs
+++ b/Content.Client/CrewManifest/CrewManifestEui.cs
@@ -43,6 +43,6 @@ public override void HandleState(EuiStateBase state)
return;
}
- _window.Populate(cast.StationName, cast.Entries);
+ _window.Populate(cast.Entries); // Coyote: Remove name
}
}
diff --git a/Content.Client/CrewManifest/CrewManifestUi.xaml.cs b/Content.Client/CrewManifest/CrewManifestUi.xaml.cs
index f07e54eb65b..f5923d55f6c 100644
--- a/Content.Client/CrewManifest/CrewManifestUi.xaml.cs
+++ b/Content.Client/CrewManifest/CrewManifestUi.xaml.cs
@@ -16,13 +16,13 @@ public CrewManifestUi()
StationName.AddStyleClass("LabelBig");
}
- public void Populate(string name, CrewManifestEntries? entries)
+ public void Populate(CrewManifestEntries? entries) // Coyote: Remove name
{
CrewManifestListing.DisposeAllChildren();
CrewManifestListing.RemoveAllChildren();
StationNameContainer.Visible = entries != null;
- StationName.Text = name;
+ StationName.Text = "Crew Manifest"; // Coyote: Remove name
if (entries == null)
return;
diff --git a/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs b/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs
index 534bf7593a8..6844d5c7fe1 100644
--- a/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs
+++ b/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs
@@ -62,9 +62,9 @@ private void UpdateUiState(EntityUid uid, EntityUid loaderUid, CrewManifestCartr
if (owningStation is null)
return;
- var (stationName, entries) = _crewManifest.GetCrewManifest(owningStation.Value);
+ var entries = _crewManifest.GetCrewManifest(); // coyote: remove name
- var state = new CrewManifestUiState(stationName, entries);
+ var state = new CrewManifestUiState(entries); // coyote: remove name
_cartridgeLoader.UpdateCartridgeUiState(loaderUid, state);
}
diff --git a/Content.Server/CrewManifest/CrewManifestEui.cs b/Content.Server/CrewManifest/CrewManifestEui.cs
index fbda27657da..d99de31841e 100644
--- a/Content.Server/CrewManifest/CrewManifestEui.cs
+++ b/Content.Server/CrewManifest/CrewManifestEui.cs
@@ -27,10 +27,10 @@ public CrewManifestEui(EntityUid station, EntityUid? owner, CrewManifestSystem c
_crewManifest = crewManifestSystem;
}
- public override CrewManifestEuiState GetNewState()
+ public override CrewManifestEuiState GetNewState() // Coyote: Remove name
{
- var (name, entries) = _crewManifest.GetCrewManifest(_station);
- return new(name, entries);
+ var entries = _crewManifest.GetCrewManifest();
+ return new(entries);
}
public override void Closed()
diff --git a/Content.Server/CrewManifest/CrewManifestSystem.cs b/Content.Server/CrewManifest/CrewManifestSystem.cs
index bd11db4caf4..60244bf9f1a 100644
--- a/Content.Server/CrewManifest/CrewManifestSystem.cs
+++ b/Content.Server/CrewManifest/CrewManifestSystem.cs
@@ -1,6 +1,9 @@
using System.Linq;
+using Content.Server.Access.Components; // Coyote
+using Content.Server.Access.Systems; // Coyote
using Content.Server.Administration;
using Content.Server.EUI;
+using Content.Server.Medical.SuitSensors; // Coyote
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Server.StationRecords;
@@ -10,6 +13,7 @@
using Content.Shared.CrewManifest;
using Content.Shared.GameTicking;
using Content.Shared.Roles;
+using Content.Shared.SSDIndicator;
using Content.Shared.StationRecords;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
@@ -26,6 +30,7 @@ public sealed class CrewManifestSystem : EntitySystem
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ [Dependency] private readonly IdCardSystem _idCardSystem = default!; // Coyote
///
/// Cached crew manifest entries. The alternative is to outright
@@ -41,7 +46,6 @@ public override void Initialize()
SubscribeLocalEvent(AfterGeneralRecordCreated);
SubscribeLocalEvent(OnRecordModified);
SubscribeLocalEvent(OnRecordRemoved);
- /* SubscribeLocalEvent(OnRoundRestart); */
SubscribeNetworkEvent(OnRequestCrewManifest);
SubscribeLocalEvent(OnBoundUiClose);
@@ -78,20 +82,20 @@ private void OnRequestCrewManifest(RequestCrewManifestMessage message, EntitySes
// wrt the amount of players readied up.
private void AfterGeneralRecordCreated(AfterGeneralRecordCreatedEvent ev)
{
- BuildCrewManifest(ev.Key.OriginStation);
- UpdateEuis(ev.Key.OriginStation);
+ // BuildCrewManifest(); // coyote: NOP, we build on open
+ // UpdateEuis(ev.Key.OriginStation);
}
private void OnRecordModified(RecordModifiedEvent ev)
{
- BuildCrewManifest(ev.Key.OriginStation);
- UpdateEuis(ev.Key.OriginStation);
+ // BuildCrewManifest(); // coyote: NOP, we build on open
+ // UpdateEuis(ev.Key.OriginStation);
}
private void OnRecordRemoved(RecordRemovedEvent ev)
{
- BuildCrewManifest(ev.Key.OriginStation);
- UpdateEuis(ev.Key.OriginStation);
+ // BuildCrewManifest(); // coyote: NOP, we build on open
+ // UpdateEuis(ev.Key.OriginStation);
}
private void OnBoundUiClose(EntityUid uid, CrewManifestViewerComponent component, BoundUIClosedEvent ev)
@@ -113,10 +117,9 @@ private void OnBoundUiClose(EntityUid uid, CrewManifestViewerComponent component
///
/// Entity uid of the station.
/// The name and crew manifest entries (unordered) of the station.
- public (string name, CrewManifestEntries? entries) GetCrewManifest(EntityUid station)
+ public CrewManifestEntries GetCrewManifest() // coyote: remove args, remove name
{
- var valid = _cachedEntries.TryGetValue(station, out var manifest);
- return (valid ? MetaData(station).EntityName : string.Empty, valid ? manifest : null);
+ return BuildCrewManifest(); // coyote
}
private void UpdateEuis(EntityUid station)
@@ -219,22 +222,37 @@ public void CloseEui(EntityUid station, ICommonSession session, EntityUid? owner
///
/// Builds the crew manifest for a station. Stores it in the cache afterwards.
///
- ///
- private void BuildCrewManifest(EntityUid station)
+ private CrewManifestEntries BuildCrewManifest()
{
- var iter = _recordsSystem.GetRecordsOfType(station);
-
+ var sensors = EntityQueryEnumerator(); // Coyote
var entries = new CrewManifestEntries();
-
var entriesSort = new List<(JobPrototype? job, CrewManifestEntry entry)>();
- foreach (var recordObject in iter)
+
+ while (sensors.MoveNext(out var uid, out var sensor)) // Coyote start
{
- var record = recordObject.Item2;
- var entry = new CrewManifestEntry(record.Name, record.JobTitle, record.JobIcon, record.JobPrototype);
+ if (sensor.User == null || TryComp(sensor.User, out var indicator) && indicator.IsSSD)
+ {
+ continue;
+ }
+ var name = Loc.GetString("suit-sensor-component-unknown-name");
+ var jobTitle = Loc.GetString("suit-sensor-component-unknown-job");
- _prototypeManager.TryIndex(record.JobPrototype, out JobPrototype? job);
- entriesSort.Add((job, entry));
- }
+ if (!_idCardSystem.TryFindIdCard(sensor.User.Value, out var card))
+ continue;
+
+ if (card.Comp.FullName != null)
+ name = card.Comp.FullName;
+
+ if (card.Comp.LocalizedJobTitle != null)
+ jobTitle = card.Comp.LocalizedJobTitle;
+
+ if (!TryComp(card, out var preset))
+ continue;
+
+ var entry = new CrewManifestEntry(name, jobTitle, card.Comp.JobIcon, preset.JobName!.Value);
+
+ entriesSort.Add((null, entry));
+ } // Coyote end
entriesSort.Sort((a, b) =>
{
@@ -246,7 +264,8 @@ private void BuildCrewManifest(EntityUid station)
});
entries.Entries = entriesSort.Select(x => x.entry).ToArray();
- _cachedEntries[station] = entries;
+ // _cachedEntries[station] = entries; // coyote: causes problems
+ return entries; // coyote
}
}
diff --git a/Content.Server/GameTicking/GameTicker.Player.cs b/Content.Server/GameTicking/GameTicker.Player.cs
index 33e13dc0676..ed3df722a4a 100644
--- a/Content.Server/GameTicking/GameTicker.Player.cs
+++ b/Content.Server/GameTicking/GameTicker.Player.cs
@@ -203,6 +203,11 @@ public void PlayerJoinGame(ICommonSession session, bool silent = false)
RaiseNetworkEvent(new TickerJoinGameEvent(), session.Channel);
}
+ public void ReturnPlayerToLobby(ICommonSession session)
+ {
+ PlayerJoinLobby(session);
+ }
+
private void PlayerJoinLobby(ICommonSession session)
{
_playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay;
diff --git a/Content.Server/Gateway/Systems/GatewaySystem.cs b/Content.Server/Gateway/Systems/GatewaySystem.cs
index b17a21ca27f..a201550eaf5 100644
--- a/Content.Server/Gateway/Systems/GatewaySystem.cs
+++ b/Content.Server/Gateway/Systems/GatewaySystem.cs
@@ -103,17 +103,22 @@ private void UpdateUserInterface(EntityUid uid, GatewayComponent comp, Transform
if (!dest.Enabled || destUid == uid)
continue;
+ if (!TryComp(destUid, out var destMeta) || destMeta.EntityLifeStage >= EntityLifeStage.Terminating)
+ continue;
+
// Show destination if either no destination comp on the map or it's ours.
TryComp(destXform.MapUid, out var gatewayDestination);
var isDockingArm = HasComp(destUid);
- Log.Debug($"Gateway {ToPrettyString(uid)} found destination {ToPrettyString(destUid)} - IsDockingArm: {isDockingArm}, HasDockingArmComp: {HasComp(destUid)}, DestName: {MetaData(destUid).EntityName}");
+ Log.Debug($"Gateway {ToPrettyString(uid)} found destination {ToPrettyString(destUid)} - IsDockingArm: {isDockingArm}, HasDockingArmComp: {HasComp(destUid)}, DestName: {destMeta.EntityName}");
destinations.Add(new GatewayDestinationData()
{
Entity = GetNetEntity(destUid),
// Fallback to grid's ID if applicable.
- Name = dest.Name.IsEmpty && destXform.GridUid != null ? FormattedMessage.FromUnformatted(MetaData(destXform.GridUid.Value).EntityName) : dest.Name ,
+ Name = dest.Name.IsEmpty && destXform.GridUid != null && TryComp(destXform.GridUid.Value, out var gridMeta)
+ ? FormattedMessage.FromUnformatted(gridMeta.EntityName)
+ : dest.Name,
Portal = HasComp(destUid),
// If NextUnlock < CurTime it's unlocked, however
// we'll always send the client if it's locked
@@ -124,10 +129,18 @@ private void UpdateUserInterface(EntityUid uid, GatewayComponent comp, Transform
}
_linkedEntity.GetLink(uid, out var current);
+ NetEntity? currentNet = null;
+
+ if (current is { } currentUid &&
+ TryComp(currentUid, out var currentMeta) &&
+ currentMeta.EntityLifeStage < EntityLifeStage.Terminating)
+ {
+ currentNet = GetNetEntity(currentUid, currentMeta);
+ }
var state = new GatewayBoundUserInterfaceState(
destinations,
- GetNetEntity(current),
+ currentNet,
comp.NextReady,
comp.Cooldown,
nextUnlock,
diff --git a/Content.Server/Ghost/GhostCommand.cs b/Content.Server/Ghost/GhostCommand.cs
index f5df115fde1..23efb61a570 100644
--- a/Content.Server/Ghost/GhostCommand.cs
+++ b/Content.Server/Ghost/GhostCommand.cs
@@ -1,9 +1,10 @@
using Content.Server.Popups;
using Content.Shared.Administration;
using Content.Shared.GameTicking;
-using Content.Shared.Mind;
-using Robust.Shared.Console;
using Content.Server.GameTicking;
+using Content.Server.Mind;
+using Robust.Server.Player;
+using Robust.Shared.Console;
namespace Content.Server.Ghost
{
@@ -11,6 +12,7 @@ namespace Content.Server.Ghost
public sealed class GhostCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entities = default!;
+ [Dependency] private readonly IPlayerManager _playerManager = default!;
public string Command => "ghost";
public string Description => Loc.GetString("ghost-command-description");
@@ -43,17 +45,20 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
return;
}
- var minds = _entities.System();
- if (!minds.TryGetMind(player, out var mindId, out var mind))
+ if (player.AttachedEntity is not { Valid: true } controlled)
{
- mindId = minds.CreateMind(player.UserId);
- mind = _entities.GetComponent(mindId);
+ shell.WriteLine(Loc.GetString("ghost-command-error-lobby"));
+ return;
}
- if (!_entities.System().OnGhostAttempt(mindId, true, true, mind: mind))
- {
- shell.WriteLine(Loc.GetString("ghost-command-denied"));
- }
+ var minds = _entities.System();
+ if (minds.TryGetMind(player, out var mindId, out var mind))
+ minds.WipeMind(mindId, mind);
+ else
+ _playerManager.SetAttachedEntity(player, null);
+
+ _entities.DeleteEntity(controlled);
+ gameTicker.ReturnPlayerToLobby(player);
}
}
}
diff --git a/Content.Server/Lizards/Systems/LizardLinkerSystem.cs b/Content.Server/Lizards/Systems/LizardLinkerSystem.cs
index b027e1a2b6c..36b0b072820 100644
--- a/Content.Server/Lizards/Systems/LizardLinkerSystem.cs
+++ b/Content.Server/Lizards/Systems/LizardLinkerSystem.cs
@@ -12,6 +12,12 @@ public override void Initialize()
private void OnFollowerStartup(Entity ent, ref ComponentStartup args)
{
+ var xform = Transform(ent.Owner);
+
+ // Trail followers are moved directly to recorded leader coordinates, so
+ // grid traversal only adds recursive reparent checks when the leader crosses grids.
+ xform.GridTraversal = false;
+
if (ent.Comp.Leader != default)
return;
@@ -19,7 +25,6 @@ private void OnFollowerStartup(Entity ent, ref Component
var enumerator = EntityQueryEnumerator();
while (enumerator.MoveNext(out var leaderUid, out var leaderComp, out var leaderXform))
{
- var xform = Transform(ent.Owner);
if (leaderXform.MapID == xform.MapID && leaderXform.Coordinates.TryDistance(EntityManager, xform.Coordinates, out var dist) && dist < 1.0f)
{
ent.Comp.Leader = leaderUid;
diff --git a/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs b/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
index f478cb3ab47..e5d0ef0e4fc 100644
--- a/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
+++ b/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
@@ -28,7 +28,8 @@
using Content.Server.Salvage.Expeditions; // Frontier
using Content.Server._NF.Medical.SuitSensors; // Frontier
using Content.Shared.Emp;
-using Content.Shared.FloofStation; // Frontier
+using Content.Shared.FloofStation;
+using Content.Shared.SSDIndicator; // Frontier
namespace Content.Server.Medical.SuitSensors;
@@ -427,6 +428,10 @@ public void SetAllSensors(EntityUid target, SuitSensorMode mode, SlotFlags slots
if (EntityManager.TryGetComponent(sensor.User.Value, out MobStateComponent? mobState))
isAlive = !_mobStateSystem.IsDead(sensor.User.Value, mobState);
+ // Coyote: Don't show SSD people on suit sensors.
+ if (TryComp(sensor.User.Value, out var ssd) && ssd.IsSSD && isAlive)
+ return null;
+
// get mob total damage
var totalDamage = 0;
if (TryComp(sensor.User.Value, out var damageable))
diff --git a/Content.Server/Movement/Systems/PullController.cs b/Content.Server/Movement/Systems/PullController.cs
index 40345a5867d..46434090448 100644
--- a/Content.Server/Movement/Systems/PullController.cs
+++ b/Content.Server/Movement/Systems/PullController.cs
@@ -202,8 +202,11 @@ private void UpdatePulledRotation(EntityUid puller, EntityUid pulled)
if (!rotatable.RotateWhilePulling)
return;
- var pulledXform = _xformQuery.GetComponent(pulled);
- var pullerXform = _xformQuery.GetComponent(puller);
+ if (!_xformQuery.TryGetComponent(pulled, out var pulledXform) ||
+ !_xformQuery.TryGetComponent(puller, out var pullerXform))
+ {
+ return;
+ }
var pullerData = TransformSystem.GetWorldPositionRotation(pullerXform);
var pulledData = TransformSystem.GetWorldPositionRotation(pulledXform);
@@ -245,7 +248,12 @@ public override void UpdateBeforeSolve(bool prediction, float frameTime)
if (pullable.Puller is not {Valid: true} puller)
continue;
- var pullerXform = _xformQuery.Get(puller);
+ if (!_xformQuery.TryGetComponent(puller, out var pullerXform))
+ {
+ RemCompDeferred(pullableEnt);
+ continue;
+ }
+
var pullerPosition = TransformSystem.GetMapCoordinates(pullerXform);
var movingTo = TransformSystem.ToMapCoordinates(mover.MovingTo);
@@ -305,7 +313,7 @@ public override void UpdateBeforeSolve(bool prediction, float frameTime)
// if the puller is weightless or can't move, then we apply the inverse impulse (Newton's third law).
// doing it under gravity produces an unsatisfying wiggling when pulling.
// If player can't move, assume they are on a chair and we need to prevent pull-moving.
- if (_gravity.IsWeightless(puller) && pullerXform.Comp.GridUid == null || !_actionBlockerSystem.CanMove(puller))
+ if ((_gravity.IsWeightless(puller) && pullerXform.GridUid == null) || !_actionBlockerSystem.CanMove(puller))
{
PhysicsSystem.WakeBody(puller);
PhysicsSystem.ApplyLinearImpulse(puller, -impulse);
diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs
index be899937116..49135289975 100644
--- a/Content.Server/Temperature/Systems/TemperatureSystem.cs
+++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs
@@ -322,11 +322,15 @@ private void OnParentChange(EntityUid uid, TemperatureComponent component,
var temperatureQuery = GetEntityQuery();
var transformQuery = GetEntityQuery();
var thresholdsQuery = GetEntityQuery();
+
+ if (!transformQuery.TryGetComponent(uid, out var xform))
+ return;
+
// We only need to update thresholds if the thresholds changed for the entity's ancestors.
var oldThresholds = args.OldParent != null
? RecalculateParentThresholds(args.OldParent.Value, transformQuery, thresholdsQuery)
: (null, null);
- var newThresholds = RecalculateParentThresholds(transformQuery.GetComponent(uid).ParentUid, transformQuery, thresholdsQuery);
+ var newThresholds = RecalculateParentThresholds(xform.ParentUid, transformQuery, thresholdsQuery);
if (oldThresholds != newThresholds)
{
@@ -361,7 +365,10 @@ private void RecursiveThresholdUpdate(EntityUid root, EntityQuery(OnAccent);
+ }
+
+ private void OnAccent(EntityUid uid, BoganAccentComponent component, AccentGetEvent args)
+ {
+ var message = args.Message;
+
+ message = _replacement.ApplyReplacements(message, "bogan");
+
+ // Prefix
+ if (_random.Prob(0.15f))
+ {
+ var pick = _random.Next(1, 4);
+
+ // Reverse sanitize capital
+ message = message[0].ToString().ToLower() + message.Remove(0, 1);
+ message = Loc.GetString($"accent-bogan-prefix-{pick}") + " " + message;
+ }
+
+ // Sanitize capital again, in case we substituted a word that should be capitalized
+ message = message[0].ToString().ToUpper() + message.Remove(0, 1);
+
+ // Suffixes
+ if (_random.Prob(0.3f))
+ {
+ var pick = _random.Next(1, 5);
+ message += Loc.GetString($"accent-bogan-suffix-{pick}");
+ }
+
+ args.Message = message;
+ }
+};
diff --git a/Content.Server/_HL/RoundPersistence/Systems/RoundPersistenceSystem.cs b/Content.Server/_HL/RoundPersistence/Systems/RoundPersistenceSystem.cs
index e1814926bf3..1f063c1abcc 100644
--- a/Content.Server/_HL/RoundPersistence/Systems/RoundPersistenceSystem.cs
+++ b/Content.Server/_HL/RoundPersistence/Systems/RoundPersistenceSystem.cs
@@ -549,12 +549,6 @@ private void SaveStationData(EntityUid stationUid, StationDataComponent stationD
}
// Get crew manifest
- var (_, manifestEntries) = _crewManifest.GetCrewManifest(stationUid);
- if (manifestEntries != null)
- {
- persistedRecords.CrewManifest = manifestEntries.Entries.ToList();
- }
-
persistence.StationRecords[stationName] = persistedRecords;
}
}
diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs
index 5cb35b97a74..467e5529114 100644
--- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs
+++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs
@@ -25,7 +25,6 @@ namespace Content.Shared.Body.Systems;
public partial class SharedBodySystem
{
[Dependency] private readonly RandomHelperSystem _randomHelper = default!; // Shitmed Change
- [Dependency] private readonly InventorySystem _inventorySystem = default!; // Shitmed Change
private static readonly ProtoId BloodlossDamageId = "Bloodloss";
private void InitializeParts()
@@ -130,7 +129,7 @@ public void DropSlotContents(Entity partEnt)
&& TryGetPartSlotContainerName(partEnt.Comp.PartType, out var containerNames))
{
foreach (var containerName in containerNames)
- _inventorySystem.DropSlotContents(partEnt.Comp.Body.Value, containerName, inventory);
+ _inventory.DropSlotContents(partEnt.Comp.Body.Value, containerName, inventory);
}
}
@@ -206,7 +205,19 @@ protected virtual void DropPart(Entity partEnt)
RaiseLocalEvent(partEnt, ref enableEvent);
var droppedEvent = new BodyPartDroppedEvent(partEnt);
RaiseLocalEvent(body, ref droppedEvent);
- SharedTransform.AttachToGridOrMap(partEnt, transform);
+
+ if (body != EntityUid.Invalid)
+ {
+ var bodyTransform = Transform(body);
+ if (bodyTransform.MapUid != null)
+ SharedTransform.DropNextTo((partEnt.Owner, transform), (body, bodyTransform));
+ }
+
+ if (transform.MapUid != null)
+ {
+ SharedTransform.AttachToGridOrMap(partEnt, transform);
+ }
+
_randomHelper.RandomOffset(partEnt, 0.5f);
}
diff --git a/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs b/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs
index 9eaca5a2d3f..27c5eb5320a 100644
--- a/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs
+++ b/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs
@@ -6,12 +6,12 @@ namespace Content.Shared.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class CrewManifestUiState : BoundUserInterfaceState
{
- public string StationName;
+ // public string StationName; // coyote: remove name
public CrewManifestEntries? Entries;
- public CrewManifestUiState(string stationName, CrewManifestEntries? entries)
+ public CrewManifestUiState(CrewManifestEntries? entries) // coyote: remove name
{
- StationName = stationName;
+ // StationName = stationName; // coyote: remove name
Entries = entries;
}
}
diff --git a/Content.Shared/CrewManifest/SharedCrewManifestSystem.cs b/Content.Shared/CrewManifest/SharedCrewManifestSystem.cs
index a9279cc7f1f..a5c1f00d7e0 100644
--- a/Content.Shared/CrewManifest/SharedCrewManifestSystem.cs
+++ b/Content.Shared/CrewManifest/SharedCrewManifestSystem.cs
@@ -21,14 +21,12 @@ public RequestCrewManifestMessage(NetEntity id)
}
[Serializable, NetSerializable]
-public sealed class CrewManifestEuiState : EuiStateBase
+public sealed class CrewManifestEuiState : EuiStateBase // Coyote: Removed StationName
{
- public string StationName { get; }
public CrewManifestEntries? Entries { get; }
- public CrewManifestEuiState(string stationName, CrewManifestEntries? entries)
+ public CrewManifestEuiState(CrewManifestEntries? entries)
{
- StationName = stationName;
Entries = entries;
}
}
diff --git a/Content.Shared/Light/Components/UnpoweredFlashlightComponent.cs b/Content.Shared/Light/Components/UnpoweredFlashlightComponent.cs
index 2953a01ced8..7a963a390fc 100644
--- a/Content.Shared/Light/Components/UnpoweredFlashlightComponent.cs
+++ b/Content.Shared/Light/Components/UnpoweredFlashlightComponent.cs
@@ -2,6 +2,7 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
namespace Content.Shared.Light.Components;
@@ -9,19 +10,19 @@ namespace Content.Shared.Light.Components;
/// This is simplified version of .
/// It doesn't consume any power and can be toggle only by verb.
///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[RegisterComponent, NetworkedComponent]
public sealed partial class UnpoweredFlashlightComponent : Component
{
[DataField("toggleFlashlightSound")]
public SoundSpecifier ToggleSound = new SoundPathSpecifier("/Audio/Items/flashlight_pda.ogg");
- [DataField, AutoNetworkedField]
+ [DataField]
public bool LightOn;
[DataField]
public EntProtoId ToggleAction = "ActionToggleLight";
- [DataField, AutoNetworkedField]
+ [DataField]
public EntityUid? ToggleActionEntity;
///
@@ -31,3 +32,16 @@ public sealed partial class UnpoweredFlashlightComponent : Component
[DataField, ViewVariables(VVAccess.ReadWrite)]
public ProtoId EmaggedColorsPrototype = "Emagged";
}
+
+[Serializable, NetSerializable]
+public sealed class UnpoweredFlashlightComponentState : ComponentState
+{
+ public readonly bool LightOn;
+ public readonly NetEntity? ToggleActionEntity;
+
+ public UnpoweredFlashlightComponentState(bool lightOn, NetEntity? toggleActionEntity)
+ {
+ LightOn = lightOn;
+ ToggleActionEntity = toggleActionEntity;
+ }
+}
diff --git a/Content.Shared/Light/EntitySystems/UnpoweredFlashlightSystem.cs b/Content.Shared/Light/EntitySystems/UnpoweredFlashlightSystem.cs
index 6dc6cbfe0b3..b77fef20b0b 100644
--- a/Content.Shared/Light/EntitySystems/UnpoweredFlashlightSystem.cs
+++ b/Content.Shared/Light/EntitySystems/UnpoweredFlashlightSystem.cs
@@ -6,6 +6,7 @@
using Content.Shared.Toggleable;
using Content.Shared.Verbs;
using Robust.Shared.Audio.Systems;
+using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -35,6 +36,33 @@ public override void Initialize()
SubscribeLocalEvent(OnMindAdded);
SubscribeLocalEvent(OnGotEmagged);
SubscribeLocalEvent(OnMapInit);
+ SubscribeLocalEvent(OnGetState);
+ SubscribeLocalEvent(OnHandleState);
+ }
+
+ private void OnGetState(EntityUid uid, UnpoweredFlashlightComponent component, ref ComponentGetState args)
+ {
+ NetEntity? toggleAction = null;
+
+ if (component.ToggleActionEntity is { } toggleActionUid &&
+ MetaData(toggleActionUid) is { } meta &&
+ meta.EntityLifeStage < EntityLifeStage.Terminating)
+ {
+ toggleAction = GetNetEntity(toggleActionUid, meta);
+ }
+
+ args.State = new UnpoweredFlashlightComponentState(component.LightOn, toggleAction);
+ }
+
+ private void OnHandleState(EntityUid uid, UnpoweredFlashlightComponent component, ref ComponentHandleState args)
+ {
+ if (args.Current is not UnpoweredFlashlightComponentState state)
+ return;
+
+ component.LightOn = state.LightOn;
+ component.ToggleActionEntity = state.ToggleActionEntity is { } action && TryGetEntity(action, out var actionUid)
+ ? actionUid
+ : null;
}
private void OnMapInit(EntityUid uid, UnpoweredFlashlightComponent component, MapInitEvent args)
diff --git a/Content.Shared/Teleportation/Components/LinkedEntityComponent.cs b/Content.Shared/Teleportation/Components/LinkedEntityComponent.cs
index b1df6f4ee7e..e771332b73c 100644
--- a/Content.Shared/Teleportation/Components/LinkedEntityComponent.cs
+++ b/Content.Shared/Teleportation/Components/LinkedEntityComponent.cs
@@ -8,14 +8,14 @@ namespace Content.Shared.Teleportation.Components;
/// Represents an entity which is linked to other entities (perhaps portals), and which can be walked through /
/// thrown into to teleport an entity.
///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[RegisterComponent, NetworkedComponent]
[Access(typeof(LinkedEntitySystem))]
public sealed partial class LinkedEntityComponent : Component
{
///
/// The entities that this entity is linked to.
///
- [DataField, AutoNetworkedField]
+ [DataField]
public HashSet LinkedEntities = new();
///
@@ -25,6 +25,17 @@ public sealed partial class LinkedEntityComponent : Component
public bool DeleteOnEmptyLinks;
}
+[Serializable, NetSerializable]
+public sealed class LinkedEntityComponentState : ComponentState
+{
+ public HashSet LinkedEntities { get; }
+
+ public LinkedEntityComponentState(HashSet linkedEntities)
+ {
+ LinkedEntities = linkedEntities;
+ }
+}
+
[Serializable, NetSerializable]
public enum LinkedEntityVisuals : byte
{
diff --git a/Content.Shared/Teleportation/Systems/LinkedEntitySystem.cs b/Content.Shared/Teleportation/Systems/LinkedEntitySystem.cs
index 35ce5665ddf..4fbb0d9cd2f 100644
--- a/Content.Shared/Teleportation/Systems/LinkedEntitySystem.cs
+++ b/Content.Shared/Teleportation/Systems/LinkedEntitySystem.cs
@@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Teleportation.Components;
+using Robust.Shared.GameStates;
namespace Content.Shared.Teleportation.Systems;
@@ -18,9 +19,41 @@ public override void Initialize()
{
base.Initialize();
+ SubscribeLocalEvent(OnGetState);
+ SubscribeLocalEvent(OnHandleState);
SubscribeLocalEvent(OnLinkShutdown);
}
+ private void OnGetState(EntityUid uid, LinkedEntityComponent component, ref ComponentGetState args)
+ {
+ var linkedEntities = new HashSet();
+
+ foreach (var linked in component.LinkedEntities)
+ {
+ if (TerminatingOrDeleted(linked) || !HasComp(linked))
+ continue;
+
+ linkedEntities.Add(GetNetEntity(linked));
+ }
+
+ args.State = new LinkedEntityComponentState(linkedEntities);
+ }
+
+ private void OnHandleState(EntityUid uid, LinkedEntityComponent component, ref ComponentHandleState args)
+ {
+ if (args.Current is not LinkedEntityComponentState state)
+ return;
+
+ component.LinkedEntities.Clear();
+ foreach (var linked in state.LinkedEntities)
+ {
+ if (!TryGetEntity(linked, out var linkedUid) || TerminatingOrDeleted(linkedUid))
+ continue;
+
+ component.LinkedEntities.Add(linkedUid.Value);
+ }
+ }
+
private void OnLinkShutdown(EntityUid uid, LinkedEntityComponent component, ComponentShutdown args)
{
// Remove any links to this entity when deleted.
diff --git a/Resources/Locale/en-US/_DV/accent/bogan.ftl b/Resources/Locale/en-US/_DV/accent/bogan.ftl
new file mode 100644
index 00000000000..fa56b0d2a58
--- /dev/null
+++ b/Resources/Locale/en-US/_DV/accent/bogan.ftl
@@ -0,0 +1,247 @@
+accent-bogan-prefix-1 = Fuckin',
+accent-bogan-prefix-2 = Ye nah,
+accent-bogan-prefix-3 = Nah, yeah, nah,
+accent-bogan-prefix-4 = Mmmmm,
+
+accent-bogan-suffix-1 = , cunt.
+accent-bogan-suffix-2 = , fuckin' oath.
+accent-bogan-suffix-3 = , fuckin' oath cunt.
+accent-bogan-suffix-4 = , ya fuckin druggo.
+accent-bogan-suffix-5 = , you fucking drug addict.
+
+accent-bogan-words-1 = woman
+accent-bogan-words-replace-1 = sheila
+
+accent-bogan-words-2 = girl
+accent-bogan-words-replace-2 = sheila
+
+accent-bogan-words-3 = guy
+accent-bogan-words-replace-3 = bloke
+
+accent-bogan-words-4 = man
+accent-bogan-words-replace-4 = bloke
+
+accent-bogan-words-5 = good
+accent-bogan-words-replace-5 = fuckin' skitz
+
+accent-bogan-words-6 = cool
+accent-bogan-words-replace-6 = skiz
+
+accent-bogan-words-7 = what?
+accent-bogan-words-replace-7 = whuddyatalkinabeet?
+
+accent-bogan-words-8 = weed
+accent-bogan-words-replace-8 = yoweed
+
+accent-bogan-words-9 = heroin
+accent-bogan-words-replace-9 = heroween
+
+accent-bogan-words-10 = popcorn
+accent-bogan-words-replace-10 = popcoin
+
+accent-bogan-words-11 = asshole
+accent-bogan-words-replace-11 = dog cunt
+
+accent-bogan-words-12 = roach
+accent-bogan-words-replace-12 = stingin' roger
+
+accent-bogan-words-13 = sup
+accent-bogan-words-replace-13 = s'goin' on
+
+accent-bogan-words-14 = what's going on
+accent-bogan-words-replace-14 = s'goin' on
+
+accent-bogan-words-15 = hey
+accent-bogan-words-replace-15 = oi
+
+accent-bogan-words-16 = hi
+accent-bogan-words-replace-16 = oi
+
+accent-bogan-words-17 = hello
+accent-bogan-words-replace-17 = oi
+
+accent-bogan-words-18 = dude
+accent-bogan-words-replace-18 = mate
+
+accent-bogan-words-19 = ruined
+accent-bogan-words-replace-19 = fucked
+
+accent-bogan-words-20 = shuttle
+accent-bogan-words-replace-20 = tinnie
+
+accent-bogan-words-21 = cargo technician
+accent-bogan-words-replace-21 = tradie
+
+accent-bogan-words-22 = cargo tech
+accent-bogan-words-replace-22 = tradie
+
+accent-bogan-words-23 = cargo
+accent-bogan-words-replace-23 = tradies
+
+accent-bogan-words-24 = its
+accent-bogan-words-replace-24 = she's
+
+accent-bogan-words-25 = epic
+accent-bogan-words-replace-25 = sick
+
+accent-bogan-words-26 = joint
+accent-bogan-words-replace-26 = durry
+
+accent-bogan-words-27 = lots
+accent-bogan-words-replace-27 = loads
+
+accent-bogan-words-28 = alot
+accent-bogan-words-replace-28 = loads
+
+accent-bogan-words-29 = cigarette
+accent-bogan-words-replace-29 = ciggy
+
+accent-bogan-words-30 = you guys
+accent-bogan-words-replace-30 = yous lot
+
+accent-bogan-words-31 = slime
+accent-bogan-words-replace-31 = chooma
+
+accent-bogan-words-32 = slimes
+accent-bogan-words-replace-32 = chooma's
+
+accent-bogan-words-33 = blunt
+accent-bogan-words-replace-33 = doobskin
+
+accent-bogan-words-34 = idiot
+accent-bogan-words-replace-34 = fuckwit
+
+accent-bogan-words-35 = true
+accent-bogan-words-replace-35 = struth
+
+accent-bogan-words-36 = lying
+accent-bogan-words-replace-36 = full of shit
+
+accent-bogan-words-37 = bye
+accent-bogan-words-replace-37 = i'll catcha later
+
+accent-bogan-words-38 = sure
+accent-bogan-words-replace-38 = easy as
+
+accent-bogan-words-39 = my
+accent-bogan-words-replace-39 = me
+
+accent-bogan-words-40 = ok
+accent-bogan-words-replace-40 = no worries
+
+accent-bogan-words-41 = smoke
+accent-bogan-words-replace-41 = smoko
+
+accent-bogan-words-42 = friend
+accent-bogan-words-replace-42 = old mate
+
+accent-bogan-words-43 = meds
+accent-bogan-words-replace-43 = drugs
+
+accent-bogan-words-44 = chemist
+accent-bogan-words-replace-44 = junkie
+
+accent-bogan-words-45 = security officer
+accent-bogan-words-replace-45 = coppa
+
+accent-bogan-words-46 = a tider
+accent-bogan-words-replace-46 = an eshay
+
+accent-bogan-words-47 = mushrooms
+accent-bogan-words-replace-47 = shrooms
+
+accent-bogan-words-48 = bar
+accent-bogan-words-replace-48 = bottle-o
+
+accent-bogan-words-49 = chicken
+accent-bogan-words-replace-49 = chook
+
+accent-bogan-words-50 = criminal
+accent-bogan-words-replace-50 = crook
+
+accent-bogan-words-51 = clothes
+accent-bogan-words-replace-51 = dacks
+
+accent-bogan-words-52 = toilet
+accent-bogan-words-replace-52 = dunny
+
+accent-bogan-words-53 = candy
+accent-bogan-words-replace-53 = lollies
+
+accent-bogan-words-54 = drunk
+accent-bogan-words-replace-54 = pissed
+
+accent-bogan-words-55 = happy
+accent-bogan-words-replace-55 = stoked
+
+accent-bogan-words-56 = sad
+accent-bogan-words-replace-56 = bumbed out
+
+accent-bogan-words-57 = awesome
+accent-bogan-words-replace-57 = legend
+
+accent-bogan-words-58 = engie
+accent-bogan-words-replace-58 = sparkie
+
+accent-bogan-words-59 = serious
+accent-bogan-words-replace-59 = dead set
+
+accent-bogan-words-60 = sunglasses
+accent-bogan-words-replace-60 = sunnies
+
+accent-bogan-words-61 = food
+accent-bogan-words-replace-61 = mac'n'cheese n' apple juice
+
+accent-bogan-words-62 = death mix
+accent-bogan-words-replace-62 = trippa snippa
+
+accent-bogan-words-63 = soap
+accent-bogan-words-replace-63 = pino clean
+
+accent-bogan-words-64 = purple
+accent-bogan-words-replace-64 = poiple
+
+accent-bogan-words-65 = wizard
+accent-bogan-words-replace-65 = magic man
+
+accent-bogan-words-66 = coward
+accent-bogan-words-replace-66 = pussy
+
+accent-bogan-words-67 = bro
+accent-bogan-words-replace-67 = big dog
+
+accent-bogan-words-68 = hot
+accent-bogan-words-replace-68 = heated
+
+accent-bogan-words-69 = cold
+accent-bogan-words-replace-69 = chilly
+
+accent-bogan-words-70 = kudzu
+accent-bogan-words-replace-70 = wacky tobaccy
+
+accent-bogan-words-71 = really?
+accent-bogan-words-replace-71 = full on?
+
+accent-bogan-words-72 = security
+accent-bogan-words-replace-72 = cop shop
+
+accent-bogan-words-73 = botany
+accent-bogan-words-replace-73 = woolies
+
+accent-bogan-words-74 = shop
+accent-bogan-words-replace-74 = dolla store
+
+accent-bogan-words-75 = money
+accent-bogan-words-replace-75 = cash
+
+accent-bogan-words-76 = its ok
+accent-bogan-words-replace-76 = she'll be right
+
+accent-bogan-words-77 = shut up
+accent-bogan-words-replace-77 = fuck up
+
+accent-bogan-words-78 = go away
+accent-bogan-words-replace-78 = piss off
+
+accent-bogan-words-79 = sec off
+accent-bogan-words-replace-79 = coppa
diff --git a/Resources/Prototypes/_CD/Traits/traits.yml b/Resources/Prototypes/_CD/Traits/traits.yml
index b7eb737236b..9cd111c6ca7 100644
--- a/Resources/Prototypes/_CD/Traits/traits.yml
+++ b/Resources/Prototypes/_CD/Traits/traits.yml
@@ -3,7 +3,7 @@
name: trait-synth-name
description: trait-synth-desc
category: Physical
- cost: 4
+ cost: 0 # Hardlight: Why did this cost 4?
speciesBlacklist: # HardLight
- IPC
- Synth
diff --git a/Resources/Prototypes/_DV/Accents/word_replacements.yml b/Resources/Prototypes/_DV/Accents/word_replacements.yml
index 01bcdd7ee25..88ae2169730 100644
--- a/Resources/Prototypes/_DV/Accents/word_replacements.yml
+++ b/Resources/Prototypes/_DV/Accents/word_replacements.yml
@@ -164,3 +164,86 @@
accent-scottish-words-161: accent-scottish-words-replace-161
accent-scottish-words-162: accent-scottish-words-replace-162
accent-scottish-words-163: accent-scottish-words-replace-163
+
+- type: accent #(Goobstation) New Yowie Accent, to whoever ends up reading this, remember to spell each word exactly
+ id: bogan
+ wordReplacements:
+ accent-bogan-words-1: accent-bogan-words-replace-1
+ accent-bogan-words-2: accent-bogan-words-replace-2
+ accent-bogan-words-3: accent-bogan-words-replace-3
+ accent-bogan-words-4: accent-bogan-words-replace-4
+ accent-bogan-words-5: accent-bogan-words-replace-5
+ accent-bogan-words-6: accent-bogan-words-replace-6
+ accent-bogan-words-7: accent-bogan-words-replace-7
+ accent-bogan-words-8: accent-bogan-words-replace-8
+ accent-bogan-words-9: accent-bogan-words-replace-9
+ accent-bogan-words-10: accent-bogan-words-replace-10
+ accent-bogan-words-11: accent-bogan-words-replace-11
+ accent-bogan-words-12: accent-bogan-words-replace-12
+ accent-bogan-words-13: accent-bogan-words-replace-13
+ accent-bogan-words-14: accent-bogan-words-replace-14
+ accent-bogan-words-15: accent-bogan-words-replace-15
+ accent-bogan-words-16: accent-bogan-words-replace-16
+ accent-bogan-words-17: accent-bogan-words-replace-17
+ accent-bogan-words-18: accent-bogan-words-replace-18
+ accent-bogan-words-19: accent-bogan-words-replace-19
+ accent-bogan-words-20: accent-bogan-words-replace-20
+ accent-bogan-words-21: accent-bogan-words-replace-21
+ accent-bogan-words-22: accent-bogan-words-replace-22
+ accent-bogan-words-23: accent-bogan-words-replace-23
+ accent-bogan-words-24: accent-bogan-words-replace-24
+ accent-bogan-words-25: accent-bogan-words-replace-25
+ accent-bogan-words-26: accent-bogan-words-replace-26
+ accent-bogan-words-27: accent-bogan-words-replace-27
+ accent-bogan-words-28: accent-bogan-words-replace-28
+ accent-bogan-words-29: accent-bogan-words-replace-29
+ accent-bogan-words-30: accent-bogan-words-replace-30
+ accent-bogan-words-31: accent-bogan-words-replace-31
+ accent-bogan-words-32: accent-bogan-words-replace-32
+ accent-bogan-words-33: accent-bogan-words-replace-33
+ accent-bogan-words-34: accent-bogan-words-replace-34
+ accent-bogan-words-35: accent-bogan-words-replace-35
+ accent-bogan-words-36: accent-bogan-words-replace-36
+ accent-bogan-words-37: accent-bogan-words-replace-37
+ accent-bogan-words-38: accent-bogan-words-replace-38
+ accent-bogan-words-39: accent-bogan-words-replace-39
+ accent-bogan-words-40: accent-bogan-words-replace-40
+ accent-bogan-words-41: accent-bogan-words-replace-41
+ accent-bogan-words-42: accent-bogan-words-replace-42
+ accent-bogan-words-43: accent-bogan-words-replace-43
+ accent-bogan-words-44: accent-bogan-words-replace-44
+ accent-bogan-words-45: accent-bogan-words-replace-45
+ accent-bogan-words-46: accent-bogan-words-replace-46
+ accent-bogan-words-47: accent-bogan-words-replace-47
+ accent-bogan-words-48: accent-bogan-words-replace-48
+ accent-bogan-words-49: accent-bogan-words-replace-49
+ accent-bogan-words-50: accent-bogan-words-replace-50
+ accent-bogan-words-51: accent-bogan-words-replace-51
+ accent-bogan-words-52: accent-bogan-words-replace-52
+ accent-bogan-words-53: accent-bogan-words-replace-53
+ accent-bogan-words-54: accent-bogan-words-replace-54
+ accent-bogan-words-55: accent-bogan-words-replace-55
+ accent-bogan-words-56: accent-bogan-words-replace-56
+ accent-bogan-words-57: accent-bogan-words-replace-57
+ accent-bogan-words-58: accent-bogan-words-replace-58
+ accent-bogan-words-59: accent-bogan-words-replace-59
+ accent-bogan-words-60: accent-bogan-words-replace-60
+ accent-bogan-words-61: accent-bogan-words-replace-61
+ accent-bogan-words-62: accent-bogan-words-replace-62
+ accent-bogan-words-63: accent-bogan-words-replace-63
+ accent-bogan-words-64: accent-bogan-words-replace-64
+ accent-bogan-words-65: accent-bogan-words-replace-65
+ accent-bogan-words-66: accent-bogan-words-replace-66
+ accent-bogan-words-67: accent-bogan-words-replace-67
+ accent-bogan-words-68: accent-bogan-words-replace-68
+ accent-bogan-words-69: accent-bogan-words-replace-69
+ accent-bogan-words-70: accent-bogan-words-replace-70
+ accent-bogan-words-71: accent-bogan-words-replace-71
+ accent-bogan-words-72: accent-bogan-words-replace-72
+ accent-bogan-words-73: accent-bogan-words-replace-73
+ accent-bogan-words-74: accent-bogan-words-replace-74
+ accent-bogan-words-75: accent-bogan-words-replace-75
+ accent-bogan-words-76: accent-bogan-words-replace-76
+ accent-bogan-words-77: accent-bogan-words-replace-77
+ accent-bogan-words-78: accent-bogan-words-replace-78
+ accent-bogan-words-79: accent-bogan-words-replace-79
diff --git a/Resources/Prototypes/_HL/Recipes/construction/Graphs/furniture/shelf.yml b/Resources/Prototypes/_HL/Recipes/construction/Graphs/furniture/shelf.yml
index f7e5680b5cc..d24c09bbd32 100644
--- a/Resources/Prototypes/_HL/Recipes/construction/Graphs/furniture/shelf.yml
+++ b/Resources/Prototypes/_HL/Recipes/construction/Graphs/furniture/shelf.yml
@@ -25,9 +25,9 @@
completed:
- !type:SpawnPrototype
prototype: SheetPlasteel
- amount: 10
+ amount: 30
- !type:SpawnPrototype
prototype: MaterialBluespace
- amount: 5
+ amount: 25
- !type:EmptyAllContainers
- !type:DeleteEntity
diff --git a/Resources/Prototypes/_Mono/Traits/speech.yml b/Resources/Prototypes/_Mono/Traits/speech.yml
new file mode 100644
index 00000000000..39d591abfc4
--- /dev/null
+++ b/Resources/Prototypes/_Mono/Traits/speech.yml
@@ -0,0 +1,10 @@
+# 1 Cost
+
+- type: trait
+ id: BoganAccent
+ name: trait-bogan-accent-name
+ description: trait-bogan-accent-desc
+ category: SpeechTraits
+ cost: 1
+ components:
+ - type: BoganAccent