Merge remote-tracking branch 'refs/remotes/wizards/master' into upstream-sync

# Conflicts:
#	.github/PULL_REQUEST_TEMPLATE.md
#	Content.Server/GameTicking/GameTicker.Spawning.cs
#	Resources/Prototypes/Datasets/Names/ai.yml
#	Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml
#	Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml
#	Resources/Prototypes/Maps/cog.yml
#	Resources/Prototypes/Roles/Jobs/Civilian/visitor.yml
#	Resources/Prototypes/Roles/Jobs/departments.yml
#	Resources/ServerInfo/Guidebook/Security/Forensics.xml
#	Resources/Textures/Structures/Furniture/Tables/reinforced.rsi/state_7.png
#	Resources/Textures/Structures/Walls/solid.rsi/meta.json
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_construct-0.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_construct-1.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_construct-2.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_construct-3.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_construct-4.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_construct-5.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over0.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over1.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over2.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over3.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over4.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over5.png
#	Resources/Textures/Structures/Walls/solid.rsi/reinf_over6.png
#	Resources/Textures/Structures/Walls/solid.rsi/rgeneric.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid0.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid1.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid2.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid3.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid4.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid5.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid6.png
#	Resources/Textures/Structures/Walls/solid.rsi/solid7.png
This commit is contained in:
Morb0
2024-09-11 10:56:49 +03:00
376 changed files with 75182 additions and 16659 deletions

View File

@@ -1,36 +1,35 @@
<!-- ЭТО ШАБЛОН ВАШЕГО PULL REQUEST. Текст между стрелками - это комментарии - они не будут видны в PR. -->
<!-- Рекомендации: https://docs.spacestation14.io/en/getting-started/pr-guideline -->
## Описание PR
<!-- Ниже опишите ваш Pull Request. Что он изменяет? На что еще это может повлиять? Постарайтесь описать все внесённые вами изменения! -->
<!-- Что вы изменили? -->
**Медиа**
<!-- Если приемлемо, добавьте скриншоты для демонстрации вашего PR. Если ваш PR представляет собой визуальное изменение, добавьте
скриншоты, иначе он может быть закрыт. -->
## Почему / Баланс
<!-- Обсудите, как это повлияет на баланс игры или объясните, почему это было изменено. Укажите ссылки на соответствующие обсуждения или issue. -->
**Проверки**
<!-- Выполнение всех следующих действий, если это приемлемо для вида изменений сильно ускорит разбор вашего PR -->
- [ ] PR полностью завершён и мне не нужна помощь чтобы его закончить.
- [ ] Я внимательно просмотрел все свои изменения и багов в них не нашёл.
- [ ] Я запускал локальный сервер со своими изменениями и всё протестировал.
- [ ] Я добавил скриншот/видео демонстрации PR в игре, **или** этот PR этого не требует.
## Технические детали
<!-- Краткое описание изменений в коде для облегчения проверки. -->
**Изменения**
## Медиа
<!-- Прикрепите медиафайлы, если PR вносит изменения в игру (одежда, предметы, механики и т.д.).
Небольшие исправления/рефакторинг освобождаются от этого требования. -->
## Требования
<!-- Подтвердите следующее, поставив X в скобках [X]: -->
- [ ] Я прочитал(а) и следую [Рекомендациям по оформлению Pull Request и Changelog](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
- [ ] Я добавил(а) медиафайлы к этому PR или он не требует демонстрации в игре.
<!-- Вы должны понимать, что несоблюдение вышеуказанного может привести к закрытию вашего PR по усмотрению сопровождающего -->
## Критические изменения
<!-- Перечислите все критические изменения, включая изменения пространств имен, публичных классов/методов/полей, переименования прототипов; и предоставьте инструкции по их исправлению. -->
**Список изменений**
<!-- Добавьте запись в Changelog, чтобы игроки знали о новых функциях или изменениях, которые могут повлиять на игровой процесс.
Убедитесь, что вы прочитали рекомендации и вынесли этот шаблон Changelog из блока комментариев, чтобы он отображался.
Changelog должен иметь символ :cl:, чтобы бот распознал изменения и добавил их в список изменений игры. -->
<!--
Здесь вы можете написать список изменений, который будет автоматически добавлен в игру, когда ваш PR будет принят.
В журнал изменений следует помещать только то, что действительно важно игрокам.
В списке изменений тип значка не является часть предложения, поэтому явно указывайте - Добавлен, Удалён, Изменён.
плохо: - add: Новый инструмент для инженеров
хорошо: - add: Добавлен новый инструмент для инженеров
Вы можете указать своё имя после символа :cl: именно оно будет отображаться в журнале изменений (иначе будет использоваться ваше имя на GitHub)
Например: :cl: Ian
-->
:cl:
- add: Добавлено веселье!
- remove: Убрано веселье!
- remove: Удалено веселье!
- tweak: Изменено веселье!
- fix: Исправлено веселье!
-->

View File

@@ -19,6 +19,8 @@ jobs:
- name: Get this week's Contributors
shell: pwsh
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: Tools/dump_github_contributors.ps1 > Resources/Credits/GitHub.txt
# TODO

View File

@@ -47,8 +47,10 @@
</Control>
<Control HorizontalExpand="True"/>
<BoxContainer Orientation="Horizontal">
<Button Name="ButtonSaveDraft" SetHeight="32" SetWidth="85"
StyleClasses="OpenRight" Text="{Loc news-write-ui-save-text}"/>
<Button Name="ButtonPreview" SetHeight="32" SetWidth="85"
StyleClasses="OpenRight" Text="{Loc news-write-ui-preview-text}"/>
StyleClasses="OpenBoth" Text="{Loc news-write-ui-preview-text}"/>
<Button Name="ButtonPublish" SetHeight="32" SetWidth="85" Text="{Loc news-write-ui-publish-text}" Access="Public"/>
</BoxContainer>
</BoxContainer>

View File

@@ -14,6 +14,7 @@ namespace Content.Client.MassMedia.Ui;
public sealed partial class ArticleEditorPanel : Control
{
public event Action? PublishButtonPressed;
public event Action<string, string>? ArticleDraftUpdated;
private bool _preview;
@@ -45,6 +46,7 @@ public sealed partial class ArticleEditorPanel : Control
ButtonPreview.OnPressed += OnPreview;
ButtonCancel.OnPressed += OnCancel;
ButtonPublish.OnPressed += OnPublish;
ButtonSaveDraft.OnPressed += OnDraftSaved;
TitleField.OnTextChanged += args => OnTextChanged(args.Text.Length, args.Control, SharedNewsSystem.MaxTitleLength);
ContentField.OnTextChanged += args => OnTextChanged(Rope.CalcTotalLength(args.TextRope), args.Control, SharedNewsSystem.MaxContentLength);
@@ -68,6 +70,9 @@ public sealed partial class ArticleEditorPanel : Control
ButtonPublish.Disabled = false;
ButtonPreview.Disabled = false;
}
// save draft regardless; they can edit down the length later
ArticleDraftUpdated?.Invoke(TitleField.Text, Rope.Collapse(ContentField.TextRope));
}
private void OnPreview(BaseButton.ButtonEventArgs eventArgs)
@@ -92,6 +97,12 @@ public sealed partial class ArticleEditorPanel : Control
Visible = false;
}
private void OnDraftSaved(BaseButton.ButtonEventArgs eventArgs)
{
ArticleDraftUpdated?.Invoke(TitleField.Text, Rope.Collapse(ContentField.TextRope));
Visible = false;
}
private void Reset()
{
_preview = false;
@@ -100,6 +111,7 @@ public sealed partial class ArticleEditorPanel : Control
PreviewLabel.SetMarkup("");
TitleField.Text = "";
ContentField.TextRope = Rope.Leaf.Empty;
ArticleDraftUpdated?.Invoke(string.Empty, string.Empty);
}
protected override void Dispose(bool disposing)

View File

@@ -25,6 +25,9 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface
_menu.ArticleEditorPanel.PublishButtonPressed += OnPublishButtonPressed;
_menu.DeleteButtonPressed += OnDeleteButtonPressed;
_menu.CreateButtonPressed += OnCreateButtonPressed;
_menu.ArticleEditorPanel.ArticleDraftUpdated += OnArticleDraftUpdated;
SendMessage(new NewsWriterArticlesRequestMessage());
}
@@ -34,7 +37,7 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface
if (state is not NewsWriterBoundUserInterfaceState cast)
return;
_menu?.UpdateUI(cast.Articles, cast.PublishEnabled, cast.NextPublish);
_menu?.UpdateUI(cast.Articles, cast.PublishEnabled, cast.NextPublish, cast.DraftTitle, cast.DraftContent);
}
private void OnPublishButtonPressed()
@@ -67,4 +70,14 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface
SendMessage(new NewsWriterDeleteMessage(articleNum));
}
private void OnCreateButtonPressed()
{
SendMessage(new NewsWriterRequestDraftMessage());
}
private void OnArticleDraftUpdated(string title, string content)
{
SendMessage(new NewsWriterSaveDraftMessage(title, content));
}
}

View File

@@ -4,6 +4,7 @@ using Robust.Client.UserInterface.XAML;
using Content.Shared.MassMedia.Systems;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.MassMedia.Ui;
@@ -16,6 +17,8 @@ public sealed partial class NewsWriterMenu : FancyWindow
public event Action<int>? DeleteButtonPressed;
public event Action? CreateButtonPressed;
public NewsWriterMenu()
{
RobustXamlLoader.Load(this);
@@ -31,7 +34,7 @@ public sealed partial class NewsWriterMenu : FancyWindow
ButtonCreate.OnPressed += OnCreate;
}
public void UpdateUI(NewsArticle[] articles, bool publishEnabled, TimeSpan nextPublish)
public void UpdateUI(NewsArticle[] articles, bool publishEnabled, TimeSpan nextPublish, string draftTitle, string draftContent)
{
ArticlesContainer.Children.Clear();
ArticleCount.Text = Loc.GetString("news-write-ui-article-count-text", ("count", articles.Length));
@@ -54,6 +57,9 @@ public sealed partial class NewsWriterMenu : FancyWindow
ButtonCreate.Disabled = !publishEnabled;
_nextPublish = nextPublish;
ArticleEditorPanel.TitleField.Text = draftTitle;
ArticleEditorPanel.ContentField.TextRope = new Rope.Leaf(draftContent);
}
protected override void FrameUpdate(FrameEventArgs args)
@@ -93,5 +99,6 @@ public sealed partial class NewsWriterMenu : FancyWindow
private void OnCreate(BaseButton.ButtonEventArgs buttonEventArgs)
{
ArticleEditorPanel.Visible = true;
CreateButtonPressed?.Invoke();
}
}

View File

@@ -107,7 +107,7 @@ namespace Content.Client.Nuke
FirstStatusLabel.Text = firstMsg;
SecondStatusLabel.Text = secondMsg;
EjectButton.Disabled = !state.DiskInserted || state.Status == NukeStatus.ARMED;
EjectButton.Disabled = !state.DiskInserted || state.Status == NukeStatus.ARMED || !state.IsAnchored;
AnchorButton.Disabled = state.Status == NukeStatus.ARMED;
AnchorButton.Pressed = state.IsAnchored;
ArmButton.Disabled = !state.AllowArm || !state.IsAnchored;

View File

@@ -1,7 +1,6 @@
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Robust.Client.GameObjects;
using Robust.Shared.Utility;
namespace Content.Client.Nutrition.EntitySystems;
@@ -50,6 +49,7 @@ public sealed class ClientFoodSequenceSystem : SharedFoodSequenceSystem
sprite.AddBlankLayer(index);
sprite.LayerMapSet(keyCode, index);
sprite.LayerSetSprite(index, state.Sprite);
sprite.LayerSetScale(index, state.Scale);
//Offset the layer
var layerPos = start.Comp.StartPosition;

View File

@@ -19,8 +19,8 @@ namespace Content.Client.Power.APC
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<ApcMenu>();
_menu.SetEntity(Owner);
_menu.OnBreaker += BreakerPressed;
}

View File

@@ -296,7 +296,7 @@ namespace Content.Server.Atmos.EntitySystems
}
else
{
flammable.OnFire = ignite;
flammable.OnFire |= ignite;
UpdateAppearance(uid, flammable);
}
}

View File

@@ -17,6 +17,8 @@ using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Random;
using Robust.Shared.Configuration;
using Content.Shared.CCVar;
namespace Content.Server.Atmos.EntitySystems
{
@@ -32,10 +34,12 @@ namespace Content.Server.Atmos.EntitySystems
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private const float TimerDelay = 0.5f;
private float _timer = 0f;
private const float MinimumSoundValvePressure = 10.0f;
private float _maxExplosionRange;
public override void Initialize()
{
@@ -51,6 +55,12 @@ namespace Content.Server.Atmos.EntitySystems
SubscribeLocalEvent<GasTankComponent, GasAnalyzerScanEvent>(OnAnalyzed);
SubscribeLocalEvent<GasTankComponent, PriceCalculationEvent>(OnGasTankPrice);
SubscribeLocalEvent<GasTankComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAlternativeVerb);
Subs.CVar(_cfg, CCVars.AtmosTankFragment, UpdateMaxRange, true);
}
private void UpdateMaxRange(float value)
{
_maxExplosionRange = value;
}
private void OnGasShutdown(Entity<GasTankComponent> gasTank, ref ComponentShutdown args)
@@ -320,7 +330,7 @@ namespace Content.Server.Atmos.EntitySystems
var pressure = component.Air.Pressure;
if (pressure > component.TankFragmentPressure)
if (pressure > component.TankFragmentPressure && _maxExplosionRange > 0)
{
// Give the gas a chance to build up more pressure.
for (var i = 0; i < 3; i++)
@@ -333,10 +343,7 @@ namespace Content.Server.Atmos.EntitySystems
// Let's cap the explosion, yeah?
// !1984
if (range > GasTankComponent.MaxExplosionRange)
{
range = GasTankComponent.MaxExplosionRange;
}
range = Math.Min(Math.Min(range, GasTankComponent.MaxExplosionRange), _maxExplosionRange);
_explosions.TriggerExplosive(owner, radius: range);

View File

@@ -1,7 +0,0 @@
namespace Content.Server.Dragon;
[RegisterComponent]
public sealed partial class DragonRuleComponent : Component
{
}

View File

@@ -16,6 +16,7 @@ using Content.Server.Info;
using Content.Server.IoC;
using Content.Server.Maps;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.Objectives;
using Content.Server.Players;
using Content.Server.Players.JobWhitelist;
using Content.Server.Players.PlayTimeTracking;

View File

@@ -238,13 +238,29 @@ namespace Content.Server.GameTicking
if (lateJoin && !silent)
{
_chatSystem.DispatchStationAnnouncement(station,
Loc.GetString("latejoin-arrival-announcement",
("character", MetaData(mob).EntityName),
("gender", character.Gender), // Corvax-LastnameGender
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))),
Loc.GetString("latejoin-arrival-sender"),
playDefaultSound: false);
if (jobPrototype.JoinNotifyCrew)
{
_chatSystem.DispatchStationAnnouncement(station,
Loc.GetString("latejoin-arrival-announcement-special",
("character", MetaData(mob).EntityName),
("gender", character.Gender), // Corvax-LastnameGender
("entity", mob),
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))),
Loc.GetString("latejoin-arrival-sender"),
playDefaultSound: false,
colorOverride: Color.Gold);
}
else
{
_chatSystem.DispatchStationAnnouncement(station,
Loc.GetString("latejoin-arrival-announcement",
("character", MetaData(mob).EntityName),
("gender", character.Gender), // Corvax-LastnameGender
("entity", mob),
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))),
Loc.GetString("latejoin-arrival-sender"),
playDefaultSound: false);
}
}
if (player.UserId == new Guid("{e887eb93-f503-4b65-95b6-2f282c014192}"))

View File

@@ -0,0 +1,4 @@
namespace Content.Server.GameTicking.Rules.Components;
[RegisterComponent]
public sealed partial class DragonRuleComponent : Component;

View File

@@ -0,0 +1,52 @@
using Content.Server.Antag;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Localizations;
using Robust.Server.GameObjects;
namespace Content.Server.GameTicking.Rules;
public sealed class DragonRuleSystem : GameRuleSystem<DragonRuleComponent>
{
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly StationSystem _station = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DragonRuleComponent, AfterAntagEntitySelectedEvent>(AfterAntagEntitySelected);
}
private void AfterAntagEntitySelected(Entity<DragonRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
{
_antag.SendBriefing(args.EntityUid, MakeBriefing(args.EntityUid), null, null);
}
private string MakeBriefing(EntityUid dragon)
{
var direction = string.Empty;
var dragonXform = Transform(dragon);
var station = _station.GetStationInMap(dragonXform.MapID);
EntityUid? stationGrid = null;
if (TryComp<StationDataComponent>(station, out var stationData))
stationGrid = _station.GetLargestGrid(stationData);
if (stationGrid is not null)
{
var stationPosition = _transform.GetWorldPosition((EntityUid)stationGrid);
var dragonPosition = _transform.GetWorldPosition(dragon);
var vectorToStation = stationPosition - dragonPosition;
direction = ContentLocalizationManager.FormatDirection(vectorToStation.GetDir());
}
var briefing = Loc.GetString("dragon-role-briefing", ("direction", direction));
return briefing;
}
}

View File

@@ -15,6 +15,7 @@ using Content.Server.Mapping;
using Content.Server.Maps;
using Content.Server.MoMMI;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.Objectives;
using Content.Server.Players;
using Content.Server.Players.JobWhitelist;
using Content.Server.Players.PlayTimeTracking;

View File

@@ -22,4 +22,16 @@ public sealed partial class NewsWriterComponent : Component
[DataField]
public SoundSpecifier ConfirmSound = new SoundPathSpecifier("/Audio/Machines/scan_finish.ogg");
/// <summary>
/// This stores the working title of the current article
/// </summary>
[DataField, ViewVariables]
public string DraftTitle = "";
/// <summary>
/// This stores the working content of the current article
/// </summary>
[DataField, ViewVariables]
public string DraftContent = "";
}

View File

@@ -51,6 +51,8 @@ public sealed class NewsSystem : SharedNewsSystem
subs.Event<NewsWriterDeleteMessage>(OnWriteUiDeleteMessage);
subs.Event<NewsWriterArticlesRequestMessage>(OnRequestArticlesUiMessage);
subs.Event<NewsWriterPublishMessage>(OnWriteUiPublishMessage);
subs.Event<NewsWriterSaveDraftMessage>(OnNewsWriterDraftUpdatedMessage);
subs.Event<NewsWriterRequestDraftMessage>(OnRequestArticleDraftMessage);
});
// News reader
@@ -256,7 +258,7 @@ public sealed class NewsSystem : SharedNewsSystem
if (!TryGetArticles(ent, out var articles))
return;
var state = new NewsWriterBoundUserInterfaceState(articles.ToArray(), ent.Comp.PublishEnabled, ent.Comp.NextPublish);
var state = new NewsWriterBoundUserInterfaceState(articles.ToArray(), ent.Comp.PublishEnabled, ent.Comp.NextPublish, ent.Comp.DraftTitle, ent.Comp.DraftContent);
_ui.SetUiState(ent.Owner, NewsWriterUiKey.Key, state);
}
@@ -318,4 +320,14 @@ public sealed class NewsSystem : SharedNewsSystem
return true;
}
private void OnNewsWriterDraftUpdatedMessage(Entity<NewsWriterComponent> ent, ref NewsWriterSaveDraftMessage args)
{
ent.Comp.DraftTitle = args.DraftTitle;
ent.Comp.DraftContent = args.DraftContent;
}
private void OnRequestArticleDraftMessage(Entity<NewsWriterComponent> ent, ref NewsWriterRequestDraftMessage msg)
{
UpdateWriterUi(ent);
}
}

View File

@@ -0,0 +1,31 @@
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Materials;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Server.Materials.Components;
/// <summary>
/// This is used for a machine that turns produce into a specified material.
/// </summary>
[RegisterComponent, Access(typeof(ProduceMaterialExtractorSystem))]
public sealed partial class ProduceMaterialExtractorComponent : Component
{
/// <summary>
/// The material that produce is converted into
/// </summary>
[DataField]
public ProtoId<MaterialPrototype> ExtractedMaterial = "Biomass";
/// <summary>
/// List of reagents that determines how much material is yielded from a produce.
/// </summary>
[DataField]
public List<ProtoId<ReagentPrototype>> ExtractionReagents = new()
{
"Nutriment"
};
[DataField]
public SoundSpecifier? ExtractSound = new SoundPathSpecifier("/Audio/Effects/waterswirl.ogg");
}

View File

@@ -258,9 +258,22 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
}
// if the item we inserted has reagents, add it in.
if (_solutionContainer.TryGetDrainableSolution(item, out _, out var drainableSolution))
if (reclaimerComponent.OnlyReclaimDrainable)
{
totalChemicals.AddSolution(drainableSolution, _prototype);
// Are we a recycler? Only use drainable solution.
if (_solutionContainer.TryGetDrainableSolution(item, out _, out var drainableSolution))
{
totalChemicals.AddSolution(drainableSolution, _prototype);
}
}
else
{
// Are we an industrial reagent grinder? Use extractable solution.
if (_solutionContainer.TryGetExtractableSolution(item, out _, out var extractableSolution))
{
totalChemicals.AddSolution(extractableSolution, _prototype);
}
}
if (!_solutionContainer.TryGetSolution(reclaimer, reclaimerComponent.SolutionContainerId, out var outputSolution) ||

View File

@@ -0,0 +1,48 @@
using System.Linq;
using Content.Server.Botany.Components;
using Content.Server.Materials.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Interaction;
using Robust.Server.Audio;
namespace Content.Server.Materials;
public sealed class ProduceMaterialExtractorSystem : EntitySystem
{
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly MaterialStorageSystem _materialStorage = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<ProduceMaterialExtractorComponent, AfterInteractUsingEvent>(OnInteractUsing);
}
private void OnInteractUsing(Entity<ProduceMaterialExtractorComponent> ent, ref AfterInteractUsingEvent args)
{
if (args.Handled)
return;
if (!this.IsPowered(ent, EntityManager))
return;
if (!TryComp<ProduceComponent>(args.Used, out var produce))
return;
if (!_solutionContainer.TryGetSolution(args.Used, produce.SolutionName, out var solution))
return;
// Can produce even have fractional amounts? Does it matter if they do?
// Questions man was never meant to answer.
var matAmount = solution.Value.Comp.Solution.Contents
.Where(r => ent.Comp.ExtractionReagents.Contains(r.Reagent.Prototype))
.Sum(r => r.Quantity.Float());
_materialStorage.TryChangeMaterialAmount(ent, ent.Comp.ExtractedMaterial, (int) matAmount);
_audio.PlayPvs(ent.Comp.ExtractSound, ent);
QueueDel(args.Used);
args.Handled = true;
}
}

View File

@@ -167,12 +167,21 @@ public sealed class NukeSystem : EntitySystem
if (component.Status == NukeStatus.ARMED)
return;
// Nuke has to have the disk in it to be moved
if (!component.DiskSlot.HasItem)
{
var msg = Loc.GetString("nuke-component-cant-anchor-toggle");
_popups.PopupEntity(msg, uid, args.Actor, PopupType.MediumCaution);
return;
}
// manually set transform anchor (bypassing anchorable)
// todo: it will break pullable system
var xform = Transform(uid);
if (xform.Anchored)
{
_transform.Unanchor(uid, xform);
_itemSlots.SetLock(uid, component.DiskSlot, true);
}
else
{
@@ -194,6 +203,7 @@ public sealed class NukeSystem : EntitySystem
_transform.SetCoordinates(uid, xform, xform.Coordinates.SnapToGrid());
_transform.AnchorEntity(uid, xform);
_itemSlots.SetLock(uid, component.DiskSlot, false);
}
UpdateUserInterface(uid, component);

View File

@@ -4,10 +4,14 @@ using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Mobs.Systems;
using Content.Shared.Nutrition;
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Nutrition.Prototypes;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Nutrition.EntitySystems;
@@ -20,12 +24,16 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly TransformSystem _transform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<FoodSequenceStartPointComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<FoodMetamorphableByAddingComponent, FoodSequenceIngredientAddedEvent>(OnIngredientAdded);
}
private void OnInteractUsing(Entity<FoodSequenceStartPointComponent> ent, ref InteractUsingEvent args)
@@ -34,47 +42,107 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
TryAddFoodElement(ent, (args.Used, sequenceElement), args.User);
}
private void OnIngredientAdded(Entity<FoodMetamorphableByAddingComponent> ent, ref FoodSequenceIngredientAddedEvent args)
{
if (!TryComp<FoodSequenceStartPointComponent>(args.Start, out var start))
return;
if (!_proto.TryIndex(args.Proto, out var elementProto))
return;
if (!ent.Comp.OnlyFinal || elementProto.Final || start.FoodLayers.Count == start.MaxLayers)
{
TryMetamorph((ent, start));
}
}
private bool TryMetamorph(Entity<FoodSequenceStartPointComponent> start)
{
List<MetamorphRecipePrototype> availableRecipes = new();
foreach (var recipe in _proto.EnumeratePrototypes<MetamorphRecipePrototype>())
{
if (recipe.Key != start.Comp.Key)
continue;
bool allowed = true;
foreach (var rule in recipe.Rules)
{
if (!rule.Check(_proto, EntityManager, start, start.Comp.FoodLayers))
{
allowed = false;
break;
}
}
if (allowed)
availableRecipes.Add(recipe);
}
if (availableRecipes.Count <= 0)
return true;
Metamorf(start, _random.Pick(availableRecipes)); //In general, if there's more than one recipe, the yml-guys screwed up. Maybe some kind of unit test is needed.
QueueDel(start);
return true;
}
private void Metamorf(Entity<FoodSequenceStartPointComponent> start, MetamorphRecipePrototype recipe)
{
var result = SpawnAtPosition(recipe.Result, Transform(start).Coordinates);
//Try putting in container
_transform.DropNextTo(result, (start, Transform(start)));
if (!_solutionContainer.TryGetSolution(result, start.Comp.Solution, out var resultSoln, out var resultSolution))
return;
if (!_solutionContainer.TryGetSolution(start.Owner, start.Comp.Solution, out var startSoln, out var startSolution))
return;
_solutionContainer.RemoveAllSolution(resultSoln.Value); //Remove all YML reagents
resultSoln.Value.Comp.Solution.MaxVolume = startSoln.Value.Comp.Solution.MaxVolume;
_solutionContainer.TryAddSolution(resultSoln.Value, startSolution);
MergeFlavorProfiles(start, result);
MergeTrash(start, result);
MergeTags(start, result);
}
private bool TryAddFoodElement(Entity<FoodSequenceStartPointComponent> start, Entity<FoodSequenceElementComponent> element, EntityUid? user = null)
{
FoodSequenceElementEntry? elementData = null;
foreach (var entry in element.Comp.Entries)
{
if (entry.Key == start.Comp.Key)
{
elementData = entry.Value;
break;
}
}
if (elementData is null)
// we can't add a live mouse to a burger.
if (!TryComp<FoodComponent>(element, out var elementFood))
return false;
if (elementFood.RequireDead && _mobState.IsAlive(element))
return false;
if (TryComp<FoodComponent>(element, out var elementFood) && elementFood.RequireDead)
{
if (_mobState.IsAlive(element))
return false;
}
//looking for a suitable FoodSequence prototype
if (!element.Comp.Entries.TryGetValue(start.Comp.Key, out var elementProto))
return false;
if (!_proto.TryIndex(elementProto, out var elementIndexed))
return false;
//if we run out of space, we can still put in one last, final finishing element.
if (start.Comp.FoodLayers.Count >= start.Comp.MaxLayers && !elementData.Final || start.Comp.Finished)
if (start.Comp.FoodLayers.Count >= start.Comp.MaxLayers && !elementIndexed.Final || start.Comp.Finished)
{
if (user is not null)
_popup.PopupEntity(Loc.GetString("food-sequence-no-space"), start, user.Value);
return false;
}
//If no specific sprites are specified, standard sprites will be used.
if (elementData.Sprite is null && element.Comp.Sprite is not null)
elementData.Sprite = element.Comp.Sprite;
//Generate new visual layer
var flip = start.Comp.AllowHorizontalFlip && _random.Prob(0.5f);
var layer = new FoodSequenceVisualLayer(elementIndexed,
_random.Pick(elementIndexed.Sprites),
new Vector2(flip ? -1 : 1, 1),
new Vector2(
_random.NextFloat(start.Comp.MinLayerOffset.X, start.Comp.MaxLayerOffset.X),
_random.NextFloat(start.Comp.MinLayerOffset.Y, start.Comp.MaxLayerOffset.Y))
);
elementData.LocalOffset = new Vector2(
_random.NextFloat(start.Comp.MinLayerOffset.X,start.Comp.MaxLayerOffset.X),
_random.NextFloat(start.Comp.MinLayerOffset.Y,start.Comp.MaxLayerOffset.Y));
start.Comp.FoodLayers.Add(elementData);
start.Comp.FoodLayers.Add(layer);
Dirty(start);
if (elementData.Final)
if (elementIndexed.Final)
start.Comp.Finished = true;
UpdateFoodName(start);
@@ -82,6 +150,10 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
MergeFlavorProfiles(start, element);
MergeTrash(start, element);
MergeTags(start, element);
var ev = new FoodSequenceIngredientAddedEvent(start, element, elementProto, user);
RaiseLocalEvent(start, ev);
QueueDel(element);
return true;
}
@@ -96,17 +168,23 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
if (start.Comp.ContentSeparator is not null)
separator = Loc.GetString(start.Comp.ContentSeparator);
HashSet<LocId> existedContentNames = new();
HashSet<ProtoId<FoodSequenceElementPrototype>> existedContentNames = new();
foreach (var layer in start.Comp.FoodLayers)
{
if (layer.Name is not null && !existedContentNames.Contains(layer.Name.Value))
existedContentNames.Add(layer.Name.Value);
if (!existedContentNames.Contains(layer.Proto))
existedContentNames.Add(layer.Proto);
}
var nameCounter = 1;
foreach (var name in existedContentNames)
foreach (var proto in existedContentNames)
{
content.Append(Loc.GetString(name));
if (!_proto.TryIndex(proto, out var protoIndexed))
continue;
if (protoIndexed.Name is null)
continue;
content.Append(Loc.GetString(protoIndexed.Name.Value));
if (nameCounter < existedContentNames.Count)
content.Append(separator);
@@ -121,19 +199,25 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
_metaData.SetEntityName(start, newName);
}
private void MergeFoodSolutions(Entity<FoodSequenceStartPointComponent> start, Entity<FoodSequenceElementComponent> element)
private void MergeFoodSolutions(EntityUid start, EntityUid element)
{
if (!_solutionContainer.TryGetSolution(start.Owner, start.Comp.Solution, out var startSolutionEntity, out var startSolution))
if (!TryComp<FoodComponent>(start, out var startFood))
return;
if (!_solutionContainer.TryGetSolution(element.Owner, element.Comp.Solution, out _, out var elementSolution))
if (!TryComp<FoodComponent>(element, out var elementFood))
return;
if (!_solutionContainer.TryGetSolution(start, startFood.Solution, out var startSolutionEntity, out var startSolution))
return;
if (!_solutionContainer.TryGetSolution(element, elementFood.Solution, out _, out var elementSolution))
return;
startSolution.MaxVolume += elementSolution.MaxVolume;
_solutionContainer.TryAddSolution(startSolutionEntity.Value, elementSolution);
}
private void MergeFlavorProfiles(Entity<FoodSequenceStartPointComponent> start, Entity<FoodSequenceElementComponent> element)
private void MergeFlavorProfiles(EntityUid start, EntityUid element)
{
if (!TryComp<FlavorProfileComponent>(start, out var startProfile))
return;
@@ -148,7 +232,7 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
}
}
private void MergeTrash(Entity<FoodSequenceStartPointComponent> start, Entity<FoodSequenceElementComponent> element)
private void MergeTrash(EntityUid start, EntityUid element)
{
if (!TryComp<FoodComponent>(start, out var startFood))
return;
@@ -162,13 +246,13 @@ public sealed class FoodSequenceSystem : SharedFoodSequenceSystem
}
}
private void MergeTags(Entity<FoodSequenceStartPointComponent> start, Entity<FoodSequenceElementComponent> element)
private void MergeTags(EntityUid start, EntityUid element)
{
if (!TryComp<TagComponent>(element, out var elementTags))
return;
EnsureComp<TagComponent>(start.Owner);
EnsureComp<TagComponent>(start);
_tag.TryAddTags(start.Owner, elementTags.Tags);
_tag.TryAddTags(start, elementTags.Tags);
}
}

View File

@@ -1,56 +1,73 @@
using Content.Server.Administration;
using System.Linq;
using Content.Server.Administration;
using Content.Shared.Administration;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Content.Shared.Prototypes;
using Robust.Server.Player;
using Robust.Shared.Console;
using Robust.Shared.Prototypes;
namespace Content.Server.Objectives.Commands
namespace Content.Server.Objectives.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class AddObjectiveCommand : LocalizedEntityCommands
{
[AdminCommand(AdminFlags.Admin)]
public sealed class AddObjectiveCommand : IConsoleCommand
[Dependency] private readonly IPlayerManager _players = default!;
[Dependency] private readonly IPrototypeManager _prototypes = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly ObjectivesSystem _objectives = default!;
public override string Command => "addobjective";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public string Command => "addobjective";
public string Description => "Adds an objective to the player's mind.";
public string Help => "addobjective <username> <objectiveID>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
if (args.Length != 2)
{
if (args.Length != 2)
{
shell.WriteLine("Expected exactly 2 arguments.");
return;
}
shell.WriteError(Loc.GetString(Loc.GetString("cmd-addobjective-invalid-args")));
return;
}
var mgr = IoCManager.Resolve<IPlayerManager>();
if (!mgr.TryGetSessionByUsername(args[0], out var data))
{
shell.WriteLine("Can't find the playerdata.");
return;
}
if (!_players.TryGetSessionByUsername(args[0], out var data))
{
shell.WriteError(Loc.GetString("cmd-addobjective-player-not-found"));
return;
}
var minds = _entityManager.System<SharedMindSystem>();
if (!minds.TryGetMind(data, out var mindId, out var mind))
{
shell.WriteLine("Can't find the mind.");
return;
}
if (!_mind.TryGetMind(data, out var mindId, out var mind))
{
shell.WriteError(Loc.GetString("cmd-addobjective-mind-not-found"));
return;
}
if (!IoCManager.Resolve<IPrototypeManager>()
.TryIndex<EntityPrototype>(args[1], out var proto) ||
!proto.TryGetComponent<ObjectiveComponent>(out _))
{
shell.WriteLine($"Can't find matching objective prototype {args[1]}");
return;
}
if (!_prototypes.TryIndex<EntityPrototype>(args[1], out var proto) ||
!proto.HasComponent<ObjectiveComponent>())
{
shell.WriteError(Loc.GetString("cmd-addobjective-objective-not-found", ("obj", args[1])));
return;
}
if (!minds.TryAddObjective(mindId, mind, args[1]))
{
// can fail for other reasons so dont pretend to be right
shell.WriteLine("Failed to add the objective. Maybe requirements dont allow that objective to be added.");
}
if (!_mind.TryAddObjective(mindId, mind, args[1]))
{
// can fail for other reasons so dont pretend to be right
shell.WriteError(Loc.GetString("cmd-addobjective-adding-failed"));
}
}
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
if (args.Length == 1)
{
var options = _players.Sessions.OrderBy(c => c.Name).Select(c => c.Name).ToArray();
return CompletionResult.FromHintOptions(options, Loc.GetString("cmd-addobjective-player-completion"));
}
if (args.Length != 2)
return CompletionResult.Empty;
return CompletionResult.FromHintOptions(
_objectives.Objectives(),
Loc.GetString(Loc.GetString("cmd-add-objective-obj-completion")));
}
}

