Merge remote-tracking branch 'space-wizards/master'
# Conflicts: # .github/CODEOWNERS # .github/workflows/publish.yml # Content.Client/Administration/UI/BanPanel/BanPanel.xaml # Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs # Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs # Content.Client/Entry/EntryPoint.cs # Content.Client/Hands/Systems/HandsSystem.cs # Content.Client/Humanoid/HumanoidAppearanceSystem.cs # Content.Client/Humanoid/SingleMarkingPicker.xaml.cs # Content.Client/IoC/ClientContentIoC.cs # Content.Client/Lobby/LobbyState.cs # Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs # Content.Client/Lobby/UI/Loadouts/LoadoutGroupContainer.xaml.cs # Content.Client/Lobby/UI/LobbyGui.xaml # Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml # Content.Client/Options/UI/EscapeMenu.xaml # Content.Client/Stealth/StealthSystem.cs # Content.Client/SurveillanceCamera/UI/SurveillanceCameraMonitorWindow.xaml.cs # Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs # Content.Client/UserInterface/Systems/Emotes/EmotesUIController.cs # Content.Client/Weapons/Ranged/Systems/GunSystem.cs # Content.IntegrationTests/Tests/Commands/SuicideCommandTests.cs # Content.IntegrationTests/Tests/Damageable/DamageableTest.cs # Content.IntegrationTests/Tests/PostMapInitTest.cs # Content.Server/Administration/Commands/AdminWhoCommand.cs # Content.Server/Administration/Commands/PardonCommand.cs # Content.Server/Administration/Commands/RoleUnbanCommand.cs # Content.Server/Administration/Commands/SetOutfitCommand.cs # Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs # Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs # Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs # Content.Server/Body/Components/BloodstreamComponent.cs # Content.Server/Body/Systems/BloodstreamSystem.cs # Content.Server/Body/Systems/MetabolizerSystem.cs # Content.Server/Body/Systems/RespiratorSystem.cs # Content.Server/Chat/Managers/ChatSanitizationManager.cs # Content.Server/Chat/Systems/ChatSystem.Emote.cs # Content.Server/Chat/Systems/ChatSystem.cs # Content.Server/CrewManifest/CrewManifestSystem.cs # Content.Server/Emp/EmpSystem.cs # Content.Server/Explosion/EntitySystems/TriggerSystem.cs # Content.Server/Fax/FaxSystem.cs # Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs # Content.Server/GameTicking/Commands/ForceMapCommand.cs # Content.Server/GameTicking/Commands/ForcePresetCommand.cs # Content.Server/GameTicking/Presets/GamePresetPrototype.cs # Content.Server/GameTicking/Rules/ChangelingRuleSystem.cs # Content.Server/GameTicking/Rules/Components/ChangelingRuleComponent.cs # Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs # Content.Server/Ghost/Roles/GhostRoleSystem.cs # Content.Server/Implants/Components/ScramImplantComponent.cs # Content.Server/Implants/SubdermalImplantSystem.cs # Content.Server/Materials/ProduceMaterialExtractorSystem.cs # Content.Server/Medical/HealthAnalyzerSystem.cs # Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs # Content.Server/NPC/Systems/NPCSystem.cs # Content.Server/Polymorph/Systems/PolymorphSystem.cs # Content.Server/Radio/EntitySystems/HeadsetSystem.cs # Content.Server/Repairable/RepairableSystem.cs # Content.Server/Revenant/EntitySystems/RevenantSystem.cs # Content.Server/RoundEnd/RoundEndSystem.cs # Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs # Content.Server/Speech/EntitySystems/FrenchAccentSystem.cs # Content.Server/Speech/EntitySystems/FrontalLispSystem.cs # Content.Server/Speech/EntitySystems/LizardAccentSystem.cs # Content.Server/Speech/EntitySystems/MothAccentSystem.cs # Content.Server/Speech/EntitySystems/OwOAccentSystem.cs # Content.Server/Station/Systems/StationSpawningSystem.cs # Content.Server/StationEvents/Events/MeteorSwarmSystem.cs # Content.Server/Stunnable/Components/StunOnCollideComponent.cs # Content.Server/SurveillanceCamera/Components/SurveillanceCameraRouterComponent.cs # Content.Server/Weapons/Ranged/Systems/GunSystem.Cartridges.cs # Content.Server/Zombies/ZombieSystem.Transform.cs # Content.Server/Zombies/ZombieSystem.cs # Content.Shared/Actions/SharedActionsSystem.cs # Content.Shared/Bed/SharedBedSystem.cs # Content.Shared/Blocking/BlockingSystem.cs # Content.Shared/Body/Systems/SharedBodySystem.Parts.cs # Content.Shared/Chemistry/Components/SolutionRegenerationComponent.cs # Content.Shared/Chemistry/EntitySystems/HypospraySystem.cs # Content.Shared/Construction/Conditions/TileNotBlocked.cs # Content.Shared/Cuffs/SharedCuffableSystem.cs # Content.Shared/Doors/Systems/SharedDoorSystem.cs # Content.Shared/Emoting/EmoteAttemptEvent.cs # Content.Shared/Eye/Blinding/Systems/BlindableSystem.cs # Content.Shared/Eye/VisibilityFlags.cs # Content.Shared/Hands/EntitySystems/SharedHandsSystem.Pickup.cs # Content.Shared/Humanoid/HumanoidCharacterAppearance.cs # Content.Shared/Interaction/SmartEquipSystem.cs # Content.Shared/Inventory/InventorySystem.Relay.cs # Content.Shared/Medical/Cryogenics/SharedCryoPodSystem.cs # Content.Shared/Medical/Healing/HealingSystem.cs # Content.Shared/Medical/HealingComponent.cs # Content.Shared/Nutrition/EntitySystems/FoodSystem.cs # Content.Shared/Slippery/SlipperySystem.cs # Content.Shared/SprayPainter/SharedSprayPainterSystem.cs # Content.Shared/Standing/StandingStateComponent.cs # Content.Shared/Standing/StandingStateSystem.cs # Content.Shared/Station/SharedStationSpawningSystem.cs # Content.Shared/Stunnable/SharedStunSystem.cs # Content.Shared/SurveillanceCamera/SharedSurveillanceCameraMonitorSystem.cs # Content.Shared/VendingMachines/VendingMachineComponent.cs # Content.Shared/Warps/WarpPointSystem.cs # Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs # Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs # Content.Shared/Wieldable/SharedWieldableSystem.cs # Resources/Audio/Ambience/Antag/attributions.yml # Resources/Audio/Ambience/Antag/changeling_start.ogg # Resources/Audio/Effects/attributions.yml # Resources/Audio/Lobby/attributions.yml # Resources/Audio/Machines/attributions.yml # Resources/Audio/Weapons/Guns/Gunshots/attributions.yml # Resources/Locale/en-US/_strings/administration/antag.ftl # Resources/Locale/en-US/_strings/administration/commands/camera.ftl # Resources/Locale/en-US/_strings/administration/commands/dsay-command.ftl # Resources/Locale/en-US/_strings/administration/commands/follow-command.ftl # Resources/Locale/en-US/_strings/administration/smites.ftl # Resources/Locale/en-US/_strings/administration/ui/admin-camera-window.ftl # Resources/Locale/en-US/_strings/administration/ui/role-bans.ftl # Resources/Locale/en-US/_strings/alerts/alerts.ftl # Resources/Locale/en-US/_strings/atmos/gas-pressure-regulator-system.ftl # Resources/Locale/en-US/_strings/bonk/components/bonkable-component.ftl # Resources/Locale/en-US/_strings/commands/add-body-part-command.ftl # Resources/Locale/en-US/_strings/commands/admin-logs-command.ftl # Resources/Locale/en-US/_strings/commands/admin-who-command.ftl # Resources/Locale/en-US/_strings/commands/asay-command.ftl # Resources/Locale/en-US/_strings/commands/crew-manifest-command.ftl # Resources/Locale/en-US/_strings/commands/deadmin-command.ftl # Resources/Locale/en-US/_strings/commands/delete-component-command.ftl # Resources/Locale/en-US/_strings/commands/destroy-mechanism-command.ftl # Resources/Locale/en-US/_strings/commands/dirty-command.ftl # Resources/Locale/en-US/_strings/commands/dsay-command.ftl # Resources/Locale/en-US/_strings/commands/dump-reagent-guide-text-command.ftl # Resources/Locale/en-US/_strings/commands/eye-commands.ftl # Resources/Locale/en-US/_strings/commands/follow-command.ftl # Resources/Locale/en-US/_strings/commands/force-map-command.ftl # Resources/Locale/en-US/_strings/commands/force-preset-command.ftl # Resources/Locale/en-US/_strings/commands/ghost-kick-command.ftl # Resources/Locale/en-US/_strings/commands/ghost-visibility-commands.ftl # Resources/Locale/en-US/_strings/commands/go-lobby-command.ftl # Resources/Locale/en-US/_strings/commands/grid-drag-command.ftl # Resources/Locale/en-US/_strings/commands/is-afk-command.ftl # Resources/Locale/en-US/_strings/commands/makesentient-command.ftl # Resources/Locale/en-US/_strings/commands/map-commands.ftl # Resources/Locale/en-US/_strings/commands/mapping-client-side-setup-command.ftl # Resources/Locale/en-US/_strings/commands/mappingclientsidesetup-command.ftl # Resources/Locale/en-US/_strings/commands/me-command.ftl # Resources/Locale/en-US/_strings/commands/mind-info-command.ftl # Resources/Locale/en-US/_strings/commands/node-vis-commands.ftl # Resources/Locale/en-US/_strings/commands/npc-command.ftl # Resources/Locale/en-US/_strings/commands/nukecodes-command.ftl # Resources/Locale/en-US/_strings/commands/ooc-command.ftl # Resources/Locale/en-US/_strings/commands/pardon-command.ftl # Resources/Locale/en-US/_strings/commands/powerstat-command.ftl # Resources/Locale/en-US/_strings/commands/promote-host-command.ftl # Resources/Locale/en-US/_strings/commands/radiation-command.ftl # Resources/Locale/en-US/_strings/commands/readmin-command.ftl # Resources/Locale/en-US/_strings/commands/remove-extra-components-command.ftl # Resources/Locale/en-US/_strings/commands/role-commands.ftl # Resources/Locale/en-US/_strings/commands/say-command.ftl # Resources/Locale/en-US/_strings/commands/set-battery-percent-command.ftl # Resources/Locale/en-US/_strings/commands/show-ambient-command.ftl # Resources/Locale/en-US/_strings/commands/show-gun-spread-command.ftl # Resources/Locale/en-US/_strings/commands/show-htn-command.ftl # Resources/Locale/en-US/_strings/commands/showrules-command.ftl # Resources/Locale/en-US/_strings/commands/spawn-entity-list-command.ftl # Resources/Locale/en-US/_strings/commands/start-singularity-command.ftl # Resources/Locale/en-US/_strings/commands/tile-pry-command.ftl # Resources/Locale/en-US/_strings/commands/toggle-decals-command.ftl # Resources/Locale/en-US/_strings/commands/toggle-disallow-late-join-command.ftl # Resources/Locale/en-US/_strings/commands/unlocknode-command.ftl # Resources/Locale/en-US/_strings/commands/whisper-command.ftl # Resources/Locale/en-US/_strings/components/gas-pressure-regulator-component.ftl # Resources/Locale/en-US/_strings/engineer-painter/engineer-painter.ftl # Resources/Locale/en-US/_strings/game-ticking/forcemap-command.ftl # Resources/Locale/en-US/_strings/interaction/interaction-popup-component.ftl # Resources/Locale/en-US/_strings/markings/vox_tattoos.ftl # Resources/Locale/en-US/_strings/materials/material-extractor.ftl # Resources/Locale/en-US/_strings/movement/eye.ftl # Resources/Locale/en-US/_strings/nutrition/components/food-component.ftl # Resources/Locale/en-US/_strings/nutrition/components/ingestion-system.ftl # Resources/Locale/en-US/_strings/nutrition/components/sealable-component.ftl # Resources/Locale/en-US/_strings/radiation/radiation-command.ftl # Resources/Locale/en-US/_strings/reagents/meta/physical-desc.ftl # Resources/Locale/en-US/_strings/research/technologies.ftl # Resources/Locale/en-US/_strings/seeds/seeds.ftl # Resources/Locale/en-US/_strings/weapons/grenades/timer-trigger.ftl # Resources/Locale/en-US/_strings/weapons/grenades/voice-trigger.ftl # Resources/Locale/en-US/commands/mapping-client-side-setup-command.ftl # Resources/Locale/en-US/recipes/tags.ftl # Resources/Maps/_Sunrise/Station/bagel.yml # Resources/Maps/_Sunrise/Station/barratry.yml # Resources/Maps/_Sunrise/Station/box.yml # Resources/Maps/_Sunrise/Station/fland.yml # Resources/Maps/_Sunrise/Station/marathon.yml # Resources/Maps/_Sunrise/Station/oasis.yml # Resources/Maps/_Sunrise/Station/packed.yml # Resources/Maps/_Sunrise/Station/plasma.yml # Resources/Maps/amber.yml # Resources/Maps/centcomm.yml # Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml # Resources/Prototypes/Catalog/Fills/Lockers/security.yml # Resources/Prototypes/Catalog/Fills/Lockers/service.yml # Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/coffee.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/sustenance.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/winterdrobe.yml # Resources/Prototypes/Entities/Clothing/Belt/belts.yml # Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml # Resources/Prototypes/Entities/Clothing/Eyes/hud.yml # Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml # Resources/Prototypes/Entities/Clothing/Head/hats.yml # Resources/Prototypes/Entities/Clothing/Head/helmets.yml # Resources/Prototypes/Entities/Clothing/Head/hoods.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/softsuits.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml # Resources/Prototypes/Entities/Mobs/NPCs/animals.yml # Resources/Prototypes/Entities/Mobs/NPCs/carp.yml # Resources/Prototypes/Entities/Mobs/NPCs/pets.yml # Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml # Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml # Resources/Prototypes/Entities/Mobs/Player/clone.yml # Resources/Prototypes/Entities/Mobs/Species/base.yml # Resources/Prototypes/Entities/Mobs/Species/dwarf.yml # Resources/Prototypes/Entities/Mobs/base.yml # Resources/Prototypes/Entities/Objects/Fun/pai.yml # Resources/Prototypes/Entities/Objects/Fun/toys.yml # Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml # Resources/Prototypes/Entities/Objects/Shields/shields.yml # Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml # Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml # Resources/Prototypes/Entities/Objects/Tools/access_configurator.yml # Resources/Prototypes/Entities/Objects/Tools/matches.yml # Resources/Prototypes/Entities/Objects/Weapons/Bombs/plastic.yml # Resources/Prototypes/Entities/Objects/Weapons/Bombs/spider.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Magazines/caseless_rifle.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Magazines/light_rifle.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Magazines/magnum.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/grenade.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml # Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml # Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml # Resources/Prototypes/Entities/Structures/Doors/Airlocks/airlocks.yml # Resources/Prototypes/Entities/Structures/Doors/airlock_groups.yml # Resources/Prototypes/Entities/Structures/Furniture/beds.yml # Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml # Resources/Prototypes/Entities/Structures/Power/debug_power.yml # Resources/Prototypes/Entities/Structures/Storage/Crates/crates.yml # Resources/Prototypes/Entities/Structures/Wallmounts/Misc/mirror.yml # Resources/Prototypes/GameRules/subgamemodes.yml # Resources/Prototypes/Reagents/Consumable/Drink/drinks.yml # Resources/Prototypes/Reagents/Consumable/Drink/soda.yml # Resources/Prototypes/Reagents/medicine.yml # Resources/Prototypes/Recipes/Lathes/Packs/tiles.yml # Resources/Prototypes/Recipes/Lathes/categories.yml # Resources/Prototypes/Recipes/Reactions/chemicals.yml # Resources/Prototypes/Roles/Antags/changeling.yml # Resources/Prototypes/name_identifier_groups.yml # Resources/Prototypes/tool_qualities.yml # Resources/ServerInfo/Guidebook/Antagonist/Zombies.xml # Resources/ServerInfo/Guidebook/Cargo/CargoBounties.xml # Resources/ServerInfo/Guidebook/Command.xml # Resources/ServerInfo/Guidebook/Glossary.xml # Resources/ServerInfo/Guidebook/NewPlayer/YourFirstCharacter.xml # Resources/ServerInfo/Guidebook/Science/Robotics.xml # Resources/ServerInfo/Guidebook/Science/ScannersAndVessels.xml # Resources/ServerInfo/Guidebook/Science/Science.xml # Resources/ServerInfo/Guidebook/SpaceStation14.xml # Resources/ServerInfo/Guidebook/Survival.xml # Resources/Textures/Clothing/Head/Hardsuits/atmospherics.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/capspace.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/cybersun.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/engineering-white.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/engineering-white.rsi/on-equipped-HELMET.png # Resources/Textures/Clothing/Head/Hardsuits/engineering.rsi/icon.png # Resources/Textures/Clothing/Head/Hardsuits/engineering.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/engineering.rsi/on-equipped-HELMET.png # Resources/Textures/Clothing/Head/Hardsuits/medical.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/salvage.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/security.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/spatiohelm.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/syndicate.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/syndiecommander.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/syndieelite.rsi/meta.json # Resources/Textures/Clothing/Head/Hardsuits/wizard.rsi/meta.json # Resources/Textures/Clothing/Head/Helmets/atmos_firehelmet.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Armor/captain_carapace.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/atmospherics.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/capspace.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/cybersun.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/engineering-white.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/engineering.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/medical.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/paramed.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/rd.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/salvage.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/security.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/spatio.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/syndicate.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/syndiecommander.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/syndieelite.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/wizard.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Suits/atmos_firesuit.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Suits/eva.rsi/meta.json # Resources/Textures/Interface/Misc/job_icons.rsi/meta.json # Resources/Textures/Objects/Misc/Lights/lampgreen.rsi/meta.json # Resources/Textures/Objects/Specific/Janitorial/janitorial_cart.rsi/meta.json # Resources/Textures/Objects/Tools/spray_painter.rsi/meta.json # Resources/Textures/Objects/Weapons/Melee/baseball_bat.rsi/meta.json # Resources/engineCommandPerms.yml # Resources/keybinds.yml # Resources/migration.yml
This commit is contained in:
commit
939076ff99
3460 changed files with 82147 additions and 46138 deletions
|
|
@ -77,6 +77,8 @@ csharp_style_expression_bodied_methods = false:suggestion
|
|||
#csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:suggestion
|
||||
|
||||
csharp_style_namespace_declarations = file_scoped:suggestion
|
||||
|
||||
# Pattern matching preferences
|
||||
#csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
#csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
|
|
|
|||
2
.github/workflows/build-docfx.yml
vendored
2
.github/workflows/build-docfx.yml
vendored
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
run: dotnet restore
|
||||
|
||||
- name: Build Project
|
||||
run: dotnet build --no-restore /p:WarningsAsErrors=nullable
|
||||
run: dotnet build --no-restore
|
||||
|
||||
- name: Build DocFX
|
||||
uses: nikeee/docfx-action@v1.0.0
|
||||
|
|
|
|||
2
.github/workflows/build-map-renderer.yml
vendored
2
.github/workflows/build-map-renderer.yml
vendored
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
run: dotnet restore
|
||||
|
||||
- name: Build Project
|
||||
run: dotnet build Content.MapRenderer --configuration Release --no-restore /p:WarningsAsErrors=nullable /m
|
||||
run: dotnet build Content.MapRenderer --configuration Release --no-restore /m
|
||||
|
||||
- name: Run Map Renderer
|
||||
run: dotnet run --project Content.MapRenderer Dev
|
||||
|
|
|
|||
2
.github/workflows/build-test-debug.yml
vendored
2
.github/workflows/build-test-debug.yml
vendored
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
run: dotnet restore
|
||||
|
||||
- name: Build Project
|
||||
run: dotnet build --configuration DebugOpt --no-restore /p:WarningsAsErrors=nullable /m
|
||||
run: dotnet build --configuration DebugOpt --no-restore /m
|
||||
|
||||
- name: Run Content.Tests
|
||||
run: dotnet test --no-build --configuration DebugOpt Content.Tests/Content.Tests.csproj -- NUnit.ConsoleOut=0
|
||||
|
|
|
|||
2
.github/workflows/labeler-needsreview.yml
vendored
2
.github/workflows/labeler-needsreview.yml
vendored
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [review_requested]
|
||||
types: [review_requested, opened]
|
||||
|
||||
jobs:
|
||||
add_label:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ If you believe someone is violating the code of conduct, we ask that you report
|
|||
|
||||
Original text courtesy of the [Speak Up! project](http://web.archive.org/web/20141109123859/http://speakup.io/coc.html).
|
||||
|
||||
## On Comunity Moderation
|
||||
## On Community Moderation
|
||||
|
||||
Deviating from the Code of Conduct on the Github repository may result in moderative actions taken by project Maintainers. This can involve your content being edited or deleted, and may result in a temporary or permanent block from the repository.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using BenchmarkDotNet.Attributes;
|
|||
using Content.IntegrationTests;
|
||||
using Content.IntegrationTests.Pair;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Warps;
|
||||
using Content.Shared.Warps;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Analyzers;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using Robust.Shared;
|
|||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Benchmarks;
|
||||
|
||||
|
|
@ -18,9 +19,11 @@ namespace Content.Benchmarks;
|
|||
[Virtual, MemoryDiagnoser]
|
||||
public class SpawnEquipDeleteBenchmark
|
||||
{
|
||||
private static readonly EntProtoId Mob = "MobHuman";
|
||||
private static readonly ProtoId<StartingGearPrototype> CaptainStartingGear = "CaptainGear";
|
||||
|
||||
private TestPair _pair = default!;
|
||||
private StationSpawningSystem _spawnSys = default!;
|
||||
private const string Mob = "MobHuman";
|
||||
private StartingGearPrototype _gear = default!;
|
||||
private EntityUid _entity;
|
||||
private EntityCoordinates _coords;
|
||||
|
|
@ -39,7 +42,7 @@ public class SpawnEquipDeleteBenchmark
|
|||
var mapData = await _pair.CreateTestMap();
|
||||
_coords = mapData.GridCoords;
|
||||
_spawnSys = server.System<StationSpawningSystem>();
|
||||
_gear = server.ProtoMan.Index<StartingGearPrototype>("CaptainGear");
|
||||
_gear = server.ProtoMan.Index(CaptainStartingGear);
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ namespace Content.Client.Access.UI;
|
|||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GroupedAccessLevelChecklist : BoxContainer
|
||||
{
|
||||
private static readonly ProtoId<AccessGroupPrototype> GeneralAccessGroup = "General";
|
||||
|
||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||
|
||||
private bool _isMonotone;
|
||||
|
|
@ -63,7 +65,7 @@ public sealed partial class GroupedAccessLevelChecklist : BoxContainer
|
|||
|
||||
// Ensure that the 'general' access group is added to handle
|
||||
// misc. access levels that aren't associated with any group
|
||||
if (_protoManager.TryIndex<AccessGroupPrototype>("General", out var generalAccessProto))
|
||||
if (_protoManager.TryIndex(GeneralAccessGroup, out var generalAccessProto))
|
||||
_groupedAccessLevels.TryAdd(generalAccessProto, new());
|
||||
|
||||
// Assign known access levels with their associated groups
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ namespace Content.Client.Actions
|
|||
else
|
||||
{
|
||||
var request = new RequestPerformActionEvent(GetNetEntity(action));
|
||||
EntityManager.RaisePredictiveEvent(request);
|
||||
RaisePredictiveEvent(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +334,12 @@ namespace Content.Client.Actions
|
|||
|
||||
private void OnEntityTargetAttempt(Entity<EntityTargetActionComponent> ent, ref ActionTargetAttemptEvent args)
|
||||
{
|
||||
if (args.Handled || args.Input.EntityUid is not { Valid: true } entity)
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
if (args.Input.EntityUid is not { Valid: true } entity)
|
||||
return;
|
||||
|
||||
// let world target component handle it
|
||||
|
|
@ -345,8 +350,6 @@ namespace Content.Client.Actions
|
|||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
var action = args.Action;
|
||||
var user = args.User;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.Frozen;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Administration.Systems;
|
||||
|
|
@ -24,6 +25,7 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
private readonly EntityLookupSystem _entityLookup;
|
||||
private readonly IUserInterfaceManager _userInterfaceManager;
|
||||
private readonly SharedRoleSystem _roles;
|
||||
private readonly IPrototypeManager _prototypeManager;
|
||||
private readonly Font _font;
|
||||
private readonly Font _fontBold;
|
||||
private AdminOverlayAntagFormat _overlayFormat;
|
||||
|
|
@ -36,8 +38,9 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
private float _overlayMergeDistance;
|
||||
|
||||
//TODO make this adjustable via GUI?
|
||||
private readonly ProtoId<RoleTypePrototype>[] _filter =
|
||||
["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"];
|
||||
private static readonly FrozenSet<ProtoId<RoleTypePrototype>> Filter =
|
||||
new ProtoId<RoleTypePrototype>[] {"SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"}
|
||||
.ToFrozenSet();
|
||||
|
||||
private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic");
|
||||
|
||||
|
|
@ -49,7 +52,8 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
EntityLookupSystem entityLookup,
|
||||
IUserInterfaceManager userInterfaceManager,
|
||||
IConfigurationManager config,
|
||||
SharedRoleSystem roles)
|
||||
SharedRoleSystem roles,
|
||||
IPrototypeManager prototypeManager)
|
||||
{
|
||||
_system = system;
|
||||
_entityManager = entityManager;
|
||||
|
|
@ -57,6 +61,7 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
_entityLookup = entityLookup;
|
||||
_userInterfaceManager = userInterfaceManager;
|
||||
_roles = roles;
|
||||
_prototypeManager = prototypeManager;
|
||||
ZIndex = 200;
|
||||
// Setting these to a specific ttf would break the antag symbols
|
||||
_font = resourceCache.NotoStack();
|
||||
|
|
@ -125,6 +130,14 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
foreach (var info in sortable.OrderBy(s => s.Item4.Y).ToList())
|
||||
{
|
||||
var playerInfo = info.Item1;
|
||||
var rolePrototype = playerInfo.RoleProto == null
|
||||
? null
|
||||
: _prototypeManager.Index(playerInfo.RoleProto.Value);
|
||||
|
||||
var roleName = Loc.GetString(rolePrototype?.Name ?? RoleTypePrototype.FallbackName);
|
||||
var roleColor = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor;
|
||||
var roleSymbol = rolePrototype?.Symbol ?? RoleTypePrototype.FallbackSymbol;
|
||||
|
||||
var aabb = info.Item2;
|
||||
var entity = info.Item3;
|
||||
var screenCoordinatesCenter = info.Item4;
|
||||
|
|
@ -209,7 +222,7 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
switch (_overlaySymbolStyle)
|
||||
{
|
||||
case AdminOverlayAntagSymbolStyle.Specific:
|
||||
symbol = playerInfo.RoleProto.Symbol;
|
||||
symbol = roleSymbol;
|
||||
break;
|
||||
case AdminOverlayAntagSymbolStyle.Basic:
|
||||
symbol = Loc.GetString("player-tab-antag-prefix");
|
||||
|
|
@ -225,17 +238,17 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
switch (_overlayFormat)
|
||||
{
|
||||
case AdminOverlayAntagFormat.Roletype:
|
||||
color = playerInfo.RoleProto.Color;
|
||||
symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||
text = _filter.Contains(playerInfo.RoleProto)
|
||||
? Loc.GetString(playerInfo.RoleProto.Name).ToUpper()
|
||||
color = roleColor;
|
||||
symbol = IsFiltered(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||
text = IsFiltered(playerInfo.RoleProto)
|
||||
? roleName.ToUpper()
|
||||
: string.Empty;
|
||||
break;
|
||||
case AdminOverlayAntagFormat.Subtype:
|
||||
color = playerInfo.RoleProto.Color;
|
||||
symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||
text = _filter.Contains(playerInfo.RoleProto)
|
||||
? _roles.GetRoleSubtypeLabel(playerInfo.RoleProto.Name, playerInfo.Subtype).ToUpper()
|
||||
color = roleColor;
|
||||
symbol = IsFiltered(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||
text = IsFiltered(playerInfo.RoleProto)
|
||||
? _roles.GetRoleSubtypeLabel(roleName, playerInfo.Subtype).ToUpper()
|
||||
: string.Empty;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -258,4 +271,12 @@ internal sealed class AdminNameOverlay : Overlay
|
|||
drawnOverlays.Add((screenCoordinatesCenter, currentOffset));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsFiltered(ProtoId<RoleTypePrototype>? roleProtoId)
|
||||
{
|
||||
if (roleProtoId == null)
|
||||
return false;
|
||||
|
||||
return Filter.Contains(roleProtoId.Value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
using Content.Shared.Administration.Components;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Client.Administration.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class HeadstandComponent : SharedHeadstandComponent
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ using Robust.Client.Graphics;
|
|||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Administration.Systems
|
||||
{
|
||||
|
|
@ -17,6 +18,7 @@ namespace Content.Client.Administration.Systems
|
|||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
private AdminNameOverlay _adminNameOverlay = default!;
|
||||
|
||||
|
|
@ -33,7 +35,8 @@ namespace Content.Client.Administration.Systems
|
|||
_entityLookup,
|
||||
_userInterfaceManager,
|
||||
_configurationManager,
|
||||
_roles);
|
||||
_roles,
|
||||
_proto);
|
||||
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using Content.Client.Administration.Components;
|
||||
using Content.Shared.Administration.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Administration.Systems;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<Control
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:viewport="clr-namespace:Content.Client.Viewport"
|
||||
MouseFilter="Stop">
|
||||
<PanelContainer StyleClasses="BackgroundDark" Name="AdminCameraWindowRoot" Access="Public">
|
||||
<BoxContainer Orientation="Vertical" Access="Public">
|
||||
<!-- Camera -->
|
||||
<Control VerticalExpand="True" Name="CameraViewBox">
|
||||
<viewport:ScalingViewport Name="CameraView"
|
||||
MinSize="100 100"
|
||||
MouseFilter="Ignore" />
|
||||
</Control>
|
||||
<!-- Controller buttons -->
|
||||
<BoxContainer Orientation="Horizontal" Margin="5 5 5 5">
|
||||
<Button StyleClasses="OpenRight" Name="FollowButton" HorizontalExpand="True" Access="Public" Text="{Loc 'admin-camera-window-follow'}" />
|
||||
<Button StyleClasses="OpenLeft" Name="PopControl" HorizontalExpand="True" Access="Public" Text="{Loc 'admin-camera-window-pop-out'}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</Control>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Eye;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Timing;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Administration.UI.AdminCamera;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class AdminCameraControl : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IClientGameTiming _timing = default!;
|
||||
|
||||
public event Action? OnFollow;
|
||||
public event Action? OnPopoutControl;
|
||||
|
||||
private readonly EyeLerpingSystem _eyeLerpingSystem;
|
||||
private readonly FixedEye _defaultEye = new();
|
||||
private AdminCameraEuiState? _nextState;
|
||||
|
||||
private const float MinimumZoom = 0.1f;
|
||||
private const float MaximumZoom = 2.0f;
|
||||
|
||||
public EntityUid? CurrentCamera;
|
||||
public float Zoom = 1.0f;
|
||||
|
||||
public bool IsPoppedOut;
|
||||
|
||||
public AdminCameraControl()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_eyeLerpingSystem = _entManager.System<EyeLerpingSystem>();
|
||||
|
||||
CameraView.Eye = _defaultEye;
|
||||
|
||||
FollowButton.OnPressed += _ => OnFollow?.Invoke();
|
||||
PopControl.OnPressed += _ => OnPopoutControl?.Invoke();
|
||||
CameraView.OnResized += OnResized;
|
||||
}
|
||||
|
||||
private new void OnResized()
|
||||
{
|
||||
var width = Math.Max(CameraView.PixelWidth, (int)Math.Floor(CameraView.MinWidth));
|
||||
var height = Math.Max(CameraView.PixelHeight, (int)Math.Floor(CameraView.MinHeight));
|
||||
|
||||
CameraView.ViewportSize = new Vector2i(width, height);
|
||||
}
|
||||
|
||||
protected override void MouseWheel(GUIMouseWheelEventArgs args)
|
||||
{
|
||||
base.MouseWheel(args);
|
||||
|
||||
if (CameraView.Eye == null)
|
||||
return;
|
||||
|
||||
Zoom = Math.Clamp(Zoom - args.Delta.Y * 0.15f * Zoom, MinimumZoom, MaximumZoom);
|
||||
CameraView.Eye.Zoom = new Vector2(Zoom, Zoom);
|
||||
args.Handle();
|
||||
}
|
||||
|
||||
public void SetState(AdminCameraEuiState state)
|
||||
{
|
||||
_nextState = state;
|
||||
}
|
||||
|
||||
// I know that this is awful, but I copied this from the solution editor anyways.
|
||||
// This is needed because EUIs update before the gamestate is applied, which means it will fail to get the uid from the net entity.
|
||||
// The suggestion from the comment in the solution editor saying to use a BUI is not ideal either:
|
||||
// - We would need to bind the UI to an entity, but with how BUIs currently work we cannot open it in the same tick as we spawn that entity on the server.
|
||||
// - We want the UI opened by the user session, not by their currently attached entity. Otherwise it would close in cases where admins move from one entity to another, for example when ghosting.
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
if (_nextState == null || _timing.LastRealTick < _nextState.Tick) // make sure the last gamestate has been applied
|
||||
return;
|
||||
|
||||
if (!_entManager.TryGetEntity(_nextState.Camera, out var cameraUid))
|
||||
return;
|
||||
|
||||
if (CurrentCamera == null)
|
||||
{
|
||||
_eyeLerpingSystem.AddEye(cameraUid.Value);
|
||||
CurrentCamera = cameraUid;
|
||||
}
|
||||
else if (CurrentCamera != cameraUid)
|
||||
{
|
||||
_eyeLerpingSystem.RemoveEye(CurrentCamera.Value);
|
||||
_eyeLerpingSystem.AddEye(cameraUid.Value);
|
||||
CurrentCamera = cameraUid;
|
||||
}
|
||||
|
||||
if (_entManager.TryGetComponent<EyeComponent>(CurrentCamera, out var eye))
|
||||
CameraView.Eye = eye.Eye ?? _defaultEye;
|
||||
}
|
||||
}
|
||||
117
Content.Client/Administration/UI/AdminCamera/AdminCameraEui.cs
Normal file
117
Content.Client/Administration/UI/AdminCamera/AdminCameraEui.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Eui;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Eui;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.Administration.UI.AdminCamera;
|
||||
|
||||
/// <summary>
|
||||
/// Admin Eui for opening a viewport window to observe entities.
|
||||
/// Use the "Open Camera" admin verb or the "camera" command to open.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed partial class AdminCameraEui : BaseEui
|
||||
{
|
||||
private readonly AdminCameraWindow _window;
|
||||
private readonly AdminCameraControl _control;
|
||||
|
||||
// If not null the camera is in "popped out" mode and is in an external window.
|
||||
private OSWindow? _OSWindow;
|
||||
|
||||
// The last location the window was located at in game.
|
||||
// Is used for getting knowing where to "pop in" external windows.
|
||||
private Vector2 _lastLocation;
|
||||
|
||||
public AdminCameraEui()
|
||||
{
|
||||
_window = new AdminCameraWindow();
|
||||
_control = new AdminCameraControl();
|
||||
|
||||
_window.Contents.AddChild(_control);
|
||||
|
||||
_control.OnFollow += () => SendMessage(new AdminCameraFollowMessage());
|
||||
_window.OnClose += () =>
|
||||
{
|
||||
if (!_control.IsPoppedOut)
|
||||
SendMessage(new CloseEuiMessage());
|
||||
};
|
||||
|
||||
_control.OnPopoutControl += () =>
|
||||
{
|
||||
if (_control.IsPoppedOut)
|
||||
PopIn();
|
||||
else
|
||||
PopOut();
|
||||
};
|
||||
}
|
||||
|
||||
// Pop the window out into an external OS window
|
||||
private void PopOut()
|
||||
{
|
||||
_lastLocation = _window.Position;
|
||||
|
||||
// TODO: When there is a way to have a minimum window size, enforce something!
|
||||
_OSWindow = new OSWindow
|
||||
{
|
||||
SetSize = _window.Size,
|
||||
Title = _window.Title ?? Loc.GetString("admin-camera-window-title-placeholder"),
|
||||
};
|
||||
|
||||
_OSWindow.Show();
|
||||
|
||||
if (_OSWindow.Root == null)
|
||||
return;
|
||||
|
||||
_control.Orphan();
|
||||
_OSWindow.Root.AddChild(_control);
|
||||
|
||||
_OSWindow.Closed += () =>
|
||||
{
|
||||
if (_control.IsPoppedOut)
|
||||
SendMessage(new CloseEuiMessage());
|
||||
};
|
||||
|
||||
_control.IsPoppedOut = true;
|
||||
_control.PopControl.Text = Loc.GetString("admin-camera-window-pop-in");
|
||||
|
||||
_window.Close();
|
||||
}
|
||||
|
||||
// Pop the window back into the in game window.
|
||||
private void PopIn()
|
||||
{
|
||||
_control.Orphan();
|
||||
_window.Contents.AddChild(_control);
|
||||
|
||||
_window.Open(_lastLocation);
|
||||
|
||||
_control.IsPoppedOut = false;
|
||||
_control.PopControl.Text = Loc.GetString("admin-camera-window-pop-out");
|
||||
|
||||
_OSWindow?.Close();
|
||||
_OSWindow = null;
|
||||
}
|
||||
|
||||
public override void Opened()
|
||||
{
|
||||
base.Opened();
|
||||
_window.OpenCentered();
|
||||
}
|
||||
|
||||
public override void Closed()
|
||||
{
|
||||
base.Closed();
|
||||
_window.Close();
|
||||
}
|
||||
|
||||
public override void HandleState(EuiStateBase baseState)
|
||||
{
|
||||
if (baseState is not AdminCameraEuiState state)
|
||||
return;
|
||||
|
||||
_window.SetState(state);
|
||||
_control.SetState(state);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
Title="{Loc admin-camera-window-title-placeholder}"
|
||||
SetSize="425 550"
|
||||
MinSize="200 225"
|
||||
Name="Window">
|
||||
</DefaultWindow>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Content.Shared.Administration;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Administration.UI.AdminCamera;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class AdminCameraWindow : DefaultWindow
|
||||
{
|
||||
public AdminCameraWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
ContentsContainer.Margin = new Thickness(5, 0, 5, 0);
|
||||
}
|
||||
|
||||
public void SetState(AdminCameraEuiState state)
|
||||
{
|
||||
Title = Loc.GetString("admin-camera-window-title", ("name", state.Name));
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ using Content.Shared.CCVar;
|
|||
using Content.Shared.Database;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
|
@ -32,14 +33,21 @@ public sealed partial class BanPanel : DefaultWindow
|
|||
private uint Multiplier { get; set; }
|
||||
private bool HasBanFlag { get; set; }
|
||||
private TimeSpan? ButtonResetOn { get; set; }
|
||||
|
||||
// This is less efficient than just holding a reference to the root control and enumerating children, but you
|
||||
// have to know how the controls are nested, which makes the code more complicated.
|
||||
private readonly List<CheckBox> _roleCheckboxes = new();
|
||||
// Role group name -> the role buttons themselves.
|
||||
private readonly Dictionary<string, List<Button>> _roleCheckboxes = new();
|
||||
private readonly ISawmill _banpanelSawmill;
|
||||
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||
|
||||
private const string ExpandedArrow = "▼";
|
||||
private const string ContractedArrow = "▶";
|
||||
|
||||
private readonly string _antagCategory = Loc.GetString("ban-panel-role-selection-antag");
|
||||
private readonly string _antagAllSelection = Loc.GetString("ban-panel-role-selection-antag-all-option");
|
||||
|
|
@ -150,68 +158,90 @@ public sealed partial class BanPanel : DefaultWindow
|
|||
|
||||
ReasonTextEdit.Placeholder = new Rope.Leaf(Loc.GetString("ban-panel-reason"));
|
||||
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
foreach (var proto in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
|
||||
var departmentJobs = _protoMan.EnumeratePrototypes<DepartmentPrototype>()
|
||||
.OrderBy(x => x.Weight);
|
||||
foreach (var proto in departmentJobs)
|
||||
{
|
||||
CreateRoleGroup(proto.ID, proto.Roles.Select(p => p.Id), proto.Color);
|
||||
var roles = proto.Roles.Select(x => _protoMan.Index(x))
|
||||
.OrderBy(x => x.ID);
|
||||
CreateRoleGroup(proto.ID, proto.Color, roles);
|
||||
}
|
||||
|
||||
var antagRoleList = prototypeManager.EnumeratePrototypes<AntagPrototype>().Select(p => p.ID).ToList();
|
||||
antagRoleList.Insert(0, _antagAllSelection);
|
||||
CreateRoleGroup(_antagCategory, antagRoleList, Color.Red);
|
||||
var antagRoles = _protoMan.EnumeratePrototypes<AntagPrototype>()
|
||||
.OrderBy(x => x.ID);
|
||||
CreateRoleGroup("Antagonist", Color.Red, antagRoles);
|
||||
}
|
||||
|
||||
private void CreateRoleGroup(string roleName, IEnumerable<string> roleList, Color color)
|
||||
/// <summary>
|
||||
/// Creates a "Role group" which stores information and logic for one "group" of roll bans.
|
||||
/// For example, all antags are one group, logi is a group, medical is a group, etc...
|
||||
/// </summary>
|
||||
private void CreateRoleGroup<T>(string groupName, Color color, IEnumerable<T> roles) where T : class, IPrototype
|
||||
{
|
||||
var outerContainer = new BoxContainer
|
||||
{
|
||||
Name = $"{roleName}GroupOuterBox",
|
||||
Name = $"{groupName}GroupOuterBox",
|
||||
HorizontalExpand = true,
|
||||
VerticalExpand = true,
|
||||
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
||||
Margin = new Thickness(4),
|
||||
};
|
||||
var departmentCheckbox = new CheckBox
|
||||
|
||||
// Stores stuff like ban all and expand buttons.
|
||||
var roleGroupHeader = new BoxContainer
|
||||
{
|
||||
Name = $"{roleName}GroupCheckbox",
|
||||
Text = roleName,
|
||||
Modulate = color,
|
||||
HorizontalAlignment = HAlignment.Left,
|
||||
Margin = new Thickness(2),
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
};
|
||||
outerContainer.AddChild(departmentCheckbox);
|
||||
|
||||
// Stores the role checkboxes themselves.
|
||||
var innerContainer = new GridContainer
|
||||
{
|
||||
Name = $"{roleName}GroupInnerBox",
|
||||
Name = $"{groupName}GroupInnerBox",
|
||||
HorizontalExpand = true,
|
||||
Columns = 4,
|
||||
Margin = new Thickness(2)
|
||||
Columns = 2,
|
||||
Visible = false,
|
||||
Margin = new Thickness(15, 5, 0, 5),
|
||||
};
|
||||
departmentCheckbox.OnToggled += args =>
|
||||
|
||||
var roleGroupCheckbox = CreateRoleGroupHeader(groupName, roleGroupHeader, color, innerContainer);
|
||||
|
||||
outerContainer.AddChild(roleGroupHeader);
|
||||
|
||||
// Add the roles themselves
|
||||
foreach (var role in roles)
|
||||
{
|
||||
if (args.Pressed && roleName == _antagCategory)
|
||||
AddRoleCheckbox(groupName, role.ID, innerContainer, roleGroupCheckbox);
|
||||
}
|
||||
|
||||
outerContainer.AddChild(innerContainer);
|
||||
|
||||
RolesContainer.AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
foreach (var child in innerContainer.Children)
|
||||
{
|
||||
if (child is CheckBox antagCheckbox && antagCheckbox.Name == $"{_antagAllSelection}RoleCheckbox")
|
||||
{
|
||||
antagCheckbox.Pressed = true;
|
||||
}
|
||||
else if (child is CheckBox otherAntagCheckbox)
|
||||
{
|
||||
otherAntagCheckbox.Pressed = false;
|
||||
}
|
||||
}
|
||||
BackgroundColor = color
|
||||
}
|
||||
else
|
||||
});
|
||||
RolesContainer.AddChild(outerContainer);
|
||||
RolesContainer.AddChild(new HSeparator());
|
||||
}
|
||||
|
||||
private Button CreateRoleGroupHeader(string groupName, BoxContainer header, Color color, GridContainer innerContainer)
|
||||
{
|
||||
var roleGroupCheckbox = new Button
|
||||
{
|
||||
Name = $"{groupName}GroupCheckbox",
|
||||
Text = "Ban all",
|
||||
Margin = new Thickness(0, 0, 5, 0),
|
||||
ToggleMode = true,
|
||||
};
|
||||
|
||||
// When this is toggled, toggle all buttons in this group so they match.
|
||||
roleGroupCheckbox.OnToggled += args =>
|
||||
{
|
||||
foreach (var role in _roleCheckboxes[groupName])
|
||||
{
|
||||
foreach (var child in innerContainer.Children)
|
||||
{
|
||||
if (child is CheckBox roleChildCheckbox)
|
||||
{
|
||||
roleChildCheckbox.Pressed = args.Pressed;
|
||||
}
|
||||
}
|
||||
role.Pressed = args.Pressed;
|
||||
}
|
||||
|
||||
if (args.Pressed)
|
||||
|
|
@ -226,15 +256,12 @@ public sealed partial class BanPanel : DefaultWindow
|
|||
}
|
||||
else
|
||||
{
|
||||
foreach (var childContainer in RolesContainer.Children)
|
||||
foreach (var roleButtons in _roleCheckboxes.Values)
|
||||
{
|
||||
if (childContainer is Container)
|
||||
foreach (var button in roleButtons)
|
||||
{
|
||||
foreach (var child in childContainer.Children)
|
||||
{
|
||||
if (child is CheckBox { Pressed: true })
|
||||
return;
|
||||
}
|
||||
if (button.Pressed)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,63 +274,72 @@ public sealed partial class BanPanel : DefaultWindow
|
|||
SeverityOption.SelectId((int)newSeverity);
|
||||
}
|
||||
};
|
||||
outerContainer.AddChild(innerContainer);
|
||||
|
||||
var isAntagonistGroup = roleName == _antagCategory;
|
||||
foreach (var role in roleList)
|
||||
var hideButton = new Button
|
||||
{
|
||||
AddRoleCheckbox(role, innerContainer, departmentCheckbox, isAntagonistGroup);
|
||||
}
|
||||
RolesContainer.AddChild(new PanelContainer
|
||||
Text = Loc.GetString("role-bans-expand-roles") + " " + ContractedArrow,
|
||||
ToggleMode = true,
|
||||
};
|
||||
hideButton.OnPressed += args =>
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = color
|
||||
}
|
||||
innerContainer.Visible = args.Button.Pressed;
|
||||
((Button)args.Button).Text = args.Button.Pressed
|
||||
? Loc.GetString("role-bans-contract-roles") + " " + ExpandedArrow
|
||||
: Loc.GetString("role-bans-expand-roles") + " " + ContractedArrow;
|
||||
};
|
||||
header.AddChild(new Label
|
||||
{
|
||||
Text = groupName,
|
||||
Modulate = color,
|
||||
Margin = new Thickness(0, 0, 5, 0),
|
||||
});
|
||||
RolesContainer.AddChild(outerContainer);
|
||||
RolesContainer.AddChild(new HSeparator());
|
||||
header.AddChild(roleGroupCheckbox);
|
||||
header.AddChild(hideButton);
|
||||
return roleGroupCheckbox;
|
||||
}
|
||||
|
||||
private void AddRoleCheckbox(string role, Control container, CheckBox header, bool isAntagonistGroup = false)
|
||||
/// <summary>
|
||||
/// Adds a checkbutton specifically for one "role" in a "group"
|
||||
/// E.g. it would add the Chief Medical Officer "role" into the "Medical" group.
|
||||
/// </summary>
|
||||
private void AddRoleCheckbox(string group, string role, GridContainer roleGroupInnerContainer, Button roleGroupCheckbox)
|
||||
{
|
||||
var roleCheckbox = new CheckBox
|
||||
var roleCheckboxContainer = new BoxContainer();
|
||||
var roleCheckButton = new Button
|
||||
{
|
||||
Name = $"{role}RoleCheckbox",
|
||||
Text = role,
|
||||
Margin = new Thickness(2),
|
||||
ToggleMode = true,
|
||||
};
|
||||
|
||||
roleCheckbox.OnToggled += args =>
|
||||
roleCheckButton.OnToggled += args =>
|
||||
{
|
||||
if (isAntagonistGroup && role == _antagAllSelection)
|
||||
{
|
||||
foreach (var child in container.Children)
|
||||
{
|
||||
if (child is CheckBox c && c != roleCheckbox)
|
||||
{
|
||||
c.Pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args is { Pressed: true, Button.Parent: { } } && args.Button.Parent.Children.OfType<CheckBox>().All(e => e.Pressed))
|
||||
header.Pressed = true;
|
||||
// Checks the role group checkbox if all the children are pressed
|
||||
if (args.Pressed && _roleCheckboxes[group].All(e => e.Pressed))
|
||||
roleGroupCheckbox.Pressed = args.Pressed;
|
||||
else
|
||||
header.Pressed = false;
|
||||
|
||||
// Ensure "All" checkbox logic within the antagonist group
|
||||
if (isAntagonistGroup && role != _antagAllSelection)
|
||||
{
|
||||
var allAntagsCheckbox = container.Children.OfType<CheckBox>().FirstOrDefault(c => c.Name == $"{_antagAllSelection}RoleCheckbox");
|
||||
if (allAntagsCheckbox != null && args.Pressed)
|
||||
{
|
||||
allAntagsCheckbox.Pressed = false;
|
||||
}
|
||||
}
|
||||
roleGroupCheckbox.Pressed = false;
|
||||
};
|
||||
container.AddChild(roleCheckbox);
|
||||
_roleCheckboxes.Add(roleCheckbox);
|
||||
|
||||
// This is adding the icon before the role name
|
||||
// Yeah, this is sus, but having to split the functions up and stuff is worse imo.
|
||||
if (_protoMan.TryIndex<JobPrototype>(role, out var jobPrototype) && _protoMan.TryIndex(jobPrototype.Icon, out var iconProto))
|
||||
{
|
||||
var jobIconTexture = new TextureRect
|
||||
{
|
||||
Texture = _entMan.System<SpriteSystem>().Frame0(iconProto.Icon),
|
||||
TextureScale = new Vector2(2.5f, 2.5f),
|
||||
Stretch = TextureRect.StretchMode.KeepCentered,
|
||||
Margin = new Thickness(5, 0, 0, 0),
|
||||
};
|
||||
roleCheckboxContainer.AddChild(jobIconTexture);
|
||||
}
|
||||
|
||||
roleCheckboxContainer.AddChild(roleCheckButton);
|
||||
|
||||
roleGroupInnerContainer.AddChild(roleCheckboxContainer);
|
||||
|
||||
_roleCheckboxes.TryAdd(group, []);
|
||||
_roleCheckboxes[group].Add(roleCheckButton);
|
||||
}
|
||||
|
||||
public void UpdateBanFlag(bool newFlag)
|
||||
|
|
@ -521,7 +557,13 @@ public sealed partial class BanPanel : DefaultWindow
|
|||
if (_roleCheckboxes.Count == 0)
|
||||
throw new DebugAssertException("RoleCheckboxes was empty");
|
||||
|
||||
rolesList.AddRange(_roleCheckboxes.Where(c => c is { Pressed: true, Text: { } }).Select(c => c.Text!));
|
||||
foreach (var button in _roleCheckboxes.Values.SelectMany(departmentButtons => departmentButtons))
|
||||
{
|
||||
if (button is { Pressed: true, Text: not null })
|
||||
{
|
||||
rolesList.Add(button.Text);
|
||||
}
|
||||
}
|
||||
|
||||
if (rolesList.Count == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
<Control HorizontalExpand="True"/>
|
||||
<Label Name="Count" Access="Public"/>
|
||||
<Control HorizontalExpand="True"/>
|
||||
<Button Name="ExportLogs" Access="Public" Text="{Loc admin-logs-export}"/>
|
||||
<Button Name="PopOutButton" Access="Public" Text="{Loc admin-logs-pop-out}"/>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Content.Client.Administration.UI.CustomControls;
|
||||
using Content.Client.Eui;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Eui;
|
||||
|
|
@ -15,6 +17,16 @@ public sealed class AdminLogsEui : BaseEui
|
|||
{
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||
[Dependency] private readonly IFileDialogManager _dialogManager = default!;
|
||||
[Dependency] private readonly ILogManager _log = default!;
|
||||
|
||||
private const char CsvSeparator = ',';
|
||||
private const string CsvQuote = "\"";
|
||||
private const string CsvHeader = "Date,ID,PlayerID,Severity,Type,Message";
|
||||
|
||||
private ISawmill _sawmill;
|
||||
|
||||
private bool _currentlyExportingLogs = false;
|
||||
|
||||
public AdminLogsEui()
|
||||
{
|
||||
|
|
@ -26,6 +38,9 @@ public sealed class AdminLogsEui : BaseEui
|
|||
LogsControl.RefreshButton.OnPressed += _ => RequestLogs();
|
||||
LogsControl.NextButton.OnPressed += _ => NextLogs();
|
||||
LogsControl.PopOutButton.OnPressed += _ => PopOut();
|
||||
LogsControl.ExportLogs.OnPressed += _ => ExportLogs();
|
||||
|
||||
_sawmill = _log.GetSawmill("admin.logs.ui");
|
||||
}
|
||||
|
||||
private WindowRoot? Root { get; set; }
|
||||
|
|
@ -74,6 +89,71 @@ public sealed class AdminLogsEui : BaseEui
|
|||
SendMessage(request);
|
||||
}
|
||||
|
||||
private async void ExportLogs()
|
||||
{
|
||||
if (_currentlyExportingLogs)
|
||||
return;
|
||||
|
||||
_currentlyExportingLogs = true;
|
||||
LogsControl.ExportLogs.Disabled = true;
|
||||
|
||||
var file = await _dialogManager.SaveFile(new FileDialogFilters(new FileDialogFilters.Group("csv")));
|
||||
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Buffer is set to 4KB for performance reasons. As the average export of 1000 logs is ~200KB
|
||||
await using var writer = new StreamWriter(file.Value.fileStream, bufferSize: 4096);
|
||||
await writer.WriteLineAsync(CsvHeader);
|
||||
foreach (var child in LogsControl.LogsContainer.Children)
|
||||
{
|
||||
if (child is not AdminLogLabel logLabel || !child.Visible)
|
||||
continue;
|
||||
|
||||
var log = logLabel.Log;
|
||||
|
||||
// Date
|
||||
// I swear to god if someone adds ,s or "s to the other fields...
|
||||
await writer.WriteAsync(log.Date.ToString("s", System.Globalization.CultureInfo.InvariantCulture));
|
||||
await writer.WriteAsync(CsvSeparator);
|
||||
// ID
|
||||
await writer.WriteAsync(log.Id.ToString());
|
||||
await writer.WriteAsync(CsvSeparator);
|
||||
// PlayerID
|
||||
var players = log.Players;
|
||||
for (var i = 0; i < players.Length; i++)
|
||||
{
|
||||
await writer.WriteAsync(players[i] + (i == players.Length - 1 ? "" : " "));
|
||||
}
|
||||
await writer.WriteAsync(CsvSeparator);
|
||||
// Severity
|
||||
await writer.WriteAsync(log.Impact.ToString());
|
||||
await writer.WriteAsync(CsvSeparator);
|
||||
// Type
|
||||
await writer.WriteAsync(log.Type.ToString());
|
||||
await writer.WriteAsync(CsvSeparator);
|
||||
// Message
|
||||
await writer.WriteAsync(CsvQuote);
|
||||
await writer.WriteAsync(log.Message.Replace(CsvQuote, CsvQuote + CsvQuote));
|
||||
await writer.WriteAsync(CsvQuote);
|
||||
|
||||
await writer.WriteLineAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
_sawmill.Error($"Error when exporting admin log:\n{exc.StackTrace}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await file.Value.fileStream.DisposeAsync();
|
||||
_currentlyExportingLogs = false;
|
||||
LogsControl.ExportLogs.Disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void PopOut()
|
||||
{
|
||||
if (LogsWindow == null)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,21 @@
|
|||
<OptionButton Name="SolutionOption" HorizontalExpand="True"/>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 4">
|
||||
<Button Name="VVButton"
|
||||
Text="{Loc 'admin-solutions-window-vv-button'}"
|
||||
ToolTip="{Loc 'admin-solutions-window-vv-button-tooltip'}"
|
||||
Disabled="True"
|
||||
HorizontalExpand="True"
|
||||
StyleClasses="OpenRight"/>
|
||||
<Button Name="SolutionButton"
|
||||
Text="{Loc 'admin-solutions-window-solution-button'}"
|
||||
ToolTip="{Loc 'admin-solutions-window-solution-button-tooltip'}"
|
||||
Disabled="True"
|
||||
HorizontalExpand="True"
|
||||
StyleClasses="OpenLeft"/>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- The total volume / capacity of the solution -->
|
||||
<BoxContainer Name="VolumeBox" Orientation="Vertical" HorizontalExpand="True" Margin="0 4"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Client.Administration.Managers;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
|
|
@ -21,6 +22,7 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
|||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IClientGameTiming _timing = default!;
|
||||
[Dependency] private readonly IClientAdminManager _admin = default!;
|
||||
|
||||
private NetEntity _target = NetEntity.Invalid;
|
||||
private string? _selectedSolution;
|
||||
|
|
@ -35,6 +37,11 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
|||
|
||||
SolutionOption.OnItemSelected += SolutionSelected;
|
||||
AddButton.OnPressed += OpenAddReagentWindow;
|
||||
VVButton.OnPressed += OpenVVWindow;
|
||||
SolutionButton.OnPressed += OpenSolutionWindow;
|
||||
|
||||
VVButton.Disabled = !_admin.CanViewVar();
|
||||
SolutionButton.Disabled = !_admin.CanViewVar();
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
|
|
@ -275,6 +282,32 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
|||
_addReagentWindow.OpenCentered();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the corresponding solution entity in a ViewVariables window.
|
||||
/// </summary>
|
||||
private void OpenVVWindow(BaseButton.ButtonEventArgs obj)
|
||||
{
|
||||
if (_solutions == null
|
||||
|| _selectedSolution == null
|
||||
|| !_solutions.TryGetValue(_selectedSolution, out var uid)
|
||||
|| !_entityManager.TryGetNetEntity(uid, out var netEntity))
|
||||
return;
|
||||
_consoleHost.ExecuteCommand($"vv {netEntity}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the corresponding Solution instance in a ViewVariables window.
|
||||
/// </summary>
|
||||
private void OpenSolutionWindow(BaseButton.ButtonEventArgs obj)
|
||||
{
|
||||
if (_solutions == null
|
||||
|| _selectedSolution == null
|
||||
|| !_solutions.TryGetValue(_selectedSolution, out var uid)
|
||||
|| !_entityManager.TryGetNetEntity(uid, out var netEntity))
|
||||
return;
|
||||
_consoleHost.ExecuteCommand($"vv /entity/{netEntity}/Solution/Solution");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a new solution is selected, set _selectedSolution and update the reagent list.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
<Button Name="FreezeAndMuteToggleButton" Text="{Loc player-panel-freeze-and-mute}" Disabled="True"/>
|
||||
<Button Name="BanButton" Text="{Loc player-panel-ban}" Disabled="True"/>
|
||||
<controls:ConfirmButton Name="RejuvenateButton" Text="{Loc player-panel-rejuvenate}" Disabled="True"/>
|
||||
<Button Name="CameraButton" Text="{Loc player-panel-camera}" Disabled="True"/>
|
||||
</GridContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ public sealed partial class PlayerPanel : FancyWindow
|
|||
public event Action<NetUserId?>? OnOpenBans;
|
||||
public event Action<NetUserId?>? OnAhelp;
|
||||
public event Action<string?>? OnKick;
|
||||
public event Action<string?>? OnCamera;
|
||||
public event Action<NetUserId?>? OnOpenBanPanel;
|
||||
public event Action<NetUserId?, bool>? OnWhitelistToggle;
|
||||
public event Action? OnFollow;
|
||||
|
|
@ -33,26 +34,27 @@ public sealed partial class PlayerPanel : FancyWindow
|
|||
|
||||
public PlayerPanel(IClientAdminManager adminManager)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_adminManager = adminManager;
|
||||
RobustXamlLoader.Load(this);
|
||||
_adminManager = adminManager;
|
||||
|
||||
UsernameCopyButton.OnPressed += _ => OnUsernameCopy?.Invoke(TargetUsername ?? "");
|
||||
BanButton.OnPressed += _ => OnOpenBanPanel?.Invoke(TargetPlayer);
|
||||
KickButton.OnPressed += _ => OnKick?.Invoke(TargetUsername);
|
||||
NotesButton.OnPressed += _ => OnOpenNotes?.Invoke(TargetPlayer);
|
||||
ShowBansButton.OnPressed += _ => OnOpenBans?.Invoke(TargetPlayer);
|
||||
AhelpButton.OnPressed += _ => OnAhelp?.Invoke(TargetPlayer);
|
||||
WhitelistToggle.OnPressed += _ =>
|
||||
{
|
||||
OnWhitelistToggle?.Invoke(TargetPlayer, _isWhitelisted);
|
||||
SetWhitelisted(!_isWhitelisted);
|
||||
};
|
||||
FollowButton.OnPressed += _ => OnFollow?.Invoke();
|
||||
FreezeButton.OnPressed += _ => OnFreeze?.Invoke();
|
||||
FreezeAndMuteToggleButton.OnPressed += _ => OnFreezeAndMuteToggle?.Invoke();
|
||||
LogsButton.OnPressed += _ => OnLogs?.Invoke();
|
||||
DeleteButton.OnPressed += _ => OnDelete?.Invoke();
|
||||
RejuvenateButton.OnPressed += _ => OnRejuvenate?.Invoke();
|
||||
UsernameCopyButton.OnPressed += _ => OnUsernameCopy?.Invoke(TargetUsername ?? "");
|
||||
BanButton.OnPressed += _ => OnOpenBanPanel?.Invoke(TargetPlayer);
|
||||
KickButton.OnPressed += _ => OnKick?.Invoke(TargetUsername);
|
||||
CameraButton.OnPressed += _ => OnCamera?.Invoke(TargetUsername);
|
||||
NotesButton.OnPressed += _ => OnOpenNotes?.Invoke(TargetPlayer);
|
||||
ShowBansButton.OnPressed += _ => OnOpenBans?.Invoke(TargetPlayer);
|
||||
AhelpButton.OnPressed += _ => OnAhelp?.Invoke(TargetPlayer);
|
||||
WhitelistToggle.OnPressed += _ =>
|
||||
{
|
||||
OnWhitelistToggle?.Invoke(TargetPlayer, _isWhitelisted);
|
||||
SetWhitelisted(!_isWhitelisted);
|
||||
};
|
||||
FollowButton.OnPressed += _ => OnFollow?.Invoke();
|
||||
FreezeButton.OnPressed += _ => OnFreeze?.Invoke();
|
||||
FreezeAndMuteToggleButton.OnPressed += _ => OnFreezeAndMuteToggle?.Invoke();
|
||||
LogsButton.OnPressed += _ => OnLogs?.Invoke();
|
||||
DeleteButton.OnPressed += _ => OnDelete?.Invoke();
|
||||
RejuvenateButton.OnPressed += _ => OnRejuvenate?.Invoke();
|
||||
}
|
||||
|
||||
public void SetUsername(string player)
|
||||
|
|
@ -122,6 +124,7 @@ public sealed partial class PlayerPanel : FancyWindow
|
|||
{
|
||||
BanButton.Disabled = !_adminManager.CanCommand("banpanel");
|
||||
KickButton.Disabled = !_adminManager.CanCommand("kick");
|
||||
CameraButton.Disabled = !_adminManager.CanCommand("camera");
|
||||
NotesButton.Disabled = !_adminManager.CanCommand("adminnotes");
|
||||
ShowBansButton.Disabled = !_adminManager.CanCommand("banlist");
|
||||
WhitelistToggle.Disabled =
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public sealed class PlayerPanelEui : BaseEui
|
|||
[Dependency] private readonly IClientAdminManager _admin = default!;
|
||||
[Dependency] private readonly IClipboardManager _clipboard = default!;
|
||||
|
||||
private PlayerPanel PlayerPanel { get; }
|
||||
private PlayerPanel PlayerPanel { get; }
|
||||
|
||||
public PlayerPanelEui()
|
||||
{
|
||||
|
|
@ -25,6 +25,7 @@ public sealed class PlayerPanelEui : BaseEui
|
|||
PlayerPanel.OnOpenNotes += id => _console.ExecuteCommand($"adminnotes \"{id}\"");
|
||||
// Kick command does not support GUIDs
|
||||
PlayerPanel.OnKick += username => _console.ExecuteCommand($"kick \"{username}\"");
|
||||
PlayerPanel.OnCamera += username => _console.ExecuteCommand($"camera \"{username}\"");
|
||||
PlayerPanel.OnOpenBanPanel += id => _console.ExecuteCommand($"banpanel \"{id}\"");
|
||||
PlayerPanel.OnOpenBans += id => _console.ExecuteCommand($"banlist \"{id}\"");
|
||||
PlayerPanel.OnAhelp += id => _console.ExecuteCommand($"openahelp \"{id}\"");
|
||||
|
|
@ -37,7 +38,7 @@ public sealed class PlayerPanelEui : BaseEui
|
|||
PlayerPanel.OnFreeze += () => SendMessage(new PlayerPanelFreezeMessage());
|
||||
PlayerPanel.OnLogs += () => SendMessage(new PlayerPanelLogsMessage());
|
||||
PlayerPanel.OnRejuvenate += () => SendMessage(new PlayerPanelRejuvenationMessage());
|
||||
PlayerPanel.OnDelete+= () => SendMessage(new PlayerPanelDeleteMessage());
|
||||
PlayerPanel.OnDelete += () => SendMessage(new PlayerPanelDeleteMessage());
|
||||
PlayerPanel.OnFollow += () => SendMessage(new PlayerPanelFollowMessage());
|
||||
|
||||
PlayerPanel.OnClose += () => SendMessage(new CloseEuiMessage());
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public sealed partial class ObjectsTab : Control
|
|||
switch (selection)
|
||||
{
|
||||
case ObjectsTabSelection.Stations:
|
||||
entities.AddRange(_entityManager.EntitySysManager.GetEntitySystem<StationSystem>().Stations);
|
||||
entities.AddRange(_entityManager.EntitySysManager.GetEntitySystem<StationSystem>().GetStationNames());
|
||||
break;
|
||||
case ObjectsTabSelection.Grids:
|
||||
{
|
||||
|
|
@ -132,8 +132,8 @@ public sealed partial class ObjectsTab : Control
|
|||
entry.OnTeleport += TeleportTo;
|
||||
entry.OnDelete += Delete;
|
||||
button.ToolTip = $"{info.Name}, {info.Entity}";
|
||||
|
||||
button.AddChild(entry);
|
||||
button.StyleClasses.Clear();
|
||||
}
|
||||
|
||||
private bool DataFilterCondition(string filter, ListData listData)
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ public sealed partial class PlayerTab : Control
|
|||
entry.OnObjectives += GetObjectives; // Sunrise-Edit
|
||||
button.AddChild(entry);
|
||||
button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
|
||||
button.StyleClasses.Clear();
|
||||
}
|
||||
|
||||
// Sunrise-Start
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using Content.Shared.Administration;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||
|
||||
|
|
@ -11,6 +13,7 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
|||
public sealed partial class PlayerTabEntry : PanelContainer
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
public Action<NetEntity?>? OnObjectives; // Sunrise-Edit
|
||||
|
||||
|
|
@ -25,6 +28,8 @@ public sealed partial class PlayerTabEntry : PanelContainer
|
|||
RobustXamlLoader.Load(this);
|
||||
var roles = _entMan.System<SharedRoleSystem>();
|
||||
|
||||
var rolePrototype = player.RoleProto == null ? null : _prototype.Index(player.RoleProto.Value);
|
||||
|
||||
UsernameLabel.Text = player.Username;
|
||||
if (!player.Connected)
|
||||
UsernameLabel.StyleClasses.Add("Disabled");
|
||||
|
|
@ -59,21 +64,21 @@ public sealed partial class PlayerTabEntry : PanelContainer
|
|||
break;
|
||||
default:
|
||||
case AdminPlayerTabSymbolOption.Specific:
|
||||
symbol = player.Antag ? player.RoleProto.Symbol : string.Empty;
|
||||
symbol = player.Antag ? rolePrototype?.Symbol ?? RoleTypePrototype.FallbackSymbol : string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
CharacterLabel.Text = Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", player.CharacterName));
|
||||
|
||||
if (player.Antag && colorAntags)
|
||||
CharacterLabel.FontColorOverride = player.RoleProto.Color;
|
||||
CharacterLabel.FontColorOverride = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor;
|
||||
if (player.IdentityName != player.CharacterName)
|
||||
CharacterLabel.Text += $" [{player.IdentityName}]";
|
||||
|
||||
SponsorLabel.Text = player.IsSponsor ? player.SponsorTitle : ""; // Sunrise-Sponsors
|
||||
|
||||
var roletype = RoleTypeLabel.Text = Loc.GetString(player.RoleProto.Name);
|
||||
var subtype = roles.GetRoleSubtypeLabel(player.RoleProto.Name, player.Subtype);
|
||||
var roletype = RoleTypeLabel.Text = Loc.GetString(rolePrototype?.Name ?? RoleTypePrototype.FallbackName);
|
||||
var subtype = roles.GetRoleSubtypeLabel(rolePrototype?.Name ?? RoleTypePrototype.FallbackName, player.Subtype);
|
||||
switch (roleSetting)
|
||||
{
|
||||
case AdminPlayerTabRoleTypeOption.RoleTypeSubtype:
|
||||
|
|
@ -96,7 +101,7 @@ public sealed partial class PlayerTabEntry : PanelContainer
|
|||
}
|
||||
|
||||
if (colorRoles)
|
||||
RoleTypeLabel.FontColorOverride = player.RoleProto.Color;
|
||||
RoleTypeLabel.FontColorOverride = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor;
|
||||
BackgroundColorPanel.PanelOverride = styleBoxFlat;
|
||||
OverallPlaytimeLabel.Text = player.PlaytimeString;
|
||||
ObjectivesButton.OnPressed += _ => OnObjectives?.Invoke(player.NetEntity); // Sunrise-Edit
|
||||
|
|
|
|||
90
Content.Client/Alerts/GenericCounterAlertSystem.cs
Normal file
90
Content.Client/Alerts/GenericCounterAlertSystem.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System.Numerics;
|
||||
using Content.Shared.Alert.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.Alerts;
|
||||
|
||||
/// <summary>
|
||||
/// This handles <see cref="GenericCounterAlertComponent"/>
|
||||
/// </summary>
|
||||
public sealed class GenericCounterAlertSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<GenericCounterAlertComponent, UpdateAlertSpriteEvent>(OnUpdateAlertSprite);
|
||||
}
|
||||
|
||||
private void OnUpdateAlertSprite(Entity<GenericCounterAlertComponent> ent, ref UpdateAlertSpriteEvent args)
|
||||
{
|
||||
var sprite = args.SpriteViewEnt.Comp;
|
||||
|
||||
var ev = new GetGenericAlertCounterAmountEvent(args.Alert);
|
||||
RaiseLocalEvent(args.ViewerEnt, ref ev);
|
||||
|
||||
if (!ev.Handled)
|
||||
return;
|
||||
|
||||
// It cannot be null if its handled, but good to check to avoid ugly null ignores.
|
||||
if (ev.Amount == null)
|
||||
return;
|
||||
|
||||
// How many digits can we display
|
||||
var maxDigitCount = GetMaxDigitCount((ent, ent, sprite));
|
||||
|
||||
// Clamp it to a positive number that we can actually display in full (no rollover to 0)
|
||||
var amount = (int) Math.Clamp(ev.Amount.Value, 0, Math.Pow(10, maxDigitCount) - 1);
|
||||
|
||||
// This is super wack but ig it works?
|
||||
var digitCount = ent.Comp.HideLeadingZeroes
|
||||
? amount.ToString().Length
|
||||
: maxDigitCount;
|
||||
|
||||
if (ent.Comp.HideLeadingZeroes)
|
||||
{
|
||||
for (var i = 0; i < ent.Comp.DigitKeys.Count; i++)
|
||||
{
|
||||
if (!_sprite.LayerMapTryGet(ent.Owner, ent.Comp.DigitKeys[i], out var layer, false))
|
||||
continue;
|
||||
|
||||
_sprite.LayerSetVisible(ent.Owner, layer, i <= digitCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once PossibleLossOfFraction
|
||||
var baseOffset = (ent.Comp.AlertSize.X - digitCount * ent.Comp.GlyphWidth) / 2 * (1f / EyeManager.PixelsPerMeter);
|
||||
|
||||
for (var i = 0; i < ent.Comp.DigitKeys.Count; i++)
|
||||
{
|
||||
if (!_sprite.LayerMapTryGet(ent.Owner, ent.Comp.DigitKeys[i], out var layer, false))
|
||||
continue;
|
||||
|
||||
var result = amount / (int) Math.Pow(10, i) % 10;
|
||||
_sprite.LayerSetRsiState(ent.Owner, layer, result.ToString());
|
||||
|
||||
if (ent.Comp.CenterGlyph)
|
||||
{
|
||||
var offset = baseOffset + (digitCount - 1 - i) * ent.Comp.GlyphWidth * (1f / EyeManager.PixelsPerMeter);
|
||||
_sprite.LayerSetOffset(ent.Owner, layer, new Vector2(offset, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of digits that we can display.
|
||||
/// </summary>
|
||||
/// <returns>The number of digits.</returns>
|
||||
private int GetMaxDigitCount(Entity<GenericCounterAlertComponent, SpriteComponent> ent)
|
||||
{
|
||||
for (var i = ent.Comp1.DigitKeys.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (_sprite.LayerExists((ent.Owner, ent.Comp2), ent.Comp1.DigitKeys[i]))
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,11 +11,14 @@ public record struct UpdateAlertSpriteEvent
|
|||
{
|
||||
public Entity<SpriteComponent> SpriteViewEnt;
|
||||
|
||||
public EntityUid ViewerEnt;
|
||||
|
||||
public AlertPrototype Alert;
|
||||
|
||||
public UpdateAlertSpriteEvent(Entity<SpriteComponent> spriteViewEnt, AlertPrototype alert)
|
||||
public UpdateAlertSpriteEvent(Entity<SpriteComponent> spriteViewEnt, EntityUid viewerEnt, AlertPrototype alert)
|
||||
{
|
||||
SpriteViewEnt = spriteViewEnt;
|
||||
ViewerEnt = viewerEnt;
|
||||
Alert = alert;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
Content.Client/Animals/Systems/ParrotMemorySystem.cs
Normal file
5
Content.Client/Animals/Systems/ParrotMemorySystem.cs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared.Animals.Systems;
|
||||
|
||||
namespace Content.Client.Animals.Systems;
|
||||
|
||||
public sealed class ParrotMemorySystem : SharedParrotMemorySystem;
|
||||
|
|
@ -62,11 +62,11 @@ public sealed class AnomalySystem : SharedAnomalySystem
|
|||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<AnomalySupercriticalComponent, SpriteComponent>();
|
||||
var query = EntityQueryEnumerator<AnomalyComponent, AnomalySupercriticalComponent, SpriteComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var super, out var sprite))
|
||||
while (query.MoveNext(out var uid, out var anomaly, out var super, out var sprite))
|
||||
{
|
||||
var completion = 1f - (float)((super.EndTime - _timing.CurTime) / super.SupercriticalDuration);
|
||||
var completion = 1f - (float) ((super.EndTime - _timing.CurTime) / anomaly.SupercriticalDuration);
|
||||
var scale = completion * (super.MaxScaleAmount - 1f) + 1f;
|
||||
_sprite.SetScale((uid, sprite), new Vector2(scale, scale));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Effects;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Humanoid;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Anomaly.Effects;
|
||||
|
|
@ -25,9 +25,8 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
|||
|
||||
var index = _sprite.LayerMapReserve((ent.Owner, sprite), ent.Comp.LayerMap);
|
||||
|
||||
if (TryComp<BodyComponent>(ent, out var body) &&
|
||||
body.Prototype is not null &&
|
||||
ent.Comp.SpeciesSprites.TryGetValue(body.Prototype.Value, out var speciesSprite))
|
||||
if (TryComp<HumanoidAppearanceComponent>(ent, out var humanoidAppearance) &&
|
||||
ent.Comp.SpeciesSprites.TryGetValue(humanoidAppearance.Species, out var speciesSprite))
|
||||
{
|
||||
_sprite.LayerSetSprite((ent.Owner, sprite), index, speciesSprite);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,10 +162,10 @@ public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
|
|||
{
|
||||
var list = new List<AtmosMonitoringConsoleLine>();
|
||||
|
||||
foreach (var ((netId, layer, hexColor), atmosPipeData) in chunk.AtmosPipeData)
|
||||
foreach (var ((netId, layer, pipeColor), atmosPipeData) in chunk.AtmosPipeData)
|
||||
{
|
||||
// Determine the correct coloration for the pipe
|
||||
var color = Color.FromHex(hexColor) * _basePipeNetColor;
|
||||
var color = pipeColor * _basePipeNetColor;
|
||||
|
||||
if (FocusNetId != null && FocusNetId != netId)
|
||||
color *= _unfocusedPipeNetColor;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.SprayPainter.Prototypes;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
/// <summary>
|
||||
/// Used to change the appearance of gas canisters.
|
||||
/// </summary>
|
||||
public sealed class GasCanisterAppearanceSystem : VisualizerSystem<GasCanisterComponent>
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, GasCanisterComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!AppearanceSystem.TryGetData<string>(uid, PaintableVisuals.Prototype, out var protoName, args.Component) || args.Sprite is not { } old)
|
||||
return;
|
||||
|
||||
if (!_prototypeManager.HasIndex(protoName))
|
||||
return;
|
||||
|
||||
// Create the given prototype and get its first layer.
|
||||
var tempUid = Spawn(protoName);
|
||||
SpriteSystem.LayerSetRsiState(uid, 0, SpriteSystem.LayerGetRsiState(tempUid, 0));
|
||||
QueueDel(tempUid);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using Content.Shared.Atmos.EntitySystems;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the client system responsible for managing and updating the gas pressure regulator interface.
|
||||
/// Inherits from the shared system <see cref="SharedGasPressureRegulatorSystem"/>.
|
||||
/// </summary>
|
||||
public sealed partial class GasPressureRegulatorSystem : SharedGasPressureRegulatorSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GasPressureRegulatorComponent, AfterAutoHandleStateEvent>(OnValveUpdate);
|
||||
}
|
||||
|
||||
private void OnValveUpdate(Entity<GasPressureRegulatorComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
UpdateUi(ent);
|
||||
}
|
||||
|
||||
protected override void UpdateUi(Entity<GasPressureRegulatorComponent> ent)
|
||||
{
|
||||
if (UserInterfaceSystem.TryGetOpenUi(ent.Owner, GasPressureRegulatorUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2007/xaml"
|
||||
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
MinSize="500 500" Resizable="True" Title="Air Alarm">
|
||||
MinSize="500 500" Resizable="True" Title="{Loc air-alarm-ui-title}">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5">
|
||||
<!-- Status (pressure, temperature, alarm state, device total, address, etc) -->
|
||||
<BoxContainer Orientation="Horizontal" Margin="0 0 0 2">
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public sealed partial class PumpControl : BoxContainer
|
|||
|
||||
foreach (var value in Enum.GetValues<VentPumpDirection>())
|
||||
{
|
||||
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||
_pumpDirection.AddItem(Loc.GetString($"air-alarm-ui-pump-direction-{value.ToString().ToLower()}"), (int) value);
|
||||
}
|
||||
|
||||
_pumpDirection.SelectId((int) _data.PumpDirection);
|
||||
|
|
@ -72,7 +72,7 @@ public sealed partial class PumpControl : BoxContainer
|
|||
|
||||
foreach (var value in Enum.GetValues<VentPressureBound>())
|
||||
{
|
||||
_pressureCheck.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||
_pressureCheck.AddItem(Loc.GetString($"air-alarm-ui-pressure-bound-{value.ToString().ToLower()}"), (int) value);
|
||||
}
|
||||
|
||||
_pressureCheck.SelectId((int) _data.PressureChecks);
|
||||
|
|
|
|||
|
|
@ -27,9 +27,15 @@
|
|||
</BoxContainer>
|
||||
<!-- Lower row: every single gas -->
|
||||
<Collapsible Margin="2 2 2 2">
|
||||
<CollapsibleHeading Title="Gas filters" />
|
||||
<CollapsibleHeading Title="{Loc 'air-alarm-ui-widget-gas-filters'}" />
|
||||
<CollapsibleBody Margin="20 0 0 0">
|
||||
<GridContainer HorizontalExpand="True" Name="CGasContainer" Columns="3" />
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Margin="2">
|
||||
<Button Name="CSelectAll" Text="{Loc 'air-alarm-ui-scrubber-select-all-gases-label'}" />
|
||||
<Button Name="CDeselectAll" Text="{Loc 'air-alarm-ui-scrubber-deselect-all-gases-label'}" />
|
||||
</BoxContainer>
|
||||
<GridContainer Name="CGasContainer" Columns="3" />
|
||||
</BoxContainer>
|
||||
</CollapsibleBody>
|
||||
</Collapsible>
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ScrubberControl : BoxContainer
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
private GasVentScrubberData _data;
|
||||
private string _address;
|
||||
|
||||
|
|
@ -22,12 +28,18 @@ public sealed partial class ScrubberControl : BoxContainer
|
|||
private FloatSpinBox _volumeRate => CVolumeRate;
|
||||
private CheckBox _wideNet => CWideNet;
|
||||
private Button _copySettings => CCopySettings;
|
||||
private Button _selectAll => CSelectAll;
|
||||
private Button _deselectAll => CDeselectAll;
|
||||
|
||||
private GridContainer _gases => CGasContainer;
|
||||
private Dictionary<Gas, Button> _gasControls = new();
|
||||
|
||||
public ScrubberControl(GasVentScrubberData data, string address)
|
||||
{
|
||||
|
||||
IoCManager.InjectDependencies(this);
|
||||
var atmosphereSystem = _entMan.System<SharedAtmosphereSystem>();
|
||||
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
Name = address;
|
||||
|
|
@ -61,7 +73,7 @@ public sealed partial class ScrubberControl : BoxContainer
|
|||
|
||||
foreach (var value in Enum.GetValues<ScrubberPumpDirection>())
|
||||
{
|
||||
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||
_pumpDirection.AddItem(Loc.GetString($"air-alarm-ui-pump-direction-{value.ToString().ToLower()}"), (int) value);
|
||||
}
|
||||
|
||||
_pumpDirection.SelectId((int) _data.PumpDirection);
|
||||
|
|
@ -78,12 +90,28 @@ public sealed partial class ScrubberControl : BoxContainer
|
|||
ScrubberDataCopied?.Invoke(_data);
|
||||
};
|
||||
|
||||
foreach (var value in Enum.GetValues<Gas>())
|
||||
var allGases = Enum.GetValues<Gas>();
|
||||
_selectAll.OnPressed += _ =>
|
||||
{
|
||||
_data.FilterGases = new HashSet<Gas>(allGases);
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
_deselectAll.OnPressed += _ =>
|
||||
{
|
||||
_data.FilterGases = [];
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
foreach (var value in allGases)
|
||||
{
|
||||
ProtoId<GasPrototype> gasProtoId = atmosphereSystem.GetGas(value);
|
||||
var gasName = _prototypeManager.Index(gasProtoId).Name;
|
||||
|
||||
var gasButton = new Button
|
||||
{
|
||||
Name = value.ToString(),
|
||||
Text = Loc.GetString($"{value}"),
|
||||
Text = Loc.GetString(gasName),
|
||||
ToggleMode = true,
|
||||
HorizontalExpand = true,
|
||||
Pressed = _data.FilterGases.Contains(value)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
using Content.Client.Message;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Prototypes;
|
||||
using Content.Shared.Temperature;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SensorInfo : BoxContainer
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
public Action<string, AtmosMonitorThresholdType, AtmosAlarmThreshold, Gas?>? OnThresholdUpdate;
|
||||
public event Action<AtmosSensorData>? SensorDataCopied;
|
||||
private string _address;
|
||||
|
|
@ -23,6 +29,9 @@ public sealed partial class SensorInfo : BoxContainer
|
|||
|
||||
public SensorInfo(AtmosSensorData data, string address)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
var atmosphereSystem = _entMan.System<SharedAtmosphereSystem>();
|
||||
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
_address = address;
|
||||
|
|
@ -45,8 +54,12 @@ public sealed partial class SensorInfo : BoxContainer
|
|||
var label = new RichTextLabel();
|
||||
|
||||
var fractionGas = amount / data.TotalMoles;
|
||||
|
||||
ProtoId<GasPrototype> gasProtoId = atmosphereSystem.GetGas(gas);
|
||||
var gasName = _prototypeManager.Index(gasProtoId).Name;
|
||||
|
||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
||||
("gas", $"{gas}"),
|
||||
("gas", Loc.GetString(gasName)),
|
||||
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
||||
("amount", $"{amount:0.####}"),
|
||||
("percentage", $"{(100 * fractionGas):0.##}")));
|
||||
|
|
@ -54,7 +67,7 @@ public sealed partial class SensorInfo : BoxContainer
|
|||
_gasLabels.Add(gas, label);
|
||||
|
||||
var threshold = data.GasThresholds[gas];
|
||||
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title", ("gas", $"{gas}")), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
|
||||
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title"), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
|
||||
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
|
||||
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
|
||||
{
|
||||
|
|
@ -90,6 +103,9 @@ public sealed partial class SensorInfo : BoxContainer
|
|||
|
||||
public void ChangeData(AtmosSensorData data)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
var atmosphereSystem = _entMan.System<SharedAtmosphereSystem>();
|
||||
|
||||
SensorAddress.Title = Loc.GetString("air-alarm-ui-window-listing-title", ("address", _address), ("state", data.AlarmState));
|
||||
|
||||
AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state-indicator",
|
||||
|
|
@ -112,8 +128,12 @@ public sealed partial class SensorInfo : BoxContainer
|
|||
}
|
||||
|
||||
var fractionGas = amount / data.TotalMoles;
|
||||
|
||||
ProtoId<GasPrototype> gasProtoId = atmosphereSystem.GetGas(gas);
|
||||
var gasName = _prototypeManager.Index(gasProtoId).Name;
|
||||
|
||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
||||
("gas", $"{gas}"),
|
||||
("gas", Loc.GetString(gasName)),
|
||||
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
||||
("amount", $"{amount:0.####}"),
|
||||
("percentage", $"{(100 * fractionGas):0.##}")));
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
HorizontalExpand="True" Orientation="Vertical"
|
||||
Margin = "20 0 0 0" MinSize="160 0" >
|
||||
<Label Name="CBoundLabel" HorizontalAlignment="Center" />
|
||||
<CheckBox Name="CBoundEnabled" HorizontalAlignment="Center" Text="{Loc 'Enable'}" Pressed="True" />
|
||||
<CheckBox Name="CBoundEnabled" HorizontalAlignment="Center" Text="{Loc 'air-alarm-ui-widget-enable'}" Pressed="True" />
|
||||
<FloatSpinBox Name="CSpinner" />
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<CollapsibleBody Margin="20 0 0 0">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<CheckBox Name="CEnabled" Text="{Loc 'Enabled'}" />
|
||||
<CheckBox Name="CEnabled" Text="{Loc 'air-alarm-ui-widget-enable'}" />
|
||||
</BoxContainer>
|
||||
<!-- Upper row: Danger bounds -->
|
||||
<BoxContainer Name="CDangerBounds" Orientation="Horizontal" Margin="0 0 0 2"/>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ namespace Content.Client.Atmos.Overlays
|
|||
{
|
||||
public sealed class GasTileOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> UnshadedShader = "unshaded";
|
||||
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IMapManager _mapManager;
|
||||
private readonly SharedMapSystem _mapSystem;
|
||||
|
|
@ -54,7 +56,7 @@ namespace Content.Client.Atmos.Overlays
|
|||
_mapManager = IoCManager.Resolve<IMapManager>();
|
||||
_mapSystem = entManager.System<SharedMapSystem>();
|
||||
_xformSys = xformSys;
|
||||
_shader = protoMan.Index<ShaderPrototype>("unshaded").Instance();
|
||||
_shader = protoMan.Index(UnshadedShader).Instance();
|
||||
ZIndex = GasOverlayZIndex;
|
||||
|
||||
_gasCount = system.VisibleGasId.Length;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Localizations;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Atmos.UI;
|
||||
|
||||
public sealed class GasPressureRegulatorBoundUserInterface(EntityUid owner, Enum uiKey)
|
||||
: BoundUserInterface(owner, uiKey)
|
||||
{
|
||||
private GasPressureRegulatorWindow? _window;
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = this.CreateWindow<GasPressureRegulatorWindow>();
|
||||
|
||||
_window.SetEntity(Owner);
|
||||
|
||||
_window.ThresholdPressureChanged += OnThresholdChanged;
|
||||
|
||||
if (EntMan.TryGetComponent(Owner, out GasPressureRegulatorComponent? comp))
|
||||
_window.SetThresholdPressureInput(comp.Threshold);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (_window == null)
|
||||
return;
|
||||
|
||||
_window.Title = Identity.Name(Owner, EntMan);
|
||||
|
||||
if (!EntMan.TryGetComponent(Owner, out GasPressureRegulatorComponent? comp))
|
||||
return;
|
||||
|
||||
_window.SetThresholdPressureLabel(comp.Threshold);
|
||||
_window.UpdateInfo(comp.InletPressure, comp.OutletPressure, comp.FlowRate);
|
||||
}
|
||||
|
||||
private void OnThresholdChanged(string newThreshold)
|
||||
{
|
||||
var sentThreshold = 0f;
|
||||
|
||||
if (UserInputParser.TryFloat(newThreshold, out var parsedNewThreshold) && parsedNewThreshold >= 0 &&
|
||||
!float.IsInfinity(parsedNewThreshold))
|
||||
{
|
||||
sentThreshold = parsedNewThreshold;
|
||||
}
|
||||
|
||||
// Autofill to zero if the user inputs an invalid value.
|
||||
_window?.SetThresholdPressureInput(sentThreshold);
|
||||
|
||||
SendPredictedMessage(new GasPressureRegulatorChangeThresholdMessage(sentThreshold));
|
||||
}
|
||||
}
|
||||
96
Content.Client/Atmos/UI/GasPressureRegulatorWindow.xaml
Normal file
96
Content.Client/Atmos/UI/GasPressureRegulatorWindow.xaml
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
SetSize="345 380"
|
||||
MinSize="345 380"
|
||||
Title="{Loc gas-pressure-regulator-ui-title}"
|
||||
Resizable="False">
|
||||
|
||||
<BoxContainer Orientation="Vertical">
|
||||
|
||||
<BoxContainer Orientation="Vertical" Margin="0 10 0 10">
|
||||
|
||||
<BoxContainer Orientation="Vertical" Align="Center">
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-outlet}" Align="Center" StyleClasses="LabelKeyText" />
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Label Name="OutletPressureLabel" Text="N/A" Margin="0 0 4 0" />
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-pressure-unit}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Orientation="Horizontal" Align="Center">
|
||||
<BoxContainer Orientation="Vertical" Align="Center" HorizontalExpand="True">
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-target}" Align="Right" StyleClasses="LabelKeyText" />
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Label Name="TargetPressureLabel" Margin="0 0 4 0" />
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-pressure-unit}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<ProgressBar Name="ToTargetBar" MaxValue="1" SetSize="5 75" Margin="10" Vertical="True" />
|
||||
|
||||
<SpriteView Name="EntityView" SetSize="64 64" Scale="3 3" OverrideDirection="North" Margin="0" />
|
||||
|
||||
<ProgressBar Name="FlowRateBar" MaxValue="1" SetSize="5 75" Margin="10" Vertical="True" />
|
||||
|
||||
<BoxContainer Orientation="Vertical" Align="Center" HorizontalExpand="True">
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-flow}" StyleClasses="LabelKeyText" />
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Name="CurrentFlowLabel" Text="N/A" Margin="0 0 4 0" />
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-flow-rate-unit}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Orientation="Vertical" Align="Center" Margin="1">
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-inlet}" Align="Center" StyleClasses="LabelKeyText" />
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Label Name="InletPressureLabel" Text="N/A" Margin="0 0 4 0" />
|
||||
<Label Text="{Loc gas-pressure-regulator-ui-pressure-unit}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Controls to Set Pressure -->
|
||||
<controls:StripeBack Name="SetPressureStripeBack" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="10 10 10 10">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<LineEdit Name="ThresholdInput" HorizontalExpand="True" MinSize="70 0" />
|
||||
<Button Name="SetThresholdButton" Text="{Loc gas-pressure-regulator-ui-set-threshold}"
|
||||
Disabled="True" Margin="5 0 0 0" />
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 5 0 0">
|
||||
<Button Name="Subtract1000Button" Text="{Loc gas-pressure-regulator-ui-subtract-1000}"
|
||||
HorizontalExpand="True" Margin="0 2 2 0"
|
||||
StyleClasses="OpenBoth" />
|
||||
<Button Name="Subtract100Button" Text="{Loc gas-pressure-regulator-ui-subtract-100}"
|
||||
HorizontalExpand="True" Margin="0 2 2 0"
|
||||
StyleClasses="OpenBoth" />
|
||||
<Button Name="Subtract10Button" Text="{Loc gas-pressure-regulator-ui-subtract-10}"
|
||||
HorizontalExpand="True" Margin="0 2 2 0"
|
||||
StyleClasses="OpenBoth" />
|
||||
<Button Name="Add10Button" Text="{Loc gas-pressure-regulator-ui-add-10}" HorizontalExpand="True"
|
||||
Margin="0 2 2 0"
|
||||
StyleClasses="OpenBoth" />
|
||||
<Button Name="Add100Button" Text="{Loc gas-pressure-regulator-ui-add-100}"
|
||||
HorizontalExpand="True" Margin="0 2 2 0"
|
||||
StyleClasses="OpenBoth" />
|
||||
<Button Name="Add1000Button" Text="{Loc gas-pressure-regulator-ui-add-1000}"
|
||||
HorizontalExpand="True" Margin="0 2 2 0"
|
||||
StyleClasses="OpenBoth" />
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 5 0 0">
|
||||
<Button Name="ZeroThresholdButton" Text="{Loc gas-pressure-regulator-ui-zero-threshold}"
|
||||
HorizontalExpand="True" Margin="0 0 5 0" />
|
||||
<Button Name="SetToCurrentPressureButton"
|
||||
Text="{Loc gas-pressure-regulator-ui-set-to-current-pressure}" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:StripeBack>
|
||||
|
||||
</BoxContainer>
|
||||
|
||||
</controls:FancyWindow>
|
||||
129
Content.Client/Atmos/UI/GasPressureRegulatorWindow.xaml.cs
Normal file
129
Content.Client/Atmos/UI/GasPressureRegulatorWindow.xaml.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
using System.Globalization;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Atmos.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Client-side UI for controlling a pressure regulator.
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasPressureRegulatorWindow : FancyWindow
|
||||
{
|
||||
private float _flowRate;
|
||||
|
||||
public GasPressureRegulatorWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
ThresholdInput.OnTextChanged += _ => SetThresholdButton.Disabled = false;
|
||||
SetThresholdButton.OnPressed += _ =>
|
||||
{
|
||||
ThresholdPressureChanged?.Invoke(ThresholdInput.Text ??= "");
|
||||
SetThresholdButton.Disabled = true;
|
||||
};
|
||||
|
||||
SetToCurrentPressureButton.OnPressed += _ =>
|
||||
{
|
||||
if (InletPressureLabel.Text != null)
|
||||
{
|
||||
ThresholdInput.Text = InletPressureLabel.Text;
|
||||
}
|
||||
|
||||
SetThresholdButton.Disabled = false;
|
||||
};
|
||||
|
||||
ZeroThresholdButton.OnPressed += _ =>
|
||||
{
|
||||
ThresholdInput.Text = "0";
|
||||
SetThresholdButton.Disabled = false;
|
||||
};
|
||||
|
||||
Add1000Button.OnPressed += _ => AdjustThreshold(1000);
|
||||
Add100Button.OnPressed += _ => AdjustThreshold(100);
|
||||
Add10Button.OnPressed += _ => AdjustThreshold(10);
|
||||
Subtract10Button.OnPressed += _ => AdjustThreshold(-10);
|
||||
Subtract100Button.OnPressed += _ => AdjustThreshold(-100);
|
||||
Subtract1000Button.OnPressed += _ => AdjustThreshold(-1000);
|
||||
return;
|
||||
|
||||
void AdjustThreshold(float adjustment)
|
||||
{
|
||||
if (float.TryParse(ThresholdInput.Text, out var currentValue))
|
||||
{
|
||||
ThresholdInput.Text = (currentValue + adjustment).ToString(CultureInfo.CurrentCulture);
|
||||
SetThresholdButton.Disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<string>? ThresholdPressureChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current threshold pressure label. This is not setting the threshold input box.
|
||||
/// </summary>
|
||||
/// <param name="threshold"> Threshold to set.</param>
|
||||
public void SetThresholdPressureLabel(float threshold)
|
||||
{
|
||||
TargetPressureLabel.Text = threshold.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the threshold pressure input field with the given value.
|
||||
/// When the client opens the UI the field will be autofilled with the current threshold pressure.
|
||||
/// </summary>
|
||||
/// <param name="input">The threshold pressure value to autofill into the input field.</param>
|
||||
public void SetThresholdPressureInput(float input)
|
||||
{
|
||||
ThresholdInput.Text = input.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the entity to be visible in the UI.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public void SetEntity(EntityUid entity)
|
||||
{
|
||||
EntityView.SetEntity(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the UI for the labels.
|
||||
/// </summary>
|
||||
/// <param name="inletPressure">The current pressure at the valve's inlet.</param>
|
||||
/// <param name="outletPressure">The current pressure at the valve's outlet.</param>
|
||||
/// <param name="flowRate">The current flow rate through the valve.</param>
|
||||
public void UpdateInfo(float inletPressure, float outletPressure, float flowRate)
|
||||
{
|
||||
if (float.TryParse(TargetPressureLabel.Text, out var parsedfloat))
|
||||
ToTargetBar.Value = inletPressure / parsedfloat;
|
||||
|
||||
InletPressureLabel.Text = float.Round(inletPressure).ToString(CultureInfo.CurrentCulture);
|
||||
OutletPressureLabel.Text = float.Round(outletPressure).ToString(CultureInfo.CurrentCulture);
|
||||
CurrentFlowLabel.Text = float.IsNaN(flowRate) ? "0" : flowRate.ToString(CultureInfo.CurrentCulture);
|
||||
_flowRate = flowRate;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
// Defines the flow rate at which the progress bar fills in one second.
|
||||
// If the flow rate is >50 L/s, the bar will take <1 second to fill.
|
||||
// If the flow rate is <50 L/s, the bar will take >1 second to fill.
|
||||
const int barFillPerSecond = 50;
|
||||
|
||||
var maxValue = FlowRateBar.MaxValue;
|
||||
|
||||
// Increment the progress bar value based on elapsed time
|
||||
FlowRateBar.Value += (_flowRate / barFillPerSecond) * args.DeltaSeconds;
|
||||
|
||||
// Reset the progress bar when it is fully filled
|
||||
if (FlowRateBar.Value >= maxValue)
|
||||
{
|
||||
FlowRateBar.Value = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,16 +2,16 @@ using Robust.Shared.Console;
|
|||
|
||||
namespace Content.Client.Audio;
|
||||
|
||||
public sealed class AmbientOverlayCommand : IConsoleCommand
|
||||
public sealed class AmbientOverlayCommand : LocalizedEntityCommands
|
||||
{
|
||||
public string Command => "showambient";
|
||||
public string Description => "Shows all AmbientSoundComponents in the viewport";
|
||||
public string Help => $"{Command}";
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var system = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AmbientSoundSystem>();
|
||||
system.OverlayEnabled ^= true;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
|
||||
|
||||
shell.WriteLine($"Ambient sound overlay set to {system.OverlayEnabled}");
|
||||
public override string Command => "showambient";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
_ambient.OverlayEnabled ^= true;
|
||||
|
||||
shell.WriteLine(Loc.GetString($"cmd-showambient-status", ("status", _ambient.OverlayEnabled)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem
|
|||
_targetTime = _gameTiming.CurTime + TimeSpan.FromSeconds(_cooldown);
|
||||
|
||||
var player = _playerManager.LocalEntity;
|
||||
if (!EntityManager.TryGetComponent(player, out TransformComponent? xform))
|
||||
if (!TryComp(player, out TransformComponent? xform))
|
||||
{
|
||||
ClearSounds();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
using Content.Shared.Bed;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Bed;
|
||||
|
||||
public sealed class StasisBedSystem : VisualizerSystem<StasisBedVisualsComponent>
|
||||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, StasisBedVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite != null
|
||||
&& AppearanceSystem.TryGetData<bool>(uid, StasisBedVisuals.IsOn, out var isOn, args.Component))
|
||||
{
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), StasisBedVisualLayers.IsOn, isOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum StasisBedVisualLayers : byte
|
||||
{
|
||||
IsOn,
|
||||
}
|
||||
5
Content.Client/Body/Systems/BloodStreamSystem.cs
Normal file
5
Content.Client/Body/Systems/BloodStreamSystem.cs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared.Body.Systems;
|
||||
|
||||
namespace Content.Client.Body.Systems;
|
||||
|
||||
public sealed class BloodstreamSystem : SharedBloodstreamSystem;
|
||||
6
Content.Client/Body/Systems/MetabolizerSystem.cs
Normal file
6
Content.Client/Body/Systems/MetabolizerSystem.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
using Content.Shared.Body.Systems;
|
||||
|
||||
namespace Content.Client.Body.Systems;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed class MetabolizerSystem : SharedMetabolizerSystem;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Numerics;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.CardboardBox;
|
||||
using Content.Shared.CardboardBox.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
|
|
@ -15,13 +15,13 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
private EntityQuery<BodyComponent> _bodyQuery;
|
||||
private EntityQuery<MobStateComponent> _mobStateQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_bodyQuery = GetEntityQuery<BodyComponent>();
|
||||
_mobStateQuery = GetEntityQuery<MobStateComponent>();
|
||||
|
||||
SubscribeNetworkEvent<PlayBoxEffectMessage>(OnBoxEffect);
|
||||
}
|
||||
|
|
@ -66,8 +66,8 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||
if (!_examine.InRangeUnOccluded(sourcePos, mapPos, box.Distance, null))
|
||||
continue;
|
||||
|
||||
// no effect for anything too exotic
|
||||
if (!_bodyQuery.HasComp(mob))
|
||||
// no effect for non-mobs that have MobMover, such as mechs and vehicles.
|
||||
if (!_mobStateQuery.HasComp(mob))
|
||||
continue;
|
||||
|
||||
var ent = Spawn(box.Effect, mapPos);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
using Content.Shared.Changeling.Transform;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Changeling.Transform;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||
{
|
||||
private ChangelingTransformMenu? _window;
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = this.CreateWindow<ChangelingTransformMenu>();
|
||||
|
||||
_window.OnIdentitySelect += SendIdentitySelect;
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (state is not ChangelingTransformBoundUserInterfaceState current)
|
||||
return;
|
||||
|
||||
_window?.UpdateState(current);
|
||||
}
|
||||
|
||||
public void SendIdentitySelect(NetEntity identityId)
|
||||
{
|
||||
SendPredictedMessage(new ChangelingTransformIdentitySelectMessage(identityId));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<ui:RadialMenu
|
||||
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
CloseButtonStyleClass="RadialMenuCloseButton"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True">
|
||||
<ui:RadialContainer Name="Main">
|
||||
</ui:RadialContainer>
|
||||
</ui:RadialMenu>
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Changeling.Transform;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Changeling.Transform;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ChangelingTransformMenu : RadialMenu
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
public event Action<NetEntity>? OnIdentitySelect;
|
||||
|
||||
public ChangelingTransformMenu()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
public void UpdateState(ChangelingTransformBoundUserInterfaceState state)
|
||||
{
|
||||
Main.DisposeAllChildren();
|
||||
foreach (var identity in state.Identites)
|
||||
{
|
||||
var identityUid = _entity.GetEntity(identity);
|
||||
|
||||
if (!_entity.TryGetComponent<MetaDataComponent>(identityUid, out var metadata))
|
||||
continue;
|
||||
|
||||
var identityName = metadata.EntityName;
|
||||
|
||||
var button = new ChangelingTransformMenuButton()
|
||||
{
|
||||
StyleClasses = { "RadialMenuButton" },
|
||||
SetSize = new Vector2(64, 64),
|
||||
ToolTip = identityName,
|
||||
};
|
||||
|
||||
var entView = new SpriteView()
|
||||
{
|
||||
SetSize = new Vector2(48, 48),
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
Stretch = SpriteView.StretchMode.Fill,
|
||||
};
|
||||
entView.SetEntity(identityUid);
|
||||
button.OnButtonUp += _ =>
|
||||
{
|
||||
OnIdentitySelect?.Invoke(identity);
|
||||
Close();
|
||||
};
|
||||
button.AddChild(entView);
|
||||
Main.AddChild(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ChangelingTransformMenuButton : RadialMenuTextureButtonWithSector;
|
||||
|
|
@ -15,8 +15,8 @@ namespace Content.Client.Changelog
|
|||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ChangelogWindow : FancyWindow
|
||||
{
|
||||
[Dependency] private readonly ChangelogManager _changelog = default!;
|
||||
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly ChangelogManager _changelog = default!;
|
||||
|
||||
public ChangelogWindow()
|
||||
{
|
||||
|
|
@ -112,15 +112,15 @@ namespace Content.Client.Changelog
|
|||
}
|
||||
|
||||
[UsedImplicitly, AnyCommand]
|
||||
public sealed class ChangelogCommand : IConsoleCommand
|
||||
public sealed class ChangelogCommand : LocalizedCommands
|
||||
{
|
||||
public string Command => "changelog";
|
||||
public string Description => "Opens the changelog";
|
||||
public string Help => "Usage: changelog";
|
||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
public override string Command => "changelog";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IUserInterfaceManager>().GetUIController<ChangelogUIController>().OpenWindow();
|
||||
_uiManager.GetUIController<ChangelogUIController>().OpenWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,10 @@ public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
|||
{
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
|
||||
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||
private const string DefaultMixingCategory = "DummyMix";
|
||||
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||
private const string DefaultGrindCategory = "DummyGrind";
|
||||
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||
private const string DefaultJuiceCategory = "DummyJuice";
|
||||
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||
private const string DefaultCondenseCategory = "DummyCondense";
|
||||
private static readonly ProtoId<MixingCategoryPrototype> DefaultMixingCategory = "DummyMix";
|
||||
private static readonly ProtoId<MixingCategoryPrototype> DefaultGrindCategory = "DummyGrind";
|
||||
private static readonly ProtoId<MixingCategoryPrototype> DefaultJuiceCategory = "DummyJuice";
|
||||
private static readonly ProtoId<MixingCategoryPrototype> DefaultCondenseCategory = "DummyCondense";
|
||||
|
||||
private readonly Dictionary<string, List<ReagentSourceData>> _reagentSources = new();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ using Content.Shared.Chemistry.EntitySystems;
|
|||
|
||||
namespace Content.Client.Chemistry.EntitySystems;
|
||||
|
||||
public sealed class HypospraySystem : SharedHypospraySystem
|
||||
public sealed class HyposprayStatusControlSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainers = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
5
Content.Client/Cloning/CloningSystem.cs
Normal file
5
Content.Client/Cloning/CloningSystem.cs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared.Cloning;
|
||||
|
||||
namespace Content.Client.Cloning;
|
||||
|
||||
public sealed partial class CloningSystem : SharedCloningSystem;
|
||||
|
|
@ -67,7 +67,7 @@ public sealed class ClientClothingSystem : ClothingSystem
|
|||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ClothingComponent, GetEquipmentVisualsEvent>(OnGetVisuals);
|
||||
SubscribeLocalEvent<ClothingComponent, InventoryTemplateUpdated>(OnInventoryTemplateUpdated);
|
||||
SubscribeLocalEvent<InventoryComponent, InventoryTemplateUpdated>(OnInventoryTemplateUpdated);
|
||||
|
||||
SubscribeLocalEvent<InventoryComponent, VisualsChangedEvent>(OnVisualsChanged);
|
||||
SubscribeLocalEvent<SpriteComponent, DidUnequipEvent>(OnDidUnequip);
|
||||
|
|
@ -90,20 +90,19 @@ public sealed class ClientClothingSystem : ClothingSystem
|
|||
}
|
||||
}
|
||||
|
||||
private void OnInventoryTemplateUpdated(Entity<ClothingComponent> ent, ref InventoryTemplateUpdated args)
|
||||
private void OnInventoryTemplateUpdated(Entity<InventoryComponent> ent, ref InventoryTemplateUpdated args)
|
||||
{
|
||||
UpdateAllSlots(ent.Owner, clothing: ent.Comp);
|
||||
UpdateAllSlots(ent.Owner, ent.Comp);
|
||||
}
|
||||
|
||||
private void UpdateAllSlots(
|
||||
EntityUid uid,
|
||||
InventoryComponent? inventoryComponent = null,
|
||||
ClothingComponent? clothing = null)
|
||||
InventoryComponent? inventoryComponent = null)
|
||||
{
|
||||
var enumerator = _inventorySystem.GetSlotEnumerator((uid, inventoryComponent));
|
||||
while (enumerator.NextItem(out var item, out var slot))
|
||||
{
|
||||
RenderEquipment(uid, item, slot.Name, inventoryComponent, clothingComponent: clothing);
|
||||
RenderEquipment(uid, item, slot.Name, inventoryComponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ namespace Content.Client.CombatMode
|
|||
{
|
||||
public sealed class ColoredScreenBorderOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> Shader = "ColoredScreenBorder";
|
||||
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
|
@ -16,7 +18,7 @@ namespace Content.Client.CombatMode
|
|||
public ColoredScreenBorderOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("ColoredScreenBorder").Instance();
|
||||
_shader = _prototypeManager.Index(Shader).Instance();
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
|
|
|
|||
|
|
@ -1,53 +1,42 @@
|
|||
using Content.Client.Markers;
|
||||
using Content.Client.Popups;
|
||||
using Content.Client.SubFloor;
|
||||
using Content.Shared.SubFloor;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Console;
|
||||
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
|
||||
|
||||
namespace Content.Client.Commands;
|
||||
|
||||
internal sealed class ShowMarkersCommand : LocalizedCommands
|
||||
internal sealed class ShowMarkersCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly MarkerSystem _markerSystem = default!;
|
||||
|
||||
public override string Command => "showmarkers";
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
_entitySystemManager.GetEntitySystem<MarkerSystem>().MarkersVisible ^= true;
|
||||
_markerSystem.MarkersVisible ^= true;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ShowSubFloor : LocalizedCommands
|
||||
internal sealed class ShowSubFloor : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly SubFloorHideSystem _subfloorSystem = default!;
|
||||
|
||||
public override string Command => "showsubfloor";
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
_entitySystemManager.GetEntitySystem<SubFloorHideSystem>().ShowAll ^= true;
|
||||
_subfloorSystem.ShowAll ^= true;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class NotifyCommand : LocalizedCommands
|
||||
internal sealed class NotifyCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
public override string Command => "notify";
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var message = args[0];
|
||||
|
||||
_entitySystemManager.GetEntitySystem<PopupSystem>().PopupCursor(message);
|
||||
_popupSystem.PopupCursor(args[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,32 +5,27 @@ using Robust.Shared.Containers;
|
|||
|
||||
namespace Content.Client.Commands;
|
||||
|
||||
public sealed class HideMechanismsCommand : LocalizedCommands
|
||||
public sealed class HideMechanismsCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SpriteSystem _spriteSystem = default!;
|
||||
|
||||
public override string Command => "hidemechanisms";
|
||||
|
||||
public override string Description => LocalizationManager.GetString($"cmd-{Command}-desc", ("showMechanismsCommand", ShowMechanismsCommand.CommandName));
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var containerSys = _entityManager.System<SharedContainerSystem>();
|
||||
var spriteSys = _entityManager.System<SpriteSystem>();
|
||||
var query = _entityManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
|
||||
var query = EntityManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out _, out var sprite))
|
||||
{
|
||||
spriteSys.SetContainerOccluded((uid, sprite), false);
|
||||
_spriteSystem.SetContainerOccluded((uid, sprite), false);
|
||||
|
||||
var tempParent = uid;
|
||||
while (containerSys.TryGetContainingContainer((tempParent, null, null), out var container))
|
||||
while (_containerSystem.TryGetContainingContainer((tempParent, null, null), out var container))
|
||||
{
|
||||
if (!container.ShowContents)
|
||||
{
|
||||
spriteSys.SetContainerOccluded((uid, sprite), true);
|
||||
_spriteSystem.SetContainerOccluded((uid, sprite), true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +1,29 @@
|
|||
using Content.Client.Actions;
|
||||
using Content.Client.Mapping;
|
||||
using Content.Client.Markers;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Client.SubFloor;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.State;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Client.Commands;
|
||||
|
||||
[UsedImplicitly]
|
||||
internal sealed class MappingClientSideSetupCommand : LocalizedCommands
|
||||
internal sealed class MappingClientSideSetupCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly ILightManager _lightManager = default!;
|
||||
[Dependency] private readonly ActionsSystem _actionSystem = default!;
|
||||
[Dependency] private readonly MarkerSystem _markerSystem = default!;
|
||||
[Dependency] private readonly SubFloorHideSystem _subfloorSystem = default!;
|
||||
|
||||
public override string Command => "mappingclientsidesetup";
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (!_lightManager.LockConsoleAccess)
|
||||
{
|
||||
_entitySystemManager.GetEntitySystem<MarkerSystem>().MarkersVisible = true;
|
||||
_lightManager.Enabled = false;
|
||||
shell.ExecuteCommand("showsubfloor");
|
||||
_entitySystemManager.GetEntitySystem<ActionsSystem>().LoadActionAssignments("/mapping_actions.yml", false);
|
||||
}
|
||||
if (_lightManager.LockConsoleAccess)
|
||||
return;
|
||||
|
||||
_markerSystem.MarkersVisible = true;
|
||||
_lightManager.Enabled = false;
|
||||
_subfloorSystem.ShowAll = true;
|
||||
_actionSystem.LoadActionAssignments("/mapping_actions.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,57 +1,46 @@
|
|||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Overlays;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Client.Commands;
|
||||
|
||||
public sealed class ShowHealthBarsCommand : LocalizedCommands
|
||||
public sealed class ShowHealthBarsCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
public override string Command => "showhealthbars";
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = _playerManager.LocalSession;
|
||||
var player = shell.Player;
|
||||
if (player == null)
|
||||
{
|
||||
shell.WriteError(LocalizationManager.GetString($"cmd-{Command}-error-not-player"));
|
||||
shell.WriteError(Loc.GetString("shell-only-players-can-run-this-command"));
|
||||
return;
|
||||
}
|
||||
|
||||
var playerEntity = player?.AttachedEntity;
|
||||
if (!playerEntity.HasValue)
|
||||
if (player.AttachedEntity is not { } playerEntity)
|
||||
{
|
||||
shell.WriteError(LocalizationManager.GetString($"cmd-{Command}-error-no-entity"));
|
||||
shell.WriteError(Loc.GetString("shell-must-be-attached-to-entity"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_entityManager.HasComponent<ShowHealthBarsComponent>(playerEntity))
|
||||
if (!EntityManager.HasComponent<ShowHealthBarsComponent>(playerEntity))
|
||||
{
|
||||
var showHealthBarsComponent = new ShowHealthBarsComponent
|
||||
{
|
||||
DamageContainers = args.Select(arg => new ProtoId<DamageContainerPrototype>(arg)).ToList(),
|
||||
HealthStatusIcon = null,
|
||||
NetSyncEnabled = false
|
||||
NetSyncEnabled = false,
|
||||
};
|
||||
|
||||
_entityManager.AddComponent(playerEntity.Value, showHealthBarsComponent, true);
|
||||
EntityManager.AddComponent(playerEntity, showHealthBarsComponent, true);
|
||||
|
||||
shell.WriteLine(LocalizationManager.GetString($"cmd-{Command}-notify-enabled", ("args", string.Join(", ", args))));
|
||||
shell.WriteLine(Loc.GetString("cmd-showhealthbars-notify-enabled", ("args", string.Join(", ", args))));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_entityManager.RemoveComponentDeferred<ShowHealthBarsComponent>(playerEntity.Value);
|
||||
shell.WriteLine(LocalizationManager.GetString($"cmd-{Command}-notify-disabled"));
|
||||
}
|
||||
|
||||
return;
|
||||
EntityManager.RemoveComponentDeferred<ShowHealthBarsComponent>(playerEntity);
|
||||
shell.WriteLine(Loc.GetString("cmd-showhealthbars-notify-disabled"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,19 @@ using Robust.Shared.Console;
|
|||
|
||||
namespace Content.Client.Commands;
|
||||
|
||||
public sealed class ShowMechanismsCommand : LocalizedCommands
|
||||
public sealed class ShowMechanismsCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly SpriteSystem _spriteSystem = default!;
|
||||
|
||||
public const string CommandName = "showmechanisms";
|
||||
|
||||
public override string Command => CommandName;
|
||||
|
||||
public override string Help => LocalizationManager.GetString($"cmd-{Command}-help", ("command", Command));
|
||||
public override string Command => "showmechanisms";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var spriteSys = _entManager.System<SpriteSystem>();
|
||||
var query = _entManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
|
||||
var query = EntityManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out _, out var sprite))
|
||||
{
|
||||
spriteSys.SetContainerOccluded((uid, sprite), false);
|
||||
_spriteSystem.SetContainerOccluded((uid, sprite), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,14 +286,14 @@ namespace Content.Client.Construction
|
|||
if (!CheckConstructionConditions(prototype, loc, dir, user, showPopup: true))
|
||||
return false;
|
||||
|
||||
ghost = EntityManager.SpawnEntity("constructionghost", loc);
|
||||
var comp = EntityManager.GetComponent<ConstructionGhostComponent>(ghost.Value);
|
||||
ghost = Spawn("constructionghost", loc);
|
||||
var comp = Comp<ConstructionGhostComponent>(ghost.Value);
|
||||
comp.Prototype = prototype;
|
||||
comp.GhostId = ghost.GetHashCode();
|
||||
EntityManager.GetComponent<TransformComponent>(ghost.Value).LocalRotation = dir.ToAngle();
|
||||
Comp<TransformComponent>(ghost.Value).LocalRotation = dir.ToAngle();
|
||||
_ghosts.Add(comp.GhostId, ghost.Value);
|
||||
|
||||
var sprite = EntityManager.GetComponent<SpriteComponent>(ghost.Value);
|
||||
var sprite = Comp<SpriteComponent>(ghost.Value);
|
||||
_sprite.SetColor((ghost.Value, sprite), new Color(48, 255, 48, 128));
|
||||
|
||||
if (targetProto.TryGetComponent(out IconComponent? icon, EntityManager.ComponentFactory))
|
||||
|
|
@ -306,7 +306,7 @@ namespace Content.Client.Construction
|
|||
else if (targetProto.Components.TryGetValue("Sprite", out _))
|
||||
{
|
||||
var dummy = EntityManager.SpawnEntity(targetProtoId, MapCoordinates.Nullspace);
|
||||
var targetSprite = EntityManager.EnsureComponent<SpriteComponent>(dummy);
|
||||
var targetSprite = EnsureComp<SpriteComponent>(dummy);
|
||||
EntityManager.System<AppearanceSystem>().OnChangeData(dummy, targetSprite);
|
||||
|
||||
for (var i = 0; i < targetSprite.AllLayers.Count(); i++)
|
||||
|
|
@ -325,7 +325,7 @@ namespace Content.Client.Construction
|
|||
_sprite.LayerSetVisible((ghost.Value, sprite), i, true);
|
||||
}
|
||||
|
||||
EntityManager.DeleteEntity(dummy);
|
||||
Del(dummy);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
|
@ -367,7 +367,7 @@ namespace Content.Client.Construction
|
|||
{
|
||||
foreach (var ghost in _ghosts)
|
||||
{
|
||||
if (EntityManager.GetComponent<TransformComponent>(ghost.Value).Coordinates.Equals(loc))
|
||||
if (Comp<TransformComponent>(ghost.Value).Coordinates.Equals(loc))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ namespace Content.Client.Construction
|
|||
throw new ArgumentException($"Can't start construction for a ghost with no prototype. Ghost id: {ghostId}");
|
||||
}
|
||||
|
||||
var transform = EntityManager.GetComponent<TransformComponent>(ghostId);
|
||||
var transform = Comp<TransformComponent>(ghostId);
|
||||
var msg = new TryStartStructureConstructionMessage(GetNetCoordinates(transform.Coordinates), ghostComp.Prototype.ID, transform.LocalRotation, ghostId.GetHashCode());
|
||||
RaiseNetworkEvent(msg);
|
||||
}
|
||||
|
|
@ -405,7 +405,7 @@ namespace Content.Client.Construction
|
|||
if (!_ghosts.TryGetValue(ghostId, out var ghost))
|
||||
return;
|
||||
|
||||
EntityManager.QueueDeleteEntity(ghost);
|
||||
QueueDel(ghost);
|
||||
_ghosts.Remove(ghostId);
|
||||
}
|
||||
|
||||
|
|
@ -416,7 +416,7 @@ namespace Content.Client.Construction
|
|||
{
|
||||
foreach (var ghost in _ghosts.Values)
|
||||
{
|
||||
EntityManager.QueueDeleteEntity(ghost);
|
||||
QueueDel(ghost);
|
||||
}
|
||||
|
||||
_ghosts.Clear();
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
|
|||
|
||||
private EntityUid _owner;
|
||||
|
||||
[ValidatePrototypeId<EntityPrototype>]
|
||||
public const string NoBoardEffectId = "FlatpackerNoBoardEffect";
|
||||
public static readonly EntProtoId NoBoardEffectId = "FlatpackerNoBoardEffect";
|
||||
|
||||
private EntityUid? _currentBoard = EntityUid.Invalid;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<OutputPath>..\bin\Content.Client\</OutputPath>
|
||||
<OutputType Condition="'$(FullRelease)' != 'True'">Exe</OutputType>
|
||||
<WarningsAsErrors>nullable</WarningsAsErrors>
|
||||
<WarningsAsErrors>RA0032;nullable</WarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<Configurations>Debug;Release;Tools;DebugOpt</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Robust.Client.Graphics;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
|
@ -7,6 +8,8 @@ namespace Content.Client.Cooldown
|
|||
{
|
||||
public sealed class CooldownGraphic : Control
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> Shader = "CooldownAnimation";
|
||||
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||
|
||||
|
|
@ -15,7 +18,7 @@ namespace Content.Client.Cooldown
|
|||
public CooldownGraphic()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = _protoMan.Index<ShaderPrototype>("CooldownAnimation").InstanceUnique();
|
||||
_shader = _protoMan.Index(Shader).InstanceUnique();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -34,7 +37,7 @@ namespace Content.Client.Cooldown
|
|||
if (Progress >= 0f)
|
||||
{
|
||||
var hue = (5f / 18f) * lerp;
|
||||
color = Color.FromHsv((hue, 0.75f, 0.75f, 0.50f));
|
||||
color = Color.FromHsv(new Vector4(hue, 0.75f, 0.75f, 0.50f));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
|||
|
||||
public readonly EntityUid Console;
|
||||
|
||||
[ValidatePrototypeId<LocalizedDatasetPrototype>]
|
||||
private const string ReasonPlaceholders = "CriminalRecordsWantedReasonPlaceholders";
|
||||
private static readonly ProtoId<LocalizedDatasetPrototype> ReasonPlaceholders = "CriminalRecordsWantedReasonPlaceholders";
|
||||
|
||||
public Action<uint?>? OnKeySelected;
|
||||
public Action<StationRecordFilterType, string>? OnFiltersChanged;
|
||||
|
|
@ -296,7 +295,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
|||
|
||||
var field = "reason";
|
||||
var title = Loc.GetString("criminal-records-status-" + status.ToString().ToLower());
|
||||
var placeholders = _proto.Index<LocalizedDatasetPrototype>(ReasonPlaceholders);
|
||||
var placeholders = _proto.Index(ReasonPlaceholders);
|
||||
var placeholder = Loc.GetString("criminal-records-console-reason-placeholder", ("placeholder", _random.Pick(placeholders))); // just funny it doesn't actually get used
|
||||
var prompt = Loc.GetString("criminal-records-console-reason");
|
||||
var entry = new QuickDialogEntry(field, QuickDialogEntryType.LongText, prompt, placeholder);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,129 @@
|
|||
using Content.Shared.Damage.Systems;
|
||||
using Content.Client.Stunnable;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Damage.Systems;
|
||||
|
||||
public sealed partial class StaminaSystem : SharedStaminaSystem
|
||||
{
|
||||
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly StunSystem _stun = default!; // Clientside Stun System
|
||||
|
||||
private const string StaminaAnimationKey = "stamina";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<StaminaComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||
SubscribeLocalEvent<ActiveStaminaComponent, ComponentShutdown>(OnActiveStaminaShutdown);
|
||||
SubscribeLocalEvent<StaminaComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
}
|
||||
|
||||
protected override void OnStamHandleState(Entity<StaminaComponent> entity, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
base.OnStamHandleState(entity, ref args);
|
||||
|
||||
TryStartAnimation(entity);
|
||||
}
|
||||
|
||||
private void OnActiveStaminaShutdown(Entity<ActiveStaminaComponent> entity, ref ComponentShutdown args)
|
||||
{
|
||||
// If we don't have active stamina, we shouldn't have stamina damage. If the update loop can trust it we can trust it.
|
||||
if (!TryComp<StaminaComponent>(entity, out var stamina))
|
||||
return;
|
||||
|
||||
StopAnimation((entity, stamina));
|
||||
}
|
||||
|
||||
protected override void OnShutdown(Entity<StaminaComponent> entity, ref ComponentShutdown args)
|
||||
{
|
||||
base.OnShutdown(entity, ref args);
|
||||
|
||||
StopAnimation(entity);
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(Entity<StaminaComponent> ent, ref MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState == MobState.Dead)
|
||||
StopAnimation(ent);
|
||||
}
|
||||
|
||||
private void TryStartAnimation(Entity<StaminaComponent> entity)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(entity, out var sprite))
|
||||
return;
|
||||
|
||||
// If the animation is running, the system should update it accordingly
|
||||
// If we're below the threshold to animate, don't try to animate
|
||||
// If we're in stamcrit don't override it
|
||||
if (entity.Comp.AnimationThreshold > entity.Comp.StaminaDamage || _animation.HasRunningAnimation(entity, StaminaAnimationKey))
|
||||
return;
|
||||
|
||||
// Don't animate if we're dead
|
||||
if (_mobState.IsDead(entity))
|
||||
return;
|
||||
|
||||
entity.Comp.StartOffset = sprite.Offset;
|
||||
|
||||
PlayAnimation((entity, entity.Comp, sprite));
|
||||
}
|
||||
|
||||
private void StopAnimation(Entity<StaminaComponent, SpriteComponent?> entity)
|
||||
{
|
||||
if(!Resolve(entity, ref entity.Comp2))
|
||||
return;
|
||||
|
||||
_animation.Stop(entity.Owner, StaminaAnimationKey);
|
||||
entity.Comp1.StartOffset = entity.Comp2.Offset;
|
||||
}
|
||||
|
||||
private void OnAnimationCompleted(Entity<StaminaComponent> entity, ref AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key != StaminaAnimationKey || !args.Finished || !TryComp<SpriteComponent>(entity, out var sprite))
|
||||
return;
|
||||
|
||||
// stop looping if we're below the threshold
|
||||
if (entity.Comp.AnimationThreshold > entity.Comp.StaminaDamage)
|
||||
{
|
||||
_animation.Stop(entity.Owner, StaminaAnimationKey);
|
||||
_sprite.SetOffset((entity, sprite), entity.Comp.StartOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasComp<AnimationPlayerComponent>(entity))
|
||||
return;
|
||||
|
||||
PlayAnimation((entity, entity.Comp, sprite));
|
||||
}
|
||||
|
||||
private void PlayAnimation(Entity<StaminaComponent, SpriteComponent> entity)
|
||||
{
|
||||
DebugTools.Assert(entity.Comp1.CritThreshold > entity.Comp1.AnimationThreshold, $"Animation threshold on {ToPrettyString(entity)} was not less than the crit threshold. This will cause errors, animation has been cancelled.");
|
||||
|
||||
var step = Math.Clamp((entity.Comp1.StaminaDamage - entity.Comp1.AnimationThreshold) /
|
||||
(entity.Comp1.CritThreshold - entity.Comp1.AnimationThreshold),
|
||||
0f,
|
||||
1f); // The things I do for project 0 warnings
|
||||
var frequency = entity.Comp1.FrequencyMin + step * entity.Comp1.FrequencyMod;
|
||||
var jitter = entity.Comp1.JitterAmplitudeMin + step * entity.Comp1.JitterAmplitudeMod;
|
||||
var breathing = entity.Comp1.BreathingAmplitudeMin + step * entity.Comp1.BreathingAmplitudeMod;
|
||||
|
||||
_animation.Play(entity.Owner,
|
||||
_stun.GetFatigueAnimation(entity.Comp2,
|
||||
frequency,
|
||||
entity.Comp1.Jitters,
|
||||
jitter * entity.Comp1.JitterMin,
|
||||
jitter * entity.Comp1.JitterMax,
|
||||
breathing,
|
||||
entity.Comp1.StartOffset,
|
||||
ref entity.Comp1.LastJitter),
|
||||
StaminaAnimationKey);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Decals;
|
||||
|
||||
public sealed class ToggleDecalCommand : IConsoleCommand
|
||||
public sealed class ToggleDecalCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _e = default!;
|
||||
[Dependency] private readonly DecalSystem _decal = default!;
|
||||
|
||||
public string Command => "toggledecals";
|
||||
public string Description => "Toggles decaloverlay";
|
||||
public string Help => $"{Command}";
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
public override string Command => "toggledecals";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
_e.System<DecalSystem>().ToggleOverlay();
|
||||
_decal.ToggleOverlay();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public sealed class DeliveryVisualizerSystem : VisualizerSystem<DeliveryComponen
|
|||
|
||||
if (!_prototype.TryIndex<JobIconPrototype>(job, out var icon))
|
||||
{
|
||||
SpriteSystem.LayerSetTexture((uid, args.Sprite), DeliveryVisualLayers.JobStamp, SpriteSystem.Frame0(_prototype.Index("JobIconUnknown")));
|
||||
SpriteSystem.LayerSetTexture((uid, args.Sprite), DeliveryVisualLayers.JobStamp, SpriteSystem.Frame0(_prototype.Index(UnknownIcon).Icon));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
using Content.Shared.Devour;
|
||||
|
||||
namespace Content.Client.Devour;
|
||||
public sealed class DevourSystem : SharedDevourSystem
|
||||
{
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Shared.Disposal;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Disposal;
|
||||
using Content.Shared.Disposal.Unit;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ namespace Content.Client.DoAfter;
|
|||
|
||||
public sealed class DoAfterOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> UnshadedShader = "unshaded";
|
||||
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IGameTiming _timing;
|
||||
private readonly IPlayerManager _player;
|
||||
|
|
@ -50,7 +52,7 @@ public sealed class DoAfterOverlay : Overlay
|
|||
var sprite = new SpriteSpecifier.Rsi(new("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
|
||||
_barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
|
||||
|
||||
_unshadedShader = protoManager.Index<ShaderPrototype>("unshaded").Instance();
|
||||
_unshadedShader = protoManager.Index(UnshadedShader).Instance();
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Doors.Systems;
|
||||
using Content.Shared.SprayPainter.Prototypes;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Doors;
|
||||
|
||||
public sealed class DoorSystem : SharedDoorSystem
|
||||
{
|
||||
[Dependency] private readonly AnimationPlayerSystem _animationSystem = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
|
|
@ -85,8 +86,8 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||
if (!AppearanceSystem.TryGetData<DoorState>(entity, DoorVisuals.State, out var state, args.Component))
|
||||
state = DoorState.Closed;
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(entity, DoorVisuals.BaseRSI, out var baseRsi, args.Component))
|
||||
UpdateSpriteLayers((entity.Owner, args.Sprite), baseRsi);
|
||||
if (AppearanceSystem.TryGetData<string>(entity, PaintableVisuals.Prototype, out var prototype, args.Component))
|
||||
UpdateSpriteLayers((entity.Owner, args.Sprite), prototype);
|
||||
|
||||
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.AnimationKey))
|
||||
_animationSystem.Stop(entity.Owner, DoorComponent.AnimationKey);
|
||||
|
|
@ -139,14 +140,14 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateSpriteLayers(Entity<SpriteComponent> sprite, string baseRsi)
|
||||
private void UpdateSpriteLayers(Entity<SpriteComponent> sprite, string targetProto)
|
||||
{
|
||||
if (!_resourceCache.TryGetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / baseRsi, out var res))
|
||||
{
|
||||
Log.Error("Unable to load RSI '{0}'. Trace:\n{1}", baseRsi, Environment.StackTrace);
|
||||
if (!_prototypeManager.TryIndex(targetProto, out var target))
|
||||
return;
|
||||
}
|
||||
|
||||
_sprite.SetBaseRsi(sprite.AsNullable(), res.RSI);
|
||||
if (!target.TryGetComponent(out SpriteComponent? targetSprite, _componentFactory))
|
||||
return;
|
||||
|
||||
_sprite.SetBaseRsi(sprite.AsNullable(), targetSprite.BaseRSI);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Content.Shared.Drowsiness;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Enums;
|
||||
|
|
@ -10,11 +10,14 @@ namespace Content.Client.Drowsiness;
|
|||
|
||||
public sealed class DrowsinessOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> Shader = "Drowsiness";
|
||||
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
private readonly StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
public override bool RequestScreenTexture => true;
|
||||
|
|
@ -29,7 +32,10 @@ public sealed class DrowsinessOverlay : Overlay
|
|||
public DrowsinessOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_drowsinessShader = _prototypeManager.Index<ShaderPrototype>("Drowsiness").InstanceUnique();
|
||||
|
||||
_statusEffects = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||
|
||||
_drowsinessShader = _prototypeManager.Index(Shader).InstanceUnique();
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
|
|
@ -39,17 +45,11 @@ public sealed class DrowsinessOverlay : Overlay
|
|||
if (playerEntity == null)
|
||||
return;
|
||||
|
||||
if (!_entityManager.HasComponent<DrowsinessComponent>(playerEntity)
|
||||
|| !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
|
||||
if (!_statusEffects.TryGetEffectsEndTimeWithComp<DrowsinessStatusEffectComponent>(playerEntity, out var endTime))
|
||||
return;
|
||||
|
||||
var statusSys = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||
if (!statusSys.TryGetTime(playerEntity.Value, SharedDrowsinessSystem.DrowsinessKey, out var time, status))
|
||||
return;
|
||||
|
||||
var curTime = _timing.CurTime;
|
||||
var timeLeft = (float)(time.Value.Item2 - curTime).TotalSeconds;
|
||||
|
||||
endTime ??= TimeSpan.MaxValue;
|
||||
var timeLeft = (float)(endTime - _timing.CurTime).Value.TotalSeconds;
|
||||
CurrentPower += 8f * (0.5f * timeLeft - CurrentPower) * args.DeltaSeconds / (timeLeft + 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Shared.Drowsiness;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Player;
|
||||
|
|
@ -9,6 +10,7 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
|||
{
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
private DrowsinessOverlay _overlay = default!;
|
||||
|
||||
|
|
@ -16,35 +18,44 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
|||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DrowsinessComponent, ComponentInit>(OnDrowsinessInit);
|
||||
SubscribeLocalEvent<DrowsinessComponent, ComponentShutdown>(OnDrowsinessShutdown);
|
||||
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectAppliedEvent>(OnDrowsinessApply);
|
||||
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRemovedEvent>(OnDrowsinessShutdown);
|
||||
|
||||
SubscribeLocalEvent<DrowsinessComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<DrowsinessComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerAttachedEvent>>(OnStatusEffectPlayerAttached);
|
||||
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerDetachedEvent>>(OnStatusEffectPlayerDetached);
|
||||
|
||||
_overlay = new();
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(EntityUid uid, DrowsinessComponent component, LocalPlayerAttachedEvent args)
|
||||
private void OnDrowsinessApply(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
||||
{
|
||||
if (_player.LocalEntity == args.Target)
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnDrowsinessShutdown(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
|
||||
{
|
||||
if (_player.LocalEntity != args.Target)
|
||||
return;
|
||||
|
||||
if (!_statusEffects.HasEffectComp<DrowsinessStatusEffectComponent>(_player.LocalEntity.Value))
|
||||
{
|
||||
_overlay.CurrentPower = 0;
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStatusEffectPlayerAttached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerAttachedEvent> args)
|
||||
{
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(EntityUid uid, DrowsinessComponent component, LocalPlayerDetachedEvent args)
|
||||
private void OnStatusEffectPlayerDetached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerDetachedEvent> args)
|
||||
{
|
||||
_overlay.CurrentPower = 0;
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
if (_player.LocalEntity is null)
|
||||
return;
|
||||
|
||||
private void OnDrowsinessInit(EntityUid uid, DrowsinessComponent component, ComponentInit args)
|
||||
{
|
||||
if (_player.LocalEntity == uid)
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnDrowsinessShutdown(EntityUid uid, DrowsinessComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (_player.LocalEntity == uid)
|
||||
if (!_statusEffects.HasEffectComp<DrowsinessStatusEffectComponent>(_player.LocalEntity.Value))
|
||||
{
|
||||
_overlay.CurrentPower = 0;
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Shared.Drugs;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Player;
|
||||
|
|
@ -17,49 +18,47 @@ public sealed class DrugOverlaySystem : EntitySystem
|
|||
|
||||
private RainbowOverlay _overlay = default!;
|
||||
|
||||
public static string RainbowKey = "SeeingRainbows";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SeeingRainbowsComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<SeeingRainbowsComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<SeeingRainbowsStatusEffectComponent, StatusEffectAppliedEvent>(OnApplied);
|
||||
SubscribeLocalEvent<SeeingRainbowsStatusEffectComponent, StatusEffectRemovedEvent>(OnRemoved);
|
||||
|
||||
SubscribeLocalEvent<SeeingRainbowsComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<SeeingRainbowsComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
SubscribeLocalEvent<SeeingRainbowsStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerAttachedEvent>>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<SeeingRainbowsStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerDetachedEvent>>(OnPlayerDetached);
|
||||
|
||||
_overlay = new();
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerAttachedEvent args)
|
||||
private void OnRemoved(Entity<SeeingRainbowsStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
|
||||
{
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
if (_player.LocalEntity != args.Target)
|
||||
return;
|
||||
|
||||
private void OnPlayerDetached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerDetachedEvent args)
|
||||
{
|
||||
_overlay.Intoxication = 0;
|
||||
_overlay.TimeTicker = 0;
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, SeeingRainbowsComponent component, ComponentInit args)
|
||||
private void OnApplied(Entity<SeeingRainbowsStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
||||
{
|
||||
if (_player.LocalEntity == uid)
|
||||
{
|
||||
_overlay.Phase = _random.NextFloat(MathF.Tau); // random starting phase for movement effect
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
if (_player.LocalEntity != args.Target)
|
||||
return;
|
||||
|
||||
_overlay.Phase = _random.NextFloat(MathF.Tau); // random starting phase for movement effect
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, SeeingRainbowsComponent component, ComponentShutdown args)
|
||||
private void OnPlayerAttached(Entity<SeeingRainbowsStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerAttachedEvent> args)
|
||||
{
|
||||
if (_player.LocalEntity == uid)
|
||||
{
|
||||
_overlay.Intoxication = 0;
|
||||
_overlay.TimeTicker = 0;
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(Entity<SeeingRainbowsStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerDetachedEvent> args)
|
||||
{
|
||||
_overlay.Intoxication = 0;
|
||||
_overlay.TimeTicker = 0;
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Drugs;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
|
|
@ -12,11 +12,15 @@ namespace Content.Client.Drugs;
|
|||
|
||||
public sealed class RainbowOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> Shader = "Rainbow";
|
||||
|
||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
private readonly StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
public override bool RequestScreenTexture => true;
|
||||
|
|
@ -37,7 +41,9 @@ public sealed class RainbowOverlay : Overlay
|
|||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_rainbowShader = _prototypeManager.Index<ShaderPrototype>("Rainbow").InstanceUnique();
|
||||
_statusEffects = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||
|
||||
_rainbowShader = _prototypeManager.Index(Shader).InstanceUnique();
|
||||
_config.OnValueChanged(CCVars.ReducedMotion, OnReducedMotionChanged, invokeImmediately: true);
|
||||
}
|
||||
|
||||
|
|
@ -54,18 +60,13 @@ public sealed class RainbowOverlay : Overlay
|
|||
if (playerEntity == null)
|
||||
return;
|
||||
|
||||
if (!_entityManager.HasComponent<SeeingRainbowsComponent>(playerEntity)
|
||||
|| !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
|
||||
if (!_statusEffects.TryGetEffectsEndTimeWithComp<SeeingRainbowsStatusEffectComponent>(playerEntity, out var endTime))
|
||||
return;
|
||||
|
||||
var statusSys = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||
if (!statusSys.TryGetTime(playerEntity.Value, DrugOverlaySystem.RainbowKey, out var time, status))
|
||||
return;
|
||||
|
||||
var timeLeft = (float)(time.Value.Item2 - time.Value.Item1).TotalSeconds;
|
||||
endTime ??= TimeSpan.MaxValue;
|
||||
var timeLeft = (float)(endTime - _timing.CurTime).Value.TotalSeconds;
|
||||
|
||||
TimeTicker += args.DeltaSeconds;
|
||||
|
||||
if (timeLeft - TimeTicker > timeLeft / 16f)
|
||||
{
|
||||
Intoxication += (timeLeft - Intoxication) * args.DeltaSeconds / 16f;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ namespace Content.Client.Drunk;
|
|||
|
||||
public sealed class DrunkOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> Shader = "Drunk";
|
||||
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
|
|
@ -30,7 +32,7 @@ public sealed class DrunkOverlay : Overlay
|
|||
public DrunkOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_drunkShader = _prototypeManager.Index<ShaderPrototype>("Drunk").InstanceUnique();
|
||||
_drunkShader = _prototypeManager.Index(Shader).InstanceUnique();
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ using Content.Client.Lobby;
|
|||
using Content.Client.MainMenu;
|
||||
using Content.Client.Parallax.Managers;
|
||||
using Content.Client.Players.PlayTimeTracking;
|
||||
using Content.Client.Playtime;
|
||||
using Content.Client.Radiation.Overlays;
|
||||
using Content.Client.Replay;
|
||||
using Content.Client.Screenshot;
|
||||
|
|
@ -83,6 +84,7 @@ namespace Content.Client.Entry
|
|||
[Dependency] private readonly DebugMonitorManager _debugMonitorManager = default!;
|
||||
[Dependency] private readonly TitleWindowManager _titleWindowManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly ClientsidePlaytimeTrackingManager _clientsidePlaytimeManager = default!;
|
||||
[Dependency] private readonly ServersHubManager _serversHubManager = default!; // Sunrise-Hub
|
||||
[Dependency] private readonly ContributorsManager _contributorsManager = default!; // Sunrise-Edit
|
||||
[Dependency] private readonly PlayerCacheManager _playerCacheManager = default!; // Sunrise-Edit
|
||||
|
|
@ -155,6 +157,7 @@ namespace Content.Client.Entry
|
|||
_extendedDisconnectInformation.Initialize();
|
||||
_jobRequirements.Initialize();
|
||||
_playbackMan.Initialize();
|
||||
_clientsidePlaytimeManager.Initialize();
|
||||
|
||||
_serversHubManager.Initialize(); // Sunrise-Hub
|
||||
_contributorsManager.Initialize(); // Sunrise-Edit
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ namespace Content.Client.Examine
|
|||
{
|
||||
var entity = args.EntityUid;
|
||||
|
||||
if (!args.EntityUid.IsValid() || !EntityManager.EntityExists(entity))
|
||||
if (!args.EntityUid.IsValid() || !Exists(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -225,7 +225,7 @@ namespace Content.Client.Examine
|
|||
|
||||
vBox.AddChild(hBox);
|
||||
|
||||
if (EntityManager.HasComponent<SpriteComponent>(target))
|
||||
if (HasComp<SpriteComponent>(target))
|
||||
{
|
||||
var spriteView = new SpriteView
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ namespace Content.Client.Explosion;
|
|||
[UsedImplicitly]
|
||||
public sealed class ExplosionOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> UnshadedShader = "unshaded";
|
||||
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
|
@ -26,7 +28,7 @@ public sealed class ExplosionOverlay : Overlay
|
|||
public ExplosionOverlay(SharedAppearanceSystem appearanceSystem)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = _proto.Index<ShaderPrototype>("unshaded").Instance();
|
||||
_shader = _proto.Index(UnshadedShader).Instance();
|
||||
_transformSystem = _entMan.System<SharedTransformSystem>();
|
||||
_appearance = appearanceSystem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
using Content.Shared.Explosion.EntitySystems;
|
||||
|
||||
namespace Content.Client.Explosion;
|
||||
|
||||
public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem
|
||||
{
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
using Content.Shared.Explosion;
|
||||
using Content.Shared.Explosion.Components;
|
||||
|
||||
namespace Content.Client.Explosion;
|
||||
|
||||
[RegisterComponent, Access(typeof(TriggerSystem))]
|
||||
public sealed partial class TriggerOnProximityComponent : SharedTriggerOnProximityComponent {}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
namespace Content.Client.Explosion;
|
||||
|
||||
public sealed partial class TriggerSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
InitializeProximity();
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,9 @@ namespace Content.Client.Eye.Blinding
|
|||
{
|
||||
public sealed class BlindOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> GreyscaleShader = "GreyscaleFullscreen";
|
||||
private static readonly ProtoId<ShaderPrototype> CircleShader = "CircleMask";
|
||||
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
|
@ -27,8 +30,8 @@ namespace Content.Client.Eye.Blinding
|
|||
public BlindOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_greyscaleShader = _prototypeManager.Index<ShaderPrototype>("GreyscaleFullscreen").InstanceUnique();
|
||||
_circleMaskShader = _prototypeManager.Index<ShaderPrototype>("CircleMask").InstanceUnique();
|
||||
_greyscaleShader = _prototypeManager.Index(GreyscaleShader).InstanceUnique();
|
||||
_circleMaskShader = _prototypeManager.Index(CircleShader).InstanceUnique();
|
||||
}
|
||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ namespace Content.Client.Eye.Blinding
|
|||
{
|
||||
public sealed class BlurryVisionOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> CataractsShader = "Cataracts";
|
||||
private static readonly ProtoId<ShaderPrototype> CircleShader = "CircleMask";
|
||||
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
|
@ -33,8 +36,8 @@ namespace Content.Client.Eye.Blinding
|
|||
public BlurryVisionOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_cataractsShader = _prototypeManager.Index<ShaderPrototype>("Cataracts").InstanceUnique();
|
||||
_circleMaskShader = _prototypeManager.Index<ShaderPrototype>("CircleMask").InstanceUnique();
|
||||
_cataractsShader = _prototypeManager.Index(CataractsShader).InstanceUnique();
|
||||
_circleMaskShader = _prototypeManager.Index(CircleShader).InstanceUnique();
|
||||
|
||||
_circleMaskShader.SetParameter("CircleMinDist", 0.0f);
|
||||
_circleMaskShader.SetParameter("CirclePow", NoMotion_Pow);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Flash;
|
||||
using Content.Shared.Flash.Components;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
|
@ -11,25 +13,31 @@ namespace Content.Client.Flash
|
|||
{
|
||||
public sealed class FlashOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> FlashedEffectShader = "FlashedEffect";
|
||||
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
|
||||
private readonly SharedFlashSystem _flash;
|
||||
private readonly StatusEffectsSystem _statusSys;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
private readonly ShaderInstance _shader;
|
||||
public float PercentComplete = 0.0f;
|
||||
private bool _reducedMotion;
|
||||
public float PercentComplete;
|
||||
public Texture? ScreenshotTexture;
|
||||
|
||||
public FlashOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").InstanceUnique();
|
||||
_shader = _prototypeManager.Index(FlashedEffectShader).InstanceUnique();
|
||||
_flash = _entityManager.System<SharedFlashSystem>();
|
||||
_statusSys = _entityManager.System<StatusEffectsSystem>();
|
||||
|
||||
_configManager.OnValueChanged(CCVars.ReducedMotion, (b) => { _reducedMotion = b; }, invokeImmediately: true);
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
|
|
@ -47,8 +55,8 @@ namespace Content.Client.Flash
|
|||
return;
|
||||
|
||||
var curTime = _timing.CurTime;
|
||||
var lastsFor = (float) (time.Value.Item2 - time.Value.Item1).TotalSeconds;
|
||||
var timeDone = (float) (curTime - time.Value.Item1).TotalSeconds;
|
||||
var lastsFor = (float)(time.Value.Item2 - time.Value.Item1).TotalSeconds;
|
||||
var timeDone = (float)(curTime - time.Value.Item1).TotalSeconds;
|
||||
|
||||
PercentComplete = timeDone / lastsFor;
|
||||
}
|
||||
|
|
@ -74,10 +82,22 @@ namespace Content.Client.Flash
|
|||
return;
|
||||
|
||||
var worldHandle = args.WorldHandle;
|
||||
_shader.SetParameter("percentComplete", PercentComplete);
|
||||
worldHandle.UseShader(_shader);
|
||||
worldHandle.DrawTextureRectRegion(ScreenshotTexture, args.WorldBounds);
|
||||
worldHandle.UseShader(null);
|
||||
if (_reducedMotion)
|
||||
{
|
||||
// TODO: This is a very simple placeholder.
|
||||
// Replace it with a proper shader once we come up with something good.
|
||||
// Turns out making an effect that is supposed to be a bright, sudden, and disorienting flash
|
||||
// not do any of that while also being equivalent in terms of game balance is hard.
|
||||
var alpha = 1 - MathF.Pow(PercentComplete, 8f); // similar falloff curve to the flash shader
|
||||
worldHandle.DrawRect(args.WorldBounds, new Color(0f, 0f, 0f, alpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
_shader.SetParameter("percentComplete", PercentComplete);
|
||||
worldHandle.UseShader(_shader);
|
||||
worldHandle.DrawTextureRectRegion(ScreenshotTexture, args.WorldBounds);
|
||||
worldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using Content.Shared.Flash;
|
||||
using Content.Shared.Flash.Components;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Player;
|
||||
|
|
|
|||
5
Content.Client/Forensics/Systems/ForensicsSystem.cs
Normal file
5
Content.Client/Forensics/Systems/ForensicsSystem.cs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared.Forensics.Systems;
|
||||
|
||||
namespace Content.Client.Forensics.Systems;
|
||||
|
||||
public sealed class ForensicsSystem : SharedForensicsSystem;
|
||||
|
|
@ -2,25 +2,17 @@
|
|||
|
||||
namespace Content.Client.Ghost.Commands;
|
||||
|
||||
public sealed class ToggleGhostVisibilityCommand : IConsoleCommand
|
||||
public sealed class ToggleGhostVisibilityCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntitySystemManager _entSysMan = default!;
|
||||
[Dependency] private readonly GhostSystem _ghost = default!;
|
||||
|
||||
public string Command => "toggleghostvisibility";
|
||||
public string Description => "Toggles ghost visibility on the client.";
|
||||
public string Help => "toggleghostvisibility [bool]";
|
||||
public override string Command => "toggleghostvisibility";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var ghostSystem = _entSysMan.GetEntitySystem<GhostSystem>();
|
||||
|
||||
if (args.Length != 0 && bool.TryParse(args[0], out var visibility))
|
||||
{
|
||||
ghostSystem.ToggleGhostVisibility(visibility);
|
||||
}
|
||||
_ghost.ToggleGhostVisibility(visibility);
|
||||
else
|
||||
{
|
||||
ghostSystem.ToggleGhostVisibility();
|
||||
}
|
||||
_ghost.ToggleGhostVisibility();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,28 +4,27 @@ using Robust.Shared.Console;
|
|||
|
||||
namespace Content.Client.Ghost;
|
||||
|
||||
public sealed class GhostToggleSelfVisibility : IConsoleCommand
|
||||
public sealed class GhostToggleSelfVisibility : LocalizedEntityCommands
|
||||
{
|
||||
public string Command => "toggleselfghost";
|
||||
public string Description => "Toggles seeing your own ghost.";
|
||||
public string Help => "toggleselfghost";
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override string Command => "toggleselfghost";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var attachedEntity = shell.Player?.AttachedEntity;
|
||||
if (!attachedEntity.HasValue)
|
||||
return;
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entityManager.HasComponent<GhostComponent>(attachedEntity))
|
||||
if (!EntityManager.HasComponent<GhostComponent>(attachedEntity))
|
||||
{
|
||||
shell.WriteError("Entity must be a ghost.");
|
||||
shell.WriteError(Loc.GetString($"cmd-toggleselfghost-must-be-ghost"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entityManager.TryGetComponent(attachedEntity, out SpriteComponent? spriteComponent))
|
||||
if (!EntityManager.TryGetComponent(attachedEntity, out SpriteComponent? spriteComponent))
|
||||
return;
|
||||
|
||||
var spriteSys = entityManager.System<SpriteSystem>();
|
||||
spriteSys.SetVisible((attachedEntity.Value, spriteComponent), !spriteComponent.Visible);
|
||||
_sprite.SetVisible((attachedEntity.Value, spriteComponent), !spriteComponent.Visible);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ namespace Content.Client.Guidebook.Controls;
|
|||
[UsedImplicitly, GenerateTypedNameReferences]
|
||||
public sealed partial class GuideReagentReaction : BoxContainer, ISearchableControl
|
||||
{
|
||||
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||
private const string DefaultMixingCategory = "DummyMix";
|
||||
private static readonly ProtoId<MixingCategoryPrototype> DefaultMixingCategory = "DummyMix";
|
||||
|
||||
private readonly IPrototypeManager _protoMan;
|
||||
|
||||
|
|
@ -55,7 +54,7 @@ public sealed partial class GuideReagentReaction : BoxContainer, ISearchableCont
|
|||
}
|
||||
else
|
||||
{
|
||||
mixingCategories.Add(protoMan.Index<MixingCategoryPrototype>(DefaultMixingCategory));
|
||||
mixingCategories.Add(protoMan.Index(DefaultMixingCategory));
|
||||
}
|
||||
SetMixingCategory(mixingCategories, prototype, sysMan);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue