diff --git a/Content.Client/_CP14/UserInterface/GuardBellBoundUserInterface.cs b/Content.Client/_CP14/UserInterface/GuardBellBoundUserInterface.cs new file mode 100644 index 0000000000..b907b1989a --- /dev/null +++ b/Content.Client/_CP14/UserInterface/GuardBellBoundUserInterface.cs @@ -0,0 +1,55 @@ +using Content.Shared.CCVar; +using Content.Shared.Chat; +using Content.Shared.Communications; +using Robust.Client.UserInterface; +using Robust.Shared.Configuration; +using Robust.Shared.Timing; + +namespace Content.Client._CP14.UserInterface +{ + public sealed class GuardBellBoundUserInterface : BoundUserInterface + { + [Dependency] private readonly IConfigurationManager _cfg = default!; + + [ViewVariables] + private GuardBellMenu? _menu; + + public GuardBellBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _menu = this.CreateWindow(); + _menu.OnAlertLevel += AlertLevelSelected; + } + + public void AlertLevelSelected(string level) + { + if (_menu!.AlertLevelSelectable) + { + _menu.CurrentLevel = level; + SendMessage(new CommunicationsConsoleSelectAlertLevelMessage(level)); + } + } + + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not CommunicationsConsoleInterfaceState commsState) + return; + + if (_menu != null) + { + _menu.AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0; + _menu.CurrentLevel = commsState.CurrentAlert; + _menu.UpdateAlertLevels(commsState.AlertLevels, _menu.CurrentLevel); + _menu.AlertLevelButton.Disabled = !_menu.AlertLevelSelectable; + } + } + } +} diff --git a/Content.Client/_CP14/UserInterface/GuardBellMenu.xaml b/Content.Client/_CP14/UserInterface/GuardBellMenu.xaml new file mode 100644 index 0000000000..70b63deba0 --- /dev/null +++ b/Content.Client/_CP14/UserInterface/GuardBellMenu.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + diff --git a/Content.Client/_CP14/UserInterface/GuardBellMenu.xaml.cs b/Content.Client/_CP14/UserInterface/GuardBellMenu.xaml.cs new file mode 100644 index 0000000000..3423421325 --- /dev/null +++ b/Content.Client/_CP14/UserInterface/GuardBellMenu.xaml.cs @@ -0,0 +1,86 @@ +using System.Globalization; +using Content.Client.UserInterface.Controls; +using Content.Shared.CCVar; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Configuration; +using Robust.Shared.Timing; +using Robust.Shared.Utility; + +namespace Content.Client._CP14.UserInterface +{ + [GenerateTypedNameReferences] + public sealed partial class GuardBellMenu : FancyWindow + { + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly ILocalizationManager _loc = default!; + + public bool AlertLevelSelectable; + public string CurrentLevel = string.Empty; + + + public event Action? OnAlertLevel; + + public GuardBellMenu() + { + IoCManager.InjectDependencies(this); + RobustXamlLoader.Load(this); + + AlertLevelButton.OnItemSelected += args => + { + var metadata = AlertLevelButton.GetItemMetadata(args.Id); + if (metadata != null && metadata is string cast) + { + OnAlertLevel?.Invoke(cast); + } + }; + + + AlertLevelButton.Disabled = !AlertLevelSelectable; + + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + } + + // The current alert could make levels unselectable, so we need to ensure that the UI reacts properly. + // If the current alert is unselectable, the only item in the alerts list will be + // the current alert. Otherwise, it will be the list of alerts, with the current alert + // selected. + public void UpdateAlertLevels(List? alerts, string currentAlert) + { + AlertLevelButton.Clear(); + + if (alerts == null) + { + var name = currentAlert; + if (_loc.TryGetString($"cp14-alert-level-{currentAlert}", out var locName)) + { + name = locName; + } + AlertLevelButton.AddItem(name); + AlertLevelButton.SetItemMetadata(AlertLevelButton.ItemCount - 1, currentAlert); + } + else + { + foreach (var alert in alerts) + { + var name = alert; + if (_loc.TryGetString($"cp14-alert-level-{alert}", out var locName)) + { + name = locName; + } + AlertLevelButton.AddItem(name); + AlertLevelButton.SetItemMetadata(AlertLevelButton.ItemCount - 1, alert); + if (alert == currentAlert) + { + AlertLevelButton.Select(AlertLevelButton.ItemCount - 1); + } + } + } + } + } +} diff --git a/Content.Server/AlertLevel/AlertLevelSystem.cs b/Content.Server/AlertLevel/AlertLevelSystem.cs index bc02808e7d..606f1242ec 100644 --- a/Content.Server/AlertLevel/AlertLevelSystem.cs +++ b/Content.Server/AlertLevel/AlertLevelSystem.cs @@ -18,7 +18,8 @@ public sealed class AlertLevelSystem : EntitySystem [Dependency] private readonly StationSystem _stationSystem = default!; // Until stations are a prototype, this is how it's going to have to be. - public const string DefaultAlertLevelSet = "stationAlerts"; + // public const string DefaultAlertLevelSet = "stationAlerts"; // OLD VANILA. Changed by CP14. + public const string DefaultAlertLevelSet = "CP14TownAlerts"; public override void Initialize() { @@ -184,7 +185,8 @@ public sealed class AlertLevelSystem : EntitySystem } // The full announcement to be spat out into chat. - var announcementFull = Loc.GetString("alert-level-announcement", ("name", name), ("announcement", announcement)); + // var announcementFull = Loc.GetString("alert-level-announcement", ("name", name), ("announcement", announcement)); // OLD VANILA. Changed by CP14. + var announcementFull = Loc.GetString("cp14-alert-level-announcement", ("name", name), ("announcement", announcement)); var playDefault = false; if (playSound) diff --git a/Resources/Audio/_CP14/Misc/attributions.yml b/Resources/Audio/_CP14/Misc/attributions.yml new file mode 100644 index 0000000000..72c34db847 --- /dev/null +++ b/Resources/Audio/_CP14/Misc/attributions.yml @@ -0,0 +1,16 @@ +# Attempted to keep the files in alphabetical order so its easier to audit. +# Finding individual authors is an unfeasible task. If you can reference the author please do so. +- files: ["safe-alert.ogg"] + license: "CC-BY-4.0" + copyright: "Created by kevp888" + source: "https://freesound.org/s/688445" + +- files: ["minor-alert.ogg"] + license: "CC0-1.0" + copyright: "Created by Horrormarkus" + source: "https://freesound.org/s/659672" + +- files: ["major-alert.ogg"] + license: "CC0-1.0" + copyright: "Created by Aeonomi" + source: "https://freesound.org/s/180329" diff --git a/Resources/Audio/_CP14/Misc/major-alert.ogg b/Resources/Audio/_CP14/Misc/major-alert.ogg new file mode 100644 index 0000000000..5caf3bdb7b Binary files /dev/null and b/Resources/Audio/_CP14/Misc/major-alert.ogg differ diff --git a/Resources/Audio/_CP14/Misc/minor-alert.ogg b/Resources/Audio/_CP14/Misc/minor-alert.ogg new file mode 100644 index 0000000000..2881b3d1ae Binary files /dev/null and b/Resources/Audio/_CP14/Misc/minor-alert.ogg differ diff --git a/Resources/Audio/_CP14/Misc/safe-alert.ogg b/Resources/Audio/_CP14/Misc/safe-alert.ogg new file mode 100644 index 0000000000..575b2331d4 Binary files /dev/null and b/Resources/Audio/_CP14/Misc/safe-alert.ogg differ diff --git a/Resources/Locale/en-US/_CP14/alert-levels/alert-levels.ftl b/Resources/Locale/en-US/_CP14/alert-levels/alert-levels.ftl new file mode 100644 index 0000000000..3a74cfb21c --- /dev/null +++ b/Resources/Locale/en-US/_CP14/alert-levels/alert-levels.ftl @@ -0,0 +1,10 @@ +cp14-alert-level-announcement = Attention! Towns threat level is now {$name}! {$announcement} + +cp14-alert-level-safe = Safe +cp14-alert-level-safe-announcement = There is no threat to the town. Town folk may return to their duties safely. + +cp14-alert-level-minor = Minor +cp14-alert-level-minor-announcement = There is a minor threat to the town. Townsfolk should return to the town for their own safety. Guards are to be at their posts armed and combat ready. + +cp14-alert-level-major = Major +cp14-alert-level-major-announcement = There is a major threat to the town. Everyone must return to the town and protect it. diff --git a/Resources/Locale/en-US/_CP14/construction/guard-bell.ftl b/Resources/Locale/en-US/_CP14/construction/guard-bell.ftl new file mode 100644 index 0000000000..9365e0c0cc --- /dev/null +++ b/Resources/Locale/en-US/_CP14/construction/guard-bell.ftl @@ -0,0 +1,2 @@ +cp14-guard-bell-menu-title = Guard Bell +cp14-guard-bell-alert-button = Change the towns threat level. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_CP14/alert-levels/alert-levels.ftl b/Resources/Locale/ru-RU/_CP14/alert-levels/alert-levels.ftl new file mode 100644 index 0000000000..85e5f5784f --- /dev/null +++ b/Resources/Locale/ru-RU/_CP14/alert-levels/alert-levels.ftl @@ -0,0 +1,10 @@ +cp14-alert-level-announcement = Внимание! Уровень угрозы города теперь { $name }! { $announcement } + +cp14-alert-level-safe = Безопасно +cp14-alert-level-safe-announcement = Угрозы городу нет. Горожане могут спокойно вернуться к своим обязанностям. + +cp14-alert-level-minor = Незначительная угроза +cp14-alert-level-minor-announcement = Городу предстоит небольшая угроза. Горожанам рекомендуется быть внимательными и не покидать пределы города в темное время суток. Стража должна находиться на своих постах вооруженными и готовыми к бою. + +cp14-alert-level-major = Большая угроза +cp14-alert-level-major-announcement = Городу предстоит большая угроза! Призываем всех жителей объединиться и подготовиться к защите своих домов и семей. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_CP14/construction/guard-bell.ftl b/Resources/Locale/ru-RU/_CP14/construction/guard-bell.ftl new file mode 100644 index 0000000000..52eb0f3f7d --- /dev/null +++ b/Resources/Locale/ru-RU/_CP14/construction/guard-bell.ftl @@ -0,0 +1,2 @@ +cp14-guard-bell-menu-title = Колокол стражи +cp14-guard-bell-alert-button = Изменяет уровень угрозы города. \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/AlertLevels/alert_levels.yml b/Resources/Prototypes/_CP14/AlertLevels/alert_levels.yml new file mode 100644 index 0000000000..e1009edc10 --- /dev/null +++ b/Resources/Prototypes/_CP14/AlertLevels/alert_levels.yml @@ -0,0 +1,22 @@ +- type: alertLevels + id: CP14TownAlerts + defaultLevel: safe + levels: + safe: + announcement: cp14-alert-level-safe-announcement + sound: /Audio/_CP14/Misc/safe-alert.ogg + color: Green + emergencyLightColor: LawnGreen + shuttleTime: 600 + minor: + announcement: cp14-alert-level-minor-announcement + sound: /Audio/_CP14/Misc/minor-alert.ogg + color: DodgerBlue + emergencyLightColor: DodgerBlue + shuttleTime: 600 + major: + announcement: cp14-alert-level-major-announcement + sound: /Audio/_CP14/Misc/major-alert.ogg + color: Red + emergencyLightColor: Red + shuttleTime: 600 \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Specific/Guard/GuardBell.yml b/Resources/Prototypes/_CP14/Entities/Objects/Specific/Guard/GuardBell.yml new file mode 100644 index 0000000000..074e81c27e --- /dev/null +++ b/Resources/Prototypes/_CP14/Entities/Objects/Specific/Guard/GuardBell.yml @@ -0,0 +1,20 @@ +- type: entity + parent: BaseStructure + id: CP14GuardBell + name: guard bell + description: A bell used to set the appropriate alert level. + categories: [ ForkFiltered ] + components: + - type: Sprite + drawdepth: Mobs + sprite: _CP14/Structures/Specific/Guard/guard_bell.rsi + layers: + - state: base + - type: ActivatableUI + key: enum.CommunicationsConsoleUiKey.Key + - type: CommunicationsConsole + title: cp14-guard-bell-menu-title + - type: UserInterface + interfaces: + enum.CommunicationsConsoleUiKey.Key: + type: GuardBellBoundUserInterface diff --git a/Resources/Prototypes/_CP14/Entities/Stations/base.yml b/Resources/Prototypes/_CP14/Entities/Stations/base.yml index d88dd7f721..b86b5883f2 100644 --- a/Resources/Prototypes/_CP14/Entities/Stations/base.yml +++ b/Resources/Prototypes/_CP14/Entities/Stations/base.yml @@ -5,7 +5,7 @@ - BaseStation - BaseStationAllEventsEligible - BaseStationJobsSpawning - - BaseStationAlertLevels #Checks fail without it + - CP14BaseTownAlerts - BaseStationRecords # Required for lobby manifest + cryo leave - CP14BaseStationCommonObjectives - CP14BaseStationSalary @@ -26,8 +26,15 @@ salary: CP14Guard: 550 +- type: entity + id: CP14BaseTownAlerts + abstract: true + components: + - type: AlertLevel + alertLevelPrototype: CP14TownAlerts + - type: entity id: CP14BaseStationDemiplaneMap abstract: true components: - - type: CP14StationDemiplaneMap \ No newline at end of file + - type: CP14StationDemiplaneMap diff --git a/Resources/Textures/_CP14/Structures/Specific/Guard/guard_bell.rsi/base.png b/Resources/Textures/_CP14/Structures/Specific/Guard/guard_bell.rsi/base.png new file mode 100644 index 0000000000..45151c94db Binary files /dev/null and b/Resources/Textures/_CP14/Structures/Specific/Guard/guard_bell.rsi/base.png differ diff --git a/Resources/Textures/_CP14/Structures/Specific/Guard/guard_bell.rsi/meta.json b/Resources/Textures/_CP14/Structures/Specific/Guard/guard_bell.rsi/meta.json new file mode 100644 index 0000000000..28fe16ddcc --- /dev/null +++ b/Resources/Textures/_CP14/Structures/Specific/Guard/guard_bell.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "All right reserved", + "copyright": "Created by Militore for CrystallEdge", + "size": { + "x": 32, + "y": 48 + }, + "states": [ + { + "name": "base" + } + ] +} \ No newline at end of file