View File

@@ -11,6 +11,9 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Linq;
using System.Text;
using Content.Server.Objectives.Commands;
using Content.Shared.Prototypes;
using Content.Shared.Roles.Jobs;
using Robust.Server.Player;
using Robust.Shared.Utility;
@@ -23,12 +26,24 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
[Dependency] private readonly SharedJobSystem _job = default!;
private IEnumerable<string>? _objectives;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRoundEndText);
_prototypeManager.PrototypesReloaded += CreateCompletions;
}
public override void Shutdown()
{
base.Shutdown();
_prototypeManager.PrototypesReloaded -= CreateCompletions;
}
/// <summary>
@@ -244,11 +259,42 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem
_player.TryGetPlayerData(mind.Comp.OriginalOwnerUserId.Value, out var sessionData))
{
var username = sessionData.UserName;
return Loc.GetString("objectives-player-user-named", ("user", username), ("name", name));
var nameWithJobMaybe = name;
if (_job.MindTryGetJobName(mind, out var jobName))
nameWithJobMaybe += ", " + jobName;
return Loc.GetString("objectives-player-user-named", ("user", username), ("name", nameWithJobMaybe));
}
return Loc.GetString("objectives-player-named", ("name", name));
}
private void CreateCompletions(PrototypesReloadedEventArgs unused)
{
CreateCompletions();
}
/// <summary>
/// Get all objective prototypes by their IDs.
/// This is used for completions in <see cref="AddObjectiveCommand"/>
/// </summary>
public IEnumerable<string> Objectives()
{
if (_objectives == null)
CreateCompletions();
return _objectives!;
}
private void CreateCompletions()
{
_objectives = _prototypeManager.EnumeratePrototypes<EntityPrototype>()
.Where(p => p.HasComponent<ObjectiveComponent>())
.Select(p => p.ID)
.Order();
}
}
/// <summary>

View File

@@ -1,5 +1,6 @@
using System.Numerics;
using System.Threading.Tasks;
using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
@@ -10,7 +11,7 @@ public sealed partial class DungeonJob
/// <summary>
/// <see cref="FillGridDunGen"/>
/// </summary>
private async Task<Dungeon> GenerateFillDunGen(DungeonData data, HashSet<Vector2i> reservedTiles)
private async Task<Dungeon> GenerateFillDunGen(FillGridDunGen fill, DungeonData data, HashSet<Vector2i> reservedTiles)
{
if (!data.Entities.TryGetValue(DungeonDataKey.Fill, out var fillEnt))
{
@@ -28,6 +29,9 @@ public sealed partial class DungeonJob
if (reservedTiles.Contains(tile))
continue;
if (fill.AllowedTiles != null && !fill.AllowedTiles.Contains(((ContentTileDefinition) _tileDefManager[tileRef.Value.Tile.TypeId]).ID))
continue;
if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
continue;

View File

@@ -230,7 +230,7 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
dungeons.AddRange(await GenerateExteriorDungen(position, exterior, reservedTiles, random));
break;
case FillGridDunGen fill:
dungeons.Add(await GenerateFillDunGen(data, reservedTiles));
dungeons.Add(await GenerateFillDunGen(fill, data, reservedTiles));
break;
case JunctionDunGen junc:
await PostGen(junc, data, dungeons[^1], reservedTiles, random);

View File

@@ -170,7 +170,7 @@ public sealed partial class RevenantSystem : EntitySystem
}
}
ChangeEssenceAmount(uid, abilityCost, component, false);
ChangeEssenceAmount(uid, -abilityCost, component, false);
_statusEffects.TryAddStatusEffect<CorporealComponent>(uid, "Corporeal", TimeSpan.FromSeconds(debuffs.Y), false);
_stun.TryStun(uid, TimeSpan.FromSeconds(debuffs.X), false);

View File

@@ -196,7 +196,7 @@ namespace Content.Server.RoundEnd
ExpectedCountdownEnd = _gameTiming.CurTime + countdownTime;
// TODO full game saves
Timer.Spawn(countdownTime, _shuttle.CallEmergencyShuttle, _countdownTokenSource.Token);
Timer.Spawn(countdownTime, _shuttle.DockEmergencyShuttle, _countdownTokenSource.Token);
ActivateCooldown();
RaiseLocalEvent(RoundEndSystemChangedEvent.Default);

View File

@@ -19,6 +19,6 @@ public sealed class DockEmergencyShuttleCommand : IConsoleCommand
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var system = _sysManager.GetEntitySystem<EmergencyShuttleSystem>();
system.CallEmergencyShuttle();
system.DockEmergencyShuttle();
}
}

View File

@@ -22,6 +22,7 @@ using Content.Shared.DeviceNetwork;
using Content.Shared.Mobs.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Preferences;
using Content.Shared.Salvage;
using Content.Shared.Shuttles.Components;
using Content.Shared.Tiles;
@@ -334,6 +335,9 @@ public sealed class ArrivalsSystem : EntitySystem
if (ev.SpawnResult != null)
return;
if (ev.HumanoidCharacterProfile?.SpawnPriority != SpawnPriorityPreference.Arrivals)
return;
// Only works on latejoin even if enabled.
if (!Enabled || _ticker.RunLevel != GameRunLevel.InRound)
return;

View File

@@ -17,7 +17,7 @@ public sealed partial class DockingSystem
private const int DockRoundingDigits = 2;
public Angle GetAngle(EntityUid uid, TransformComponent xform, EntityUid targetUid, TransformComponent targetXform, EntityQuery<TransformComponent> xformQuery)
public Angle GetAngle(EntityUid uid, TransformComponent xform, EntityUid targetUid, TransformComponent targetXform)
{
var (shuttlePos, shuttleRot) = _transform.GetWorldPositionRotation(xform);
var (targetPos, targetRot) = _transform.GetWorldPositionRotation(targetXform);
@@ -288,9 +288,7 @@ public sealed partial class DockingSystem
// Prioritise by priority docks, then by maximum connected ports, then by most similar angle.
validDockConfigs = validDockConfigs
.OrderByDescending(x => x.Docks.Any(docks =>
TryComp<PriorityDockComponent>(docks.DockBUid, out var priority) &&
priority.Tag?.Equals(priorityTag) == true))
.OrderByDescending(x => IsConfigPriority(x, priorityTag))
.ThenByDescending(x => x.Docks.Count)
.ThenBy(x => Math.Abs(Angle.ShortestDistance(x.Angle.Reduced(), targetGridAngle).Theta)).ToList();
@@ -301,6 +299,13 @@ public sealed partial class DockingSystem
return location;
}
public bool IsConfigPriority(DockingConfig config, string? priorityTag)
{
return config.Docks.Any(docks =>
TryComp<PriorityDockComponent>(docks.DockBUid, out var priority)
&& priority.Tag?.Equals(priorityTag) == true);
}
/// <summary>
/// Checks whether the shuttle can warp to the specified position.
/// </summary>

View File

@@ -1,3 +1,4 @@
using System.Linq;
using System.Numerics;
using System.Threading;
using Content.Server.Access.Systems;
@@ -255,18 +256,19 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
}
/// <summary>
/// Attempts to dock the emergency shuttle to the station.
/// Attempts to dock a station's emergency shuttle.
/// </summary>
public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
/// <seealso cref="DockEmergencyShuttle"/>
public ShuttleDockResult? DockSingleEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
{
if (!Resolve(stationUid, ref stationShuttle))
return;
return null;
if (!TryComp(stationShuttle.EmergencyShuttle, out TransformComponent? xform) ||
!TryComp<ShuttleComponent>(stationShuttle.EmergencyShuttle, out var shuttle))
{
Log.Error($"Attempted to call an emergency shuttle for an uninitialized station? Station: {ToPrettyString(stationUid)}. Shuttle: {ToPrettyString(stationShuttle.EmergencyShuttle)}");
return;
return null;
}
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(stationUid));
@@ -274,60 +276,126 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
// UHH GOOD LUCK
if (targetGrid == null)
{
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false);
_logger.Add(
LogType.EmergencyShuttle,
LogImpact.High,
$"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
return new ShuttleDockResult
{
Station = (stationUid, stationShuttle),
ResultType = ShuttleDockResultType.GoodLuck,
};
}
ShuttleDockResultType resultType;
if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, out var config, DockTag))
{
_logger.Add(
LogType.EmergencyShuttle,
LogImpact.High,
$"Emergency shuttle {ToPrettyString(stationUid)} docked with stations");
resultType = _dock.IsConfigPriority(config, DockTag)
? ShuttleDockResultType.PriorityDock
: ShuttleDockResultType.OtherDock;
}
else
{
_logger.Add(
LogType.EmergencyShuttle,
LogImpact.High,
$"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
resultType = ShuttleDockResultType.NoDock;
}
return new ShuttleDockResult
{
Station = (stationUid, stationShuttle),
DockingConfig = config,
ResultType = resultType,
TargetGrid = targetGrid,
};
}
/// <summary>
/// Do post-shuttle-dock setup. Announce to the crew and set up shuttle timers.
/// </summary>
public void AnnounceShuttleDock(ShuttleDockResult result, bool extended)
{
var shuttle = result.Station.Comp.EmergencyShuttle;
DebugTools.Assert(shuttle != null);
if (result.ResultType == ShuttleDockResultType.GoodLuck)
{
_chatSystem.DispatchStationAnnouncement(
result.Station,
Loc.GetString("emergency-shuttle-good-luck"),
playDefaultSound: false);
// TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
return;
}
var xformQuery = GetEntityQuery<TransformComponent>();
DebugTools.Assert(result.TargetGrid != null);
if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag))
// Send station announcement.
var targetXform = Transform(result.TargetGrid.Value);
var angle = _dock.GetAngle(
shuttle.Value,
Transform(shuttle.Value),
result.TargetGrid.Value,
targetXform);
var direction = ContentLocalizationManager.FormatDirection(angle.GetDir());
var location = FormattedMessage.RemoveMarkupPermissive(
_navMap.GetNearestBeaconString((shuttle.Value, Transform(shuttle.Value))));
var extendedText = extended ? Loc.GetString("emergency-shuttle-extended") : "";
var locKey = result.ResultType == ShuttleDockResultType.NoDock
? "emergency-shuttle-nearby"
: "emergency-shuttle-docked";
_chatSystem.DispatchStationAnnouncement(
result.Station,
Loc.GetString(
locKey,
("time", $"{_consoleAccumulator:0}"),
("direction", direction),
("location", location),
("extended", extendedText)),
playDefaultSound: false);
// Trigger shuttle timers on the shuttle.
var time = TimeSpan.FromSeconds(_consoleAccumulator);
if (TryComp<DeviceNetworkComponent>(shuttle, out var netComp))
{
if (TryComp(targetGrid.Value, out TransformComponent? targetXform))
var payload = new NetworkPayload
{
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
var direction = ContentLocalizationManager.FormatDirection(angle.GetDir());
var location = FormattedMessage.RemoveMarkupPermissive(_navMap.GetNearestBeaconString((stationShuttle.EmergencyShuttle.Value, xform)));
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", direction), ("location", location)), playDefaultSound: false);
}
// shuttle timers
var time = TimeSpan.FromSeconds(_consoleAccumulator);
if (TryComp<DeviceNetworkComponent>(stationShuttle.EmergencyShuttle.Value, out var netComp))
{
var payload = new NetworkPayload
{
[ShuttleTimerMasks.ShuttleMap] = stationShuttle.EmergencyShuttle.Value,
[ShuttleTimerMasks.SourceMap] = targetXform?.MapUid,
[ShuttleTimerMasks.DestMap] = _roundEnd.GetCentcomm(),
[ShuttleTimerMasks.ShuttleTime] = time,
[ShuttleTimerMasks.SourceTime] = time,
[ShuttleTimerMasks.DestTime] = time + TimeSpan.FromSeconds(TransitTime),
[ShuttleTimerMasks.Docked] = true
};
_deviceNetworkSystem.QueuePacket(stationShuttle.EmergencyShuttle.Value, null, payload, netComp.TransmitFrequency);
}
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} docked with stations");
// TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast(), true);
[ShuttleTimerMasks.ShuttleMap] = shuttle,
[ShuttleTimerMasks.SourceMap] = targetXform.MapUid,
[ShuttleTimerMasks.DestMap] = _roundEnd.GetCentcomm(),
[ShuttleTimerMasks.ShuttleTime] = time,
[ShuttleTimerMasks.SourceTime] = time,
[ShuttleTimerMasks.DestTime] = time + TimeSpan.FromSeconds(TransitTime),
[ShuttleTimerMasks.Docked] = true,
};
_deviceNetworkSystem.QueuePacket(shuttle.Value, null, payload, netComp.TransmitFrequency);
}
else
{
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
{
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
var direction = ContentLocalizationManager.FormatDirection(angle.GetDir());
var location = FormattedMessage.RemoveMarkupPermissive(_navMap.GetNearestBeaconString((stationShuttle.EmergencyShuttle.Value, xform)));
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-nearby", ("time", $"{_consoleAccumulator:0}"), ("direction", direction), ("location", location)), playDefaultSound: false);
}
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
// TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
}
// Play announcement audio.
var audioFile = result.ResultType == ShuttleDockResultType.NoDock
? "/Audio/Misc/notice1.ogg"
: "/Audio/Announcements/shuttle_dock.ogg";
// TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal(audioFile, Filter.Broadcast(), true);
}
private void OnStationInit(EntityUid uid, StationCentcommComponent component, MapInitEvent args)
@@ -353,9 +421,12 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
}
/// <summary>
/// Spawns the emergency shuttle for each station and starts the countdown until controls unlock.
/// Teleports the emergency shuttle to its station and starts the countdown until it launches.
/// </summary>
public void CallEmergencyShuttle()
/// <remarks>
/// If the emergency shuttle is disabled, this immediately ends the round.
/// </remarks>
public void DockEmergencyShuttle()
{
if (EmergencyShuttleArrived)
return;
@@ -371,9 +442,34 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
var dockResults = new List<ShuttleDockResult>();
while (query.MoveNext(out var uid, out var comp))
{
CallEmergencyShuttle(uid, comp);
if (DockSingleEmergencyShuttle(uid, comp) is { } dockResult)
dockResults.Add(dockResult);
}
// Make the shuttle wait longer if it couldn't dock in the normal spot.
// We have to handle the possibility of there being multiple stations, so since the shuttle timer is global,
// use the WORST value we have.
var worstResult = dockResults.Max(x => x.ResultType);
var multiplier = worstResult switch
{
ShuttleDockResultType.OtherDock => _configManager.GetCVar(
CCVars.EmergencyShuttleDockTimeMultiplierOtherDock),
ShuttleDockResultType.NoDock => _configManager.GetCVar(
CCVars.EmergencyShuttleDockTimeMultiplierNoDock),
// GoodLuck doesn't get a multiplier.
// Quite frankly at that point the round is probably so fucked that you'd rather it be over ASAP.
_ => 1,
};
_consoleAccumulator *= multiplier;
foreach (var shuttleDockResult in dockResults)
{
AnnounceShuttleDock(shuttleDockResult, multiplier > 1);
}
_commsConsole.UpdateCommsConsoleInterface();
@@ -579,4 +675,66 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
return _transformSystem.GetWorldMatrix(shuttleXform).TransformBox(grid.LocalAABB).Contains(_transformSystem.GetWorldPosition(xform));
}
/// <summary>
/// A result of a shuttle dock operation done by <see cref="EmergencyShuttleSystem.DockSingleEmergencyShuttle"/>.
/// </summary>
/// <seealso cref="ShuttleDockResultType"/>
public sealed class ShuttleDockResult
{
/// <summary>
/// The station for which the emergency shuttle got docked.
/// </summary>
public Entity<StationEmergencyShuttleComponent> Station;
/// <summary>
/// The target grid of the station that the shuttle tried to dock to.
/// </summary>
/// <remarks>
/// Not present if <see cref="ResultType"/> is <see cref="ShuttleDockResultType.GoodLuck"/>.
/// </remarks>
public EntityUid? TargetGrid;
/// <summary>
/// Enum code describing the dock result.
/// </summary>
public ShuttleDockResultType ResultType;
/// <summary>
/// The docking config used to actually dock to the station.
/// </summary>
/// <remarks>
/// Only present if <see cref="ResultType"/> is <see cref="ShuttleDockResultType.PriorityDock"/>
/// or <see cref="ShuttleDockResultType.NoDock"/>.
/// </remarks>
public DockingConfig? DockingConfig;
}
/// <summary>
/// Emergency shuttle dock result codes used by <see cref="ShuttleDockResult"/>.
/// </summary>
public enum ShuttleDockResultType : byte
{
// This enum is ordered from "best" to "worst". This is used to sort the results.
/// <summary>
/// The shuttle was docked at a priority dock, which is the intended destination.
/// </summary>
PriorityDock,
/// <summary>
/// The shuttle docked at another dock on the station then the intended priority dock.
/// </summary>
OtherDock,
/// <summary>
/// The shuttle couldn't find any suitable dock on the station at all, it did not dock.
/// </summary>
NoDock,
/// <summary>
/// No station grid was found at all, shuttle did not get moved.
/// </summary>
GoodLuck,
}
}

