Merge branch 'master' of https://github.com/space-wizards/space-station-14 into upstream
# Conflicts: # Content.Client/Administration/Managers/ClientAdminManager.cs # Content.Client/Administration/Systems/BwoinkSystem.cs # Content.Client/Alerts/ClientAlertsSystem.cs # Content.Client/Audio/BackgroundAudioSystem.cs # Content.Client/CardboardBox/CardboardBoxSystem.cs # Content.Client/Chemistry/UI/InjectorStatusControl.cs # Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml # Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs # Content.Client/Clothing/ClientClothingSystem.cs # Content.Client/CriminalRecords/CriminalRecordsConsoleBoundUserInterface.cs # Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs # Content.Client/Decals/Overlays/DecalOverlay.cs # Content.Client/DoAfter/DoAfterOverlay.cs # Content.Client/Doors/AirlockSystem.cs # Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml # Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs # Content.Client/Launcher/LauncherConnectingGui.xaml # Content.Client/Launcher/LauncherConnectingGui.xaml.cs # Content.Client/Lobby/LobbyState.cs # Content.Client/Lobby/UI/LobbyGui.xaml.cs # Content.Client/MainMenu/UI/MainMenuControl.xaml # Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml # Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml.cs # Content.Client/MassMedia/Ui/NewsWriteMenu.xaml # Content.Client/MassMedia/Ui/NewsWriteMenu.xaml.cs # Content.Client/Options/UI/Tabs/MiscTab.xaml # Content.Client/Options/UI/Tabs/MiscTab.xaml.cs # Content.Client/Outline/InteractionOutlineSystem.cs # Content.Client/Overlays/ShowSecurityIconsSystem.cs # Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs # Content.Client/Popups/PopupOverlay.cs # Content.Client/Popups/PopupSystem.cs # Content.Client/Preferences/ClientPreferencesManager.cs # Content.Client/Preferences/UI/HumanoidProfileEditor.xaml # Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs # Content.Client/StatusIcon/StatusIconOverlay.cs # Content.Client/Stylesheets/StyleNano.cs # Content.Client/UserInterface/Systems/Bwoink/AHelpUIController.cs # Content.Client/UserInterface/Systems/Chat/ChatUIController.cs # Content.Server/Access/Systems/IdCardConsoleSystem.cs # Content.Server/Administration/Commands/BanCommand.cs # Content.Server/Administration/Notes/AdminMessageEui.cs # Content.Server/Administration/Notes/AdminNotesSystem.cs # Content.Server/Administration/Notes/IAdminNotesManager.cs # Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs # Content.Server/Administration/Systems/BwoinkSystem.cs # Content.Server/Administration/UI/PermissionsEui.cs # Content.Server/Antag/AntagSelectionSystem.cs # Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs # Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs # Content.Server/Chat/Systems/ChatSystem.cs # Content.Server/Chemistry/EntitySystems/InjectorSystem.cs # Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs # Content.Server/Connection/ConnectionManager.cs # Content.Server/CriminalRecords/Systems/CriminalRecordsConsoleSystem.cs # Content.Server/Database/DatabaseRecords.cs # Content.Server/Database/ServerDbBase.cs # Content.Server/Database/ServerDbManager.cs # Content.Server/DeviceLinking/Systems/SignalTimerSystem.cs # Content.Server/Doors/Systems/DoorSystem.cs # Content.Server/Execution/ExecutionSystem.cs # Content.Server/Explosion/EntitySystems/ExplosionSystem.cs # Content.Server/Fax/FaxSystem.cs # Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs # Content.Server/GameTicking/GameTicker.Replays.cs # Content.Server/GameTicking/GameTicker.RoundFlow.cs # Content.Server/GameTicking/Rules/Components/ThiefRuleComponent.cs # Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs # Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs # Content.Server/GameTicking/Rules/RevolutionaryRuleSystem.cs # Content.Server/GameTicking/Rules/ThiefRuleSystem.cs # Content.Server/GameTicking/Rules/TraitorRuleSystem.cs # Content.Server/GameTicking/Rules/ZombieRuleSystem.cs # Content.Server/Hands/Systems/HandsSystem.cs # Content.Server/Holosign/HolosignSystem.cs # Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.cs # Content.Server/Info/InfoSystem.cs # Content.Server/Kitchen/EntitySystems/SharpSystem.cs # Content.Server/Magic/MagicSystem.cs # Content.Server/MagicMirror/MagicMirrorSystem.cs # Content.Server/Mapping/MappingSystem.cs # Content.Server/MassMedia/Systems/NewsSystem.cs # Content.Server/Medical/Components/HealthAnalyzerComponent.cs # Content.Server/Medical/CrewMonitoring/CrewMonitoringServerSystem.cs # Content.Server/Medical/CryoPodSystem.cs # Content.Server/Medical/HealthAnalyzerSystem.cs # Content.Server/Nutrition/EntitySystems/OpenableSystem.cs # Content.Server/Preferences/Managers/ServerPreferencesManager.cs # Content.Server/Remotes/DoorRemoteSystem.cs # Content.Server/Resist/EscapeInventorySystem.cs # Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs # Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs # Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs # Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs # Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs # Content.Server/Species/Systems/NymphSystem.cs # Content.Server/StationEvents/Components/GasLeakRuleComponent.cs # Content.Server/StationEvents/EventManagerSystem.cs # Content.Server/Store/Systems/StoreSystem.Ui.cs # Content.Server/Strip/StrippableSystem.cs # Content.Server/VendingMachines/VendingMachineSystem.cs # Content.Server/Weapons/Ranged/Systems/GunSystem.cs # Content.Shared.Database/LogType.cs # Content.Shared/Actions/SharedActionsSystem.cs # Content.Shared/Administration/AdminFlags.cs # Content.Shared/Administration/SharedBwoinkSystem.cs # Content.Shared/Anomaly/SharedAnomalySystem.cs # Content.Shared/Bed/Sleep/SharedSleepingSystem.cs # Content.Shared/Buckle/SharedBuckleSystem.Strap.cs # Content.Shared/Chat/ChatChannel.cs # Content.Shared/Chemistry/Components/InjectorComponent.cs # Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs # Content.Shared/Chemistry/SharedReagentDispenser.cs # Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs # Content.Shared/CriminalRecords/Systems/SharedCriminalRecordsConsoleSystem.cs # Content.Shared/Cuffs/SharedCuffableSystem.cs # Content.Shared/Doors/Systems/SharedDoorSystem.cs # Content.Shared/Friction/TileFrictionController.cs # Content.Shared/Humanoid/Prototypes/SpeciesPrototype.cs # Content.Shared/Humanoid/SharedHumanoidAppearanceSystem.cs # Content.Shared/Implants/SharedImplanterSystem.cs # Content.Shared/Lock/LockSystem.cs # Content.Shared/MedicalScanner/HealthAnalyzerScannedUserMessage.cs # Content.Shared/Nutrition/Components/OpenableComponent.cs # Content.Shared/Nutrition/EntitySystems/SharedOpenableSystem.cs # Content.Shared/Nutrition/EntitySystems/ThirstSystem.cs # Content.Shared/Preferences/HumanoidCharacterProfile.cs # Content.Shared/Preferences/ICharacterProfile.cs # Content.Shared/Projectiles/SharedProjectileSystem.cs # Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs # Content.Shared/Security/SecurityStatus.cs # Content.Shared/Security/Systems/DeployableBarrierSystem.cs # Content.Shared/Slippery/SlipperySystem.cs # Content.Shared/Species/Systems/ReformSystem.cs # Content.Shared/Standing/StandingStateSystem.cs # Content.Shared/StatusIcon/StatusIconPrototype.cs # Content.Shared/Store/ListingPrototype.cs # Content.Shared/VendingMachines/SharedVendingMachineSystem.cs # Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs # README.md # Resources/Audio/Ambience/Antag/pirate_start.ogg # Resources/Changelog/Changelog.yml # Resources/Credits/GitHub.txt # Resources/Locale/en-US/criminal-records/criminal-records.ftl # Resources/Locale/en-US/escape-menu/ui/options-menu.ftl # Resources/Locale/en-US/medical/components/health-analyzer-component.ftl # Resources/Locale/en-US/reagents/meta/biological.ftl # Resources/Locale/en-US/reagents/meta/fun.ftl # Resources/Locale/en-US/reagents/meta/physical-desc.ftl # Resources/Locale/en-US/seeds/seeds.ftl # Resources/Locale/en-US/wires/wire-names.ftl # Resources/Maps/Shuttles/cargo_fland.yml # Resources/Maps/core.yml # Resources/Maps/europa.yml # Resources/Maps/fland.yml # Resources/Maps/origin.yml # Resources/Maps/saltern.yml # Resources/Maps/train.yml # Resources/Prototypes/Actions/diona.yml # Resources/Prototypes/Atmospherics/gases.yml # Resources/Prototypes/Catalog/Cargo/cargo_emergency.yml # Resources/Prototypes/Catalog/Cargo/cargo_engines.yml # Resources/Prototypes/Catalog/Cargo/cargo_fun.yml # Resources/Prototypes/Catalog/Cargo/cargo_security.yml # Resources/Prototypes/Catalog/Cargo/cargo_service.yml # Resources/Prototypes/Catalog/Cargo/cargo_vending.yml # Resources/Prototypes/Catalog/Fills/Boxes/general.yml # Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml # Resources/Prototypes/Catalog/Fills/Crates/engines.yml # Resources/Prototypes/Catalog/Fills/Items/briefcases.yml # Resources/Prototypes/Catalog/Fills/Items/toolboxes.yml # Resources/Prototypes/Catalog/Fills/Lockers/dressers.yml # Resources/Prototypes/Catalog/Fills/Lockers/heads.yml # Resources/Prototypes/Catalog/Fills/Lockers/security.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/bardrobe.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/lawdrobe.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/medidrobe.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/robotics.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml # Resources/Prototypes/Catalog/uplink_catalog.yml # Resources/Prototypes/Datasets/Names/first_male.yml # Resources/Prototypes/Datasets/tips.yml # Resources/Prototypes/Entities/Clothing/Hands/colored.yml # Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml # Resources/Prototypes/Entities/Clothing/Head/hats.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml # Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml # Resources/Prototypes/Entities/Mobs/NPCs/animals.yml # Resources/Prototypes/Entities/Mobs/Player/silicon.yml # Resources/Prototypes/Entities/Mobs/Species/base.yml # Resources/Prototypes/Entities/Mobs/Species/slime.yml # Resources/Prototypes/Entities/Mobs/Species/vox.yml # Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml # Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml # Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml # Resources/Prototypes/Entities/Objects/Devices/Electronics/signaller.yml # Resources/Prototypes/Entities/Objects/Devices/nuke.yml # Resources/Prototypes/Entities/Objects/Devices/pda.yml # Resources/Prototypes/Entities/Objects/Fun/toys.yml # Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml # Resources/Prototypes/Entities/Objects/Materials/parts.yml # Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml # Resources/Prototypes/Entities/Objects/Misc/implanters.yml # Resources/Prototypes/Entities/Objects/Misc/kudzu.yml # Resources/Prototypes/Entities/Objects/Misc/rubber_stamp.yml # Resources/Prototypes/Entities/Objects/Shields/shields.yml # Resources/Prototypes/Entities/Objects/Specific/Hydroponics/tools.yml # Resources/Prototypes/Entities/Objects/Specific/Medical/handheld_crew_monitor.yml # Resources/Prototypes/Entities/Objects/Specific/Medical/healthanalyzer.yml # Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml # Resources/Prototypes/Entities/Objects/Weapons/Bombs/firebomb.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml # Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml # Resources/Prototypes/Entities/Structures/Decoration/curtains.yml # Resources/Prototypes/Entities/Structures/Doors/Airlocks/access.yml # Resources/Prototypes/Entities/Structures/Doors/MaterialDoors/material_doors.yml # Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml # Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml # Resources/Prototypes/Entities/Structures/Machines/lathe.yml # Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml # Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml # Resources/Prototypes/Entities/Structures/Storage/glass_box.yml # Resources/Prototypes/Entities/Structures/Wallmounts/fireaxe_cabinet.yml # Resources/Prototypes/Entities/Structures/Wallmounts/switch.yml # Resources/Prototypes/Entities/Structures/Walls/asteroid.yml # Resources/Prototypes/Entities/Structures/Walls/grille.yml # Resources/Prototypes/Entities/Structures/Walls/walls.yml # Resources/Prototypes/Entities/Structures/Windows/window.yml # Resources/Prototypes/Entities/Structures/stairs.yml # Resources/Prototypes/GameRules/events.yml # Resources/Prototypes/Hydroponics/seeds.yml # Resources/Prototypes/Maps/saltern.yml # Resources/Prototypes/Reagents/biological.yml # Resources/Prototypes/Reagents/fun.yml # Resources/Prototypes/Recipes/Construction/Graphs/utilities/solarpanel.yml # Resources/Prototypes/Recipes/Construction/weapons.yml # Resources/Prototypes/Recipes/Crafting/improvised.yml # Resources/Prototypes/Recipes/Lathes/clothing.yml # Resources/Prototypes/Recipes/Reactions/fun.yml # Resources/Prototypes/Research/arsenal.yml # Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml # Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml # Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml # Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml # Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml # Resources/Prototypes/Roles/Jobs/Security/detective.yml # Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml # Resources/Prototypes/Roles/Jobs/departments.yml # Resources/Prototypes/Species/human.yml # Resources/Prototypes/Species/vox.yml # Resources/Prototypes/Stacks/Materials/materials.yml # Resources/Prototypes/StatusEffects/health.yml # Resources/Prototypes/Tiles/plating.yml # Resources/Prototypes/Voice/speech_emote_sounds.yml # Resources/Prototypes/Voice/speech_emotes.yml # Resources/Prototypes/explosion.yml # Resources/Prototypes/game_presets.yml # Resources/Prototypes/lobbyscreens.yml # Resources/Prototypes/secret_weights.yml # Resources/Prototypes/tags.yml # Resources/ServerInfo/Guidebook/Jobs.xml # Resources/ServerInfo/Guidebook/Science/ArtifactReports.xml # Resources/Textures/Clothing/Belt/emt.rsi/meta.json # Resources/Textures/Clothing/Head/Hats/beret_medic.rsi/meta.json # Resources/Textures/Clothing/Head/Hats/beret_qm.rsi/meta.json # Resources/Textures/Clothing/Head/Soft/bluesoft_flipped.rsi/meta.json # Resources/Textures/Clothing/Head/Soft/corpsoft_flipped.rsi/meta.json # Resources/Textures/Clothing/Head/Soft/greensoft_flipped.rsi/meta.json # Resources/Textures/Clothing/Head/Soft/greysoft_flipped.rsi/meta.json # Resources/Textures/Clothing/Head/Soft/paramedicsoft_flipped.rsi/meta.json # Resources/Textures/Clothing/Mask/neckgaiterred.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/slayer.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/syndicate.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Suits/syndicate.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/qmformal.rsi/meta.json # Resources/Textures/Decals/Overlays/greyscale.rsi/checkerNESW.png # Resources/Textures/Decals/Overlays/greyscale.rsi/checkerNWSE.png # Resources/Textures/Decals/Overlays/greyscale.rsi/fulltile_overlay.png # Resources/Textures/Decals/Overlays/greyscale.rsi/halftile_overlay.png # Resources/Textures/Decals/Overlays/greyscale.rsi/halftile_overlay_180.png # Resources/Textures/Decals/Overlays/greyscale.rsi/halftile_overlay_270.png # Resources/Textures/Decals/Overlays/greyscale.rsi/halftile_overlay_90.png # Resources/Textures/Decals/Overlays/greyscale.rsi/quartertile_overlay.png # Resources/Textures/Decals/Overlays/greyscale.rsi/quartertile_overlay_180.png # Resources/Textures/Decals/Overlays/greyscale.rsi/quartertile_overlay_270.png # Resources/Textures/Decals/Overlays/greyscale.rsi/quartertile_overlay_90.png # Resources/Textures/Decals/Overlays/greyscale.rsi/threequartertile_overlay.png # Resources/Textures/Decals/Overlays/greyscale.rsi/threequartertile_overlay_180.png # Resources/Textures/Decals/Overlays/greyscale.rsi/threequartertile_overlay_270.png # Resources/Textures/Decals/Overlays/greyscale.rsi/threequartertile_overlay_90.png # Resources/Textures/Interface/Misc/job_icons.rsi/meta.json # Resources/Textures/Interface/emotions.svg.192dpi.png.yml # Resources/Textures/LobbyScreens/dead-in-space.png.yml # Resources/Textures/LobbyScreens/doomed.webp.yml # Resources/Textures/LobbyScreens/pharmacy.png.yml # Resources/Textures/LobbyScreens/pharmacy.webp.yml # Resources/Textures/LobbyScreens/robotics.webp.yml # Resources/Textures/LobbyScreens/supermatter.png.yml # Resources/Textures/LobbyScreens/susstation.png.yml # Resources/Textures/LobbyScreens/warden.png.yml # Resources/Textures/LobbyScreens/warden.webp.yml # Resources/Textures/Mobs/Customization/human_hair.rsi/meta.json # Resources/Textures/Mobs/Effects/brute_damage.rsi/LLeg_Brute_40.png # Resources/Textures/Mobs/Effects/brute_damage.rsi/RLeg_Brute_40.png # Resources/Textures/Objects/Devices/nuke.rsi/meta.json # Resources/Textures/Objects/Devices/nuke.rsi/nuclearbomb_deployed.png # Resources/Textures/Objects/Devices/nuke.rsi/nuclearbomb_exploding.png # Resources/Textures/Objects/Devices/nuke.rsi/nuclearbomb_timing.png # Resources/Textures/Objects/Misc/books.rsi/meta.json # Resources/Textures/Objects/Misc/bureaucracy.rsi/paper_stamp-lawyer.png # Resources/Textures/Objects/Storage/boxes.rsi/meta.json # Resources/Textures/Objects/Tools/t-ray.rsi/tray-off.png # Resources/Textures/Objects/Tools/t-ray.rsi/tray-on.png # Resources/Textures/Objects/Weapons/Guns/Battery/mini-ebow.rsi/bolt.png # Resources/Textures/Structures/Doors/Airlocks/Standard/external.rsi/emergency_open_unlit.png # Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle_syndicate.rsi/emergency_open_unlit.png # Resources/Textures/Structures/Doors/Windoors/plasma.rsi/emergency_unlit.png # Resources/Textures/Structures/Doors/Windoors/uranium.rsi/emergency_unlit.png # Resources/Textures/Structures/Power/Generation/Singularity/emitter.rsi/locked.png # Resources/Textures/Tiles/attributions.yml # Resources/Textures/Tiles/shuttleblue.png # Resources/Textures/Tiles/shuttleorange.png # Resources/Textures/Tiles/shuttlepurple.png # Resources/Textures/Tiles/shuttlered.png # Resources/Textures/Tiles/shuttlewhite.png # Resources/Textures/White/Fluff/DOOMMAX/cap_cap.rsi/meta.json # Resources/Textures/White/Fluff/HSKveez/hardsuit.rsi/meta.json # Resources/Textures/White/Fluff/Vtergot/strictgloves.rsi/meta.json # Resources/clientCommandPerms.yml # Resources/migration.yml
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Prying.Components;
|
||||
using Content.Shared.Wires;
|
||||
|
||||
namespace Content.Shared.Doors.Systems;
|
||||
|
||||
@@ -8,18 +10,112 @@ public abstract class SharedAirlockSystem : EntitySystem
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] protected readonly SharedDoorSystem DoorSystem = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
[Dependency] private readonly SharedWiresSystem _wiresSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<AirlockComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
SubscribeLocalEvent<AirlockComponent, DoorStateChangedEvent>(OnStateChanged);
|
||||
SubscribeLocalEvent<AirlockComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
||||
SubscribeLocalEvent<AirlockComponent, BeforeDoorDeniedEvent>(OnBeforeDoorDenied);
|
||||
SubscribeLocalEvent<AirlockComponent, GetPryTimeModifierEvent>(OnGetPryMod);
|
||||
SubscribeLocalEvent<AirlockComponent, BeforePryEvent>(OnBeforePry);
|
||||
}
|
||||
|
||||
protected virtual void OnBeforeDoorClosed(EntityUid uid, AirlockComponent airlock, BeforeDoorClosedEvent args)
|
||||
private void OnBeforeDoorClosed(EntityUid uid, AirlockComponent airlock, BeforeDoorClosedEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
if (!airlock.Safety)
|
||||
args.PerformCollisionCheck = false;
|
||||
|
||||
// only block based on bolts / power status when initially closing the door, not when its already
|
||||
// mid-transition. Particularly relevant for when the door was pried-closed with a crowbar, which bypasses
|
||||
// the initial power-check.
|
||||
|
||||
if (TryComp(uid, out DoorComponent? door)
|
||||
&& !door.Partial
|
||||
&& !CanChangeState(uid, airlock))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStateChanged(EntityUid uid, AirlockComponent component, DoorStateChangedEvent args)
|
||||
{
|
||||
// Only show the maintenance panel if the airlock is closed
|
||||
if (TryComp<WiresPanelComponent>(uid, out var wiresPanel))
|
||||
{
|
||||
_wiresSystem.ChangePanelVisibility(uid, wiresPanel, component.OpenPanelVisible || args.State != DoorState.Open);
|
||||
}
|
||||
// If the door is closed, we should look if the bolt was locked while closing
|
||||
UpdateAutoClose(uid, component);
|
||||
|
||||
// Make sure the airlock auto closes again next time it is opened
|
||||
if (args.State == DoorState.Closed)
|
||||
component.AutoClose = true;
|
||||
}
|
||||
|
||||
private void OnBeforeDoorOpened(EntityUid uid, AirlockComponent component, BeforeDoorOpenedEvent args)
|
||||
{
|
||||
if (!CanChangeState(uid, component))
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnBeforeDoorDenied(EntityUid uid, AirlockComponent component, BeforeDoorDeniedEvent args)
|
||||
{
|
||||
if (!CanChangeState(uid, component))
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnGetPryMod(EntityUid uid, AirlockComponent component, ref GetPryTimeModifierEvent args)
|
||||
{
|
||||
if (component.Powered)
|
||||
args.PryTimeModifier *= component.PoweredPryModifier;
|
||||
|
||||
if (DoorSystem.IsBolted(uid))
|
||||
args.PryTimeModifier *= component.BoltedPryModifier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the auto close timer.
|
||||
/// </summary>
|
||||
public void UpdateAutoClose(EntityUid uid, AirlockComponent? airlock = null, DoorComponent? door = null)
|
||||
{
|
||||
if (!Resolve(uid, ref airlock, ref door))
|
||||
return;
|
||||
|
||||
if (door.State != DoorState.Open)
|
||||
return;
|
||||
|
||||
if (!airlock.AutoClose)
|
||||
return;
|
||||
|
||||
if (!CanChangeState(uid, airlock))
|
||||
return;
|
||||
|
||||
var autoev = new BeforeDoorAutoCloseEvent();
|
||||
RaiseLocalEvent(uid, autoev);
|
||||
if (autoev.Cancelled)
|
||||
return;
|
||||
|
||||
DoorSystem.SetNextStateChange(uid, airlock.AutoCloseDelay * airlock.AutoCloseDelayModifier);
|
||||
}
|
||||
|
||||
private void OnBeforePry(EntityUid uid, AirlockComponent component, ref BeforePryEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
if (!component.Powered || args.PryPowered)
|
||||
return;
|
||||
|
||||
args.Message = "airlock-component-cannot-pry-is-powered-message";
|
||||
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
public void UpdateEmergencyLightStatus(EntityUid uid, AirlockComponent component)
|
||||
@@ -30,6 +126,7 @@ public abstract class SharedAirlockSystem : EntitySystem
|
||||
public void ToggleEmergencyAccess(EntityUid uid, AirlockComponent component)
|
||||
{
|
||||
component.EmergencyAccess = !component.EmergencyAccess;
|
||||
Dirty(uid, component); // This only runs on the server apparently so we need this.
|
||||
UpdateEmergencyLightStatus(uid, component);
|
||||
}
|
||||
|
||||
@@ -45,4 +142,9 @@ public abstract class SharedAirlockSystem : EntitySystem
|
||||
{
|
||||
component.Safety = value;
|
||||
}
|
||||
|
||||
public bool CanChangeState(EntityUid uid, AirlockComponent component)
|
||||
{
|
||||
return component.Powered && !DoorSystem.IsBolted(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Prying.Components;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Shared.Doors.Systems;
|
||||
|
||||
public abstract class SharedDoorBoltSystem : EntitySystem
|
||||
{
|
||||
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforeDoorDeniedEvent>(OnBeforeDoorDenied);
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforePryEvent>(OnDoorPry);
|
||||
|
||||
}
|
||||
|
||||
private void OnDoorPry(EntityUid uid, DoorBoltComponent component, ref BeforePryEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
if (!component.BoltsDown || args.Force)
|
||||
return;
|
||||
|
||||
args.Message = "airlock-component-cannot-pry-is-bolted-message";
|
||||
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
private void OnBeforeDoorOpened(EntityUid uid, DoorBoltComponent component, BeforeDoorOpenedEvent args)
|
||||
{
|
||||
if (component.BoltsDown)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnBeforeDoorClosed(EntityUid uid, DoorBoltComponent component, BeforeDoorClosedEvent args)
|
||||
{
|
||||
if (component.BoltsDown)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnBeforeDoorDenied(EntityUid uid, DoorBoltComponent component, BeforeDoorDeniedEvent args)
|
||||
{
|
||||
if (component.BoltsDown)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
public void SetBoltWireCut(DoorBoltComponent component, bool value)
|
||||
{
|
||||
component.BoltWireCut = value;
|
||||
}
|
||||
}
|
||||
109
Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs
Normal file
109
Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Prying.Components;
|
||||
|
||||
namespace Content.Shared.Doors.Systems;
|
||||
|
||||
public abstract partial class SharedDoorSystem
|
||||
{
|
||||
public void InitializeBolts()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforeDoorDeniedEvent>(OnBeforeDoorDenied);
|
||||
SubscribeLocalEvent<DoorBoltComponent, BeforePryEvent>(OnDoorPry);
|
||||
SubscribeLocalEvent<DoorBoltComponent, DoorStateChangedEvent>(OnStateChanged);
|
||||
}
|
||||
|
||||
private void OnDoorPry(EntityUid uid, DoorBoltComponent component, ref BeforePryEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
if (!component.BoltsDown || args.Force)
|
||||
return;
|
||||
|
||||
args.Message = "airlock-component-cannot-pry-is-bolted-message";
|
||||
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
private void OnBeforeDoorOpened(EntityUid uid, DoorBoltComponent component, BeforeDoorOpenedEvent args)
|
||||
{
|
||||
if (component.BoltsDown)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnBeforeDoorClosed(EntityUid uid, DoorBoltComponent component, BeforeDoorClosedEvent args)
|
||||
{
|
||||
if (component.BoltsDown)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnBeforeDoorDenied(EntityUid uid, DoorBoltComponent component, BeforeDoorDeniedEvent args)
|
||||
{
|
||||
if (component.BoltsDown)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
public void SetBoltWireCut(Entity<DoorBoltComponent> ent, bool value)
|
||||
{
|
||||
ent.Comp.BoltWireCut = value;
|
||||
Dirty(ent, ent.Comp);
|
||||
}
|
||||
|
||||
public void UpdateBoltLightStatus(Entity<DoorBoltComponent> ent)
|
||||
{
|
||||
AppearanceSystem.SetData(ent, DoorVisuals.BoltLights, GetBoltLightsVisible(ent));
|
||||
}
|
||||
|
||||
public bool GetBoltLightsVisible(Entity<DoorBoltComponent> ent)
|
||||
{
|
||||
return ent.Comp.BoltLightsEnabled &&
|
||||
ent.Comp.BoltsDown &&
|
||||
ent.Comp.Powered;
|
||||
}
|
||||
|
||||
public void SetBoltLightsEnabled(Entity<DoorBoltComponent> ent, bool value)
|
||||
{
|
||||
if (ent.Comp.BoltLightsEnabled == value)
|
||||
return;
|
||||
|
||||
ent.Comp.BoltLightsEnabled = value;
|
||||
Dirty(ent, ent.Comp);
|
||||
UpdateBoltLightStatus(ent);
|
||||
}
|
||||
|
||||
public void SetBoltsDown(Entity<DoorBoltComponent> ent, bool value, EntityUid? user = null, bool predicted = false)
|
||||
{
|
||||
if (ent.Comp.BoltsDown == value)
|
||||
return;
|
||||
|
||||
ent.Comp.BoltsDown = value;
|
||||
Dirty(ent, ent.Comp);
|
||||
UpdateBoltLightStatus(ent);
|
||||
|
||||
var sound = value ? ent.Comp.BoltDownSound : ent.Comp.BoltUpSound;
|
||||
if (predicted)
|
||||
Audio.PlayPredicted(sound, ent, user: user);
|
||||
else
|
||||
Audio.PlayPvs(sound, ent);
|
||||
}
|
||||
|
||||
private void OnStateChanged(Entity<DoorBoltComponent> entity, ref DoorStateChangedEvent args)
|
||||
{
|
||||
// If the door is closed, we should look if the bolt was locked while closing
|
||||
UpdateBoltLightStatus(entity);
|
||||
}
|
||||
|
||||
public bool IsBolted(EntityUid uid, DoorBoltComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return component.BoltsDown;
|
||||
}
|
||||
}
|
||||
@@ -2,27 +2,34 @@ using System.Linq;
|
||||
using Content.Shared._White.Keyhole.Components;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Prying.Components;
|
||||
using Content.Shared.Prying.Systems;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Tools.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Doors.Systems;
|
||||
|
||||
public abstract class SharedDoorSystem : EntitySystem
|
||||
public abstract partial class SharedDoorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
|
||||
[Dependency] protected readonly IGameTiming GameTiming = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] protected readonly SharedPhysicsSystem PhysicsSystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
||||
@@ -32,7 +39,11 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
[Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!;
|
||||
[Dependency] private readonly OccluderSystem _occluder = default!;
|
||||
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; //WD edit
|
||||
[Dependency] private readonly PryingSystem _pryingSystem = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
|
||||
[ValidatePrototypeId<TagPrototype>]
|
||||
public const string DoorBumpTag = "DoorBumpOpener";
|
||||
|
||||
/// <summary>
|
||||
/// A body must have an intersection percentage larger than this in order to be considered as colliding with a
|
||||
@@ -53,6 +64,8 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
InitializeBolts();
|
||||
|
||||
SubscribeLocalEvent<DoorComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<DoorComponent, ComponentRemove>(OnRemove);
|
||||
|
||||
@@ -63,8 +76,13 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
SubscribeLocalEvent<DoorComponent, StartCollideEvent>(HandleCollide);
|
||||
SubscribeLocalEvent<DoorComponent, PreventCollideEvent>(PreventCollision);
|
||||
SubscribeLocalEvent<DoorComponent, BeforePryEvent>(OnBeforePry);
|
||||
SubscribeLocalEvent<DoorComponent, PriedEvent>(OnAfterPry);
|
||||
SubscribeLocalEvent<DoorComponent, WeldableAttemptEvent>(OnWeldAttempt);
|
||||
SubscribeLocalEvent<DoorComponent, WeldableChangedEvent>(OnWeldChanged);
|
||||
SubscribeLocalEvent<DoorComponent, GetPryTimeModifierEvent>(OnPryTimeModifier);
|
||||
|
||||
SubscribeLocalEvent<DoorComponent, OnAttemptEmagEvent>(OnAttemptEmag);
|
||||
SubscribeLocalEvent<DoorComponent, GotEmaggedEvent>(OnEmagged);
|
||||
}
|
||||
|
||||
protected virtual void OnComponentInit(Entity<DoorComponent> ent, ref ComponentInit args)
|
||||
@@ -81,6 +99,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
door.State = DoorState.Open;
|
||||
door.Partial = false;
|
||||
}
|
||||
|
||||
if (door.State == DoorState.Closing)
|
||||
{
|
||||
// force to closed.
|
||||
@@ -103,7 +122,37 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
_activeDoors.Remove(door);
|
||||
}
|
||||
|
||||
#region StateManagement
|
||||
private void OnAttemptEmag(EntityUid uid, DoorComponent door, ref OnAttemptEmagEvent args)
|
||||
{
|
||||
if (!TryComp<AirlockComponent>(uid, out var airlock))
|
||||
{
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsBolted(uid) || !airlock.Powered)
|
||||
{
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (door.State != DoorState.Closed)
|
||||
{
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEmagged(EntityUid uid, DoorComponent door, ref GotEmaggedEvent args)
|
||||
{
|
||||
if (!SetState(uid, DoorState.Emagging, door))
|
||||
return;
|
||||
|
||||
Audio.PlayPredicted(door.SparkSound, uid, args.UserUid, AudioParams.Default.WithVolume(8));
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
#region StateManagement
|
||||
|
||||
private void OnHandleState(Entity<DoorComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
var door = ent.Comp;
|
||||
@@ -116,14 +165,14 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
AppearanceSystem.SetData(ent, DoorVisuals.State, door.State);
|
||||
}
|
||||
|
||||
protected void SetState(EntityUid uid, DoorState state, DoorComponent? door = null)
|
||||
protected bool SetState(EntityUid uid, DoorState state, DoorComponent? door = null)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return;
|
||||
return false;
|
||||
|
||||
// If no change, return to avoid firing a new DoorStateChangedEvent.
|
||||
if (state == door.State)
|
||||
return;
|
||||
return false;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
@@ -151,6 +200,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
door.Partial = false;
|
||||
if (door.NextStateChange == null)
|
||||
_activeDoors.Remove((uid, door));
|
||||
|
||||
break;
|
||||
case DoorState.Closed:
|
||||
// May want to keep the door around to re-check for opening if we got a contact during closing.
|
||||
@@ -162,14 +212,21 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
Dirty(uid, door);
|
||||
RaiseLocalEvent(uid, new DoorStateChangedEvent(state));
|
||||
AppearanceSystem.SetData(uid, DoorVisuals.State, door.State);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Interactions
|
||||
protected virtual void OnActivate(EntityUid uid, DoorComponent door, ActivateInWorldEvent args)
|
||||
#region Interactions
|
||||
|
||||
protected void OnActivate(EntityUid uid, DoorComponent door, ActivateInWorldEvent args)
|
||||
{
|
||||
// avoid client-mispredicts, as the server will definitely handle this event
|
||||
if (args.Handled || !door.ClickOpen)
|
||||
return;
|
||||
|
||||
if (!TryToggleDoor(uid, door, args.User, predicted: true))
|
||||
_pryingSystem.TryPry(uid, args.User, out _);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -187,6 +244,55 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open or close a door after it has been successfully pried.
|
||||
/// </summary>
|
||||
private void OnAfterPry(EntityUid uid, DoorComponent door, ref PriedEvent args)
|
||||
{
|
||||
switch (door.State)
|
||||
{
|
||||
case DoorState.Closed:
|
||||
_adminLog.Add(LogType.Action, LogImpact.Medium,
|
||||
$"{ToPrettyString(args.User)} pried {ToPrettyString(uid)} open");
|
||||
|
||||
StartOpening(uid, door, args.User, true);
|
||||
break;
|
||||
case DoorState.Open:
|
||||
_adminLog.Add(LogType.Action, LogImpact.Medium,
|
||||
$"{ToPrettyString(args.User)} pried {ToPrettyString(uid)} closed");
|
||||
|
||||
StartClosing(uid, door, args.User, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWeldAttempt(EntityUid uid, DoorComponent component, WeldableAttemptEvent args)
|
||||
{
|
||||
if (component.CurrentlyCrushing.Count > 0)
|
||||
{
|
||||
args.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.State != DoorState.Closed && component.State != DoorState.Welded)
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWeldChanged(EntityUid uid, DoorComponent component, ref WeldableChangedEvent args)
|
||||
{
|
||||
switch (component.State)
|
||||
{
|
||||
case DoorState.Closed:
|
||||
SetState(uid, DoorState.Welded, component);
|
||||
break;
|
||||
case DoorState.Welded:
|
||||
SetState(uid, DoorState.Closed, component);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the door state/visuals and play an access denied sound when a user without access interacts with the
|
||||
/// door.
|
||||
@@ -205,46 +311,56 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
if (ev.Cancelled)
|
||||
return;
|
||||
|
||||
SetState(uid, DoorState.Denying, door);
|
||||
if (!SetState(uid, DoorState.Denying, door))
|
||||
return;
|
||||
|
||||
if (door.DenySound != null)
|
||||
PlaySound(uid, door.DenySound, AudioParams.Default.WithVolume(-3), user, predicted);
|
||||
if (predicted)
|
||||
Audio.PlayPredicted(door.DenySound, uid, user, AudioParams.Default.WithVolume(-3));
|
||||
else if (_net.IsServer)
|
||||
Audio.PlayPvs(door.DenySound, uid, AudioParams.Default.WithVolume(-3));
|
||||
}
|
||||
|
||||
|
||||
public bool TryToggleDoor(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return false;
|
||||
|
||||
// WD edit start
|
||||
if (TryComp<KeyholeComponent>(uid, out var keyholeComponent))
|
||||
if (TryComp<KeyholeComponent>(uid, out var keyholeComponent) && keyholeComponent.Locked)
|
||||
{
|
||||
if (keyholeComponent.Locked)
|
||||
if (predicted)
|
||||
{
|
||||
PlaySound(uid, keyholeComponent.DoorLockedSound, AudioParams.Default.WithVolume(-3), uid, true);
|
||||
_popupSystem.PopupEntity(Loc.GetString("door-locked-via-key", ("door", uid)), uid);
|
||||
return false;
|
||||
Audio.PlayPredicted(keyholeComponent.DoorLockedSound, uid, user, AudioParams.Default.WithVolume(-3));
|
||||
}
|
||||
else
|
||||
{
|
||||
Audio.PlayPvs(keyholeComponent.DoorLockedSound, uid, AudioParams.Default.WithVolume(-3));
|
||||
}
|
||||
|
||||
Popup.PopupEntity(Loc.GetString("door-locked-via-key", ("door", uid)), uid);
|
||||
return false;
|
||||
}
|
||||
// WD edit end
|
||||
|
||||
if (door.State is DoorState.Closed or DoorState.Denying)
|
||||
return door.State switch
|
||||
{
|
||||
return TryOpen(uid, door, user, predicted, quiet: door.State == DoorState.Denying);
|
||||
}
|
||||
else if (door.State == DoorState.Open)
|
||||
{
|
||||
return TryClose(uid, door, user, predicted);
|
||||
}
|
||||
|
||||
return false;
|
||||
DoorState.Closed or DoorState.Denying => TryOpen(uid, door, user, predicted,
|
||||
quiet: door.State == DoorState.Denying),
|
||||
DoorState.Open => TryClose(uid, door, user, predicted),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Opening
|
||||
public bool TryOpen(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false, bool quiet = false)
|
||||
#endregion
|
||||
|
||||
#region Opening
|
||||
|
||||
public bool TryOpen(
|
||||
EntityUid uid,
|
||||
DoorComponent? door = null,
|
||||
EntityUid? user = null,
|
||||
bool predicted = false,
|
||||
bool quiet = false)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return false;
|
||||
@@ -273,7 +389,8 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
if (!HasAccess(uid, user, door))
|
||||
{
|
||||
if (!quiet)
|
||||
Deny(uid, door);
|
||||
Deny(uid, door, user, predicted: true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -288,22 +405,23 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
/// <param name="user"> The user (if any) opening the door</param>
|
||||
/// <param name="predicted">Whether the interaction would have been
|
||||
/// predicted. See comments in the PlaySound method on the Server system for details</param>
|
||||
public virtual void StartOpening(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||
public void StartOpening(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return;
|
||||
|
||||
SetState(uid, DoorState.Opening, door);
|
||||
var lastState = door.State;
|
||||
|
||||
if (door.OpenSound != null)
|
||||
PlaySound(uid, door.OpenSound, AudioParams.Default.WithVolume(-5), user, predicted);
|
||||
if (!SetState(uid, DoorState.Opening, door))
|
||||
return;
|
||||
|
||||
// I'm not sure what the intent here is/was? It plays a sound if the user is opening a door with a hands
|
||||
// component, but no actual hands!? What!? Is this the sound of them head-butting the door to get it to open??
|
||||
// I'm 99% sure something is wrong here, but I kind of want to keep it this way.
|
||||
if (predicted)
|
||||
Audio.PlayPredicted(door.OpenSound, uid, user, AudioParams.Default.WithVolume(-5));
|
||||
else if (_net.IsServer)
|
||||
Audio.PlayPvs(door.OpenSound, uid, AudioParams.Default.WithVolume(-5));
|
||||
|
||||
if (user != null && TryComp(user.Value, out HandsComponent? hands) && hands.Hands.Count == 0)
|
||||
PlaySound(uid, door.TryOpenDoorSound, AudioParams.Default.WithVolume(-2), user, predicted);
|
||||
if (lastState == DoorState.Emagging && TryComp<DoorBoltComponent>(uid, out var doorBoltComponent))
|
||||
SetBoltsDown((uid, doorBoltComponent), !doorBoltComponent.BoltsDown, user, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -319,17 +437,18 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
door.NextStateChange = GameTiming.CurTime + door.CloseTimeTwo;
|
||||
_activeDoors.Add((uid, door));
|
||||
Dirty(uid, door);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Closing
|
||||
#endregion
|
||||
|
||||
#region Closing
|
||||
|
||||
public bool TryClose(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return false;
|
||||
|
||||
if (!CanClose(uid, door, user, false))
|
||||
if (!CanClose(uid, door, user))
|
||||
return false;
|
||||
|
||||
StartClosing(uid, door, user, predicted);
|
||||
@@ -342,9 +461,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
/// <param name="uid"> The uid of the door</param>
|
||||
/// <param name="door"> The doorcomponent of the door</param>
|
||||
/// <param name="user"> The user (if any) opening the door</param>
|
||||
/// <param name="predicted">Whether the interaction would have been
|
||||
/// predicted. See comments in the PlaySound method on the Server system for details</param>
|
||||
public bool CanClose(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool quiet = true)
|
||||
public bool CanClose(EntityUid uid, DoorComponent? door = null, EntityUid? user = null)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return false;
|
||||
@@ -354,8 +471,8 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
if (door.State is DoorState.Welded or DoorState.Closed)
|
||||
return false;
|
||||
|
||||
var ev = new BeforeDoorClosedEvent(door.PerformCollisionCheck, user); //WD EDIT
|
||||
RaiseLocalEvent(uid, ev, false);
|
||||
var ev = new BeforeDoorClosedEvent(door.PerformCollisionCheck, user);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
if (ev.Cancelled)
|
||||
return false;
|
||||
|
||||
@@ -365,15 +482,18 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
return !ev.PerformCollisionCheck || !GetColliding(uid).Any();
|
||||
}
|
||||
|
||||
public virtual void StartClosing(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||
public void StartClosing(EntityUid uid, DoorComponent? door = null, EntityUid? user = null, bool predicted = false)
|
||||
{
|
||||
if (!Resolve(uid, ref door))
|
||||
return;
|
||||
|
||||
SetState(uid, DoorState.Closing, door);
|
||||
if (!SetState(uid, DoorState.Closing, door))
|
||||
return;
|
||||
|
||||
if (door.CloseSound != null)
|
||||
PlaySound(uid, door.CloseSound, AudioParams.Default.WithVolume(-5), user, predicted);
|
||||
if (predicted)
|
||||
Audio.PlayPredicted(door.CloseSound, uid, user, AudioParams.Default.WithVolume(-5));
|
||||
else if (_net.IsServer)
|
||||
Audio.PlayPvs(door.CloseSound, uid, AudioParams.Default.WithVolume(-5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -386,7 +506,6 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
return false;
|
||||
|
||||
door.Partial = true;
|
||||
Dirty(uid, door);
|
||||
|
||||
// Make sure no entity waled into the airlock when it started closing.
|
||||
if (!CanClose(uid, door))
|
||||
@@ -399,6 +518,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
|
||||
SetCollidable(uid, true, door, physics);
|
||||
door.NextStateChange = GameTiming.CurTime + door.CloseTimeTwo;
|
||||
Dirty(uid, door);
|
||||
_activeDoors.Add((uid, door));
|
||||
|
||||
// Crush any entities. Note that we don't check airlock safety here. This should have been checked before
|
||||
@@ -406,9 +526,10 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
Crush(uid, door, physics);
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Collisions
|
||||
#endregion
|
||||
|
||||
#region Collisions
|
||||
|
||||
protected virtual void SetCollidable(
|
||||
EntityUid uid,
|
||||
@@ -479,18 +600,22 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
|
||||
//TODO: Make only shutters ignore these objects upon colliding instead of all airlocks
|
||||
// Excludes Glasslayer for windows, GlassAirlockLayer for windoors, TableLayer for tables
|
||||
if (!otherPhysics.CanCollide || otherPhysics.CollisionLayer == (int)CollisionGroup.GlassLayer || otherPhysics.CollisionLayer == (int)CollisionGroup.GlassAirlockLayer || otherPhysics.CollisionLayer == (int)CollisionGroup.TableLayer)
|
||||
if (!otherPhysics.CanCollide || otherPhysics.CollisionLayer == (int) CollisionGroup.GlassLayer ||
|
||||
otherPhysics.CollisionLayer == (int) CollisionGroup.GlassAirlockLayer ||
|
||||
otherPhysics.CollisionLayer == (int) CollisionGroup.TableLayer)
|
||||
continue;
|
||||
|
||||
//If the colliding entity is a slippable item ignore it by the airlock
|
||||
if (otherPhysics.CollisionLayer == (int)CollisionGroup.SlipLayer && otherPhysics.CollisionMask == (int)CollisionGroup.ItemMask)
|
||||
if (otherPhysics.CollisionLayer == (int) CollisionGroup.SlipLayer &&
|
||||
otherPhysics.CollisionMask == (int) CollisionGroup.ItemMask)
|
||||
continue;
|
||||
|
||||
//For when doors need to close over conveyor belts
|
||||
if (otherPhysics.CollisionLayer == (int) CollisionGroup.ConveyorMask)
|
||||
continue;
|
||||
|
||||
if ((physics.CollisionMask & otherPhysics.CollisionLayer) == 0 && (otherPhysics.CollisionMask & physics.CollisionLayer) == 0)
|
||||
if ((physics.CollisionMask & otherPhysics.CollisionLayer) == 0 &&
|
||||
(otherPhysics.CollisionMask & physics.CollisionLayer) == 0)
|
||||
continue;
|
||||
|
||||
if (_entityLookup.GetWorldAABB(otherPhysics.Owner).IntersectPercentage(doorAABB) < IntersectPercentage)
|
||||
@@ -508,19 +633,36 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleCollide(EntityUid uid, DoorComponent door, ref StartCollideEvent args)
|
||||
/// <summary>
|
||||
/// Open a door if a player or door-bumper (PDA, ID-card) collide with the door. Sadly, bullets no longer
|
||||
/// generate "access denied" sounds as you fire at a door.
|
||||
/// </summary>
|
||||
private void HandleCollide(EntityUid uid, DoorComponent door, ref StartCollideEvent args)
|
||||
{
|
||||
// TODO ACCESS READER move access reader to shared and predict door opening/closing
|
||||
// Then this can be moved to the shared system without mispredicting.
|
||||
}
|
||||
#endregion
|
||||
if (!door.BumpOpen)
|
||||
return;
|
||||
|
||||
#region Access
|
||||
if (door.State is not (DoorState.Closed or DoorState.Denying))
|
||||
return;
|
||||
|
||||
var otherUid = args.OtherEntity;
|
||||
|
||||
if (Tags.HasTag(otherUid, DoorBumpTag))
|
||||
TryOpen(uid, door, otherUid, quiet: door.State == DoorState.Denying);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Access
|
||||
|
||||
/// <summary>
|
||||
/// Does the user have the permissions required to open this door?
|
||||
/// </summary>
|
||||
public bool HasAccess(EntityUid uid, EntityUid? user = null, DoorComponent? door = null, AccessReaderComponent? access = null)
|
||||
public bool HasAccess(
|
||||
EntityUid uid,
|
||||
EntityUid? user = null,
|
||||
DoorComponent? door = null,
|
||||
AccessReaderComponent? access = null)
|
||||
{
|
||||
// TODO network AccessComponent for predicting doors
|
||||
|
||||
@@ -534,7 +676,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
|
||||
// Anyone can click to open firelocks
|
||||
if (Resolve(uid, ref door) && door.State == DoorState.Closed &&
|
||||
TryComp<FirelockComponent>(uid, out var firelock))
|
||||
TryComp<FirelockComponent>(uid, out _))
|
||||
return true;
|
||||
|
||||
if (!Resolve(uid, ref access, false))
|
||||
@@ -547,7 +689,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
// Some game modes modify access rules.
|
||||
AccessTypes.AllowAllIdExternal => !isExternal || _accessReaderSystem.IsAllowed(user.Value, uid, access),
|
||||
AccessTypes.AllowAllNoExternal => !isExternal,
|
||||
_ => _accessReaderSystem.IsAllowed(user.Value, uid, access)
|
||||
_ => _accessReaderSystem.IsAllowed(user.Value, uid, access)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -563,21 +705,26 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
{
|
||||
/// <summary> ID based door access. </summary>
|
||||
Id,
|
||||
|
||||
/// <summary>
|
||||
/// Allows everyone to open doors, except external which airlocks are still handled with ID's
|
||||
/// </summary>
|
||||
AllowAllIdExternal,
|
||||
|
||||
/// <summary>
|
||||
/// Allows everyone to open doors, except external airlocks which are never allowed, even if the user has
|
||||
/// ID access.
|
||||
/// </summary>
|
||||
AllowAllNoExternal,
|
||||
|
||||
/// <summary> Allows everyone to open all doors. </summary>
|
||||
AllowAll
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Updating
|
||||
#endregion
|
||||
|
||||
#region Updating
|
||||
|
||||
/// <summary>
|
||||
/// Schedule an open or closed door to progress to the next state after some time.
|
||||
/// </summary>
|
||||
@@ -606,6 +753,19 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
_activeDoors.Add((uid, door));
|
||||
}
|
||||
|
||||
protected void CheckDoorBump(Entity<DoorComponent, PhysicsComponent> ent)
|
||||
{
|
||||
var (uid, door, physics) = ent;
|
||||
if (door.BumpOpen)
|
||||
{
|
||||
foreach (var other in PhysicsSystem.GetContactingEntities(uid, physics, approximate: true))
|
||||
{
|
||||
if (Tags.HasTag(other, DoorBumpTag) && TryOpen(uid, door, other, quiet: true))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterate over active doors and progress them to the next state if they need to be updated.
|
||||
/// </summary>
|
||||
@@ -638,8 +798,6 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckDoorBump(Entity<DoorComponent, PhysicsComponent> ent) { }
|
||||
|
||||
/// <summary>
|
||||
/// Makes a door proceed to the next state (if applicable).
|
||||
/// </summary>
|
||||
@@ -651,7 +809,7 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
if (door.CurrentlyCrushing.Count > 0)
|
||||
// This is a closed door that is crushing people and needs to auto-open. Note that we don't check "can open"
|
||||
// here. The door never actually finished closing and we don't want people to get stuck inside of doors.
|
||||
StartOpening(ent, door, predicted: true);
|
||||
StartOpening(ent, door);
|
||||
|
||||
switch (door.State)
|
||||
{
|
||||
@@ -684,11 +842,12 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
|
||||
case DoorState.Open:
|
||||
// This door is open, and queued for an auto-close.
|
||||
if (!TryClose(ent, door, predicted: true))
|
||||
if (!TryClose(ent, door))
|
||||
{
|
||||
// The door failed to close (blocked?). Try again in one second.
|
||||
door.NextStateChange = time + TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DoorState.Welded:
|
||||
@@ -697,7 +856,6 @@ public abstract class SharedDoorSystem : EntitySystem
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected abstract void PlaySound(EntityUid uid, SoundSpecifier soundSpecifier, AudioParams audioParams, EntityUid? predictingPlayer, bool predicted);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user