View File

@@ -669,8 +669,28 @@ public sealed partial class ShuttleSystem
/// Tries to dock with the target grid, otherwise falls back to proximity.
/// This bypasses FTL travel time.
/// </summary>
public bool TryFTLDock(EntityUid shuttleUid, ShuttleComponent component, EntityUid targetUid, string? priorityTag = null)
public bool TryFTLDock(
EntityUid shuttleUid,
ShuttleComponent component,
EntityUid targetUid,
string? priorityTag = null)
{
return TryFTLDock(shuttleUid, component, targetUid, out _, priorityTag);
}
/// <summary>
/// Tries to dock with the target grid, otherwise falls back to proximity.
/// This bypasses FTL travel time.
/// </summary>
public bool TryFTLDock(
EntityUid shuttleUid,
ShuttleComponent component,
EntityUid targetUid,
[NotNullWhen(true)] out DockingConfig? config,
string? priorityTag = null)
{
config = null;
if (!_xformQuery.TryGetComponent(shuttleUid, out var shuttleXform) ||
!_xformQuery.TryGetComponent(targetUid, out var targetXform) ||
targetXform.MapUid == null ||
@@ -679,7 +699,7 @@ public sealed partial class ShuttleSystem
return false;
}
var config = _dockSystem.GetDockingConfig(shuttleUid, targetUid, priorityTag);
config = _dockSystem.GetDockingConfig(shuttleUid, targetUid, priorityTag);
if (config != null)
{

View File

@@ -1,8 +1,11 @@
using Content.Server.GameTicking;
using Content.Server.Spawners.Components;
using Content.Server.Station.Systems;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Server.Containers;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Spawners.EntitySystems;
@@ -11,6 +14,7 @@ public sealed class ContainerSpawnPointSystem : EntitySystem
{
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
@@ -26,6 +30,13 @@ public sealed class ContainerSpawnPointSystem : EntitySystem
if (args.SpawnResult != null)
return;
// If it's just a spawn pref check if it's for cryo (silly).
if (args.HumanoidCharacterProfile?.SpawnPriority != SpawnPriorityPreference.Cryosleep &&
(!_proto.TryIndex(args.Job?.Prototype, out var jobProto) || jobProto.JobEntity == null))
{
return;
}
var query = EntityQueryEnumerator<ContainerSpawnPointComponent, ContainerManagerComponent, TransformComponent>();
var possibleContainers = new List<Entity<ContainerSpawnPointComponent, ContainerManagerComponent, TransformComponent>>();

View File

@@ -21,6 +21,7 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
{
SubscribeLocalEvent<SurveillanceCameraMonitorComponent, SurveillanceCameraDeactivateEvent>(OnSurveillanceCameraDeactivate);
SubscribeLocalEvent<SurveillanceCameraMonitorComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<SurveillanceCameraMonitorComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<SurveillanceCameraMonitorComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
SubscribeLocalEvent<SurveillanceCameraMonitorComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<SurveillanceCameraMonitorComponent, AfterActivatableUIOpenEvent>(OnToggleInterface);
@@ -196,6 +197,12 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
}
}
private void OnShutdown(EntityUid uid, SurveillanceCameraMonitorComponent component, ComponentShutdown args)
{
RemoveActiveCamera(uid, component);
}
private void OnToggleInterface(EntityUid uid, SurveillanceCameraMonitorComponent component,
AfterActivatableUIOpenEvent args)
{

View File

@@ -321,6 +321,13 @@ public sealed class SurveillanceCameraSystem : EntitySystem
{
AddActiveViewer(camera, player, monitor, component);
}
// Add monitor without viewers
if (players.Count == 0 && monitor != null)
{
component.ActiveMonitors.Add(monitor.Value);
UpdateVisuals(camera, component);
}
}
// Switch the set of active viewers from one camera to another.
@@ -349,13 +356,12 @@ public sealed class SurveillanceCameraSystem : EntitySystem
public void RemoveActiveViewer(EntityUid camera, EntityUid player, EntityUid? monitor = null, SurveillanceCameraComponent? component = null, ActorComponent? actor = null)
{
if (!Resolve(camera, ref component)
|| !Resolve(player, ref actor))
{
if (!Resolve(camera, ref component))
return;
}
_viewSubscriberSystem.RemoveViewSubscriber(camera, actor.PlayerSession);
if (Resolve(player, ref actor))
_viewSubscriberSystem.RemoveViewSubscriber(camera, actor.PlayerSession);
component.ActiveViewers.Remove(player);
if (monitor != null)
@@ -377,6 +383,13 @@ public sealed class SurveillanceCameraSystem : EntitySystem
{
RemoveActiveViewer(camera, player, monitor, component);
}
// Even if not removing any viewers, remove the monitor
if (players.Count == 0 && monitor != null)
{
component.ActiveMonitors.Remove(monitor.Value);
UpdateVisuals(camera, component);
}
}
private void UpdateVisuals(EntityUid uid, SurveillanceCameraComponent? component = null, AppearanceComponent? appearance = null)

View File

@@ -7,10 +7,16 @@ namespace Content.Server.Temperature.Components;
public sealed partial class TemperatureProtectionComponent : Component
{
/// <summary>
/// How much to multiply temperature deltas by.
/// Multiplier for the transferred heat when heating up
/// </summary>
[DataField]
public float Coefficient = 1.0f;
public float HeatingCoefficient = 1.0f;
/// <summary>
/// Multiplier for the transferred heat when cooling down
/// </summary>
[DataField]
public float CoolingCoefficient = 1.0f;
}
/// <summary>

View File

@@ -299,7 +299,11 @@ public sealed class TemperatureSystem : EntitySystem
private void OnTemperatureChangeAttempt(EntityUid uid, TemperatureProtectionComponent component,
InventoryRelayedEvent<ModifyChangedTemperatureEvent> args)
{
var ev = new GetTemperatureProtectionEvent(component.Coefficient);
var coefficient = args.Args.TemperatureDelta < 0
? component.CoolingCoefficient
: component.HeatingCoefficient;
var ev = new GetTemperatureProtectionEvent(coefficient);
RaiseLocalEvent(uid, ref ev);
args.Args.TemperatureDelta *= ev.Coefficient;

View File

@@ -1240,6 +1240,13 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<float> AtmosHeatScale =
CVarDef.Create("atmos.heat_scale", 8f, CVar.SERVERONLY);
/// <summary>
/// Maximum explosion radius for explosions caused by bursting a gas tank ("max caps").
/// Setting this to zero disables the explosion but still allows the tank to burst and leak.
/// </summary>
public static readonly CVarDef<float> AtmosTankFragment =
CVarDef.Create("atmos.max_explosion_range", 26f, CVar.SERVERONLY);
/*
* MIDI instruments
*/
@@ -1556,6 +1563,18 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<float> EmergencyShuttleDockTime =
CVarDef.Create("shuttle.emergency_dock_time", 180f, CVar.SERVERONLY);
/// <summary>
/// If the emergency shuttle can't dock at a priority port, the dock time will be multiplied with this value.
/// </summary>
public static readonly CVarDef<float> EmergencyShuttleDockTimeMultiplierOtherDock =
CVarDef.Create("shuttle.emergency_dock_time_multiplier_other_dock", 1.6667f, CVar.SERVERONLY);
/// <summary>
/// If the emergency shuttle can't dock at all, the dock time will be multiplied with this value.
/// </summary>
public static readonly CVarDef<float> EmergencyShuttleDockTimeMultiplierNoDock =
CVarDef.Create("shuttle.emergency_dock_time_multiplier_no_dock", 2f, CVar.SERVERONLY);
/// <summary>
/// How long after the console is authorized for the shuttle to early launch.
/// </summary>

View File

@@ -1,4 +1,5 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.Kitchen.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.FixedPoint;
@@ -34,6 +35,17 @@ public abstract partial class SharedSolutionContainerSystem
return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution);
}
public bool TryGetExtractableSolution(Entity<ExtractableComponent?, SolutionContainerManagerComponent?> entity, [NotNullWhen(true)] out Entity<SolutionComponent>? soln, [NotNullWhen(true)] out Solution? solution)
{
if (!Resolve(entity, ref entity.Comp1, logMissing: false))
{
(soln, solution) = (default!, null);
return false;
}
return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.GrindableSolution, out soln, out solution);
}
public bool TryGetDumpableSolution(Entity<DumpableSolutionComponent?, SolutionContainerManagerComponent?> entity, [NotNullWhen(true)] out Entity<SolutionComponent>? soln, [NotNullWhen(true)] out Solution? solution)
{
if (!Resolve(entity, ref entity.Comp1, logMissing: false))

View File

@@ -42,11 +42,11 @@ public sealed class DamageContactsSystem : EntitySystem
{
var otherUid = args.OtherEntity;
if (!TryComp<PhysicsComponent>(uid, out var body))
if (!TryComp<PhysicsComponent>(otherUid, out var body))
return;
var damageQuery = GetEntityQuery<DamageContactsComponent>();
foreach (var ent in _physics.GetContactingEntities(uid, body))
foreach (var ent in _physics.GetContactingEntities(otherUid, body))
{
if (ent == uid)
continue;

View File

@@ -1,12 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Fluids.Components;
/// <summary>
/// Blocks this entity's ability to spill solution containing entities via the verb menu.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class PreventSpillerComponent : Component
{
}

View File

@@ -34,7 +34,7 @@ public abstract partial class SharedPuddleSystem
private void AddSpillVerb(Entity<SpillableComponent> entity, ref GetVerbsEvent<Verb> args)
{
if (!args.CanAccess || !args.CanInteract)
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
return;
if (!_solutionContainerSystem.TryGetSolution(args.Target, entity.Comp.SolutionName, out var soln, out var solution))
@@ -46,10 +46,6 @@ public abstract partial class SharedPuddleSystem
if (solution.Volume == FixedPoint2.Zero)
return;
if (HasComp<PreventSpillerComponent>(args.User))
return;
Verb verb = new()
{
Text = Loc.GetString("spill-target-verb-get-data-text")

View File

@@ -15,12 +15,16 @@ public sealed class NewsWriterBoundUserInterfaceState : BoundUserInterfaceState
public readonly NewsArticle[] Articles;
public readonly bool PublishEnabled;
public readonly TimeSpan NextPublish;
public readonly string DraftTitle;
public readonly string DraftContent;
public NewsWriterBoundUserInterfaceState(NewsArticle[] articles, bool publishEnabled, TimeSpan nextPublish)
public NewsWriterBoundUserInterfaceState(NewsArticle[] articles, bool publishEnabled, TimeSpan nextPublish, string draftTitle, string draftContent)
{
Articles = articles;
PublishEnabled = publishEnabled;
NextPublish = nextPublish;
DraftTitle = draftTitle;
DraftContent = draftContent;
}
}
@@ -53,3 +57,21 @@ public sealed class NewsWriterDeleteMessage : BoundUserInterfaceMessage
public sealed class NewsWriterArticlesRequestMessage : BoundUserInterfaceMessage
{
}
[Serializable, NetSerializable]
public sealed class NewsWriterSaveDraftMessage : BoundUserInterfaceMessage
{
public readonly string DraftTitle;
public readonly string DraftContent;
public NewsWriterSaveDraftMessage(string draftTitle, string draftContent)
{
DraftTitle = draftTitle;
DraftContent = draftContent;
}
}
[Serializable, NetSerializable]
public sealed class NewsWriterRequestDraftMessage : BoundUserInterfaceMessage
{
}

View File

@@ -69,6 +69,13 @@ public sealed partial class MaterialReclaimerComponent : Component
[DataField]
public string? SolutionContainerId;
/// <summary>
/// If the reclaimer should attempt to reclaim all solutions or just drainable ones
/// Difference between Recycler and Industrial Reagent Grinder
/// </summary>
[DataField]
public bool OnlyReclaimDrainable = true;
/// <summary>
/// a whitelist for what entities can be inserted into this reclaimer
/// </summary>

View File

@@ -0,0 +1,17 @@
using Content.Shared.Nutrition.EntitySystems;
using Robust.Shared.GameStates;
namespace Content.Shared.Nutrition.Components;
/// <summary>
/// Attempts to metamorphose a modular food when a new ingredient is added.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedFoodSequenceSystem))]
public sealed partial class FoodMetamorphableByAddingComponent : Component
{
/// <summary>
/// if true, the metamorphosis will only be attempted when the sequence ends, not when each element is added.
/// </summary>
[DataField]
public bool OnlyFinal = true;
}

View File

@@ -1,55 +1,25 @@
using System.Numerics;
using Content.Shared.Nutrition.EntitySystems;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Content.Shared.Nutrition.Prototypes;
using Content.Shared.Tag;
using Robust.Shared.Prototypes;
namespace Content.Shared.Nutrition.Components;
/// <summary>
/// Tndicates that this entity can be inserted into FoodSequence, which will transfer all reagents to the target.
/// Indicates that this entity can be inserted into FoodSequence, which will transfer all reagents to the target.
/// </summary>
[RegisterComponent, Access(typeof(SharedFoodSequenceSystem))]
public sealed partial class FoodSequenceElementComponent : Component
{
/// <summary>
/// the same object can be used in different sequences, and it will have a different sprite in different sequences.
/// The same object can be used in different sequences, and it will have a different data in then.
/// </summary>
[DataField(required: true)]
public Dictionary<string, FoodSequenceElementEntry> Entries = new();
public Dictionary<ProtoId<TagPrototype>, ProtoId<FoodSequenceElementPrototype>> Entries = new();
/// <summary>
/// which solution we will add to the main dish
/// Which solution we will add to the main dish
/// </summary>
[DataField]
public string Solution = "food";
/// <summary>
/// state used to generate the appearance of the added layer
/// </summary>
[DataField]
public SpriteSpecifier? Sprite;
}
[DataRecord, Serializable, NetSerializable]
public sealed class FoodSequenceElementEntry
{
/// <summary>
/// A localized name piece to build into the item name generator.
/// </summary>
public LocId? Name { get; set; } = null;
/// <summary>
/// overriding default sprite
/// </summary>
public SpriteSpecifier? Sprite { get; set; } = null;
/// <summary>
/// If the layer is the final one, it can be added over the limit, but no other layers can be added after it.
/// </summary>
public bool Final { get; set; } = false;
/// <summary>
/// the shear of a particular layer. Allows a little "randomization" of each layer.
/// </summary>
public Vector2 LocalOffset { get; set; } = Vector2.Zero;
}

View File

@@ -1,6 +1,11 @@
using System.Numerics;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Nutrition.Prototypes;
using Content.Shared.Tag;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Nutrition.Components;
@@ -14,7 +19,7 @@ public sealed partial class FoodSequenceStartPointComponent : Component
/// A key that determines which types of food elements can be attached to a food.
/// </summary>
[DataField(required: true)]
public string Key = string.Empty;
public ProtoId<TagPrototype> Key = string.Empty;
/// <summary>
/// The maximum number of layers of food that can be placed on this item.
@@ -22,62 +27,20 @@ public sealed partial class FoodSequenceStartPointComponent : Component
[DataField]
public int MaxLayers = 10;
/// <summary>
/// Start shift from the center of the sprite where the first layer of food will be placed.
/// </summary>
[DataField]
public Vector2 StartPosition = Vector2.Zero;
/// <summary>
/// Shift from the start position applied to each subsequent layer.
/// </summary>
[DataField]
public Vector2 Offset = Vector2.Zero;
/// <summary>
/// Can we put more layers?
/// </summary>
[DataField]
public bool Finished;
/// <summary>
/// list of sprite states to be displayed on this object.
/// </summary>
[DataField, AutoNetworkedField]
public List<FoodSequenceElementEntry> FoodLayers = new();
public HashSet<string> RevealedLayers = new();
/// <summary>
/// target layer, where new layers will be added. This allows you to control the order of generative layers and static layers.
/// </summary>
[DataField]
public string TargetLayerMap = "foodSequenceLayers";
/// <summary>
/// If true, the generative layers will be placed in reverse order.
/// </summary>
[DataField]
public bool InverseLayers;
/// <summary>
/// each layer will get a random offset in the specified range
/// </summary>
[DataField]
public Vector2 MaxLayerOffset = Vector2.Zero;
/// <summary>
/// each layer will get a random offset in the specified range
/// </summary>
[DataField]
public Vector2 MinLayerOffset = Vector2.Zero;
/// <summary>
/// solution where reagents will be added from newly added ingredients
/// </summary>
[DataField]
public string Solution = "food";
#region name generation
/// <summary>
/// LocId with a name generation pattern.
/// </summary>
@@ -101,4 +64,96 @@ public sealed partial class FoodSequenceStartPointComponent : Component
/// </summary>
[DataField]
public LocId? NameSuffix;
#endregion
#region visual
/// <summary>
/// list of sprite states to be displayed on this object.
/// </summary>
[DataField, AutoNetworkedField]
public List<FoodSequenceVisualLayer> FoodLayers = new();
/// <summary>
/// If true, the generative layers will be placed in reverse order.
/// </summary>
[DataField]
public bool InverseLayers;
/// <summary>
/// target layer, where new layers will be added. This allows you to control the order of generative layers and static layers.
/// </summary>
[DataField]
public string TargetLayerMap = "foodSequenceLayers";
/// <summary>
/// Start shift from the center of the sprite where the first layer of food will be placed.
/// </summary>
[DataField]
public Vector2 StartPosition = Vector2.Zero;
/// <summary>
/// Shift from the start position applied to each subsequent layer.
/// </summary>
[DataField]
public Vector2 Offset = Vector2.Zero;
/// <summary>
/// each layer will get a random offset in the specified range
/// </summary>
[DataField]
public Vector2 MaxLayerOffset = Vector2.Zero;
/// <summary>
/// each layer will get a random offset in the specified range
/// </summary>
[DataField]
public Vector2 MinLayerOffset = Vector2.Zero;
[DataField]
public bool AllowHorizontalFlip = true;
public HashSet<string> RevealedLayers = new();
#endregion
}
/// <summary>
/// class that synchronizes with the client
/// Stores all the necessary information for rendering the FoodSequence element
/// </summary>
[DataRecord, Serializable, NetSerializable]
public record struct FoodSequenceVisualLayer
{
/// <summary>
/// reference to the original prototype of the layer. Used to edit visual layers.
/// </summary>
public ProtoId<FoodSequenceElementPrototype> Proto;
/// <summary>
/// Sprite rendered in sequence
/// </summary>
public SpriteSpecifier? Sprite { get; set; } = SpriteSpecifier.Invalid;
/// <summary>
/// Relative size of the sprite displayed in FoodSequence
/// </summary>
public Vector2 Scale { get; set; } = Vector2.One;
/// <summary>
/// The offset of a particular layer. Allows a little position randomization of each layer.
/// </summary>
public Vector2 LocalOffset { get; set; } = Vector2.Zero;
public FoodSequenceVisualLayer(ProtoId<FoodSequenceElementPrototype> proto,
SpriteSpecifier? sprite,
Vector2 scale,
Vector2 offset)
{
Proto = proto;
Sprite = sprite;
Scale = scale;
LocalOffset = offset;
}
}

View File

@@ -1,5 +1,8 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.DoAfter;
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Nutrition;
@@ -67,3 +70,8 @@ public record struct SliceFoodEvent();
public sealed partial class SliceFoodDoAfterEvent : SimpleDoAfterEvent
{
}
/// <summary>
/// Raised on FoodSequence start element entity when new ingredient is added to FoodSequence
/// </summary>
public record struct FoodSequenceIngredientAddedEvent(EntityUid Start, EntityUid Element, ProtoId<FoodSequenceElementPrototype> Proto, EntityUid? User = null);

View File

@@ -0,0 +1,218 @@
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Destructible.Thresholds;
using Content.Shared.Nutrition.Components;
using Content.Shared.Tag;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Nutrition.FoodMetamorphRules;
/// <summary>
/// abstract rules that are used to verify the correct foodSequence for recipe
/// </summary>
[ImplicitDataDefinitionForInheritors]
[Serializable, NetSerializable]
public abstract partial class FoodMetamorphRule
{
public abstract bool Check(IPrototypeManager protoMan, EntityManager entMan, EntityUid food, List<FoodSequenceVisualLayer> ingredients);
}
/// <summary>
/// The requirement that the sequence be within the specified size limit
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class SequenceLength : FoodMetamorphRule
{
[DataField(required: true)]
public MinMax Range;
public override bool Check(IPrototypeManager protoMan, EntityManager entMan, EntityUid food, List<FoodSequenceVisualLayer> ingredients)
{
return ingredients.Count <= Range.Max && ingredients.Count >= Range.Min;
}
}
/// <summary>
/// A requirement that the last element of the sequence have one or all of the required tags
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class LastElementHasTags : FoodMetamorphRule
{
[DataField(required: true)]
public List<ProtoId<TagPrototype>> Tags = new ();
[DataField]
public bool NeedAll = true;
public override bool Check(IPrototypeManager protoMan, EntityManager entMan, EntityUid food, List<FoodSequenceVisualLayer> ingredients)
{
var lastIngredient = ingredients[ingredients.Count - 1];
if (!protoMan.TryIndex(lastIngredient.Proto, out var protoIndexed))
return false;
foreach (var tag in Tags)
{
var containsTag = protoIndexed.Tags.Contains(tag);
if (NeedAll && !containsTag)
{
return false;
}
if (!NeedAll && containsTag)
{
return true;
}
}
return NeedAll;
}
}
/// <summary>
/// A requirement that the specified sequence element have one or all of the required tags
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class ElementHasTags : FoodMetamorphRule
{
[DataField(required: true)]
public int ElementNumber = 0;
[DataField(required: true)]
public List<ProtoId<TagPrototype>> Tags = new ();
[DataField]
public bool NeedAll = true;
public override bool Check(IPrototypeManager protoMan, EntityManager entMan, EntityUid food, List<FoodSequenceVisualLayer> ingredients)
{
if (ingredients.Count < ElementNumber + 1)
return false;
if (!protoMan.TryIndex(ingredients[ElementNumber].Proto, out var protoIndexed))
return false;
foreach (var tag in Tags)
{
var containsTag = protoIndexed.Tags.Contains(tag);
if (NeedAll && !containsTag)
{
return false;
}
if (!NeedAll && containsTag)
{
return true;
}
}
return NeedAll;
}
}
/// <summary>
/// requirement that the food contains certain reagents (e.g. sauces)
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class FoodHasReagent : FoodMetamorphRule
{
[DataField(required: true)]
public ProtoId<ReagentPrototype> Reagent = new();
[DataField(required: true)]
public MinMax Count;
[DataField]
public string Solution = "food";
public override bool Check(IPrototypeManager protoMan, EntityManager entMan, EntityUid food, List<FoodSequenceVisualLayer> ingredients)
{
if (!entMan.TryGetComponent<SolutionContainerManagerComponent>(food, out var solMan))
return false;
var solutionMan = entMan.System<SharedSolutionContainerSystem>();
if (!solutionMan.TryGetSolution(food, Solution, out var foodSoln, out var foodSolution))
return false;
foreach (var (id, quantity) in foodSoln.Value.Comp.Solution.Contents)
{
if (id.Prototype != Reagent.Id)
continue;
if (quantity < Count.Min || quantity > Count.Max)
break;
return true;
}
return false;
}
}
/// <summary>
/// A requirement that there be X ingredients in the sequence that have one or all of the specified tags.
/// </summary>
[UsedImplicitly]
[Serializable, NetSerializable]
public sealed partial class IngredientsWithTags : FoodMetamorphRule
{
[DataField(required: true)]
public List<ProtoId<TagPrototype>> Tags = new ();
[DataField(required: true)]
public MinMax Count = new();
[DataField]
public bool NeedAll = true;
public override bool Check(IPrototypeManager protoMan, EntityManager entMan, EntityUid food, List<FoodSequenceVisualLayer> ingredients)
{
var count = 0;
foreach (var ingredient in ingredients)
{
if (!protoMan.TryIndex(ingredient.Proto, out var protoIndexed))
continue;
var allowed = false;
if (NeedAll)
{
allowed = true;
foreach (var tag in Tags)
{
if (!protoIndexed.Tags.Contains(tag))
{
allowed = false;
break;
}
}
}
else
{
allowed = false;
foreach (var tag in Tags)
{
if (protoIndexed.Tags.Contains(tag))
{
allowed = true;
break;
}
}
}
if (allowed)
count++;
}
return count >= Count.Min && count <= Count.Max;
}
}

View File

@@ -0,0 +1,38 @@
using Content.Shared.Tag;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Nutrition.Prototypes;
/// <summary>
/// Unique data storage block for different FoodSequence layers
/// </summary>
[Prototype("foodSequenceElement")]
public sealed partial class FoodSequenceElementPrototype : IPrototype
{
[IdDataField] public string ID { get; private set; } = default!;
/// <summary>
/// sprite options. A random one will be selected and used to display the layer.
/// </summary>
[DataField]
public List<SpriteSpecifier> Sprites { get; private set; } = new();
/// <summary>
/// A localized name piece to build into the item name generator.
/// </summary>
[DataField]
public LocId? Name { get; private set; }
/// <summary>
/// If the layer is the final one, it can be added over the limit, but no other layers can be added after it.
/// </summary>
[DataField]
public bool Final { get; private set; }
/// <summary>
/// Tag list of this layer. Used for recipes for food metamorphosis.
/// </summary>
[DataField]
public List<ProtoId<TagPrototype>> Tags { get; set; } = new();
}

View File

@@ -0,0 +1,32 @@
using Content.Shared.Nutrition.FoodMetamorphRules;
using Content.Shared.Tag;
using Robust.Shared.Prototypes;
namespace Content.Shared.Nutrition.Prototypes;
/// <summary>
/// Stores a recipe so that FoodSequence assembled in the right sequence can turn into a special meal.
/// </summary>
[Prototype]
public sealed partial class MetamorphRecipePrototype : IPrototype
{
[IdDataField] public string ID { get; private set; } = default!;
/// <summary>
/// The key of the FoodSequence being collected. For example “burger” “taco” etc.
/// </summary>
[DataField(required: true)]
public ProtoId<TagPrototype> Key = string.Empty;
/// <summary>
/// The entity that will be created as a result of this recipe, and into which all the reagents will be transferred.
/// </summary>
[DataField(required: true)]
public EntProtoId Result = default!;
/// <summary>
/// A sequence of rules that must be followed for FoodSequence to metamorphose into a special food.
/// </summary>
[DataField]
public List<FoodMetamorphRule> Rules = new();
}

View File

@@ -1,3 +1,6 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.DungeonGenerators;
/// <summary>
@@ -7,4 +10,11 @@ namespace Content.Shared.Procedural.DungeonGenerators;
/// DungeonData keys are:
/// - Fill
/// </remarks>
public sealed partial class FillGridDunGen : IDunGenLayer;
public sealed partial class FillGridDunGen : IDunGenLayer
{
/// <summary>
/// Tiles the fill can occur on.
/// </summary>
[DataField]
public HashSet<ProtoId<ContentTileDefinition>>? AllowedTiles;
}

View File

@@ -86,7 +86,7 @@ public sealed partial class RevenantComponent : Component
/// The amount of essence that is needed to use the ability.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("defileCost")]
public FixedPoint2 DefileCost = -30;
public FixedPoint2 DefileCost = 30;
/// <summary>
/// The status effects applied after the ability
@@ -121,7 +121,7 @@ public sealed partial class RevenantComponent : Component
/// The amount of essence that is needed to use the ability.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("overloadCost")]
public FixedPoint2 OverloadCost = -40;
public FixedPoint2 OverloadCost = 40;
/// <summary>
/// The status effects applied after the ability
@@ -149,7 +149,7 @@ public sealed partial class RevenantComponent : Component
/// The amount of essence that is needed to use the ability.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("blightCost")]
public float BlightCost = -50;
public float BlightCost = 50;
/// <summary>
/// The status effects applied after the ability
@@ -171,7 +171,7 @@ public sealed partial class RevenantComponent : Component
/// The amount of essence that is needed to use the ability.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("malfunctionCost")]
public FixedPoint2 MalfunctionCost = -60;
public FixedPoint2 MalfunctionCost = 60;
/// <summary>
/// The status effects applied after the ability

View File

@@ -4,7 +4,7 @@ using Robust.Shared.GameStates;
namespace Content.Shared.StepTrigger.Components;
/// <summary>
/// This is used for marking step trigger events that require the user to wear shoes, such as for glass shards.
/// This is used for marking step trigger events that require the user to wear shoes or have protection of some sort, such as for glass shards.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class ClothingRequiredStepTriggerComponent : Component;
public sealed partial class PreventableStepTriggerComponent : Component;

View File

@@ -5,11 +5,11 @@ using Robust.Shared.GameStates;
namespace Content.Shared.StepTrigger.Components;
/// <summary>
/// This is used for cancelling step trigger events if the user is wearing clothing in a valid slot.
/// This is used for cancelling preventable step trigger events if the user is wearing clothing in a valid slot or if the user itself has the component.
/// </summary>
[RegisterComponent, NetworkedComponent]
[Access(typeof(StepTriggerImmuneSystem))]
public sealed partial class ClothingRequiredStepTriggerImmuneComponent : Component, IClothingSlots
public sealed partial class ProtectedFromStepTriggersComponent : Component, IClothingSlots
{
[DataField]
public SlotFlags Slots { get; set; } = SlotFlags.FEET;

View File

@@ -1,9 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared.StepTrigger.Components;
/// <summary>
/// Grants the attached entity to step triggers.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class StepTriggerImmuneComponent : Component;

View File

@@ -1,7 +1,6 @@
using Content.Shared.Examine;
using Content.Shared.Inventory;
using Content.Shared.StepTrigger.Components;
using Content.Shared.Tag;
namespace Content.Shared.StepTrigger.Systems;
@@ -12,25 +11,19 @@ public sealed class StepTriggerImmuneSystem : EntitySystem
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<StepTriggerImmuneComponent, StepTriggerAttemptEvent>(OnStepTriggerAttempt);
SubscribeLocalEvent<ClothingRequiredStepTriggerComponent, StepTriggerAttemptEvent>(OnStepTriggerClothingAttempt);
SubscribeLocalEvent<ClothingRequiredStepTriggerComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<PreventableStepTriggerComponent, StepTriggerAttemptEvent>(OnStepTriggerClothingAttempt);
SubscribeLocalEvent<PreventableStepTriggerComponent, ExaminedEvent>(OnExamined);
}
private void OnStepTriggerAttempt(Entity<StepTriggerImmuneComponent> ent, ref StepTriggerAttemptEvent args)
private void OnStepTriggerClothingAttempt(Entity<PreventableStepTriggerComponent> ent, ref StepTriggerAttemptEvent args)
{
args.Cancelled = true;
}
private void OnStepTriggerClothingAttempt(EntityUid uid, ClothingRequiredStepTriggerComponent component, ref StepTriggerAttemptEvent args)
{
if (_inventory.TryGetInventoryEntity<ClothingRequiredStepTriggerImmuneComponent>(args.Tripper, out _))
if (HasComp<ProtectedFromStepTriggersComponent>(args.Tripper) || _inventory.TryGetInventoryEntity<ProtectedFromStepTriggersComponent>(args.Tripper, out _))
{
args.Cancelled = true;
}
}
private void OnExamined(EntityUid uid, ClothingRequiredStepTriggerComponent component, ExaminedEvent args)
private void OnExamined(EntityUid uid, PreventableStepTriggerComponent component, ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("clothing-required-step-trigger-examine"));
}

View File

@@ -5,8 +5,8 @@
- files: ["ninja_greeting.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from TG station."
source: "https://github.com/tgstation/tgstation/blob/b02b93ce2ab891164511a973493cdf951b4120f7/sound/effects/ninja_greeting.ogg"
copyright: "Created by Chillyconmor"
source: "https://github.com/space-wizards/space-station-14/blob/master/Resources/Audio/Misc/ninja_greeting.ogg"
- files: ["thief_greeting.ogg"]
license: "CC-BY-NC-4.0"

View File

@@ -519,5 +519,13 @@ Entries:
id: 64
time: '2024-08-31T11:38:04.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30433
- author: nikthechampiongr
changes:
- message: The addobjective command will now offer completions for username and
objectives.
type: Tweak
id: 65
time: '2024-09-08T07:28:43.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30456
Name: Admin
Order: 1

View File

@@ -1,366 +1,4 @@
Entries:
- author: Errant
changes:
- message: Items should no longer be missing from backpacks at spawn.
type: Fix
id: 6801
time: '2024-06-22T10:43:18.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29336
- author: Donchan, marboww
changes:
- message: New Nuke Detonation Song "Sound Station 14"
type: Add
id: 6802
time: '2024-06-22T15:09:41.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29345
- author: deltanedas
changes:
- message: Doors access logging can now be disabled by snipping or pulsing a LOG
wire.
type: Tweak
id: 6803
time: '2024-06-22T15:12:58.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29094
- author: notafet
changes:
- message: Reduce air alarm sensitivity to plasma, tritium, and carbon dioxide.
type: Tweak
id: 6804
time: '2024-06-22T15:22:07.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29331
- author: Damn Feds
changes:
- message: thief toolbox kits now better describe contents
type: Tweak
id: 6805
time: '2024-06-22T15:44:18.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/27771
- author: lzk228
changes:
- message: Prying reinforced tile now will give you back metal rod
type: Tweak
id: 6806
time: '2024-06-22T15:47:02.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29084
- author: nikthechampiongr
changes:
- message: Locked firelocks can no longer be pried by hand when powered.
type: Tweak
id: 6807
time: '2024-06-22T17:49:50.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29221
- author: Floofi
changes:
- message: Added lemon juice to the Boozemat!
type: Add
id: 6808
time: '2024-06-22T23:46:19.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/27465
- author: Cojoke-dot
changes:
- message: You can now put hats on Medibots
type: Add
id: 6809
time: '2024-06-23T00:28:20.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28584
- author: WarMechanic
changes:
- message: The TEG now powers itself once started.
type: Tweak
id: 6810
time: '2024-06-23T01:46:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29072
- author: eoineoineoin
changes:
- message: Hand labelers can now apply labels to buttons, switches, and levers
type: Tweak
id: 6811
time: '2024-06-23T14:52:30.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29378
- author: Tayrtahn
changes:
- message: Jugs in the ChemVend are labeled again.
type: Fix
id: 6812
time: '2024-06-23T17:31:34.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29178
- author: DrEnzyme
changes:
- message: Add bagels and poppy seed bagels.
type: Add
id: 6813
time: '2024-06-23T19:33:12.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/24799
- author: PJB3005
changes:
- message: Ghosts can now examine details on objects from any range.
type: Tweak
id: 6814
time: '2024-06-24T15:36:53.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29404
- author: Emisse
changes:
- message: atmos, elite syndie, and deathsquad hardsuits are now the only fireproof
suits
type: Tweak
id: 6815
time: '2024-06-24T22:03:05.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29416
- author: Bhijn and Myr
changes:
- message: The colors of the LEDs on the heater and freezer thermomachines has been
changed from red/green (respectively) to orange/cyan (respectively). In laymen's
terms, this makes thermomachines far more reasonably differentiable for those
with colorblindness.
type: Tweak
id: 6816
time: '2024-06-24T22:40:20.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29397
- author: Elysium206
changes:
- message: Increased Security Riot shields durability significantly and makes actively
blocking better
type: Tweak
id: 6817
time: '2024-06-25T03:56:46.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29239
- author: Tayrtahn
changes:
- message: Fixed space ninja's starting with their internals disabled.
type: Fix
id: 6818
time: '2024-06-25T06:28:48.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29213
- author: PJB3005
changes:
- message: Low pressure damage now does only 1/4th as much damage. This is a band-aid
until better mechanics exists for the crew to deal with breaches of various
kinds.
type: Remove
id: 6819
time: '2024-06-26T00:48:26.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29478
- author: lzk228
changes:
- message: Blood now has less satiation.
type: Tweak
id: 6820
time: '2024-06-26T02:27:11.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29433
- author: Veritable-Calamity
changes:
- message: Moldy food can now be collected in the Janitors' trash bags.
type: Fix
id: 6821
time: '2024-06-26T03:26:59.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29380
- author: Plykiya
changes:
- message: You can now interact with magic mirrors.
type: Fix
id: 6822
time: '2024-06-26T14:25:11.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29491
- author: Doomsdrayk
changes:
- message: Disposal units no longer protect their contents from nuclear explosions.
type: Fix
id: 6823
time: '2024-06-26T14:25:43.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29438
- author: Tayrtahn
changes:
- message: Pills and pill canisters no longer have two labels.
type: Fix
id: 6824
time: '2024-06-27T02:08:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29499
- author: PJB3005
changes:
- message: You can no longer place items onto tabletop games. The feature could
be easily abused to crash the server.
type: Remove
id: 6825
time: '2024-06-27T14:57:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29513
- author: KonstantinAngelov
changes:
- message: Chef's Cookbook has a more IC name.
type: Tweak
id: 6826
time: '2024-06-27T15:11:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29467
- author: metalgearsloth
changes:
- message: Ushanka no longer applies an accent to your name.
type: Tweak
id: 6827
time: '2024-06-28T00:08:09.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29524
- author: JIPDawg
changes:
- message: Changed the sound of pulling back the foam crossbow from the sound of
a Flash to just pulling back a bow.
type: Tweak
id: 6828
time: '2024-06-28T00:23:17.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29508
- author: Plykiya
changes:
- message: Do-after bars performed inside containers are hidden from view.
type: Add
id: 6829
time: '2024-06-28T03:34:24.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29487
- author: slarticodefast
changes:
- message: Passive vents now have the correct sprite.
type: Fix
id: 6830
time: '2024-06-28T12:33:03.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29536
- author: Plykiya
changes:
- message: Icons in the chameleon menu now appear correctly.
type: Fix
id: 6831
time: '2024-06-28T21:21:36.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29539
- author: DogZeroX
changes:
- message: Bananium no longer emit rads
type: Remove
id: 6832
time: '2024-06-28T23:28:27.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29545
- author: TokenStyle
changes:
- message: Mechs can now be destroyed!
type: Tweak
id: 6833
time: '2024-06-29T03:28:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29338
- author: metalgearsloth
changes:
- message: Typing indicators are now predicted.
type: Fix
id: 6834
time: '2024-06-29T03:33:56.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29551
- author: Arteben
changes:
- message: Added favorite tab for construction!
type: Add
id: 6835
time: '2024-06-29T04:10:00.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26347
- author: deltanedas
changes:
- message: Traitors can now be assigned to deconstruct the station's nuke for its
precious plutonium core.
type: Add
- message: Added the Objectives category in the uplink with a Core Extraction Toolbox
for deconstructing said nuke.
type: Add
id: 6836
time: '2024-06-29T04:11:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26786
- author: slarticodefast
changes:
- message: Air vents now have yellow lights if they are in under-pressure lockout.
type: Add
id: 6837
time: '2024-06-29T05:02:48.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29527
- author: metalgearsloth
changes:
- message: Fix character traits not being validated.
type: Fix
id: 6838
time: '2024-06-29T05:39:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28730
- author: PJB3005
changes:
- message: '"Steal plutonium core" traitor objective has been reverted.'
type: Remove
id: 6839
time: '2024-06-29T15:23:03.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29578
- author: MureixloL
changes:
- message: Changed some vending machine point lights to match the vendors better.
type: Tweak
id: 6840
time: '2024-06-30T03:46:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29590
- author: metalgearsloth
changes:
- message: Fix trait categories not respecting unlimited points.
type: Fix
id: 6841
time: '2024-06-30T04:28:49.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29600
- author: ShadowCommander
changes:
- message: Fixed sprite layers disappearing when inserting or removing an item on
entities such as belts, janitor trolley, clipboard, etc.
type: Fix
id: 6842
time: '2024-06-30T04:34:06.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29461
- author: Plykiya
changes:
- message: Syndicate traitor reinforcements price has been changed from 16 TC to
14 TC.
type: Tweak
- message: Nuclear ops reinforcements price has been changed from 16 TC to 35 TC.
type: Tweak
id: 6843
time: '2024-06-30T12:28:01.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29557
- author: Plykiya
changes:
- message: Skeletons are now immune to flashes.
type: Add
id: 6844
time: '2024-06-30T13:42:40.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29604
- author: Plykiya
changes:
- message: The lock on emagged borgs no longer breaks, preventing unauthorized access
and emag checking.
type: Tweak
id: 6845
time: '2024-06-30T13:46:45.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29605
- author: metalgearsloth
changes:
- message: Accentless speech now costs 2 trait points.
type: Tweak
id: 6846
time: '2024-06-30T13:47:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29603
- author: deltanedas
changes:
- message: Fixed sleeper agents not showing up in the round end summary.
type: Fix
id: 6847
time: '2024-06-30T13:51:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29468
- author: EmoGarbage404
changes:
- message: The design on the bar sign can now be changed via a menu.
type: Add
id: 6848
time: '2024-06-30T16:20:58.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29068
- author: Hmeister
changes:
- message: The CE hardsuit is now fireproof again.
type: Tweak
id: 6849
time: '2024-06-30T17:56:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29516
- author: EmoGarbage404
changes:
- message: Blurry vision no longer causes names to momentarily appear as "???" when
@@ -3853,3 +3491,424 @@
id: 7300
time: '2024-09-07T03:04:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31905
- author: Futuristic
changes:
- message: Remove binary encryption key from RD lockers
type: Remove
id: 7301
time: '2024-09-07T05:30:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31909
- author: EmoGarbage404
changes:
- message: Firesuits are now worse at keeping in heat and winter clothes make you
get warmer quicker.
type: Tweak
id: 7302
time: '2024-09-07T05:37:17.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30662
- author: Boaz1111
changes:
- message: The maple wing marking for moths now have a secondary color palette.
type: Tweak
id: 7303
time: '2024-09-07T05:48:40.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31691
- author: lzk228
changes:
- message: Bottle and syringe names are remade into labels.
type: Tweak
id: 7304
time: '2024-09-07T05:51:36.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29956
- author: Ian321
changes:
- message: The AgriChem kit now links to the botanical chemicals guidebook.
type: Tweak
- message: The botanical chemicals guidebook has been expanded.
type: Tweak
id: 7305
time: '2024-09-07T06:23:01.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31896
- author: Lank
changes:
- message: The Antimov and Overseer law boards are no longer available roundstart.
type: Remove
id: 7306
time: '2024-09-07T08:45:51.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31908
- author: lzk228
changes:
- message: Books cannot longer be inserted in crates as paper labels
type: Fix
id: 7307
time: '2024-09-07T13:22:11.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31919
- author: qwerltaz
changes:
- message: Reduced wall closet range. It's now much easier to not close yourself
inside by accident.
type: Tweak
id: 7308
time: '2024-09-07T23:44:29.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31933
- author: Ilya246
changes:
- message: Reagents that make you flammable no longer extinguish you.
type: Fix
id: 7309
time: '2024-09-07T23:44:58.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31930
- author: LucasTheDrgn
changes:
- message: Restored functionality to the Industrial Reagent Grinder
type: Fix
id: 7310
time: '2024-09-07T23:47:02.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31903
- author: EmoGarbage404
changes:
- message: Added the biogenerator! Botany can use this machine to create various
materials, chemicals, and food items out of the
type: Add
id: 7311
time: '2024-09-08T05:34:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30694
- author: TheShuEd
changes:
- message: Returned Taco microwave recipes (people were sad)
type: Add
- message: added an alternative method of crafting some burgers, through the correct
assembly sequence of modular food.
type: Add
- message: severely cut back on the number of items you can put on burgers, tacos,
or kebabs. This had poor design, and things need to be separately resprited
by adding them on modular food.
type: Tweak
id: 7312
time: '2024-09-08T06:22:27.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31012
- author: metalgearsloth
changes:
- message: Fix the FTL bubbles sometimes persisting.
type: Fix
- message: Fix AI eye being able to FTL.
type: Fix
- message: Fix the AI eye being able to be FTL smashed.
type: Fix
id: 7313
time: '2024-09-08T08:12:24.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31952
- author: PopGamer46
changes:
- message: Fixed being able to craft the justice helmet with a justice helmet
type: Fix
id: 7314
time: '2024-09-08T10:21:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31957
- author: Killerqu00
changes:
- message: Seclite is now restricted to security.
type: Tweak
- message: Handcuffs are now restricted to security and command.
type: Tweak
- message: Trench whistle is now minor contraband.
type: Tweak
id: 7315
time: '2024-09-08T12:06:01.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31956
- author: Psychpsyo
changes:
- message: The random sentience event should now actually happen again.
type: Fix
id: 7316
time: '2024-09-08T12:10:50.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31953
- author: Beck Thompson
changes:
- message: Gold and silver rings now give a small amount of materials when scrapped.
type: Tweak
id: 7317
time: '2024-09-08T16:10:05.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31847
- author: K-Dynamic
changes:
- message: added missing missing resistance values for directional plasma and uranium
windows
type: Fix
id: 7318
time: '2024-09-08T18:08:06.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31975
- author: qwerltaz
changes:
- message: Power cables on the ground are now offset and do not obscure each other
or pipes beneath.
type: Tweak
id: 7319
time: '2024-09-09T10:00:18.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32000
- author: ArtisticRoomba
changes:
- message: Budget insulated gloves now leave behind yellow frayed insulative fibers
instead of yellow insulative fibers. Detectives, rejoice!
type: Tweak
id: 7320
time: '2024-09-09T10:30:25.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31886
- author: slarticodefast
changes:
- message: Revenants or other mobs without hands can no longer spill jugs.
type: Fix
id: 7321
time: '2024-09-09T11:02:15.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31438
- author: PJB3005
changes:
- message: The emergency shuttle will now wait at the station longer if it couldn't
dock at evac.
type: Tweak
id: 7322
time: '2024-09-09T18:10:28.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31496
- author: Boaz1111
changes:
- message: Pacifists can now use grapple guns.
type: Tweak
id: 7323
time: '2024-09-09T19:15:32.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32014
- author: lzk228
changes:
- message: All bots are available for disguise with the Chameleon Ppotlight
type: Tweak
id: 7324
time: '2024-09-09T19:18:01.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32006
- author: DieselMohawk
changes:
- message: Added Security Trooper Uniform
type: Add
id: 7325
time: '2024-09-09T19:19:16.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31997
- author: qwerltaz
changes:
- message: Dragon ghost role now spawns outside the station.
type: Tweak
- message: Dragon ghost role now spawns where advertised!
type: Fix
id: 7326
time: '2024-09-09T19:22:41.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31890
- author: yuitop
changes:
- message: Fixed some cases when surveillance camera's red light not turning off
when needed
type: Fix
id: 7327
time: '2024-09-09T19:23:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31831
- author: Blackern5000
changes:
- message: Normal and reinforced windows have been made directly upgradable using
rods, plasma, uranium, or plasteel.
type: Add
- message: Reinforced plasma and uranium windows have been made tougher.
type: Tweak
- message: Windows have been made to correctly display their damage visuals.
type: Fix
- message: Reinforced plasma windows have been given the correct amount of hp and
no longer have 12x the amount they should.
type: Fix
id: 7328
time: '2024-09-09T19:26:10.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31978
- author: Cojoke-dot
changes:
- message: Nuclear bombs now require the Nuclear Authentification Disk to toggle
anchor.
type: Tweak
id: 7329
time: '2024-09-09T19:30:26.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/29565
- author: Hreno
changes:
- message: Display agents' jobs in the Round End Summary window.
type: Add
id: 7330
time: '2024-09-09T19:31:53.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31652
- author: deltanedas
changes:
- message: Adjusted the costs and production times of all electronics so they're
more consistent with eachother.
type: Tweak
id: 7331
time: '2024-09-09T19:34:18.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31524
- author: Winkarst-cpu
changes:
- message: Now fire axe (the flaming one), and an advanced circular saw are Syndicate
contraband.
type: Fix
- message: Now encryption keys are restricted according to their department.
type: Fix
- message: Now ERT, Deathsquad and Central Command Official items are restricted
to the Central Command.
type: Fix
- message: Now acolyte armor, a thieving beacon and the thief's undetermined toolbox
are minor contraband.
type: Fix
- message: Now bladed flatcaps are not a contraband (stealth item).
type: Fix
- message: Now mercenary clothes, magazines, speedloaders and cartridges are contraband.
type: Fix
- message: Now cleanades are restricted to the Service.
type: Fix
- message: Now metal foam grenades are restricted to the Engineering.
type: Fix
- message: Now flash, smoke, and tear gas grenades are restricted to the Security.
type: Fix
- message: Now combat gloves are restricted to Security and Cargo.
type: Fix
- message: The Central Command restricted contraband group and department were added.
type: Add
id: 7332
time: '2024-09-09T19:36:25.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31606
- author: themias
changes:
- message: Unpublished news article progress is automatically saved
type: Tweak
id: 7333
time: '2024-09-09T19:38:49.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31491
- author: metalgearsloth
changes:
- message: Fix spawn prefs.
type: Fix
id: 7334
time: '2024-09-09T19:39:16.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31892
- author: lzk228
changes:
- message: The captain now have special late join message.
type: Tweak
id: 7335
time: '2024-09-09T19:57:37.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31991
- author: Thinbug0
changes:
- message: Teal gloves can now be found at the ClothesMate!
type: Add
id: 7336
time: '2024-09-09T21:47:53.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31865
- author: chillyconmor
changes:
- message: Space Ninjas now have a new intro song.
type: Add
id: 7337
time: '2024-09-09T22:12:25.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31055
- author: DieselMohawk
changes:
- message: Made Trooper Uniform accessible for Security Officers in loadouts
type: Fix
id: 7338
time: '2024-09-09T23:59:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32019
- author: IProduceWidgets
changes:
- message: Visitors now can have the correct Id cards and PDA!
type: Fix
- message: ghost roles should now attempt to tell you what your antag status is
in a popup when you join the raffle.
type: Tweak
- message: ERT chaplains should now be able to use bibles.
type: Fix
- message: Many new unknown shuttle events to make them more unique.
type: Add
- message: Syndicate escape pods will once again appear.
type: Fix
- message: Unknown Shuttle events will be much rarer.
type: Tweak
id: 7339
time: '2024-09-10T06:40:00.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28098
- author: ScarKy0
changes:
- message: Renamed Circuit Boards to be Law Boards instead.
type: Tweak
id: 7340
time: '2024-09-10T10:27:42.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31914
- author: ScarKy0
changes:
- message: Arrival Screens now show time again.
type: Fix
id: 7341
time: '2024-09-10T19:08:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32037
- author: themias
changes:
- message: The Justice Helm can now only be crafted using a security helmet.
type: Fix
id: 7342
time: '2024-09-10T19:08:37.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32042
- author: TurboTrackerss14
changes:
- message: Gas tank explosions ("max caps") have a reduced range on WizDen servers
until they can be reworked into a proper game mechanic.
type: Remove
id: 7343
time: '2024-09-10T22:05:12.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31437
- author: Boaz1111
changes:
- message: Researching Advanced Atmospherics now requires Atmospherics to be researched.
type: Tweak
id: 7344
time: '2024-09-10T22:19:17.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32048
- author: DiposableCrewmember42
changes:
- message: Fixed Revenant ability cost checks. Revenants can no longer spam abilities
without Essence.
type: Fix
id: 7345
time: '2024-09-10T23:07:07.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32050
- author: ArtisticRoomba
changes:
- message: The salvage magnet circuitboard has been added to QM's locker. It can
also be made at the circuit imprinter roundstart. NOW GET BACK TO WORK!!!
type: Tweak
id: 7346
time: '2024-09-10T23:25:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31996
- author: Lank
changes:
- message: Several antagonist shuttle events have been removed.
type: Remove
id: 7347
time: '2024-09-10T23:26:59.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32052
- author: Vermidia
changes:
- message: Borgs and other creatures that shouldn't get hurt stepping on things
no longer get hurt stepping on things.
type: Fix
- message: Honkbots slip again
type: Fix
id: 7348
time: '2024-09-11T02:12:08.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31011
- author: EmoGarbage404
changes:
- message: The mining asteroid now generates small structures full of treasure and
equipment. Keep an eye open for them, nestled within the rock.
type: Add
id: 7349
time: '2024-09-11T03:33:42.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31638

View File

@@ -3,7 +3,6 @@
[game]
desc = "Official English Space Station 14 servers. Medium roleplay ruleset. you must be whitelisted by playing on other Wizard's Den servers if there are more than 15 online players."
hostname = "[EN] Wizard's Den Salamander [US West RP]"
soft_max_players = 130
[server]
rules_file = "MRPRuleset"

View File

@@ -38,3 +38,6 @@ see_own_notes = true
deadmin_on_join = true
new_player_threshold = 600
alert.min_players_sharing_connection = 2
[atmos]
max_explosion_range = 5

File diff suppressed because one or more lines are too long

View File

@@ -86,7 +86,7 @@ figurines-atmostech-3 = Frezon...
figurines-atmostech-4 = Tritium...
figurines-atmostech-5 = Glory to Atmosia!
figurines-rd-1 = Blowing all of the borgs!
figurines-rd-1 = Blowing up all of the borgs!
figurines-rd-2 = Tier 3 arsenal? No way.
figurines-scientist-1 = Someone else must have made those bombs!

View File

@@ -2,4 +2,4 @@ dragon-round-end-agent-name = dragon
objective-issuer-dragon = [color=#7567b6]Space Dragon[/color]
dragon-role-briefing = Summon 3 carp rifts and take over this quadrant!
dragon-role-briefing = Summon 3 carp rifts and take over this quadrant! The station is located {$direction}.

View File

@@ -2,6 +2,7 @@ forensic-fibers = {LOC($material)} fibers
forensic-fibers-colored = {LOC($color)} {LOC($material)} fibers
fibers-insulative = insulative
fibers-insulative-frayed = frayed insulative
fibers-synthetic = synthetic
fibers-leather = leather
fibers-durathread = durathread
@@ -15,6 +16,7 @@ fibers-purple = purple
fibers-red = red
fibers-black = black
fibers-blue = blue
fibers-teal = teal
fibers-brown = brown
fibers-grey = grey
fibers-green = green

View File

@@ -33,7 +33,8 @@ player-first-join-message = Player {$name} joined for the first time.
# Displayed in chat to admins when a player leaves
player-leave-message = Player {$name} left.
latejoin-arrival-announcement = {$character} ({$job}) has arrived at the station!
latejoin-arrival-announcement = {$character} ({$job}) { CONJUGATE-HAVE($entity) } arrived at the station!
latejoin-arrival-announcement-special = {$job} {$character} on deck!
latejoin-arrival-sender = Station
latejoin-arrivals-direction = A shuttle transferring you to your station will arrive shortly.
latejoin-arrivals-direction-time = A shuttle transferring you to your station will arrive in {$time}.

View File

@@ -15,6 +15,11 @@ ghost-role-information-antagonist-rules = You are a [color=red][bold]Solo Antago
You don't remember any of your previous life, and you don't remember anything you learned as a ghost.
You are allowed to remember knowledge about the game in general, such as how to cook, how to use objects, etc.
You are absolutely [color=red]NOT[/color] allowed to remember, say, the name, appearance, etc. of your previous character.
ghost-role-information-rules-team-antagonist = You are a [color=red][bold]Team Antagonist[/bold][/color]. Your intentions are clear, and harmful to the station and its crew.
You must [bold]work with your team[/bold] or follow reasonable directions from your team leaders.
You don't remember any of your previous life, and you don't remember anything you learned as a ghost.
You are allowed to remember knowledge about the game in general, such as how to cook, how to use objects, etc.
You are absolutely [color=red]NOT[/color] allowed to remember, say, the name, appearance, etc. of your previous character.
ghost-role-information-familiar-rules = You are a [color=#6495ed][bold]Familiar[/bold][/color]. Serve the interests of your master, whatever those may be.
You don't remember any of your previous life, and you don't remember anything you learned as a ghost.
You are allowed to remember knowledge about the game in general, such as how to cook, how to use objects, etc.
@@ -81,11 +86,15 @@ ghost-role-information-kobold-name = Kobold
ghost-role-information-kobold-description = Be the little gremlin you are, yell at people and beg for meat!
ghost-role-information-rat-king-name = Rat King
ghost-role-information-rat-king-description = You are the Rat King, your interests are food, food, and more food. Cooperate with or fight against the station for food. Did I say food interests you?
ghost-role-information-rat-servant-name = Rat Servant
ghost-role-information-rat-servant-description = You are a Rat Servant. You must follow your king's orders.
ghost-role-information-salvage-carp-name = Space carp on salvage wreck
ghost-role-information-salvage-carp-description = Defend the loot inside the salvage wreck!
ghost-role-information-sentient-carp-name = Sentient Carp
ghost-role-information-sentient-carp-description = Help the dragon flood the station with carps!
@@ -223,27 +232,77 @@ ghost-role-information-syndicate-monkey-reinforcement-name = Syndicate Monkey Ag
ghost-role-information-syndicate-monkey-reinforcement-description = Someone needs reinforcements. You, a trained monkey, will help them.
ghost-role-information-syndicate-monkey-reinforcement-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with the agent who summoned you.
ghost-role-information-lost-cargo-technical-name = Lost Cargo Technician
ghost-role-information-lost-cargo-technical-description = Something went wrong and your cargo shuttle with the goods was beamed into the sector to another station.
ghost-role-information-clown-troupe-name = Space Clown
ghost-role-information-clown-troupe-description = You and your troupe have come to cheer up this station with your best jokes. Honk!
ghost-role-information-traveling-chef-name = Traveling Chef
ghost-role-information-traveling-chef-description = You are a chef on a traveling shuttle of exotic cuisine. Delight the station with delicious food!
ghost-role-information-disaster-victim-name = Disaster Victim
ghost-role-information-disaster-victim-description = You were rescued in an escape pod from another station that suffered a terrible fate. Perhaps you will be found and rescued.
ghost-role-information-syndie-disaster-victim-name = Syndie Disaster Victim
ghost-role-information-syndie-disaster-victim-description = You're a regular passenger from a syndicate station. Unfortunately, an evacuation pod has thrown you into an enemy sector.....
ghost-role-information-syndicate-kobold-reinforcement-name = Syndicate Kobold Agent
ghost-role-information-syndicate-kobold-reinforcement-description = Someone needs reinforcements. You, a trained kobold, will help them.
ghost-role-information-syndicate-kobold-reinforcement-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with the agent who summoned you.
ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg
ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg
ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them.
ghost-role-information-security-name = Security
ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation...
ghost-role-information-medical-name = Medical
ghost-role-information-medical-virologist-name = Virologist
ghost-role-information-medical-geneticist-name = Geneticist
ghost-role-information-medical-dentist-name = Dentist
ghost-role-information-medical-description = You are a medical professional, but seem to have found yourself in a strange situation...
ghost-role-information-cargo-name = Cargo
ghost-role-information-cargo-description = You are part of a logistics mission, but seem to have found yourself in a strange situation...
ghost-role-information-engineering-name = Engineering
ghost-role-information-engineering-description = You are on an engineering job, but seem to have found yourself in a strange situation...
ghost-role-information-science-name = Science
ghost-role-information-science-description = You are part of a science team, but seem to have found yourself in a strange situation...
ghost-role-information-civilian-name = Civilian
ghost-role-information-civilian-description = You were just hanging out, but seem to have found yourself in a strange situation...
ghost-role-information-civilian-centcom-lawyer-name = Centcom Lawyer
ghost-role-information-civilian-centcom-lawyer-description = A lawyer direct from the Central Legal Division.
ghost-role-information-command-name = Commander
ghost-role-information-command-description = You are a member of command, but seem to have found yourself in a strange situation...
ghost-role-information-lost-challenge-commander-name = Commander on Shore Leave
ghost-role-information-lost-challenge-commander-description = You are a command member from another starship who was granted shore leave with one of your cargo technicians.
ghost-role-information-lost-challenge-commander-rules = You are not hostile to the station, do what you must to ensure your own survival.
You don't remember any of your previous life, and you don't remember anything you learned as a ghost.
You are allowed to remember knowledge about the game in general, such as how to cook, how to use objects, etc.
You are absolutely [color=red]NOT[/color] allowed to remember, say, the name, appearance, etc. of your previous character.
ghost-role-information-lost-challenge-cargo-technican-name = Cargo Chauffeur
ghost-role-information-lost-challenge-cargo-technican-description = You are a cargo technician who was granted shore leave with one of your commanding officers.
ghost-role-information-lost-challenge-cargo-technican-rules = You are not hostile to the station, do what you must to ensure your own survival.
You don't remember any of your previous life, and you don't remember anything you learned as a ghost.
You are allowed to remember knowledge about the game in general, such as how to cook, how to use objects, etc.
You are absolutely [color=red]NOT[/color] allowed to remember, say, the name, appearance, etc. of your previous character.
ghost-role-information-disaster-victim-name = Disaster Victim
ghost-role-information-disaster-victim-description = You were rescued in an escape pod from another station that suffered a terrible fate. Perhaps you will be found and rescued.
ghost-role-information-syndie-disaster-victim-name = Syndicate Disaster Victim
ghost-role-information-syndie-disaster-victim-description = You're a regular passenger from a syndicate station. Unfortunately, an evacuation pod has thrown you into an enemy sector...
ghost-role-information-syndie-soldier-name = Syndicate Soldier
ghost-role-information-syndie-soldier-description = You are a soldier from the Syndicate.
ghost-role-information-syndie-soldier-teamlead-name = Syndicate Team Leader
ghost-role-information-syndie-soldier-teamlead-description = You are the fire team leader for a Syndicate operative taskforce.
ghost-role-information-blackmarketeer-name = Black Market Trader
ghost-role-information-blackmarketeer-description = Make trades or take odd jobs to collect the most interesting items by the end of the shift.
ghost-role-information-cossack-name = Ancient traveler
ghost-role-information-cossack-description = From a history lost to time, you find yourself cast into this day and age.
ghost-role-information-pirate-name = Space Pirate
ghost-role-information-pirate-description = Argh matey! Collect some cool loot, but make sure to avoid security and salvage!
ghost-role-information-pirate-captain-name = Space Pirate Captain
ghost-role-information-pirate-captain-description = Argh matey! You are in charge here and need to devise a plan to get that juicy loot by hook or by crook. Just make sure to avoid security and salvage!
ghost-role-information-artifact-name = Sentient Artifact
ghost-role-information-artifact-description = Enact your eldritch whims. Forcibly activate your nodes for good or for evil.
ghost-role-information-syndie-assaultborg-name = Syndicate Assault Borg
ghost-role-information-syndie-assaultborg-description = Nuclear operatives needs reinforcements. You, a cold silicon killing machine, will help them. More dakka!

View File

@@ -1,6 +1,7 @@
department-Cargo-description = Complete bounties, earn Spessos, and order useful supplies for the crew.
department-Civilian-description = Perform small helpful tasks to keep the station sane and well catered.
department-Command-description = Manage the crew and keep them working efficiently.
department-CentralCommand-description = Manage the crew and keep them working efficiently.
department-Engineering-description = Keep the power on and the station operational.
department-Medical-description = Keep the crew healthy.
department-Security-description = Keep the peace around the station.

View File

@@ -1,6 +1,7 @@
department-Cargo = Cargo
department-Civilian = Civilian
department-Command = Command
department-CentralCommand = Central Command
department-Engineering = Engineering
department-Medical = Medical
department-Security = Security

View File

@@ -46,4 +46,4 @@ job-description-serviceworker = Learn the basics of bartending, cooking, and gro
job-description-station-ai = Follow your laws, serve the crew.
job-description-visitor = Enjoy your visit to the station.
job-description-warden = Patrol the security department, ensure that no one is stealing from the armory, and make sure that all prisoners are processed and let out when their time is up.
job-description-zookeeper = Put on a joyful display of cute animals and space carps for all the crew to see. Currently available on Oasis.
job-description-zookeeper = Put on a joyful display of cute animals and space carps for all the crew to see. Currently available on Cog and Oasis.

View File

@@ -21,6 +21,8 @@ job-name-hop = Head of Personnel
job-name-captain = Captain
job-name-serviceworker = Service Worker
job-name-centcomoff = CentComm Official
job-name-cburn = Centcomm Quarantine Officer
job-name-deathsquad = Centcomm Agent
job-name-reporter = Reporter
job-name-musician = Musician
job-name-librarian = Librarian

View File

@@ -1,2 +1,4 @@
lathe-component-upgrade-speed = speed
lathe-component-upgrade-material-use = material use
lathe-component-output-slot-beaker-name = Beaker slot

View File

@@ -6,3 +6,7 @@ lathe-category-parts = Parts
lathe-category-robotics = Robotics
lathe-category-tools = Tools
lathe-category-weapons = Weapons
lathe-category-food = Food
lathe-category-chemicals = Chemicals
lathe-category-materials = Materials

View File

@@ -94,7 +94,8 @@ marking-MothWingsJungle = Wings (Jungle)
marking-MothWingsLadybug-ladybug = Wing
marking-MothWingsLadybug = Wings (Ladybug)
marking-MothWingsMaple-maple = Wing
marking-MothWingsMaple-maple_primary = Primary
marking-MothWingsMaple-maple_secondary = Secondary
marking-MothWingsMaple = Wings (Maple)
marking-MothWingsMoffra-moffra_primary = Primary

View File

@@ -15,7 +15,8 @@ news-write-ui-articles-label = Articles:
news-write-ui-delete-text = Delete
news-write-ui-publish-text = Publish
news-write-ui-create-text = Create
news-write-ui-cancel-text = Cancel
news-write-ui-cancel-text = Clear
news-write-ui-save-text = Save
news-write-ui-preview-text = Preview
news-write-ui-article-count-0 = 0 Articles
news-write-ui-article-count-text = {$count} Articles

View File

@@ -1,4 +1,5 @@
nuke-component-cant-anchor-floor = The anchoring bolts fail to lock into the floor!
nuke-component-cant-anchor-toggle = The nuclear authentication disk is required to toggle the floor bolts!
nuke-component-announcement-sender = Nuclear Fission Explosive
nuke-component-announcement-armed = Attention! The station's self-destruct mechanism has been engaged {$location}. {$time} seconds until detonation. If this was made in error, the mechanism may still be disarmed.
nuke-component-announcement-unarmed = The station's self-destruct was deactivated! Have a nice day!

View File

@@ -4,7 +4,7 @@ food-sequence-no-space = You can't put any more!
food-sequence-content-chicken = chicken
food-sequence-content-duck = duck
food-sequence-content-crab = crabs
food-sequence-content-crab = crab
food-sequence-content-dragon = dragon
food-sequence-content-snake = snake
food-sequence-content-xeno = xeno
@@ -83,6 +83,7 @@ food-sequence-burger-content-raw-meat = raw
food-sequence-burger-content-meat = meaty
food-sequence-burger-content-carp = carpo
food-sequence-burger-content-bear = bear
food-sequence-burger-content-crab = crabs
food-sequence-burger-content-penguin = peng
food-sequence-burger-content-corgi = corgi
food-sequence-burger-content-goliath = goli

View File

@@ -0,0 +1,12 @@
# addobjectives
cmd-addobjective-desc = Adds an objective to the player's mind.
cmd-addobjective-help = addobjective <username> <objectiveID>
cmd-addobjective-invalid-args = Expected exactly 2 arguments.
cmd-addobjective-player-not-found = Can't find the playerdata.
cmd-addobjective-mind-not-found = Can't find the mind.
cmd-addobjective-objective-not-found = Can't find matching objective prototype {$obj}
cmd-addobjective-adding-failed = Failed to add the objective. Maybe requirements dont allow that objective to be added.
cmd-addobjective-player-completion = <Player>
cmd-add-objective-obj-completion = <Objective>

View File

@@ -13,9 +13,10 @@ emergency-shuttle-command-launch-desc = Early launches the emergency shuttle if
# Emergency shuttle
emergency-shuttle-left = The Emergency Shuttle has left the station. Estimate {$transitTime} seconds until the shuttle arrives at CentComm.
emergency-shuttle-launch-time = The emergency shuttle will launch in {$consoleAccumulator} seconds.
emergency-shuttle-docked = The Emergency Shuttle has docked {$direction} of the station, {$location}. It will leave in {$time} seconds.
emergency-shuttle-docked = The Emergency Shuttle has docked {$direction} of the station, {$location}. It will leave in {$time} seconds.{$extended}
emergency-shuttle-good-luck = The Emergency Shuttle is unable to find a station. Good luck.
emergency-shuttle-nearby = The Emergency Shuttle is unable to find a valid docking port. It has warped in {$direction} of the station, {$location}.
emergency-shuttle-nearby = The Emergency Shuttle is unable to find a valid docking port. It has warped in {$direction} of the station, {$location}. It will leave in {$time} seconds.{$extended}
emergency-shuttle-extended = {" "}Launch time has been extended due to inconvenient circumstances.
# Emergency shuttle console popup / announcement
emergency-shuttle-console-no-early-launches = Early launch is disabled

View File

@@ -43,7 +43,7 @@ uplink-supermatter-grenade-name = Supermatter Grenade
uplink-supermatter-grenade-desc = Grenade that simulates delamination of a suppermatter engine, generates powerful gravity well. Explosion comparable to a Mini Bomb.
uplink-whitehole-grenade-name = Whitehole Grenade
uplink-whitehole-grenade-desc = Grenade that are repulses everything around for about 10 seconds. Very useful in small rooms and for chasing someone.
uplink-whitehole-grenade-desc = Grenade that repulses everything around for about 10 seconds. Very useful in small rooms and for chasing someone.
uplink-penguin-grenade-name = Grenade Penguin
uplink-penguin-grenade-desc = A small, highly-aggressive penguin with a grenade strapped around its neck. Harvested by the Syndicate from icy shit-hole planets.
@@ -70,7 +70,7 @@ uplink-exploding-syndicate-bomb-fake-name = Decoy Syndicate Bomb
uplink-exploding-syndicate-bomb-fake-desc = A training bomb carefully made to look just like the real thing. In all ways similar to a syndicate bomb, but only creates a tiny explosion.
uplink-cluster-grenade-name = Cluster Grenade
uplink-cluster-grenade-desc = Three explosive grenades bundled together, the grenades get launched after the 3.5 second timer runs out.
uplink-cluster-grenade-desc = Three explosive grenades bundled together. The cluster splits after 3.5 seconds.
uplink-incendiary-grenade-name = Incendiary Grenade
uplink-incendiary-grenade-desc = Releases a spray of incendiary fragments, igniting anyone near the detonation area.
@@ -134,7 +134,7 @@ uplink-reinforcement-radio-cyborg-assault-name = Syndicate Assault Cyborg Telepo
uplink-reinforcement-radio-cyborg-assault-desc = A lean, mean killing machine with access to an Energy Sword, LMG, Cryptographic Sequencer, and a Pinpointer.
uplink-stealth-box-name = Stealth Box
uplink-stealth-box-desc = A box outfitted with stealth technology, sneak around with this and don't move too fast now!
uplink-stealth-box-desc = A box outfitted with stealth technology. Sneak around unnoticed, but don't move too fast or you'll be revealed!
uplink-headset-name = Syndicate Over-ear Headset
uplink-headset-desc = A headset that allows you to communicate with other syndicate operatives. Has 4 slots for encryption keys.
@@ -158,7 +158,7 @@ uplink-radio-jammer-name = Radio Jammer
uplink-radio-jammer-desc = This device will disrupt any nearby outgoing radio communication as well as suit sensors when activated.
uplink-syndicate-weapon-module-name = Weapon Cyborg Module
uplink-syndicate-weapon-module-desc = This module will give a cyborg advanced laser and machete
uplink-syndicate-weapon-module-desc = Upgrades a cyborg with both a machete and an advanced laser.
uplink-syndicate-martyr-module-name = Martyr Cyborg Module
uplink-syndicate-martyr-module-desc = Turn your emagged borg friend into a walking bomb with just this module. Make sure they're loyal to your cause, results may vary.
@@ -229,7 +229,7 @@ uplink-buldog-bundle-name = Bulldog Bundle
uplink-buldog-bundle-desc = Lean and mean: Contains the popular Bulldog Shotgun, a 12g beanbag drum and three 12g buckshot drums.
uplink-grenade-launcher-bundle-name = China-Lake Bundle
uplink-grenade-launcher-bundle-desc = An old China-Lake grenade launcher bundled with 11 rounds of various destruction capability.
uplink-grenade-launcher-bundle-desc = An old China-Lake grenade launcher bundled with 11 rounds of varying destructive capability.
uplink-l6-saw-bundle-name = L6 Saw Bundle
uplink-l6-saw-bundle-desc = More dakka: The iconic L6 light machine gun, bundled with 2 box magazines.
@@ -254,7 +254,7 @@ uplink-duffel-surgery-name = Surgical Duffel Bag
uplink-duffel-surgery-desc = A large duffel bag containing a full suite of surgical tools.
uplink-power-sink-name = Power Sink
uplink-power-sink-desc = Drains immense amounts of electricity from the grid. Use wrench to connect it to wires.
uplink-power-sink-desc = Drains immense amounts of electricity from the grid, then explodes once it's saturated. Use wrench to connect it to wires.
uplink-carp-dehydrated-name = Dehydrated Space Carp
uplink-carp-dehydrated-desc = Looks like a plush toy carp, but just add water and it becomes a real-life space carp!
@@ -304,7 +304,7 @@ uplink-clothing-no-slips-shoes-name = No-slip Shoes
uplink-clothing-no-slips-shoes-desc = Chameleon shoes that protect you from slips.
uplink-clothing-thieving-gloves-name = Thieving Gloves
uplink-clothing-thieving-gloves-desc = Discretely steal from pockets and increase your thieving technique with these fancy new gloves, all while looking like normal gloves!
uplink-clothing-thieving-gloves-desc = Discretely steal from pockets and improve your thieving technique with these fancy new gloves. They even look like normal gloves!
uplink-clothing-outer-vest-web-name = Web Vest
uplink-clothing-outer-vest-web-desc = A synthetic armor vest. This one has added webbing and ballistic plates.
@@ -335,7 +335,7 @@ uplink-cyberpen-name = Cybersun Pen
uplink-cyberpen-desc = Cybersun's legal department pen, invaluable for forging documents and escaping prisons. Smells vaguely of hard-light and war profiteering.
uplink-decoy-disk-name = Decoy Nuclear Disk
uplink-decoy-disk-desc = A piece of plastic with a lenticular printing, made to look like a nuclear auth disk.
uplink-decoy-disk-desc = A piece of plastic with a lenticular printing, made to look like a nuclear authentication disk.
uplink-cigarettes-name = Syndicate Smokes Packet
uplink-cigarettes-desc = Elite cigarettes for elite agents. Infused with medicine for when you need to do more than calm your nerves.
@@ -353,7 +353,7 @@ uplink-soap-name = Soap
uplink-soap-desc = An untrustworthy bar of soap. Smells of fear.
uplink-ultrabright-lantern-name = Extra-Bright Lantern
uplink-ultrabright-lantern-desc = It can be used to blind people like a flash.
uplink-ultrabright-lantern-desc = This ultra-bright lantern can be used to blind people, similar to a flash.
uplink-combat-medkit-name = Combat Medical Kit
uplink-combat-medkit-desc = A medkit made for fixing combat injuries.
@@ -362,7 +362,7 @@ uplink-combat-medipen-name = Combat Medipen
uplink-combat-medipen-desc = A single-use medipen containing chemicals that regenerate most types of damage.
uplink-nocturine-chemistry-bottle-name = Nocturine Bottle
uplink-nocturine-chemistry-bottle-desc = A chemical that makes it very hard for your target to stand up.
uplink-nocturine-chemistry-bottle-desc = A chemical that puts your target straight to sleep.
uplink-stimpack-name = Hyperzine Injector
uplink-stimpack-desc = The legendary chemical produced by Donk Co. for the Syndicate. Injecting yourself with this will increase your run speed and let you recover from stuns faster for 30 seconds.
@@ -438,7 +438,7 @@ uplink-barber-scissors-name = Barber Scissors
uplink-barber-scissors-desc = A good tool to give your fellow agent a nice haircut, unless you want to give it to yourself.
uplink-backpack-syndicate-name = Syndicate backpack
uplink-backpack-syndicate-desc = Lightweight explosion-proof a backpack for holding various traitor goods
uplink-backpack-syndicate-desc = A lightweight explosion-proof backpack for holding various traitor goods
uplink-combat-bakery-name = Combat Bakery Kit
uplink-combat-bakery-desc = A kit of clandestine baked weapons. Contains a baguette sword, a pair of throwing croissants, and a syndicate microwave board for making more. Once the job is done, eat the evidence.

View File

@@ -14,4 +14,4 @@ apc-menu-power-state-none = None
# For the flavor text on the footer
apc-menu-flavor-left = Contact an engineer for assistance.
apc-menu-flavor-right = v1.1
apc-menu-flavor-right = v1.2

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -117,11 +117,12 @@ entities:
rot: -1.5707963267948966 rad
pos: 1.5,-0.5
parent: 1
- proto: AtmosDeviceFanDirectional
- proto: AtmosDeviceFanTiny
entities:
- uid: 4
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 0.5,-2.5
parent: 1
- proto: BoxMRE
@@ -201,8 +202,8 @@ entities:
immutable: False
temperature: 293.14673
moles:
- 1.7459903
- 6.568249
- 1.8856695
- 7.0937095
- 0
- 0
- 0
@@ -219,10 +220,10 @@ entities:
showEnts: False
occludes: True
ents:
- 7
- 6
- 8
- 9
- 6
- 7
- proto: ClothingOuterSuitEmergency
entities:
- uid: 7
@@ -239,13 +240,6 @@ entities:
- type: Transform
pos: 0.5,-0.5
parent: 1
- proto: DisasterVictimSpawner
entities:
- uid: 20
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- proto: GeneratorWallmountAPU
entities:
- uid: 21
@@ -253,6 +247,13 @@ entities:
- type: Transform
pos: -0.5,-1.5
parent: 1
- proto: Grille
entities:
- uid: 34
components:
- type: Transform
pos: 0.5,0.5
parent: 1
- proto: Gyroscope
entities:
- uid: 32
@@ -269,6 +270,18 @@ entities:
- type: Physics
canCollide: False
- type: InsideEntityStorage
- proto: NTVisitorSpawner
entities:
- uid: 20
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- uid: 33
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- proto: Poweredlight
entities:
- uid: 22

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1345,7 +1345,7 @@ entities:
- type: Transform
pos: -1.5,-3.5
parent: 1
- proto: WindoorCargoLocked
- proto: Windoor
entities:
- uid: 184
components:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,526 @@
meta:
format: 6
postmapinit: false
tilemap:
0: Space
1: FloorMetalDiamond
77: FloorShuttleOrange
80: FloorShuttleWhite
112: Lattice
113: Plating
entities:
- proto: ""
entities:
- uid: 1
components:
- type: MetaData
name: PC-Luxury
- type: Transform
pos: -0.50006104,-0.5
parent: invalid
- type: MapGrid
chunks:
0,0:
ind: 0,0
tiles: UAAAAAAATQAAAAAAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAcQAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcQAAAAAAcQAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
version: 6
-1,0:
ind: -1,0
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcQAAAAAATQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
version: 6
-1,-1:
ind: -1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcQAAAAAATQAAAAAA
version: 6
0,-1:
ind: 0,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAcQAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAATQAAAAAAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
version: 6
- type: Broadphase
- type: Physics
bodyStatus: InAir
angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
- type: Fixtures
fixtures: {}
- type: OccluderTree
- type: SpreaderGrid
- type: Shuttle
- type: GridPathfinding
- type: Gravity
gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
- type: DecalGrid
chunkCollection:
version: 2
nodes:
- node:
color: '#FFFFFFFF'
id: BotGreyscale
decals:
0: -1,-1
1: 1,-1
- node:
color: '#FFFFFFFF'
id: BoxGreyscale
decals:
2: -1,0
3: 1,0
- type: GridAtmosphere
version: 2
data:
tiles:
0,0:
0: 19
1: 1088
0,-1:
0: 12544
1: 1024
-1,0:
0: 8
1: 1088
-1,-1:
0: 32768
1: 1024
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 21.824879
- 82.10312
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- volume: 2500
immutable: True
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
chunkSize: 4
- type: GasTileOverlay
- type: RadiationGridResistance
- proto: AirCanister
entities:
- uid: 40
components:
- type: Transform
anchored: True
pos: -0.5,0.5
parent: 1
- type: Physics
bodyType: Static
- proto: AirlockGlassShuttle
entities:
- uid: 2
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- proto: APCBasic
entities:
- uid: 41
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 1.5,-1.5
parent: 1
- proto: AtmosDeviceFanDirectional
entities:
- uid: 49
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- proto: BookEarth
entities:
- uid: 51
components:
- type: MetaData
name: 'How to Fly: For Dum Dums'
- type: Transform
pos: 0.50006104,1.4869615
parent: 1
- type: Paper
content: >+
[head=2][bold]Steps to flying:[/bold][/head]
1. Locate power generation or storage. Some small crafts utilize P.A.C.M.A.N. brand generators.
2. Ensure your generator is connected to the power network. Some small crafts utilize only a Medium Voltage (MV) network!
3. Fuel and start your generator or power source.
4. Wait for your shuttle to prime, and all services to come online.
5. Use the Shuttle Console to locate your destination of choice. You may find further away destinations on the Map tab when scanning for objects.
6. Attempt to avoid crashing you forgot to buy insurance.
- proto: CableApcExtension
entities:
- uid: 42
components:
- type: Transform
pos: 1.5,-1.5
parent: 1
- uid: 43
components:
- type: Transform
pos: 1.5,-0.5
parent: 1
- uid: 44
components:
- type: Transform
pos: 0.5,-0.5
parent: 1
- uid: 45
components:
- type: Transform
pos: 0.5,0.5
parent: 1
- uid: 52
components:
- type: Transform
pos: 0.5,1.5
parent: 1
- proto: CableMV
entities:
- uid: 46
components:
- type: Transform
pos: 1.5,-0.5
parent: 1
- uid: 47
components:
- type: Transform
pos: 1.5,-1.5
parent: 1
- proto: ChairPilotSeat
entities:
- uid: 3
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 0.5,0.5
parent: 1
- proto: ComputerShuttle
entities:
- uid: 4
components:
- type: Transform
pos: 0.5,1.5
parent: 1
- proto: CrateMaterialPlasma
entities:
- uid: 48
components:
- type: Transform
pos: -0.5,-0.5
parent: 1
- type: Lock
locked: False
- type: EntityStorage
air:
volume: 200
immutable: False
temperature: 293.14673
moles:
- 1.7459903
- 6.568249
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- proto: Flare
entities:
- uid: 53
components:
- type: Transform
pos: 0.7396444,1.3668714
parent: 1
- uid: 54
components:
- type: Transform
pos: 0.53131104,-0.591462
parent: 1
- type: Item
heldPrefix: lit
- type: IgnitionSource
ignited: True
- proto: GasPassiveVent
entities:
- uid: 37
components:
- type: Transform
rot: 3.141592653589793 rad
pos: -1.5,-1.5
parent: 1
- proto: GasPipeBend
entities:
- uid: 34
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -1.5,-0.5
parent: 1
- proto: GasPipeStraight
entities:
- uid: 35
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -0.5,-0.5
parent: 1
- proto: GasPort
entities:
- uid: 18
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -0.5,0.5
parent: 1
- proto: GasVentPump
entities:
- uid: 19
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 0.5,0.5
parent: 1
- proto: GasVentScrubber
entities:
- uid: 36
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 0.5,-0.5
parent: 1
- proto: Grille
entities:
- uid: 24
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -0.5,1.5
parent: 1
- uid: 25
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -0.5,2.5
parent: 1
- uid: 26
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 0.5,2.5
parent: 1
- uid: 27
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 1.5,2.5
parent: 1
- uid: 28
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 1.5,1.5
parent: 1
- uid: 29
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 2.5,0.5
parent: 1
- uid: 30
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 2.5,-0.5
parent: 1
- uid: 31
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -1.5,-0.5
parent: 1
- uid: 32
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -1.5,0.5
parent: 1
- proto: Gyroscope
entities:
- uid: 33
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: 1.5,0.5
parent: 1
- proto: NTVisitorSpawner
entities:
- uid: 50
components:
- type: Transform
pos: 0.5,0.5
parent: 1
- proto: PortableGeneratorPacman
entities:
- uid: 38
components:
- type: Transform
anchored: True
pos: 1.5,-0.5
parent: 1
- type: Physics
bodyType: Static
- proto: PoweredSmallLight
entities:
- uid: 39
components:
- type: Transform
rot: 3.141592653589793 rad
pos: -0.5,-0.5
parent: 1
- proto: ShuttleWindow
entities:
- uid: 9
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: -1.5,-0.5
parent: 1
- uid: 10
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: -1.5,0.5
parent: 1
- uid: 11
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: -0.5,1.5
parent: 1
- uid: 12
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: -0.5,2.5
parent: 1
- uid: 13
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 0.5,2.5
parent: 1
- uid: 14
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 1.5,2.5
parent: 1
- uid: 15
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 1.5,1.5
parent: 1
- uid: 16
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 2.5,0.5
parent: 1
- uid: 17
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 2.5,-0.5
parent: 1
- proto: Thruster
entities:
- uid: 20
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 2.5,-1.5
parent: 1
- uid: 21
components:
- type: Transform
rot: 3.141592653589793 rad
pos: -1.5,-1.5
parent: 1
- uid: 22
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -1.5,2.5
parent: 1
- uid: 23
components:
- type: Transform
pos: 2.5,2.5
parent: 1
- proto: WallShuttle
entities:
- uid: 5
components:
- type: Transform
pos: -0.5,-1.5
parent: 1
- uid: 6
components:
- type: Transform
pos: 1.5,-1.5
parent: 1
- proto: WallShuttleDiagonal
entities:
- uid: 7
components:
- type: Transform
pos: -1.5,1.5
parent: 1
- uid: 8
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 2.5,1.5
parent: 1
...

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More