From 951f37d2e31124aab9ac0805dda0bd97f9955f92 Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Fri, 7 Aug 2020 18:08:08 -0700 Subject: [PATCH] TGUI Engineering: Squashed Edition (Commits Below) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TGUI APCs TGUI vending machines Fix AI default_tgui_interaction TGUI Airlocks Station & Atmospheric Alert TGUI + Misc NTOS-TGUI Fixes TGUI Air Alarms & Central Atmospheric Control Airlock TGUI TG... got rid of UI for fire alarm. í´· TGUI Gas Heating/Cooling System TGUI Gas Pump & Passive Gate + Fixes TGUI Omni Atmospherics TGUI Pipe Dispensers & RPD TGUI IntelliCore & Vending Fix TGUI Handheld Tanks TGUI Portable Pump & Scrubber TGUI Tank Dispenser & Canisters TGUI Radios TGUI SMES & Air Alarm adjustment Tweak vending machine interfaces a tad TGUI Algae Farm TGUI general_air_control - Distro & Waste Console - Riot Control Console - Atmos Intake Console - Engine Cooling Console TGUI Heavy Scrubber Control (and body scanner fix) TGUI trinary devices & shutoff monitor TGUI Telecomms Log Browser TGUI Telecomms Machine Browser TGUI Spaceheater Internal Panel TGUI Gravity Generator TGUI Id Cards & Fix ID Card Images TGUI Id Card Redesign TGUI Turbolift TGUI Suit Cycler & Suit Storage Unit & Vending Fixes TGUI Power Monitor TGUI Signalers TGUI Employment Records TGUI Drone Console TGUI RIGSuits TGUI PA & PACMAN, and Margin Fix TGUI Solar Panels & Fix Power Monitor Adjust TGUI modules & their interaction with NTOS TGUI RCON TGUI Message Monitor Bump TGUI line limit to 120 (ParadiseSS13/Paradise#14002) TGUI Exonet & NTNet Relay TGUI Telecomms Multitool Menu TGUI Shield Capacitor & Shield Generator TGUI Supermatter-everything & Refactors --- .../binary_devices/algae_generator_vr.dm | 57 +- .../components/binary_devices/passive_gate.dm | 90 +-- .../components/binary_devices/pump.dm | 67 +- .../components/omni_devices/filter.dm | 62 +- .../components/omni_devices/mixer.dm | 64 +- .../components/omni_devices/omni_base.dm | 2 +- .../components/trinary_devices/filter.dm | 165 ++-- .../components/trinary_devices/mixer.dm | 125 +-- .../components/unary/cold_sink.dm | 56 +- .../components/unary/heat_source.dm | 58 +- .../components/unary/vent_pump.dm | 6 + code/__defines/subsystems.dm | 2 +- code/datums/outfits/outfit.dm | 1 + code/game/machinery/air_alarm.dm | 447 +++++------ code/game/machinery/atmo_control.dm | 332 ++++---- .../atmoalter/area_atmos_computer.dm | 162 ++-- .../atmoalter/area_atmos_computer_vr.dm | 11 +- code/game/machinery/atmoalter/canister.dm | 169 ++-- code/game/machinery/atmoalter/pump.dm | 98 ++- code/game/machinery/atmoalter/scrubber.dm | 66 +- code/game/machinery/camera/camera.dm | 2 +- code/game/machinery/computer/RCON_Console.dm | 11 +- code/game/machinery/computer/aifixer.dm | 2 +- code/game/machinery/computer/atmos_alert.dm | 64 +- code/game/machinery/computer/atmos_control.dm | 10 +- code/game/machinery/computer/message.dm | 603 +++++--------- .../machinery/computer/shutoff_monitor.dm | 10 +- code/game/machinery/computer/skills.dm | 629 +++++++-------- code/game/machinery/computer/station_alert.dm | 16 +- code/game/machinery/doors/airlock.dm | 220 ++++-- .../airlock_controllers.dm | 110 +-- .../airlock_controllers_dummy.dm | 1 + .../airlock_docking_controller.dm | 43 +- .../airlock_docking_controller_multi.dm | 63 +- .../embedded_controller_base.dm | 34 +- .../simple_docking_controller.dm | 34 +- code/game/machinery/exonet_node.dm | 95 +-- code/game/machinery/fire_alarm.dm | 82 +- code/game/machinery/pipe/pipe_dispenser.dm | 169 ++-- code/game/machinery/pipe/pipe_recipes.dm | 172 ++-- code/game/machinery/spaceheater.dm | 112 +-- code/game/machinery/suit_storage_unit.dm | 375 +++++---- code/game/machinery/telecomms/logbrowser.dm | 230 +++--- .../telecomms/machine_interactions.dm | 428 +++++----- .../machinery/telecomms/telecomunications.dm | 2 + code/game/machinery/telecomms/telemonitor.dm | 154 ++-- code/game/machinery/vending.dm | 87 +- code/game/objects/items/devices/aicard.dm | 95 ++- .../objects/items/devices/radio/headset.dm | 2 +- .../game/objects/items/devices/radio/radio.dm | 208 ++--- code/game/objects/items/weapons/RPD_vr.dm | 421 ++++------ .../items/weapons/id cards/station_ids.dm | 52 +- .../game/objects/items/weapons/tanks/tanks.dm | 119 ++- .../game/objects/structures/tank_dispenser.dm | 144 ++-- code/modules/assembly/signaler.dm | 85 +- code/modules/clothing/glasses/hud_vr.dm | 12 +- .../rig/modules/specific/ai_container.dm | 4 +- code/modules/clothing/spacesuits/rig/rig.dm | 117 +-- .../clothing/spacesuits/rig/rig_tgui.dm | 164 ++++ .../clothing/spacesuits/rig/rig_verbs.dm | 2 +- .../silicon/robot/drone/drone_console.dm | 154 ++-- code/modules/mob/living/silicon/subystems.dm | 16 +- code/modules/mob/new_player/new_player.dm | 1 - .../modular_computers/NTNet/NTNet_relay.dm | 54 +- .../programs/engineering/alarm_monitor.dm | 115 +-- .../programs/engineering/atmos_control.dm | 95 +-- .../programs/engineering/power_monitor.dm | 93 +-- .../programs/engineering/rcon_console.dm | 128 +-- .../programs/engineering/shutoff_monitor.dm | 52 +- .../engineering/supermatter_monitor.dm | 114 +-- .../programs/security/alarm_monitor.dm | 2 +- code/modules/nifsoft/software/06_screens.dm | 8 +- code/modules/power/apc.dm | 448 +++++------ code/modules/power/breaker_box.dm | 2 +- code/modules/power/generator.dm | 68 +- code/modules/power/gravitygenerator_vr.dm | 37 +- code/modules/power/port_gen.dm | 140 ++-- code/modules/power/powernet.dm | 4 +- code/modules/power/sensors/powernet_sensor.dm | 73 +- .../power/sensors/sensor_monitoring.dm | 9 +- .../particle_accelerator/particle_control.dm | 107 ++- code/modules/power/smes.dm | 138 ++-- code/modules/power/smes_construction.dm | 2 +- code/modules/power/solar.dm | 131 ++-- code/modules/power/supermatter/supermatter.dm | 21 +- code/modules/resleeving/infomorph.dm | 2 +- code/modules/shieldgen/shield_capacitor.dm | 78 +- code/modules/shieldgen/shield_gen.dm | 140 ++-- code/modules/shuttles/escape_pods.dm | 65 +- code/modules/tgui/modules/alarm.dm | 138 ++++ code/modules/tgui/modules/atmos_control.dm | 110 +++ code/modules/tgui/modules/power_monitor.dm | 85 ++ code/modules/tgui/modules/rcon.dm | 118 +++ code/modules/tgui/modules/shutoff_monitor.dm | 46 ++ .../tgui/modules/supermatter_monitor.dm | 108 +++ code/modules/turbolift/turbolift_console.dm | 83 +- maps/tether/tether_phoronlock.dm | 41 +- nano/images/tether_nanomap_z1.png | Bin 24076 -> 23848 bytes nano/templates/advanced_airlock_console.tmpl | 60 -- nano/templates/aicard.tmpl | 103 --- nano/templates/air_alarm.tmpl | 217 ----- nano/templates/alarm_monitor.tmpl | 38 - nano/templates/algae_farm_vr.tmpl | 70 -- nano/templates/apc.tmpl | 229 ------ nano/templates/atmo_control.tmpl | 224 ------ nano/templates/atmos_alert.tmpl | 18 - nano/templates/atmos_control.tmpl | 10 - nano/templates/atmos_control_map_content.tmpl | 13 - nano/templates/atmos_control_map_header.tmpl | 20 - nano/templates/canister.tmpl | 83 -- nano/templates/crew_monitor.tmpl | 32 - nano/templates/crew_monitor_map_content.tmpl | 13 - nano/templates/crew_monitor_map_header.tmpl | 20 - nano/templates/docking_airlock_console.tmpl | 96 --- nano/templates/door_access_console.tmpl | 42 - nano/templates/escape_pod_berth_console.tmpl | 42 - nano/templates/escape_pod_console.tmpl | 95 --- nano/templates/exonet_node.tmpl | 49 -- nano/templates/freezer.tmpl | 62 -- nano/templates/gas_pump.tmpl | 44 -- nano/templates/generator.tmpl | 142 ---- nano/templates/gravity_generator.tmpl | 45 -- nano/templates/hardsuit.tmpl | 257 ------ nano/templates/mod_sec_camera.tmpl | 36 - nano/templates/mod_sec_camera_map_header.tmpl | 44 -- nano/templates/multi_docking_console.tmpl | 37 - nano/templates/ntnet_relay.tmpl | 32 - nano/templates/omni_filter.tmpl | 87 -- nano/templates/omni_mixer.tmpl | 102 --- nano/templates/pacman.tmpl | 113 --- nano/templates/phoron_airlock_console.tmpl | 47 -- nano/templates/portpump.tmpl | 100 --- nano/templates/portscrubber.tmpl | 91 --- nano/templates/power_monitor.tmpl | 96 --- nano/templates/power_monitor_map_content.tmpl | 33 - nano/templates/power_monitor_map_header.tmpl | 33 - nano/templates/pressure_regulator.tmpl | 76 -- nano/templates/radio_basic.tmpl | 110 --- nano/templates/rcon.tmpl | 73 -- nano/templates/sec_camera.tmpl | 37 - nano/templates/sec_camera_map_content.tmpl | 20 - nano/templates/sec_camera_map_header.tmpl | 38 - nano/templates/shutoff_monitor.tmpl | 13 - nano/templates/simple_airlock_console.tmpl | 36 - nano/templates/simple_docking_console.tmpl | 99 --- .../templates/simple_docking_console_pod.tmpl | 101 --- nano/templates/smes.tmpl | 104 --- nano/templates/supermatter_crystal.tmpl | 25 - nano/templates/supermatter_monitor.tmpl | 125 --- nano/templates/tanks.tmpl | 47 -- nano/templates/vending_machine.tmpl | 56 -- tgui/packages/tgui/interfaces/AICard.js | 122 +++ tgui/packages/tgui/interfaces/APC.js | 288 +++++++ tgui/packages/tgui/interfaces/AiAirlock.js | 193 +++++ .../packages/tgui/interfaces/AiSupermatter.js | 90 +++ tgui/packages/tgui/interfaces/AirAlarm.js | 325 ++++++++ tgui/packages/tgui/interfaces/AlgaeFarm.js | 111 +++ .../tgui/interfaces/AreaScrubberControl.js | 121 +++ .../tgui/interfaces/AtmosAlertConsole.js | 50 ++ tgui/packages/tgui/interfaces/AtmosControl.js | 121 +++ tgui/packages/tgui/interfaces/AtmosFilter.js | 60 ++ tgui/packages/tgui/interfaces/AtmosMixer.js | 78 ++ tgui/packages/tgui/interfaces/Canister.js | 144 ++++ tgui/packages/tgui/interfaces/DroneConsole.js | 102 +++ .../tgui/interfaces/EmbeddedController.js | 740 ++++++++++++++++++ tgui/packages/tgui/interfaces/ExonetNode.js | 70 ++ tgui/packages/tgui/interfaces/GasPump.js | 71 ++ .../tgui/interfaces/GasTemperatureSystem.js | 82 ++ .../tgui/interfaces/GeneralAtmoControl.js | 318 ++++++++ .../tgui/interfaces/GeneralRecords.js | 285 +++++++ .../tgui/interfaces/GravityGenerator.js | 59 ++ tgui/packages/tgui/interfaces/IDCard.js | 205 +++++ .../tgui/interfaces/MessageMonitor.js | 399 ++++++++++ tgui/packages/tgui/interfaces/NTNetRelay.js | 100 +++ .../tgui/interfaces/NtosAtmosControl.js | 15 + .../tgui/interfaces/NtosPowerMonitor.js | 15 + tgui/packages/tgui/interfaces/NtosRCON.js | 15 + .../tgui/interfaces/NtosShutoffMonitor.js | 15 + .../interfaces/NtosStationAlertConsole.js | 15 + .../tgui/interfaces/NtosSupermatterMonitor.js | 15 + tgui/packages/tgui/interfaces/OmniFilter.js | 99 +++ tgui/packages/tgui/interfaces/OmniMixer.js | 148 ++++ .../tgui/interfaces/ParticleAccelerator.js | 64 ++ .../packages/tgui/interfaces/PipeDispenser.js | 74 ++ .../tgui/interfaces/PortableGenerator.js | 102 +++ tgui/packages/tgui/interfaces/PortablePump.js | 70 ++ .../tgui/interfaces/PortableScrubber.js | 39 + tgui/packages/tgui/interfaces/PowerMonitor.js | 301 +++++++ .../tgui/interfaces/PressureRegulator.js | 116 +++ tgui/packages/tgui/interfaces/RCON.js | 164 ++++ tgui/packages/tgui/interfaces/RIGSuit.js | 312 ++++++++ tgui/packages/tgui/interfaces/Radio.js | 150 ++++ .../tgui/interfaces/RapidPipeDispenser.js | 194 +++++ .../tgui/interfaces/ShieldCapacitor.js | 60 ++ .../tgui/interfaces/ShieldGenerator.js | 162 ++++ .../tgui/interfaces/ShutoffMonitor.js | 61 ++ tgui/packages/tgui/interfaces/Signaler.js | 91 +++ tgui/packages/tgui/interfaces/Smes.js | 195 +++++ tgui/packages/tgui/interfaces/SolarControl.js | 130 +++ tgui/packages/tgui/interfaces/SpaceHeater.js | 62 ++ .../tgui/interfaces/StationAlertConsole.js | 73 ++ tgui/packages/tgui/interfaces/SuitCycler.js | 193 +++++ .../tgui/interfaces/SuitStorageUnit.js | 222 ++++++ .../tgui/interfaces/SupermatterMonitor.js | 170 ++++ tgui/packages/tgui/interfaces/TEGenerator.js | 93 +++ tgui/packages/tgui/interfaces/Tank.js | 87 ++ .../packages/tgui/interfaces/TankDispenser.js | 42 + .../tgui/interfaces/TelecommsLogBrowser.js | 241 ++++++ .../interfaces/TelecommsMachineBrowser.js | 118 +++ .../tgui/interfaces/TelecommsMultitoolMenu.js | 222 ++++++ tgui/packages/tgui/interfaces/Turbolift.js | 83 ++ tgui/packages/tgui/interfaces/Vending.js | 165 ++++ .../tgui/interfaces/common/AtmosControls.js | 170 ++++ .../common/InterfaceLockNoticeBox.js | 65 ++ .../tgui/interfaces/common/PortableAtmos.js | 86 ++ tgui/packages/tgui/public/tgui.bundle.css | 2 +- tgui/packages/tgui/public/tgui.bundle.js | 19 +- .../tgui/styles/interfaces/IDCard.scss | 15 + .../tgui/styles/interfaces/Turbolift.scss | 19 + .../tgui/styles/layouts/NtosWindow.scss | 2 +- tgui/packages/tgui/styles/main.scss | 2 + vorestation.dme | 7 + 222 files changed, 13749 insertions(+), 9249 deletions(-) create mode 100644 code/modules/clothing/spacesuits/rig/rig_tgui.dm create mode 100644 code/modules/tgui/modules/alarm.dm create mode 100644 code/modules/tgui/modules/atmos_control.dm create mode 100644 code/modules/tgui/modules/power_monitor.dm create mode 100644 code/modules/tgui/modules/rcon.dm create mode 100644 code/modules/tgui/modules/shutoff_monitor.dm create mode 100644 code/modules/tgui/modules/supermatter_monitor.dm delete mode 100644 nano/templates/advanced_airlock_console.tmpl delete mode 100644 nano/templates/aicard.tmpl delete mode 100644 nano/templates/air_alarm.tmpl delete mode 100644 nano/templates/alarm_monitor.tmpl delete mode 100644 nano/templates/algae_farm_vr.tmpl delete mode 100644 nano/templates/apc.tmpl delete mode 100644 nano/templates/atmo_control.tmpl delete mode 100644 nano/templates/atmos_alert.tmpl delete mode 100644 nano/templates/atmos_control.tmpl delete mode 100644 nano/templates/atmos_control_map_content.tmpl delete mode 100644 nano/templates/atmos_control_map_header.tmpl delete mode 100644 nano/templates/canister.tmpl delete mode 100644 nano/templates/crew_monitor.tmpl delete mode 100644 nano/templates/crew_monitor_map_content.tmpl delete mode 100644 nano/templates/crew_monitor_map_header.tmpl delete mode 100644 nano/templates/docking_airlock_console.tmpl delete mode 100644 nano/templates/door_access_console.tmpl delete mode 100644 nano/templates/escape_pod_berth_console.tmpl delete mode 100644 nano/templates/escape_pod_console.tmpl delete mode 100644 nano/templates/exonet_node.tmpl delete mode 100644 nano/templates/freezer.tmpl delete mode 100644 nano/templates/gas_pump.tmpl delete mode 100644 nano/templates/generator.tmpl delete mode 100644 nano/templates/gravity_generator.tmpl delete mode 100644 nano/templates/hardsuit.tmpl delete mode 100644 nano/templates/mod_sec_camera.tmpl delete mode 100644 nano/templates/mod_sec_camera_map_header.tmpl delete mode 100644 nano/templates/multi_docking_console.tmpl delete mode 100644 nano/templates/ntnet_relay.tmpl delete mode 100644 nano/templates/omni_filter.tmpl delete mode 100644 nano/templates/omni_mixer.tmpl delete mode 100644 nano/templates/pacman.tmpl delete mode 100644 nano/templates/phoron_airlock_console.tmpl delete mode 100644 nano/templates/portpump.tmpl delete mode 100644 nano/templates/portscrubber.tmpl delete mode 100644 nano/templates/power_monitor.tmpl delete mode 100644 nano/templates/power_monitor_map_content.tmpl delete mode 100644 nano/templates/power_monitor_map_header.tmpl delete mode 100644 nano/templates/pressure_regulator.tmpl delete mode 100644 nano/templates/radio_basic.tmpl delete mode 100644 nano/templates/rcon.tmpl delete mode 100644 nano/templates/sec_camera.tmpl delete mode 100644 nano/templates/sec_camera_map_content.tmpl delete mode 100644 nano/templates/sec_camera_map_header.tmpl delete mode 100644 nano/templates/shutoff_monitor.tmpl delete mode 100644 nano/templates/simple_airlock_console.tmpl delete mode 100644 nano/templates/simple_docking_console.tmpl delete mode 100644 nano/templates/simple_docking_console_pod.tmpl delete mode 100644 nano/templates/smes.tmpl delete mode 100644 nano/templates/supermatter_crystal.tmpl delete mode 100644 nano/templates/supermatter_monitor.tmpl delete mode 100644 nano/templates/tanks.tmpl delete mode 100644 nano/templates/vending_machine.tmpl create mode 100644 tgui/packages/tgui/interfaces/AICard.js create mode 100644 tgui/packages/tgui/interfaces/APC.js create mode 100644 tgui/packages/tgui/interfaces/AiAirlock.js create mode 100644 tgui/packages/tgui/interfaces/AiSupermatter.js create mode 100644 tgui/packages/tgui/interfaces/AirAlarm.js create mode 100644 tgui/packages/tgui/interfaces/AlgaeFarm.js create mode 100644 tgui/packages/tgui/interfaces/AreaScrubberControl.js create mode 100644 tgui/packages/tgui/interfaces/AtmosAlertConsole.js create mode 100644 tgui/packages/tgui/interfaces/AtmosControl.js create mode 100644 tgui/packages/tgui/interfaces/AtmosFilter.js create mode 100644 tgui/packages/tgui/interfaces/AtmosMixer.js create mode 100644 tgui/packages/tgui/interfaces/Canister.js create mode 100644 tgui/packages/tgui/interfaces/DroneConsole.js create mode 100644 tgui/packages/tgui/interfaces/EmbeddedController.js create mode 100644 tgui/packages/tgui/interfaces/ExonetNode.js create mode 100644 tgui/packages/tgui/interfaces/GasPump.js create mode 100644 tgui/packages/tgui/interfaces/GasTemperatureSystem.js create mode 100644 tgui/packages/tgui/interfaces/GeneralAtmoControl.js create mode 100644 tgui/packages/tgui/interfaces/GeneralRecords.js create mode 100644 tgui/packages/tgui/interfaces/GravityGenerator.js create mode 100644 tgui/packages/tgui/interfaces/IDCard.js create mode 100644 tgui/packages/tgui/interfaces/MessageMonitor.js create mode 100644 tgui/packages/tgui/interfaces/NTNetRelay.js create mode 100644 tgui/packages/tgui/interfaces/NtosAtmosControl.js create mode 100644 tgui/packages/tgui/interfaces/NtosPowerMonitor.js create mode 100644 tgui/packages/tgui/interfaces/NtosRCON.js create mode 100644 tgui/packages/tgui/interfaces/NtosShutoffMonitor.js create mode 100644 tgui/packages/tgui/interfaces/NtosStationAlertConsole.js create mode 100644 tgui/packages/tgui/interfaces/NtosSupermatterMonitor.js create mode 100644 tgui/packages/tgui/interfaces/OmniFilter.js create mode 100644 tgui/packages/tgui/interfaces/OmniMixer.js create mode 100644 tgui/packages/tgui/interfaces/ParticleAccelerator.js create mode 100644 tgui/packages/tgui/interfaces/PipeDispenser.js create mode 100644 tgui/packages/tgui/interfaces/PortableGenerator.js create mode 100644 tgui/packages/tgui/interfaces/PortablePump.js create mode 100644 tgui/packages/tgui/interfaces/PortableScrubber.js create mode 100644 tgui/packages/tgui/interfaces/PowerMonitor.js create mode 100644 tgui/packages/tgui/interfaces/PressureRegulator.js create mode 100644 tgui/packages/tgui/interfaces/RCON.js create mode 100644 tgui/packages/tgui/interfaces/RIGSuit.js create mode 100644 tgui/packages/tgui/interfaces/Radio.js create mode 100644 tgui/packages/tgui/interfaces/RapidPipeDispenser.js create mode 100644 tgui/packages/tgui/interfaces/ShieldCapacitor.js create mode 100644 tgui/packages/tgui/interfaces/ShieldGenerator.js create mode 100644 tgui/packages/tgui/interfaces/ShutoffMonitor.js create mode 100644 tgui/packages/tgui/interfaces/Signaler.js create mode 100644 tgui/packages/tgui/interfaces/Smes.js create mode 100644 tgui/packages/tgui/interfaces/SolarControl.js create mode 100644 tgui/packages/tgui/interfaces/SpaceHeater.js create mode 100644 tgui/packages/tgui/interfaces/StationAlertConsole.js create mode 100644 tgui/packages/tgui/interfaces/SuitCycler.js create mode 100644 tgui/packages/tgui/interfaces/SuitStorageUnit.js create mode 100644 tgui/packages/tgui/interfaces/SupermatterMonitor.js create mode 100644 tgui/packages/tgui/interfaces/TEGenerator.js create mode 100644 tgui/packages/tgui/interfaces/Tank.js create mode 100644 tgui/packages/tgui/interfaces/TankDispenser.js create mode 100644 tgui/packages/tgui/interfaces/TelecommsLogBrowser.js create mode 100644 tgui/packages/tgui/interfaces/TelecommsMachineBrowser.js create mode 100644 tgui/packages/tgui/interfaces/TelecommsMultitoolMenu.js create mode 100644 tgui/packages/tgui/interfaces/Turbolift.js create mode 100644 tgui/packages/tgui/interfaces/Vending.js create mode 100644 tgui/packages/tgui/interfaces/common/AtmosControls.js create mode 100644 tgui/packages/tgui/interfaces/common/InterfaceLockNoticeBox.js create mode 100644 tgui/packages/tgui/interfaces/common/PortableAtmos.js create mode 100644 tgui/packages/tgui/styles/interfaces/IDCard.scss create mode 100644 tgui/packages/tgui/styles/interfaces/Turbolift.scss diff --git a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm index 1c308a0e0b..fb686820ee 100644 --- a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm +++ b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm @@ -140,7 +140,7 @@ /obj/machinery/atmospherics/binary/algae_farm/attack_hand(mob/user) if(..()) return 1 - ui_interact(user) + tgui_interact(user) /obj/machinery/atmospherics/binary/algae_farm/RefreshParts() ..() @@ -165,7 +165,13 @@ moles_per_tick = initial(moles_per_tick) + (manip_rating**2 - 1) -/obj/machinery/atmospherics/binary/algae_farm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/atmospherics/binary/algae_farm/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AlgaeFarm", name) + ui.open() + +/obj/machinery/atmospherics/binary/algae_farm/tgui_data(mob/user) var/data[0] data["panelOpen"] = panel_open @@ -198,41 +204,28 @@ "percent" = air2.total_moles ? round((air2.gas[output_gas] / air2.total_moles) * 100) : 0, "moles" = round(air2.gas[output_gas], 0.01)) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "algae_farm_vr.tmpl", "Algae Farm Control Panel", 500, 600) - ui.set_initial_data(data) - ui.set_auto_update(TRUE) - ui.open() + return data -/obj/machinery/atmospherics/binary/algae_farm/Topic(href, href_list) +/obj/machinery/atmospherics/binary/algae_farm/tgui_act(action, params) if(..()) - return 1 - usr.set_machine(src) + return TRUE add_fingerprint(usr) - // Queue management can be done even while busy - if(href_list["activate"]) - update_use_power(USE_POWER_ACTIVE) - update_icon() - updateUsrDialog() - return - - if(href_list["deactivate"]) - update_use_power(USE_POWER_IDLE) - update_icon() - updateUsrDialog() - return - - if(href_list["ejectMaterial"]) - var/matName = href_list["ejectMaterial"] - if(!(matName in stored_material)) - return - eject_materials(matName, 0) - updateUsrDialog() - return + switch(action) + if("toggle") + if(use_power == USE_POWER_IDLE) + update_use_power(USE_POWER_ACTIVE) + else + update_use_power(USE_POWER_IDLE) + update_icon() + . = TRUE + if("ejectMaterial") + var/matName = params["mat"] + if(!(matName in stored_material)) + return + eject_materials(matName, 0) + . = TRUE // TODO - These should be replaced with materials datum. diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index 1c501e87f0..bfbcb48734 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -209,18 +209,21 @@ /obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob) if(..()) return - src.add_fingerprint(usr) - if(!src.allowed(user)) + add_fingerprint(usr) + if(!allowed(user)) to_chat(user, "Access denied.") return - usr.set_machine(src) - ui_interact(user) - return + tgui_interact(user) -/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/atmospherics/binary/passive_gate/tgui_interact(mob/user, datum/tgui/ui) if(stat & (BROKEN|NOPOWER)) return + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PressureRegulator", name) + ui.open() +/obj/machinery/atmospherics/binary/passive_gate/tgui_data(mob/user) // this is the data which will be sent to the ui var/data[0] @@ -235,51 +238,48 @@ "last_flow_rate" = round(last_flow_rate*10), ) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "pressure_regulator.tmpl", name, 470, 370) - ui.set_initial_data(data) // when the ui is first opened this is the data it will use - ui.open() // open the new ui window - ui.set_auto_update(1) // auto update every Master Controller tick + return data -/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list) - if(..()) return 1 +/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, params) + if(..()) + return TRUE - if(href_list["toggle_valve"]) - unlocked = !unlocked + switch(action) + if("toggle_valve") + . = TRUE + unlocked = !unlocked + if("regulate_mode") + . = TRUE + switch(params["mode"]) + if("off") regulate_mode = REGULATE_NONE + if("input") regulate_mode = REGULATE_INPUT + if("output") regulate_mode = REGULATE_OUTPUT - if(href_list["regulate_mode"]) - switch(href_list["regulate_mode"]) - if ("off") regulate_mode = REGULATE_NONE - if ("input") regulate_mode = REGULATE_INPUT - if ("output") regulate_mode = REGULATE_OUTPUT + if("set_press") + . = TRUE + switch(params["press"]) + if("min") + target_pressure = 0 + if("max") + target_pressure = max_pressure_setting + if("set") + var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure) as num + src.target_pressure = between(0, new_pressure, max_pressure_setting) - switch(href_list["set_press"]) - if ("min") - target_pressure = 0 - if ("max") - target_pressure = max_pressure_setting - if ("set") - var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure) as num - src.target_pressure = between(0, new_pressure, max_pressure_setting) + if("set_flow_rate") + . = TRUE + switch(params["press"]) + if("min") + set_flow_rate = 0 + if("max") + set_flow_rate = air1.volume + if("set") + var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate) as num + src.set_flow_rate = between(0, new_flow_rate, air1.volume) - switch(href_list["set_flow_rate"]) - if ("min") - set_flow_rate = 0 - if ("max") - set_flow_rate = air1.volume - if ("set") - var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[air1.volume]kPa)","Flow Rate Control",src.set_flow_rate) as num - src.set_flow_rate = between(0, new_flow_rate, air1.volume) - - usr.set_machine(src) //Is this even needed with NanoUI? - src.update_icon() - src.add_fingerprint(usr) - return + update_icon() + add_fingerprint(usr) /obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) if (!W.is_wrench()) diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index 0df0217497..54e034dc92 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -143,10 +143,15 @@ Thus, the two variables affect pump operation are set in New(): return 1 -/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/atmospherics/binary/pump/tgui_interact(mob/user, datum/tgui/ui) if(stat & (BROKEN|NOPOWER)) return + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GasPump", name) + ui.open() +/obj/machinery/atmospherics/binary/pump/tgui_data(mob/user) // this is the data which will be sent to the ui var/data[0] @@ -159,15 +164,7 @@ Thus, the two variables affect pump operation are set in New(): "max_power_draw" = power_rating, ) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "gas_pump.tmpl", name, 470, 290) - ui.set_initial_data(data) // when the ui is first opened this is the data it will use - ui.open() // open the new ui window - ui.set_auto_update(1) // auto update every Master Controller tick + return data /obj/machinery/atmospherics/binary/pump/Initialize() . = ..() @@ -204,36 +201,40 @@ Thus, the two variables affect pump operation are set in New(): update_icon() return -/obj/machinery/atmospherics/binary/pump/attack_hand(user as mob) +/obj/machinery/atmospherics/binary/pump/attack_ghost(mob/user) + tgui_interact(user) + +/obj/machinery/atmospherics/binary/pump/attack_hand(mob/user) if(..()) return - src.add_fingerprint(usr) - if(!src.allowed(user)) + add_fingerprint(usr) + if(!allowed(user)) to_chat(user, "Access denied.") return - usr.set_machine(src) - ui_interact(user) - return + tgui_interact(user) -/obj/machinery/atmospherics/binary/pump/Topic(href,href_list) - if(..()) return 1 +/obj/machinery/atmospherics/binary/pump/tgui_act(action, params) + if(..()) + return TRUE - if(href_list["power"]) - update_use_power(!use_power) + switch(action) + if("power") + update_use_power(!use_power) + . = TRUE + if("set_press") + var/press = params["press"] + switch(press) + if("min") + target_pressure = 0 + if("max") + target_pressure = max_pressure_setting + if("set") + var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure) as num + src.target_pressure = between(0, new_pressure, max_pressure_setting) + . = TRUE - switch(href_list["set_press"]) - if ("min") - target_pressure = 0 - if ("max") - target_pressure = max_pressure_setting - if ("set") - var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure) as num - src.target_pressure = between(0, new_pressure, max_pressure_setting) - - usr.set_machine(src) - src.add_fingerprint(usr) - - src.update_icon() + add_fingerprint(usr) + update_icon() /obj/machinery/atmospherics/binary/pump/power_change() var/old_stat = stat diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm index 9f0862d800..56171a0880 100644 --- a/code/ATMOSPHERICS/components/omni_devices/filter.dm +++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm @@ -87,23 +87,14 @@ return 1 -/obj/machinery/atmospherics/omni/atmos_filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - - var/list/data = new() - - data = build_uidata() - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "omni_filter.tmpl", "Omni Filter Control", 330, 330) - ui.set_initial_data(data) - +/obj/machinery/atmospherics/omni/atmos_filter/tgui_interact(mob/user,datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "OmniFilter", name) ui.open() -/obj/machinery/atmospherics/omni/atmos_filter/proc/build_uidata() - var/list/data = new() +/obj/machinery/atmospherics/omni/atmos_filter/tgui_data(mob/user) + var/list/data = list() data["power"] = use_power data["config"] = configuring @@ -156,34 +147,41 @@ else return null -/obj/machinery/atmospherics/omni/atmos_filter/Topic(href, href_list) - if(..()) return 1 - switch(href_list["command"]) +/obj/machinery/atmospherics/omni/atmos_filter/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) if("power") if(!configuring) update_use_power(!use_power) else update_use_power(USE_POWER_OFF) + . = TRUE if("configure") configuring = !configuring if(configuring) update_use_power(USE_POWER_OFF) - - //only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on - if(configuring && !use_power) - switch(href_list["command"]) - if("set_flow_rate") - var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate) as num - set_flow_rate = between(0, new_flow_rate, max_flow_rate) - if("switch_mode") - switch_mode(dir_flag(href_list["dir"]), mode_return_switch(href_list["mode"])) - if("switch_filter") - var/new_filter = input(usr,"Select filter mode:","Change filter",href_list["mode"]) in list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide") - switch_filter(dir_flag(href_list["dir"]), mode_return_switch(new_filter)) + . = TRUE + if("set_flow_rate") + if(!configuring || use_power) + return + var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate) as num + set_flow_rate = between(0, new_flow_rate, max_flow_rate) + . = TRUE + if("switch_mode") + if(!configuring || use_power) + return + switch_mode(dir_flag(params["dir"]), mode_return_switch(params["mode"])) + . = TRUE + if("switch_filter") + if(!configuring || use_power) + return + var/new_filter = input(usr,"Select filter mode:","Change filter",params["mode"]) in list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide") + switch_filter(dir_flag(params["dir"]), mode_return_switch(new_filter)) + . = TRUE update_icon() - SSnanoui.update_uis(src) - return /obj/machinery/atmospherics/omni/atmos_filter/proc/mode_return_switch(var/mode) switch(mode) diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm index 0210d09e69..077be63b30 100644 --- a/code/ATMOSPHERICS/components/omni_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm @@ -124,22 +124,13 @@ return 1 -/obj/machinery/atmospherics/omni/mixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - usr.set_machine(src) - - var/list/data = new() - - data = build_uidata() - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "omni_mixer.tmpl", "Omni Mixer Control", 360, 330) - ui.set_initial_data(data) - +/obj/machinery/atmospherics/omni/mixer/tgui_interact(mob/user,datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "OmniMixer", name) ui.open() -/obj/machinery/atmospherics/omni/mixer/proc/build_uidata() +/obj/machinery/atmospherics/omni/mixer/tgui_data(mob/user) var/list/data = new() data["power"] = use_power @@ -172,36 +163,45 @@ return data -/obj/machinery/atmospherics/omni/mixer/Topic(href, href_list) - if(..()) return 1 +/obj/machinery/atmospherics/omni/mixer/tgui_act(action, params) + if(..()) + return TRUE - switch(href_list["command"]) + switch(action) if("power") + . = TRUE if(!configuring) update_use_power(!use_power) else update_use_power(USE_POWER_OFF) if("configure") + . = TRUE configuring = !configuring if(configuring) update_use_power(USE_POWER_OFF) - - //only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on - if(configuring && !use_power) - switch(href_list["command"]) - if("set_flow_rate") - var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate) as num - set_flow_rate = between(0, new_flow_rate, max_flow_rate) - if("switch_mode") - switch_mode(dir_flag(href_list["dir"]), href_list["mode"]) - if("switch_con") - change_concentration(dir_flag(href_list["dir"])) - if("switch_conlock") - con_lock(dir_flag(href_list["dir"])) + if("set_flow_rate") + . = TRUE + if(!configuring || use_power) + return + var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate) as num + set_flow_rate = between(0, new_flow_rate, max_flow_rate) + if("switch_mode") + . = TRUE + if(!configuring || use_power) + return + switch_mode(dir_flag(params["dir"]), params["mode"]) + if("switch_con") + . = TRUE + if(!configuring || use_power) + return + change_concentration(dir_flag(params["dir"])) + if("switch_conlock") + . = TRUE + if(!configuring || use_power) + return + con_lock(dir_flag(params["dir"])) update_icon() - SSnanoui.update_uis(src) - return /obj/machinery/atmospherics/omni/mixer/proc/switch_mode(var/port = NORTH, var/mode = ATM_NONE) if(mode != ATM_INPUT && mode != ATM_OUTPUT) diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm index 54acc3db99..be7f905a77 100644 --- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm +++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm @@ -110,7 +110,7 @@ return src.add_fingerprint(usr) - ui_interact(user) + tgui_interact(user) return /obj/machinery/atmospherics/omni/proc/build_icons() diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index bde060a11a..e2aaee092c 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -111,7 +111,7 @@ if(frequency) set_frequency(frequency) -/obj/machinery/atmospherics/trinary/atmos_filter/attack_hand(user as mob) // -- TLE +/obj/machinery/atmospherics/trinary/atmos_filter/attack_hand(user) // -- TLE if(..()) return @@ -119,81 +119,106 @@ to_chat(user, "Access denied.") return - var/dat - var/current_filter_type - switch(filter_type) - if(0) - current_filter_type = "Phoron" - if(1) - current_filter_type = "Oxygen" - if(2) - current_filter_type = "Nitrogen" - if(3) - current_filter_type = "Carbon Dioxide" - if(4) - current_filter_type = "Nitrous Oxide" - if(-1) - current_filter_type = "Nothing" - else - current_filter_type = "ERROR - Report this bug to the admin, please!" + tgui_interact(user) - dat += {" - Power: [use_power?"On":"Off"]
- Filtering: [current_filter_type]

-

Set Filter Type:

- Phoron
- Oxygen
- Nitrogen
- Carbon Dioxide
- Nitrous Oxide
- Nothing
-
- Set Flow Rate Limit: - [src.set_flow_rate]L/s | Change
- Flow rate: [round(last_flow_rate, 0.1)]L/s - "} + // var/dat + // var/current_filter_type + // switch(filter_type) + // if(0) + // current_filter_type = "Phoron" + // if(1) + // current_filter_type = "Oxygen" + // if(2) + // current_filter_type = "Nitrogen" + // if(3) + // current_filter_type = "Carbon Dioxide" + // if(4) + // current_filter_type = "Nitrous Oxide" + // if(-1) + // current_filter_type = "Nothing" + // else + // current_filter_type = "ERROR - Report this bug to the admin, please!" - user << browse("[src.name] control[dat]", "window=atmos_filter") - onclose(user, "atmos_filter") - return + // dat += {" + // Power: [use_power?"On":"Off"]
+ // Filtering: [current_filter_type]

+ //

Set Filter Type:

+ // Phoron
+ // Oxygen
+ // Nitrogen
+ // Carbon Dioxide
+ // Nitrous Oxide
+ // Nothing
+ //
+ // Set Flow Rate Limit: + // [src.set_flow_rate]L/s | Change
+ // Flow rate: [round(last_flow_rate, 0.1)]L/s + // "} -/obj/machinery/atmospherics/trinary/atmos_filter/Topic(href, href_list) // -- TLE + // user << browse("[src.name] control[dat]", "window=atmos_filter") + // onclose(user, "atmos_filter") + + + +/obj/machinery/atmospherics/trinary/atmos_filter/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AtmosFilter", name) + ui.open() + +/obj/machinery/atmospherics/trinary/atmos_filter/tgui_data(mob/user) + var/list/data = list() + + data["on"] = use_power + data["rate"] = set_flow_rate + data["max_rate"] = air1.volume + + data["filter_types"] = list() + data["filter_types"] += list(list("name" = "Nothing", "f_type" = -1, "selected" = filter_type == -1)) + data["filter_types"] += list(list("name" = "Phoron", "f_type" = 0, "selected" = filter_type == 0)) + data["filter_types"] += list(list("name" = "Oxygen", "f_type" = 1, "selected" = filter_type == 1)) + data["filter_types"] += list(list("name" = "Nitrogen", "f_type" = 2, "selected" = filter_type == 2)) + data["filter_types"] += list(list("name" = "Carbon Dioxide", "f_type" = 3, "selected" = filter_type == 3)) + data["filter_types"] += list(list("name" = "Nitrous Oxide", "f_type" = 4, "selected" = filter_type == 4)) + + return data + +/obj/machinery/atmospherics/trinary/atmos_filter/tgui_act(action, params) if(..()) - return 1 - usr.set_machine(src) - src.add_fingerprint(usr) - if(href_list["filterset"]) - filter_type = text2num(href_list["filterset"]) + return TRUE - filtered_out.Cut() //no need to create new lists unnecessarily - switch(filter_type) - if(0) //removing hydrocarbons - filtered_out += "phoron" - filtered_out += "oxygen_agent_b" - if(1) //removing O2 - filtered_out += "oxygen" - if(2) //removing N2 - filtered_out += "nitrogen" - if(3) //removing CO2 - filtered_out += "carbon_dioxide" - if(4)//removing N2O - filtered_out += "sleeping_agent" + switch(action) + if("power") + update_use_power(!use_power) + if("rate") + var/rate = params["rate"] + if(rate == "max") + rate = air1.volume + . = TRUE + else if(text2num(rate) != null) + rate = text2num(rate) + . = TRUE + if(.) + set_flow_rate = clamp(rate, 0, air1.volume) + if("filter") + . = TRUE + filter_type = text2num(params["filterset"]) + filtered_out.Cut() //no need to create new lists unnecessarily + switch(filter_type) + if(0) //removing hydrocarbons + filtered_out += "phoron" + filtered_out += "oxygen_agent_b" + if(1) //removing O2 + filtered_out += "oxygen" + if(2) //removing N2 + filtered_out += "nitrogen" + if(3) //removing CO2 + filtered_out += "carbon_dioxide" + if(4)//removing N2O + filtered_out += "sleeping_agent" - if (href_list["temp"]) - src.temp = null - if(href_list["set_flow_rate"]) - var/new_flow_rate = input(usr,"Enter new flow rate (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate) as num - src.set_flow_rate = max(0, min(air1.volume, new_flow_rate)) - if(href_list["power"]) - update_use_power(!use_power) - src.update_icon() - src.updateUsrDialog() -/* - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) -*/ - return + add_fingerprint(usr) + update_icon() // // Mirrored Orientation - Flips the output dir to opposite side from normal. diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 62b4b763b8..ef2a4c1a8a 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -77,59 +77,88 @@ return 1 +/obj/machinery/atmospherics/trinary/mixer/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AtmosMixer", name) + ui.open() + +/obj/machinery/atmospherics/trinary/mixer/tgui_data(mob/user) + var/list/data = list() + data["on"] = use_power + data["set_pressure"] = round(set_flow_rate) + data["max_pressure"] = min(air1.volume, air2.volume) + data["node1_concentration"] = round(mixing_inputs[air1]*100, 1) + data["node2_concentration"] = round(mixing_inputs[air2]*100, 1) + var/list/node_connects = get_node_connect_dirs() + data["node1_dir"] = dir_name(node_connects[1],TRUE) + data["node2_dir"] = dir_name(node_connects[2],TRUE) + return data + /obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob) if(..()) return - src.add_fingerprint(usr) - if(!src.allowed(user)) - to_chat(user, "Access denied.") - return - usr.set_machine(src) - var/list/node_connects = get_node_connect_dirs() - var/dat = {"Power: [use_power?"On":"Off"]
- Set Flow Rate Limit: - [set_flow_rate]L/s | Change -
- Flow Rate: [round(last_flow_rate, 0.1)]L/s -

- Node 1 ([dir_name(node_connects[1],TRUE)]) Concentration: - - - - - [mixing_inputs[air1]]([mixing_inputs[air1]*100]%) - + - + -
- Node 2 ([dir_name(node_connects[2],TRUE)]) Concentration: - - - - - [mixing_inputs[air2]]([mixing_inputs[air2]*100]%) - + - + - "} + tgui_interact(user) + // src.add_fingerprint(usr) + // if(!src.allowed(user)) + // to_chat(user, "Access denied.") + // return + // usr.set_machine(src) + // var/list/node_connects = get_node_connect_dirs() + // var/dat = {"Power: [use_power?"On":"Off"]
+ // Set Flow Rate Limit: + // [set_flow_rate]L/s | Change + //
+ // Flow Rate: [round(last_flow_rate, 0.1)]L/s + //

+ // Node 1 ([dir_name(node_connects[1],TRUE)]) Concentration: + // - + // - + // [mixing_inputs[air1]]([mixing_inputs[air1]*100]%) + // + + // + + //
+ // Node 2 ([dir_name(node_connects[2],TRUE)]) Concentration: + // - + // - + // [mixing_inputs[air2]]([mixing_inputs[air2]*100]%) + // + + // + + // "} - user << browse("[src.name] control[dat]", "window=atmo_mixer") - onclose(user, "atmo_mixer") - return + // user << browse("[src.name] control[dat]", "window=atmo_mixer") + // onclose(user, "atmo_mixer") + // return -/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list) - if(..()) return 1 - if(href_list["power"]) - update_use_power(!use_power) - if(href_list["set_press"]) - var/max_flow_rate = min(air1.volume, air2.volume) - var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",src.set_flow_rate) as num - src.set_flow_rate = max(0, min(max_flow_rate, new_flow_rate)) - if(href_list["node1_c"]) - var/value = text2num(href_list["node1_c"]) - src.mixing_inputs[air1] = max(0, min(1, src.mixing_inputs[air1] + value)) - src.mixing_inputs[air2] = 1.0 - mixing_inputs[air1] - if(href_list["node2_c"]) - var/value = text2num(href_list["node2_c"]) - src.mixing_inputs[air2] = max(0, min(1, src.mixing_inputs[air2] + value)) - src.mixing_inputs[air1] = 1.0 - mixing_inputs[air2] - src.update_icon() - src.updateUsrDialog() - return +/obj/machinery/atmospherics/trinary/mixer/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("power") + update_use_power(!use_power) + . = TRUE + if("pressure") + var/pressure = params["pressure"] + if(pressure == "max") + pressure = min(air1.volume, air2.volume) + . = TRUE + else if(text2num(pressure) != null) + pressure = text2num(pressure) + . = TRUE + if(.) + set_flow_rate = clamp(pressure, 0, min(air1.volume, air2.volume)) + if("node1") + var/value = text2num(params["concentration"]) + mixing_inputs[air1] = max(0, min(1, value / 100)) + mixing_inputs[air2] = 1.0 - mixing_inputs[air1] + . = TRUE + if("node2") + var/value = text2num(params["concentration"]) + mixing_inputs[air2] = max(0, min(1, value / 100)) + mixing_inputs[air1] = 1.0 - mixing_inputs[air2] + . = TRUE + update_icon() // // "T" Orientation - Inputs are on oposite sides instead of adjacent diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm index 2c53c47583..3568a87a42 100644 --- a/code/ATMOSPHERICS/components/unary/cold_sink.dm +++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm @@ -53,12 +53,18 @@ return /obj/machinery/atmospherics/unary/freezer/attack_ai(mob/user as mob) - ui_interact(user) + tgui_interact(user) /obj/machinery/atmospherics/unary/freezer/attack_hand(mob/user as mob) - ui_interact(user) + tgui_interact(user) -/obj/machinery/atmospherics/unary/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/atmospherics/unary/freezer/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GasTemperatureSystem", name) + ui.open() + +/obj/machinery/atmospherics/unary/freezer/tgui_data(mob/user) // this is the data which will be sent to the ui var/data[0] data["on"] = use_power ? 1 : 0 @@ -76,34 +82,26 @@ temp_class = "average" data["gasTemperatureClass"] = temp_class - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 440, 300) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data -/obj/machinery/atmospherics/unary/freezer/Topic(href, href_list) +/obj/machinery/atmospherics/unary/freezer/tgui_act(action, params) if(..()) - return 1 - if(href_list["toggleStatus"]) - update_use_power(!use_power) - update_icon() - if(href_list["temp"]) - var/amount = text2num(href_list["temp"]) - if(amount > 0) - set_temperature = min(set_temperature + amount, 1000) - else - set_temperature = max(set_temperature + amount, 0) - if(href_list["setPower"]) //setting power to 0 is redundant anyways - var/new_setting = between(0, text2num(href_list["setPower"]), 100) - set_power_level(new_setting) + return TRUE + + . = TRUE + switch(action) + if("toggleStatus") + update_use_power(!use_power) + update_icon() + if("setGasTemperature") + var/amount = text2num(params["temp"]) + if(amount > 0) + set_temperature = min(amount, 1000) + else + set_temperature = max(amount, 0) + if("setPower") //setting power to 0 is redundant anyways + var/new_setting = between(0, text2num(params["value"]), 100) + set_power_level(new_setting) add_fingerprint(usr) diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm index ad852affdc..365be85b70 100644 --- a/code/ATMOSPHERICS/components/unary/heat_source.dm +++ b/code/ATMOSPHERICS/components/unary/heat_source.dm @@ -75,12 +75,18 @@ update_icon() /obj/machinery/atmospherics/unary/heater/attack_ai(mob/user as mob) - ui_interact(user) + tgui_interact(user) /obj/machinery/atmospherics/unary/heater/attack_hand(mob/user as mob) - ui_interact(user) + tgui_interact(user) -/obj/machinery/atmospherics/unary/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/atmospherics/unary/heater/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GasTemperatureSystem", name) + ui.open() + +/obj/machinery/atmospherics/unary/heater/tgui_data(mob/user) // this is the data which will be sent to the ui var/data[0] data["on"] = use_power ? 1 : 0 @@ -91,39 +97,31 @@ data["targetGasTemperature"] = round(set_temperature) data["powerSetting"] = power_setting - var/temp_class = "normal" + var/temp_class = "average" if(air_contents.temperature > (T20C+40)) temp_class = "bad" data["gasTemperatureClass"] = temp_class - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 440, 300) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data -/obj/machinery/atmospherics/unary/heater/Topic(href, href_list) +/obj/machinery/atmospherics/unary/heater/tgui_act(action, params) if(..()) - return 1 - if(href_list["toggleStatus"]) - update_use_power(!use_power) - update_icon() - if(href_list["temp"]) - var/amount = text2num(href_list["temp"]) - if(amount > 0) - set_temperature = min(set_temperature + amount, max_temperature) - else - set_temperature = max(set_temperature + amount, 0) - if(href_list["setPower"]) //setting power to 0 is redundant anyways - var/new_setting = between(0, text2num(href_list["setPower"]), 100) - set_power_level(new_setting) + return TRUE + + . = TRUE + switch(action) + if("toggleStatus") + update_use_power(!use_power) + update_icon() + if("setGasTemperature") + var/amount = text2num(params["temp"]) + if(amount > 0) + set_temperature = min(amount, max_temperature) + else + set_temperature = max(amount, 0) + if("setPower") //setting power to 0 is redundant anyways + var/new_setting = between(0, text2num(params["value"]), 100) + set_power_level(new_setting) add_fingerprint(usr) diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 593d3cbd8b..792d53d65d 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -374,6 +374,12 @@ ONE_ATMOSPHERE*50 ) + if("reset_external_pressure" in signal.data) + external_pressure_bound = ONE_ATMOSPHERE + + if("reset_internal_pressure" in signal.data) + internal_pressure_bound = 0 + if(signal.data["init"] != null) name = signal.data["init"] return diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 79b82bfe22..4e333dac06 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -58,6 +58,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define INIT_ORDER_MAPPING 25 #define INIT_ORDER_DECALS 20 #define INIT_ORDER_JOB 17 +#define INIT_ORDER_ALARM 16 // Must initialize before atoms. #define INIT_ORDER_ATOMS 15 #define INIT_ORDER_MACHINES 10 #define INIT_ORDER_SHUTTLES 3 @@ -70,7 +71,6 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define INIT_ORDER_HOLOMAPS -5 #define INIT_ORDER_NIGHTSHIFT -6 #define INIT_ORDER_OVERLAY -7 -#define INIT_ORDER_ALARM -8 #define INIT_ORDER_OPENSPACE -10 #define INIT_ORDER_XENOARCH -20 #define INIT_ORDER_CIRCUIT -21 diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 846b519f77..a2d3e9b728 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -101,6 +101,7 @@ var/list/outfits_decls_by_type_ H.equip_to_slot_or_del(new path(H), slot_in_backpack) post_equip(H) + if(W) // We set ID info last to ensure the ID photo is as correct as possible. H.set_id_info(W) return 1 diff --git a/code/game/machinery/air_alarm.dm b/code/game/machinery/air_alarm.dm index b410a40a64..041e43b905 100644 --- a/code/game/machinery/air_alarm.dm +++ b/code/game/machinery/air_alarm.dm @@ -125,6 +125,7 @@ // breathable air according to human/Life() TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa + TLV["nitrogen"] = list(0, 0,135,140) // Partial pressure, kpa TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa TLV["phoron"] = list(-1.0, -1.0, 0, 0.5) // Partial pressure, kpa TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa @@ -463,7 +464,7 @@ frequency.post_signal(src, alert_signal) /obj/machinery/alarm/attack_ai(mob/user) - ui_interact(user) + tgui_interact(user) /obj/machinery/alarm/attack_hand(mob/user) . = ..() @@ -472,157 +473,150 @@ return interact(user) /obj/machinery/alarm/interact(mob/user) - ui_interact(user) + tgui_interact(user) wires.Interact(user) -/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) - var/data[0] - var/remote_connection = 0 - var/remote_access = 0 - if(state) - var/list/href = state.href_list(user) - remote_connection = href["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer - remote_access = href["remote_access"] // Remote access means we also have the privilege to alter the air alarm. +/obj/machinery/alarm/tgui_status(mob/user) + if(isAI(user) && aidisabled) + to_chat(user, "AI control has been disabled.") + else if(!shorted) + return ..() + return STATUS_CLOSE - data["locked"] = locked && !issilicon(user) - data["remote_connection"] = remote_connection - data["remote_access"] = remote_access - data["rcon"] = rcon_setting - data["screen"] = screen - - populate_status(data) - - if(!(locked && !remote_connection) || remote_access || issilicon(user)) - populate_controls(data) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) +/obj/machinery/alarm/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, datum/tgui_state/state) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "air_alarm.tmpl", name, 325, 625, master_ui = master_ui, state = state) - ui.set_initial_data(data) + ui = new(user, src, "AirAlarm", name, parent_ui) + if(state) + ui.set_state(state) ui.open() - ui.set_auto_update(1) -/obj/machinery/alarm/proc/populate_status(var/data) - var/turf/location = get_turf(src) - var/datum/gas_mixture/environment = location.return_air() - var/total = environment.total_moles +/obj/machinery/alarm/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = list( + "locked" = locked, + "siliconUser" = issilicon(user), + "remoteUser" = !!ui.parent_ui, + "danger_level" = danger_level, + "target_temperature" = "[target_temperature - T0C]C", + "rcon" = rcon_setting, + ) - var/list/environment_data = new - data["has_environment"] = total - if(total) - var/pressure = environment.return_pressure() - environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon_dioxide"] / total * 100, "unit" = "%", "danger_level" = co2_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_dangerlevel) - data["total_danger"] = danger_level - data["environment"] = environment_data - data["atmos_alarm"] = alarm_area.atmosalm - data["fire_alarm"] = alarm_area.fire != null - data["target_temperature"] = "[target_temperature - T0C]C" + var/area/A = get_area(src) + data["atmos_alarm"] = A?.atmosalm + data["fire_alarm"] = A?.fire -/obj/machinery/alarm/proc/populate_controls(var/list/data) - switch(screen) - if(AALARM_SCREEN_MAIN) - data["mode"] = mode - if(AALARM_SCREEN_VENT) - var/vents[0] - for(var/id_tag in alarm_area.air_vent_names) - var/long_name = alarm_area.air_vent_names[id_tag] - var/list/info = alarm_area.air_vent_info[id_tag] - if(!info) - continue - vents[++vents.len] = list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "power" = info["power"], - "checks" = info["checks"], - "direction" = info["direction"], - "external" = info["external"] - ) - data["vents"] = vents - if(AALARM_SCREEN_SCRUB) - var/scrubbers[0] - for(var/id_tag in alarm_area.air_scrub_names) - var/long_name = alarm_area.air_scrub_names[id_tag] - var/list/info = alarm_area.air_scrub_info[id_tag] - if(!info) - continue - scrubbers[++scrubbers.len] = list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "power" = info["power"], - "scrubbing" = info["scrubbing"], - "panic" = info["panic"], - "filters" = list() - ) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Oxygen", "command" = "o2_scrub", "val" = info["filter_o2"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrogen", "command" = "n2_scrub", "val" = info["filter_n2"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Carbon Dioxide", "command" = "co2_scrub","val" = info["filter_co2"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Toxin" , "command" = "tox_scrub","val" = info["filter_phoron"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrous Oxide", "command" = "n2o_scrub","val" = info["filter_n2o"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Fuel", "command" = "fuel_scrub","val" = info["filter_fuel"])) - data["scrubbers"] = scrubbers - if(AALARM_SCREEN_MODE) - var/modes[0] - modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0) - modes[++modes.len] = list("name" = "Replace Air - Siphons out air while replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 0) - modes[++modes.len] = list("name" = "Panic - Siphons air out of the room", "mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1) - modes[++modes.len] = list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_CYCLE, "selected" = mode == AALARM_MODE_CYCLE, "danger" = 1) - modes[++modes.len] = list("name" = "Fill - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FILL, "selected" = mode == AALARM_MODE_FILL, "danger" = 0) - modes[++modes.len] = list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0) - data["modes"] = modes - data["mode"] = mode - if(AALARM_SCREEN_SENSORS) - var/list/selected - var/thresholds[0] + var/turf/T = get_turf(src) + var/datum/gas_mixture/environment = T.return_air() - var/list/gas_names = list( - "oxygen" = "O2", - "carbon dioxide" = "CO2", - "phoron" = "Toxin", - "other" = "Other") - for(var/g in gas_names) - thresholds[++thresholds.len] = list("name" = gas_names[g], "settings" = list()) - selected = TLV[g] - for(var/i = 1, i <= 4, i++) - thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i])) + data["environment_data"] = list() + var/pressure = environment.return_pressure() + data["environment_data"] += list(list( + "name" = "Pressure", + "value" = pressure, + "unit" = "kPa", + "danger_level" = get_danger_level(pressure, TLV["pressure"]) + )) + var/temperature = environment.temperature + data["environment_data"] += list(list( + "name" = "Temperature", + "value" = temperature, + "unit" = "K ([round(temperature - T0C, 0.1)]C)", + "danger_level" = get_danger_level(temperature, TLV["temperature"]) + )) - selected = TLV["pressure"] - thresholds[++thresholds.len] = list("name" = "Pressure", "settings" = list()) + var/total_moles = environment.total_moles + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume + for(var/gas_id in environment.gas) + if(!(gas_id in TLV)) + continue + data["environment_data"] += list(list( + "name" = gas_id, + "value" = environment.gas[gas_id] / total_moles * 100, + "unit" = "%", + "danger_level" = get_danger_level(environment.gas[gas_id] * partial_pressure, TLV[gas_id]) + )) + + if(!locked || issilicon(user) || data["remoteUser"]) + data["vents"] = list() + for(var/id_tag in A.air_vent_names) + var/long_name = A.air_vent_names[id_tag] + var/list/info = A.air_vent_info[id_tag] + if(!info) + continue + data["vents"] += list(list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "checks" = info["checks"], + "excheck" = info["checks"]&1, + "incheck" = info["checks"]&2, + "direction" = info["direction"], + "external" = info["external"], + "internal" = info["internal"], + "extdefault"= (info["external"] == ONE_ATMOSPHERE), + "intdefault"= (info["internal"] == 0), + )) + + data["scrubbers"] = list() + for(var/id_tag in alarm_area.air_scrub_names) + var/long_name = alarm_area.air_scrub_names[id_tag] + var/list/info = alarm_area.air_scrub_info[id_tag] + if(!info) + continue + data["scrubbers"] += list(list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "scrubbing" = info["scrubbing"], + "panic" = info["panic"], + "filters" = list() + )) + data["scrubbers"][data["scrubbers"].len]["filters"] += list(list("name" = "Oxygen", "command" = "o2_scrub", "val" = info["filter_o2"])) + data["scrubbers"][data["scrubbers"].len]["filters"] += list(list("name" = "Nitrogen", "command" = "n2_scrub", "val" = info["filter_n2"])) + data["scrubbers"][data["scrubbers"].len]["filters"] += list(list("name" = "Carbon Dioxide", "command" = "co2_scrub","val" = info["filter_co2"])) + data["scrubbers"][data["scrubbers"].len]["filters"] += list(list("name" = "Toxin" , "command" = "tox_scrub","val" = info["filter_phoron"])) + data["scrubbers"][data["scrubbers"].len]["filters"] += list(list("name" = "Nitrous Oxide", "command" = "n2o_scrub","val" = info["filter_n2o"])) + data["scrubbers"][data["scrubbers"].len]["filters"] += list(list("name" = "Fuel", "command" = "fuel_scrub","val" = info["filter_fuel"])) + + var/list/modes = list() + data["mode"] = mode + modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0) + modes[++modes.len] = list("name" = "Replace Air - Siphons out air while replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 0) + modes[++modes.len] = list("name" = "Panic - Siphons air out of the room", "mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1) + modes[++modes.len] = list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_CYCLE, "selected" = mode == AALARM_MODE_CYCLE, "danger" = 1) + modes[++modes.len] = list("name" = "Fill - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FILL, "selected" = mode == AALARM_MODE_FILL, "danger" = 0) + modes[++modes.len] = list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0) + data["modes"] = modes + + var/list/selected + var/list/thresholds = list() + + var/list/gas_names = list("oxygen", "carbon dioxide", "phoron", "other") + for(var/g in gas_names) + thresholds[++thresholds.len] = list("name" = g, "settings" = list()) + selected = TLV[g] for(var/i = 1, i <= 4, i++) - thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = i, "selected" = selected[i])) + thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i])) - selected = TLV["temperature"] - thresholds[++thresholds.len] = list("name" = "Temperature", "settings" = list()) - for(var/i = 1, i <= 4, i++) - thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = i, "selected" = selected[i])) + selected = TLV["pressure"] + thresholds[++thresholds.len] = list("name" = "Pressure", "settings" = list()) + for(var/i = 1, i <= 4, i++) + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = i, "selected" = selected[i])) - data["thresholds"] = thresholds + selected = TLV["temperature"] + thresholds[++thresholds.len] = list("name" = "Temperature", "settings" = list()) + for(var/i = 1, i <= 4, i++) + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = i, "selected" = selected[i])) -/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list()) - if(aidisabled && isAI(user)) - to_chat(user, "AI control for \the [src] interface has been disabled.") - return STATUS_CLOSE + data["thresholds"] = thresholds + return data - . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE +/obj/machinery/alarm/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - if(. == STATUS_INTERACTIVE) - var/extra_href = state.href_list(usr) - // Prevent remote users from altering RCON settings unless they already have access - if(href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"]) - . = STATUS_UPDATE - - return min(..(), .) - -/obj/machinery/alarm/Topic(href, href_list, var/datum/topic_state/state) - if(..(href, href_list, state)) - return 1 - - // hrefs that can always be called -walter0o - if(href_list["rcon"]) - var/attempted_rcon_setting = text2num(href_list["rcon"]) + if(action == "rcon") + var/attempted_rcon_setting = text2num(params["rcon"]) switch(attempted_rcon_setting) if(RCON_NO) @@ -631,9 +625,9 @@ rcon_setting = RCON_AUTO if(RCON_YES) rcon_setting = RCON_YES - return 1 + return TRUE - if(href_list["temperature"]) + if(action == "temperature") var/list/selected = TLV["temperature"] var/max_temperature = min(selected[3] - T0C, MAX_TEMPERATURE) var/min_temperature = max(selected[2] - T0C, MIN_TEMPERATURE) @@ -643,119 +637,80 @@ to_chat(usr, "Temperature must be between [min_temperature]C and [max_temperature]C") else target_temperature = input_temperature + T0C - return 1 + return TRUE + + // Account for remote users here. + // Yes, this is kinda snowflaky; however, I would argue it would be far more snowflakey + // to include "custom hrefs" and all the other bullshit that nano states have just for the + // like, two UIs, that want remote access to other UIs. + if((locked && !issilicon(usr) && !istype(state, /datum/tgui_state/air_alarm_remote)) || (issilicon(usr) && aidisabled)) + return - // hrefs that need the AA unlocked -walter0o - var/extra_href = state.href_list(usr) - if(!(locked && !extra_href["remote_connection"]) || extra_href["remote_access"] || issilicon(usr)) - if(href_list["command"]) - var/device_id = href_list["id_tag"] - switch(href_list["command"]) - if("set_external_pressure") - var/input_pressure = input("What pressure you like the system to mantain?", "Pressure Controls") as num|null - if(isnum(input_pressure)) - send_signal(device_id, list(href_list["command"] = input_pressure)) - return 1 + var/device_id = params["id_tag"] + switch(action) + if("lock") + if(issilicon(usr) && !wires.is_cut(WIRE_IDSCAN)) + locked = !locked + . = TRUE + if( "power", + "o2_scrub", + "n2_scrub", + "co2_scrub", + "tox_scrub", + "n2o_scrub", + "fuel_scrub", + "panic_siphon", + "scrubbing", + "direction") + send_signal(device_id, list("[action]" = text2num(params["val"])), usr) + . = TRUE + if("excheck") + send_signal(device_id, list("checks" = text2num(params["val"])^1), usr) + . = TRUE + if("incheck") + send_signal(device_id, list("checks" = text2num(params["val"])^2), usr) + . = TRUE + if("set_external_pressure", "set_internal_pressure") + var/target = params["value"] + if(!isnull(target)) + send_signal(device_id, list("[action]" = target), usr) + . = TRUE + if("reset_external_pressure") + send_signal(device_id, list("reset_external_pressure"), usr) + . = TRUE + if("reset_internal_pressure") + send_signal(device_id, list("reset_internal_pressure"), usr) + . = TRUE + if("threshold") + var/env = params["env"] - if("reset_external_pressure") - send_signal(device_id, list(href_list["command"] = ONE_ATMOSPHERE)) - return 1 - - if( "power", - "adjust_external_pressure", - "checks", - "o2_scrub", - "n2_scrub", - "co2_scrub", - "tox_scrub", - "n2o_scrub", - "fuel_scrub", - "panic_siphon", - "scrubbing", - "direction") - - send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]))) - return 1 - - if("set_threshold") - var/env = href_list["env"] - var/threshold = text2num(href_list["var"]) - var/list/selected = TLV[env] - var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") - var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null | num - if(isnull(newval)) - return 1 - if(newval<0) - selected[threshold] = -1.0 - else if(env=="temperature" && newval>5000) - selected[threshold] = 5000 - else if(env=="pressure" && newval>50*ONE_ATMOSPHERE) - selected[threshold] = 50*ONE_ATMOSPHERE - else if(env!="temperature" && env!="pressure" && newval>200) - selected[threshold] = 200 - else - newval = round(newval,0.01) - selected[threshold] = newval - if(threshold == 1) - if(selected[1] > selected[2]) - selected[2] = selected[1] - if(selected[1] > selected[3]) - selected[3] = selected[1] - if(selected[1] > selected[4]) - selected[4] = selected[1] - if(threshold == 2) - if(selected[1] > selected[2]) - selected[1] = selected[2] - if(selected[2] > selected[3]) - selected[3] = selected[2] - if(selected[2] > selected[4]) - selected[4] = selected[2] - if(threshold == 3) - if(selected[1] > selected[3]) - selected[1] = selected[3] - if(selected[2] > selected[3]) - selected[2] = selected[3] - if(selected[3] > selected[4]) - selected[4] = selected[3] - if(threshold == 4) - if(selected[1] > selected[4]) - selected[1] = selected[4] - if(selected[2] > selected[4]) - selected[2] = selected[4] - if(selected[3] > selected[4]) - selected[3] = selected[4] - - apply_mode() - return 1 - - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - return 1 - - if(href_list["atmos_unlock"]) - switch(href_list["atmos_unlock"]) - if("0") - alarm_area.firedoors_close() - if("1") - alarm_area.firedoors_open() - return 1 - - if(href_list["atmos_alarm"]) + var/name = params["var"] + var/value = input("New [name] for [env]:", name, TLV[env][name]) as num|null + if(!isnull(value) && !..()) + if(value < 0) + TLV[env][name] = -1 + else + TLV[env][name] = round(value, 0.01) + // investigate_log(" treshold value for [env]:[name] was set to [value] by [key_name(usr)]",INVESTIGATE_ATMOS) + . = TRUE + if("mode") + mode = text2num(params["mode"]) + // investigate_log("was turned to [get_mode_name(mode)] mode by [key_name(usr)]",INVESTIGATE_ATMOS) + apply_mode(usr) + . = TRUE + if("alarm") if(alarm_area.atmosalert(2, src)) apply_danger_level(2) - update_icon() - return 1 + . = TRUE + if("reset") + atmos_reset() + . = TRUE + update_icon() - if(href_list["atmos_reset"]) - if(alarm_area.atmosalert(0, src)) - apply_danger_level(0) - update_icon() - return 1 - - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - apply_mode() - return 1 +/obj/machinery/alarm/proc/atmos_reset() + if(alarm_area.atmosalert(0, src)) + apply_danger_level(0) + update_icon() /obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob) add_fingerprint(user) diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 5ebcfeef43..2d87fcd45a 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -94,7 +94,7 @@ obj/machinery/computer/general_air_control/Destroy() if(..(user)) return - ui_interact(user) + tgui_interact(user) /obj/machinery/computer/general_air_control/receive_signal(datum/signal/signal) if(!signal || signal.encryption) return @@ -104,9 +104,13 @@ obj/machinery/computer/general_air_control/Destroy() sensor_information[id_tag] = signal.data -/obj/machinery/computer/general_air_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/computer/general_air_control/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GeneralAtmoControl", name) + ui.open() +/obj/machinery/computer/general_air_control/tgui_data(mob/user) var/list/data = list() var/sensors_ui[0] if(sensors.len) @@ -119,12 +123,7 @@ obj/machinery/computer/general_air_control/Destroy() data["sensors"] = sensors_ui - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmo_control.tmpl", name, 525, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(5) + return data /obj/machinery/computer/general_air_control/proc/set_frequency(new_frequency) radio_controller.remove_object(src, frequency) @@ -147,20 +146,9 @@ obj/machinery/computer/general_air_control/Destroy() var/pressure_setting = ONE_ATMOSPHERE * 45 circuit = /obj/item/weapon/circuitboard/air_management/tank_control -/obj/machinery/computer/general_air_control/large_tank_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/computer/general_air_control/large_tank_control/tgui_data(mob/user) + var/list/data = ..() - var/list/data = list() - var/sensors_ui[0] - if(sensors.len) - for(var/id_tag in sensors) - var/long_name = sensors[id_tag] - var/list/sensor_data = sensor_information[id_tag] - sensors_ui[++sensors_ui.len] = list("long_name" = long_name, "sensor_data" = sensor_data) - else - sensors_ui = null - - data["sensors"] = sensors_ui data["tanks"] = 1 if(input_info) @@ -175,13 +163,10 @@ obj/machinery/computer/general_air_control/Destroy() data["input_flow_setting"] = round(input_flow_setting, 0.1) data["pressure_setting"] = pressure_setting + data["max_pressure"] = 50*ONE_ATMOSPHERE + data["max_flowrate"] = ATMOS_DEFAULT_VOLUME_PUMP + 500 - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmo_control.tmpl", name, 660, 500) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(5) + return data /obj/machinery/computer/general_air_control/large_tank_control/receive_signal(datum/signal/signal) if(!signal || signal.encryption) return @@ -195,54 +180,56 @@ obj/machinery/computer/general_air_control/Destroy() else ..(signal) -/obj/machinery/computer/general_air_control/large_tank_control/Topic(href, href_list) +/obj/machinery/computer/general_air_control/large_tank_control/tgui_act(action, params) if(..()) - return 1 + return TRUE - if(href_list["adj_pressure"]) - var/change = text2num(href_list["adj_pressure"]) - pressure_setting = between(0, pressure_setting + change, 50*ONE_ATMOSPHERE) - return 1 + switch(action) + if("adj_pressure") + var/new_pressure = text2num(params["adj_pressure"]) + pressure_setting = between(0, new_pressure, 50*ONE_ATMOSPHERE) + return TRUE - if(href_list["adj_input_flow_rate"]) - var/change = text2num(href_list["adj_input_flow_rate"]) - input_flow_setting = between(0, input_flow_setting + change, ATMOS_DEFAULT_VOLUME_PUMP + 500) //default flow rate limit for air injectors - return 1 + if("adj_input_flow_rate") + var/new_flow = text2num(params["adj_input_flow_rate"]) + input_flow_setting = between(0, new_flow, ATMOS_DEFAULT_VOLUME_PUMP + 500) //default flow rate limit for air injectors + return TRUE if(!radio_connection) - return 0 + return FALSE var/datum/signal/signal = new signal.transmission_method = TRANSMISSION_RADIO //radio signal signal.source = src - if(href_list["in_refresh_status"]) - input_info = null - signal.data = list ("tag" = input_tag, "status" = 1) - . = 1 + switch(action) + if("in_refresh_status") + input_info = null + signal.data = list ("tag" = input_tag, "status" = 1) + . = TRUE - if(href_list["in_toggle_injector"]) - input_info = null - signal.data = list ("tag" = input_tag, "power_toggle" = 1) - . = 1 + if("in_toggle_injector") + input_info = null + signal.data = list ("tag" = input_tag, "power_toggle" = 1) + . = TRUE - if(href_list["in_set_flowrate"]) - input_info = null - signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]") - . = 1 + if("in_set_flowrate") + input_info = null + signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]") + . = TRUE - if(href_list["out_refresh_status"]) - output_info = null - signal.data = list ("tag" = output_tag, "status" = 1) - . = 1 + if("out_refresh_status") + output_info = null + signal.data = list ("tag" = output_tag, "status" = 1) + . = TRUE - if(href_list["out_toggle_power"]) - output_info = null - signal.data = list ("tag" = output_tag, "power_toggle" = 1) - . = 1 + if("out_toggle_power") + output_info = null + signal.data = list ("tag" = output_tag, "power_toggle" = 1) + . = TRUE - if(href_list["out_set_pressure"]) - output_info = null - signal.data = list ("tag" = output_tag, "set_internal_pressure" = "[pressure_setting]") - . = 1 + if("out_set_pressure") + output_info = null + signal.data = list ("tag" = output_tag, "set_internal_pressure" = "[pressure_setting]") + . = TRUE signal.data["sigtype"]="command" radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) @@ -258,40 +245,29 @@ obj/machinery/computer/general_air_control/Destroy() var/pressure_setting = 100 circuit = /obj/item/weapon/circuitboard/air_management/supermatter_core -/obj/machinery/computer/general_air_control/supermatter_core/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - - var/list/data = list() - var/sensors_ui[0] - if(sensors.len) - for(var/id_tag in sensors) - var/long_name = sensors[id_tag] - var/list/sensor_data = sensor_information[id_tag] - sensors_ui[++sensors_ui.len] = list("long_name" = long_name, "sensor_data" = sensor_data) - else - sensors_ui = null - - data["sensors"] = sensors_ui +/obj/machinery/computer/general_air_control/supermatter_core/tgui_data(mob/user) + var/list/data = ..() data["core"] = 1 if(input_info) data["input_info"] = list("power" = input_info["power"], "volume_rate" = round(input_info["volume_rate"], 0.1)) else data["input_info"] = null + if(output_info) - data["output_info"] = list("power" = output_info["power"], "pressure_limit" = output_info["external"]) + // Yes, TECHNICALLY this is not output pressure, it's a pressure LIMIT. HOWEVER. The fact that the UI uses "output_pressure" + // in EXACTLY THE SAME WAY as "pressure_limit" means this should just pass it as the other fucking data argument because holy shit what the + // fuck + data["output_info"] = list("power" = output_info["power"], "output_pressure" = output_info["external"]) else data["output_info"] = null data["input_flow_setting"] = round(input_flow_setting, 0.1) data["pressure_setting"] = pressure_setting + data["max_pressure"] = 10*ONE_ATMOSPHERE + data["max_flowrate"] = ATMOS_DEFAULT_VOLUME_PUMP + 500 - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmo_control.tmpl", name, 650, 500) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(5) + return data /obj/machinery/computer/general_air_control/supermatter_core/receive_signal(datum/signal/signal) if(!signal || signal.encryption) return @@ -305,54 +281,56 @@ obj/machinery/computer/general_air_control/Destroy() else ..(signal) -/obj/machinery/computer/general_air_control/supermatter_core/Topic(href, href_list) +/obj/machinery/computer/general_air_control/supermatter_core/tgui_act(action, params) if(..()) - return 1 + return TRUE - if(href_list["adj_pressure"]) - var/change = text2num(href_list["adj_pressure"]) - pressure_setting = between(0, pressure_setting + change, 10*ONE_ATMOSPHERE) - return 1 + switch(action) + if("adj_pressure") + var/new_pressure = text2num(params["adj_pressure"]) + pressure_setting = between(0, new_pressure, 10*ONE_ATMOSPHERE) + return TRUE - if(href_list["adj_input_flow_rate"]) - var/change = text2num(href_list["adj_input_flow_rate"]) - input_flow_setting = between(0, input_flow_setting + change, ATMOS_DEFAULT_VOLUME_PUMP + 500) //default flow rate limit for air injectors - return 1 + if("adj_input_flow_rate") + var/new_flow = text2num(params["adj_input_flow_rate"]) + input_flow_setting = between(0, new_flow, ATMOS_DEFAULT_VOLUME_PUMP + 500) //default flow rate limit for air injectors + return TRUE if(!radio_connection) - return 0 + return FALSE var/datum/signal/signal = new signal.transmission_method = TRANSMISSION_RADIO //radio signal signal.source = src - if(href_list["in_refresh_status"]) - input_info = null - signal.data = list ("tag" = input_tag, "status" = 1) - . = 1 + switch(action) + if("in_refresh_status") + input_info = null + signal.data = list ("tag" = input_tag, "status" = 1) + . = TRUE - if(href_list["in_toggle_injector"]) - input_info = null - signal.data = list ("tag" = input_tag, "power_toggle" = 1) - . = 1 + if("in_toggle_injector") + input_info = null + signal.data = list ("tag" = input_tag, "power_toggle" = 1) + . = TRUE - if(href_list["in_set_flowrate"]) - input_info = null - signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]") - . = 1 + if("in_set_flowrate") + input_info = null + signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]") + . = TRUE - if(href_list["out_refresh_status"]) - output_info = null - signal.data = list ("tag" = output_tag, "status" = 1) - . = 1 + if("out_refresh_status") + output_info = null + signal.data = list ("tag" = output_tag, "status" = 1) + . = TRUE - if(href_list["out_toggle_power"]) - output_info = null - signal.data = list ("tag" = output_tag, "power_toggle" = 1) - . = 1 + if("out_toggle_power") + output_info = null + signal.data = list ("tag" = output_tag, "power_toggle" = 1) + . = TRUE - if(href_list["out_set_pressure"]) - output_info = null - signal.data = list ("tag" = output_tag, "set_external_pressure" = "[pressure_setting]", "checks" = 1) - . = 1 + if("out_set_pressure") + output_info = null + signal.data = list ("tag" = output_tag, "set_external_pressure" = "[pressure_setting]", "checks" = 1) + . = TRUE signal.data["sigtype"]="command" radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) @@ -370,7 +348,7 @@ obj/machinery/computer/general_air_control/Destroy() /obj/machinery/computer/general_air_control/fuel_injection/process() if(automation) if(!radio_connection) - return 0 + return FALSE var/injecting = 0 for(var/id_tag in sensor_information) @@ -396,20 +374,8 @@ obj/machinery/computer/general_air_control/Destroy() ..() -/obj/machinery/computer/general_air_control/fuel_injection/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - - var/list/data = list() - var/sensors_ui[0] - if(sensors.len) - for(var/id_tag in sensors) - var/long_name = sensors[id_tag] - var/list/sensor_data = sensor_information[id_tag] - sensors_ui[++sensors_ui.len] = list("long_name" = long_name, "sensor_data" = sensor_data) - else - sensors_ui = null - - data["sensors"] = sensors_ui +/obj/machinery/computer/general_air_control/fuel_injection/tgui_data(mob/user) + var/list/data = ..() data["fuel"] = 1 data["automation"] = automation @@ -418,12 +384,7 @@ obj/machinery/computer/general_air_control/Destroy() else data["device_info"] = null - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmo_control.tmpl", name, 650, 500) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(5) + return data /obj/machinery/computer/general_air_control/fuel_injection/receive_signal(datum/signal/signal) if(!signal || signal.encryption) return @@ -435,55 +396,60 @@ obj/machinery/computer/general_air_control/Destroy() else ..(signal) -/obj/machinery/computer/general_air_control/fuel_injection/Topic(href, href_list) +/obj/machinery/computer/general_air_control/fuel_injection/tgui_act(action, params) if(..()) - return + return TRUE + + switch(action) + if("refresh_status") + device_info = null + if(!radio_connection) + return FALSE - if(href_list["refresh_status"]) - device_info = null - if(!radio_connection) - return 0 + var/datum/signal/signal = new + signal.transmission_method = TRANSMISSION_RADIO //radio signal + signal.source = src + signal.data = list( + "tag" = device_tag, + "status" = 1, + "sigtype"="command" + ) + radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) + . = TRUE - var/datum/signal/signal = new - signal.transmission_method = TRANSMISSION_RADIO //radio signal - signal.source = src - signal.data = list( - "tag" = device_tag, - "status" = 1, - "sigtype"="command" - ) - radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) + if("toggle_automation") + automation = !automation + . = TRUE - if(href_list["toggle_automation"]) - automation = !automation + if("toggle_injector") + device_info = null + if(!radio_connection) + return FALSE - if(href_list["toggle_injector"]) - device_info = null - if(!radio_connection) - return 0 + var/datum/signal/signal = new + signal.transmission_method = TRANSMISSION_RADIO //radio signal + signal.source = src + signal.data = list( + "tag" = device_tag, + "power_toggle" = 1, + "sigtype"="command" + ) - var/datum/signal/signal = new - signal.transmission_method = TRANSMISSION_RADIO //radio signal - signal.source = src - signal.data = list( - "tag" = device_tag, - "power_toggle" = 1, - "sigtype"="command" - ) + radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) + . = TRUE - radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) + if("injection") + if(!radio_connection) + return FALSE - if(href_list["injection"]) - if(!radio_connection) - return 0 + var/datum/signal/signal = new + signal.transmission_method = TRANSMISSION_RADIO //radio signal + signal.source = src + signal.data = list( + "tag" = device_tag, + "inject" = 1, + "sigtype"="command" + ) - var/datum/signal/signal = new - signal.transmission_method = TRANSMISSION_RADIO //radio signal - signal.source = src - signal.data = list( - "tag" = device_tag, - "inject" = 1, - "sigtype"="command" - ) - - radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) \ No newline at end of file + radio_connection.post_signal(src, signal, radio_filter = RADIO_ATMOSIA) + . = TRUE \ No newline at end of file diff --git a/code/game/machinery/atmoalter/area_atmos_computer.dm b/code/game/machinery/atmoalter/area_atmos_computer.dm index 125b55eb7f..55523ed079 100644 --- a/code/game/machinery/atmoalter/area_atmos_computer.dm +++ b/code/game/machinery/atmoalter/area_atmos_computer.dm @@ -24,94 +24,70 @@ /obj/machinery/computer/area_atmos/attack_hand(var/mob/user as mob) if(..(user)) return - src.add_fingerprint(usr) - var/dat = {" - - - - - -

Area Air Control

- [status]
- Scan - "} - for(var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber in connectedscrubbers) - dat += {" - - - - "} + tgui_interact(user) - dat += {" -
- [scrubber.name]
- Pressure: [round(scrubber.air_contents.return_pressure(), 0.01)] kPa
- Flow Rate: [round(scrubber.last_flow_rate,0.1)] L/s
-
- Turn On - Turn Off
- Load: [round(scrubber.last_power_draw)] W -

- [zone] - - "} - user << browse("[dat]", "window=miningshuttle;size=400x400") - status = "" - -/obj/machinery/computer/area_atmos/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - - - if(href_list["scan"]) - scanscrubbers() - else if(href_list["toggle"]) - var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber = locate(href_list["scrub"]) +/obj/machinery/computer/area_atmos/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AreaScrubberControl", name) + ui.open() +/obj/machinery/computer/area_atmos/tgui_data(mob/user) + var/list/data = list() + + data["scrubbers"] = list() + for(var/id in connectedscrubbers) + var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber = connectedscrubbers[id] if(!validscrubber(scrubber)) - spawn(20) - status = "ERROR: Couldn't connect to scrubber! (timeout)" - connectedscrubbers -= scrubber - src.updateUsrDialog() - return + connectedscrubbers -= scrubber + continue + data["scrubbers"].Add(list(list( + "id" = id, + "name" = scrubber.name, + "on" = scrubber.on, + "pressure" = scrubber.air_contents.return_pressure(), + "flow_rate" = scrubber.last_flow_rate, + "load" = scrubber.last_power_draw, + "area" = get_area(scrubber), + ))) - scrubber.on = text2num(href_list["toggle"]) - scrubber.update_icon() + return data + +/obj/machinery/computer/area_atmos/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("toggle") + var/scrub_id = params["id"] + var/obj/machinery/portable_atmospherics/powered/scrubber/huge/S = connectedscrubbers["[scrub_id]"] + if(!validscrubber(S)) + connectedscrubbers -= S + return TRUE + S.on = !S.on + S.update_icon() + . = TRUE + if("allon") + INVOKE_ASYNC(src, .proc/toggle_all, TRUE) + . = TRUE + if("alloff") + INVOKE_ASYNC(src, .proc/toggle_all, FALSE) + . = TRUE + if("scan") + scanscrubbers() + . = TRUE + + add_fingerprint(usr) + +/obj/machinery/computer/area_atmos/proc/toggle_all(on) + for(var/id in connectedscrubbers) + var/obj/machinery/portable_atmospherics/powered/scrubber/huge/S = connectedscrubbers["[id]"] + if(!validscrubber(S)) + connectedscrubbers -= S + continue + S.on = on + S.update_icon() + CHECK_TICK /obj/machinery/computer/area_atmos/proc/validscrubber(obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber as obj) if(!isobj(scrubber) || get_dist(scrubber.loc, src.loc) > src.range || scrubber.loc.z != src.loc.z) @@ -119,13 +95,12 @@ return TRUE /obj/machinery/computer/area_atmos/proc/scanscrubbers() - connectedscrubbers = new() + connectedscrubbers = list() var/found = 0 for(var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber in range(range, src.loc)) - if(istype(scrubber)) - found = 1 - connectedscrubbers += scrubber + found = 1 + connectedscrubbers["[scrubber.id]"] = scrubber if(!found) status = "ERROR: No scrubber found!" @@ -142,7 +117,7 @@ var/found = 0 var/area/A = get_area(src) for(var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber in A) - connectedscrubbers += scrubber + connectedscrubbers["[scrubber.id]"] = scrubber found = 1 if(!found) @@ -151,7 +126,10 @@ src.updateUsrDialog() /obj/machinery/computer/area_atmos/area/validscrubber(var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber) - if(get_area(scrubber) == get_area(src)) - return 1 + if(!istype(scrubber)) + return FALSE - return 0 + if(get_area(scrubber) == get_area(src)) + return TRUE + + return FALSE diff --git a/code/game/machinery/atmoalter/area_atmos_computer_vr.dm b/code/game/machinery/atmoalter/area_atmos_computer_vr.dm index e489bb39fb..e20e8e1b71 100644 --- a/code/game/machinery/atmoalter/area_atmos_computer_vr.dm +++ b/code/game/machinery/atmoalter/area_atmos_computer_vr.dm @@ -17,12 +17,15 @@ for(var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber in world) if(scrubber.scrub_id == src.scrub_id) - connectedscrubbers += scrubber + connectedscrubbers["[scrubber.id]"] = scrubber - src.updateUsrDialog() + SStgui.update_uis(src) /obj/machinery/computer/area_atmos/tag/validscrubber(var/obj/machinery/portable_atmospherics/powered/scrubber/huge/scrubber) + if(!istype(scrubber)) + return FALSE + if(scrubber.scrub_id == src.scrub_id) - return 1 + return TRUE - return 0 + return FALSE \ No newline at end of file diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 3a012a1ccd..7faf1115fe 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -266,105 +266,108 @@ update_flag return src.attack_hand(user) /obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) - return src.ui_interact(user) + return tgui_interact(user) -/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if (src.destroyed) +/obj/machinery/portable_atmospherics/canister/tgui_state(mob/user) + return GLOB.tgui_physical_state + +/obj/machinery/portable_atmospherics/canister/tgui_interact(mob/user, datum/tgui/ui) + if(destroyed) return + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Canister", name) + ui.open() - // this is the data which will be sent to the ui - var/data[0] - data["name"] = name +/obj/machinery/portable_atmospherics/canister/tgui_data(mob/user) + var/list/data = list() data["canLabel"] = can_label ? 1 : 0 - data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) + data["connected"] = connected_port ? 1 : 0 + data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) data["releasePressure"] = round(release_pressure ? release_pressure : 0) + data["defaultReleasePressure"] = round(initial(release_pressure)) data["minReleasePressure"] = round(ONE_ATMOSPHERE/10) data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE) data["valveOpen"] = valve_open ? 1 : 0 - data["hasHoldingTank"] = holding ? 1 : 0 - if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure())) + if(holding) + data["holding"] = list() + data["holding"]["name"] = holding.name + data["holding"]["pressure"] = round(holding.air_contents.return_pressure()) + else + data["holding"] = null - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data -/obj/machinery/portable_atmospherics/canister/Topic(href, href_list) +/obj/machinery/portable_atmospherics/canister/tgui_act(action, params) + if(..()) + return TRUE - //Do not use "if(..()) return" here, canisters will stop working in unpowered areas like space or on the derelict. // yeah but without SOME sort of Topic check any dick can mess with them via exploits as he pleases -walter0o - //First comment might be outdated. - if (!istype(src.loc, /turf)) - return 0 - - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) // exploit protection -walter0o - usr << browse(null, "window=canister") - onclose(usr, "canister") - return - - if(href_list["toggle"]) - if (valve_open) - if (holding) - release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding]
" + switch(action) + if("relabel") + if(can_label) + var/list/colors = list(\ + "\[N2O\]" = "redws", \ + "\[N2\]" = "red", \ + "\[O2\]" = "blue", \ + "\[Phoron\]" = "orangeps", \ + "\[CO2\]" = "black", \ + "\[Air\]" = "grey", \ + "\[CAUTION\]" = "yellow", \ + ) + var/label = input("Choose canister label", "Gas canister") as null|anything in colors + if(label) + canister_color = colors[label] + icon_state = colors[label] + name = "Canister: [label]" + if("pressure") + var/pressure = params["pressure"] + if(pressure == "reset") + pressure = initial(release_pressure) + . = TRUE + else if(pressure == "min") + pressure = ONE_ATMOSPHERE/10 + . = TRUE + else if(pressure == "max") + pressure = 10*ONE_ATMOSPHERE + . = TRUE + else if(pressure == "input") + pressure = input("New release pressure ([ONE_ATMOSPHERE/10]-[10*ONE_ATMOSPHERE] kPa):", name, release_pressure) as num|null + if(!isnull(pressure) && !..()) + . = TRUE + else if(text2num(pressure) != null) + pressure = text2num(pressure) + . = TRUE + if(.) + release_pressure = clamp(round(pressure), ONE_ATMOSPHERE/10, 10*ONE_ATMOSPHERE) + if("valve") + if(valve_open) + if(holding) + release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding]
" + else + release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the air
" else - release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the air
" - else - if (holding) - release_log += "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the [holding]
" - else - release_log += "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the air
" - log_open() - valve_open = !valve_open + if(holding) + release_log += "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the [holding]
" + else + release_log += "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the air
" + log_open() + valve_open = !valve_open + . = TRUE + if("eject") + if(holding) + if(valve_open) + valve_open = 0 + release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding]
" + if(istype(holding, /obj/item/weapon/tank)) + holding.manipulated_by = usr.real_name + holding.loc = loc + holding = null + . = TRUE - if (href_list["remove_tank"]) - if(holding) - if (valve_open) - valve_open = 0 - release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding]
" - if(istype(holding, /obj/item/weapon/tank)) - holding.manipulated_by = usr.real_name - holding.loc = loc - holding = null - - if (href_list["pressure_adj"]) - var/diff = text2num(href_list["pressure_adj"]) - if(diff > 0) - release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff) - else - release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff) - - if (href_list["relabel"]) - if (can_label) - var/list/colors = list(\ - "\[N2O\]" = "redws", \ - "\[N2\]" = "red", \ - "\[O2\]" = "blue", \ - "\[Phoron\]" = "orangeps", \ - "\[CO2\]" = "black", \ - "\[Air\]" = "grey", \ - "\[CAUTION\]" = "yellow", \ - ) - var/label = input("Choose canister label", "Gas canister") as null|anything in colors - if (label) - src.canister_color = colors[label] - src.icon_state = colors[label] - src.name = "Canister: [label]" - - src.add_fingerprint(usr) + add_fingerprint(usr) update_icon() - return 1 - /obj/machinery/portable_atmospherics/canister/phoron/New() ..() diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index 758c2a57cb..74e4804661 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -119,51 +119,73 @@ return src.attack_hand(user) /obj/machinery/portable_atmospherics/powered/pump/attack_hand(var/mob/user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/portable_atmospherics/powered/pump/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1) +/obj/machinery/portable_atmospherics/powered/pump/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortablePump", name) + ui.open() + + +/obj/machinery/portable_atmospherics/powered/pump/tgui_state(mob/user) + return GLOB.tgui_physical_state + +/obj/machinery/portable_atmospherics/powered/pump/tgui_data(mob/user) var/list/data[0] - data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) - data["targetpressure"] = round(target_pressure) - data["pump_dir"] = direction_out - data["minpressure"] = round(pressuremin) - data["maxpressure"] = round(pressuremax) + data["on"] = on ? TRUE : FALSE + data["direction"] = !direction_out ? TRUE : FALSE + data["connected"] = connected_port ? TRUE : FALSE + data["pressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["target_pressure"] = round(target_pressure ? target_pressure : 0) + data["default_pressure"] = round(initial(target_pressure)) + data["min_pressure"] = round(pressuremin) + data["max_pressure"] = round(pressuremax) + data["powerDraw"] = round(last_power_draw) data["cellCharge"] = cell ? cell.charge : 0 data["cellMaxCharge"] = cell ? cell.maxcharge : 1 - data["on"] = on ? 1 : 0 - data["hasHoldingTank"] = holding ? 1 : 0 - if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + if(holding) + data["holding"] = list() + data["holding"]["name"] = holding.name + data["holding"]["pressure"] = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0) + else + data["holding"] = null + + return data - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "portpump.tmpl", "Portable Pump", 480, 410, state = physical_state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/portable_atmospherics/powered/pump/Topic(href, href_list) +/obj/machinery/portable_atmospherics/powered/pump/tgui_act(action, params) if(..()) - return 1 + return TRUE - if(href_list["power"]) - on = !on - . = 1 - if(href_list["direction"]) - direction_out = !direction_out - . = 1 - if (href_list["remove_tank"]) - if(holding) - holding.loc = loc - holding = null - . = 1 - if (href_list["pressure_adj"]) - var/diff = text2num(href_list["pressure_adj"]) - target_pressure = min(10*ONE_ATMOSPHERE, max(0, target_pressure+diff)) - . = 1 + switch(action) + if("power") + on = !on + . = 1 + if("direction") + direction_out = !direction_out + . = 1 + if("eject") + if(holding) + holding.loc = loc + holding = null + . = 1 + if("pressure") + var/pressure = params["pressure"] + if(pressure == "reset") + pressure = initial(target_pressure) + . = TRUE + else if(pressure == "min") + pressure = pressuremin + . = TRUE + else if(pressure == "max") + pressure = pressuremax + . = TRUE + else if(text2num(pressure) != null) + pressure = text2num(pressure) + . = TRUE + if(.) + target_pressure = clamp(round(pressure), pressuremin, pressuremax) - if(.) - update_icon() + update_icon() diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 219cf7801f..b6e4c0e124 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -96,49 +96,53 @@ return src.attack_hand(user) /obj/machinery/portable_atmospherics/powered/scrubber/attack_hand(var/mob/user) - ui_interact(user) - return + tgui_interact(user) -/obj/machinery/portable_atmospherics/powered/scrubber/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1) - var/list/data[0] - data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) +/obj/machinery/portable_atmospherics/powered/scrubber/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableScrubber", name) + ui.open() + +/obj/machinery/portable_atmospherics/powered/scrubber/tgui_data(mob/user) + var/list/data = list() + data["on"] = on ? 1 : 0 + data["connected"] = connected_port ? 1 : 0 + data["pressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["rate"] = round(volume_rate) data["minrate"] = round(minrate) data["maxrate"] = round(maxrate) data["powerDraw"] = round(last_power_draw) data["cellCharge"] = cell ? cell.charge : 0 data["cellMaxCharge"] = cell ? cell.maxcharge : 1 - data["on"] = on ? 1 : 0 - data["hasHoldingTank"] = holding ? 1 : 0 - if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + if(holding) + data["holding"] = list() + data["holding"]["name"] = holding.name + data["holding"]["pressure"] = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0) + else + data["holding"] = null - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "portscrubber.tmpl", "Portable Scrubber", 480, 400, state = physical_state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data - -/obj/machinery/portable_atmospherics/powered/scrubber/Topic(href, href_list) +/obj/machinery/portable_atmospherics/powered/scrubber/tgui_act(action, params) if(..()) - return 1 + return TRUE + + switch(action) + if("power") + on = !on + . = TRUE + if("eject") + if(holding) + holding.loc = loc + holding = null + . = TRUE + if("volume_adj") + volume_rate = CLAMP(text2num(params["vol"]), minrate, maxrate) + . = TRUE - if(href_list["power"]) - on = !on - . = 1 - if (href_list["remove_tank"]) - if(holding) - holding.loc = loc - holding = null - . = 1 - if (href_list["volume_adj"]) - var/diff = text2num(href_list["volume_adj"]) - volume_rate = CLAMP(volume_rate+diff, minrate, maxrate) - . = 1 update_icon() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 4bd203d0ba..73b78cb148 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -447,7 +447,7 @@ network.Cut() update_coverage(1) -/obj/machinery/camera/proc/nano_structure() +/obj/machinery/camera/proc/tgui_structure() var/cam[0] cam["name"] = sanitize(c_tag) cam["deact"] = !can_use() diff --git a/code/game/machinery/computer/RCON_Console.dm b/code/game/machinery/computer/RCON_Console.dm index fbd1190fd7..d6df0d2d6d 100644 --- a/code/game/machinery/computer/RCON_Console.dm +++ b/code/game/machinery/computer/RCON_Console.dm @@ -13,7 +13,7 @@ circuit = /obj/item/weapon/circuitboard/rcon_console req_one_access = list(access_engine) var/current_tag = null - var/datum/nano_module/rcon/rcon + var/datum/tgui_module/rcon/rcon /obj/machinery/computer/rcon/New() ..() @@ -29,13 +29,12 @@ // Description: Opens UI of this machine. /obj/machinery/computer/rcon/attack_hand(var/mob/user as mob) ..() - ui_interact(user) + tgui_interact(user) // Proc: ui_interact() -// Parameters: 4 (standard NanoUI parameters) -// Description: Uses dark magic (NanoUI) to render this machine's UI -/obj/machinery/computer/rcon/ui_interact(mob/user, ui_key = "rcon", var/datum/nanoui/ui = null, var/force_open = 1) - rcon.ui_interact(user, ui_key, ui, force_open) +// Description: Uses dark magic (TGUI) to render this machine's UI +/obj/machinery/computer/rcon/tgui_interact(mob/user, datum/tgui/ui) + rcon.tgui_interact(user, ui) /obj/machinery/computer/rcon/update_icon() ..() diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index f83a87c266..3ec9e2c841 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -82,7 +82,7 @@ /obj/machinery/computer/aifixer/tgui_act(action, params) if(..()) - return + return TRUE if(!occupier) restoring = FALSE diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index 7f5c27a0d4..304c254837 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -17,16 +17,22 @@ var/global/list/minor_air_alarms = list() atmosphere_alarm.register_alarm(src, /obj/machinery/computer/station_alert/update_icon) /obj/machinery/computer/atmos_alert/Destroy() - atmosphere_alarm.unregister_alarm(src) - ..() + atmosphere_alarm.unregister_alarm(src) + ..() /obj/machinery/computer/atmos_alert/attack_hand(mob/user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - var/major_alarms[0] - var/minor_alarms[0] +/obj/machinery/computer/atmos_alert/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AtmosAlertConsole", name) + ui.open() + +/obj/machinery/computer/atmos_alert/tgui_data(mob/user) + var/list/data = list() + var/list/major_alarms = list() + var/list/minor_alarms = list() for(var/datum/alarm/alarm in atmosphere_alarm.major_alarms(get_z(src))) major_alarms[++major_alarms.len] = list("name" = sanitize(alarm.alarm_name()), "ref" = "\ref[alarm]") @@ -37,12 +43,7 @@ var/global/list/minor_air_alarms = list() data["priority_alarms"] = major_alarms data["minor_alarms"] = minor_alarms - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmos_alert.tmpl", src.name, 500, 500) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data /obj/machinery/computer/atmos_alert/update_icon() if(!(stat & (NOPOWER|BROKEN))) @@ -57,26 +58,21 @@ var/global/list/minor_air_alarms = list() icon_screen = initial(icon_screen) ..() -/obj/machinery/computer/atmos_alert/Topic(href, href_list) +/obj/machinery/computer/atmos_alert/tgui_act(action, params) if(..()) - return 1 + return TRUE - if(href_list["clear_alarm"]) - var/datum/alarm/alarm = locate(href_list["clear_alarm"]) in atmosphere_alarm.alarms - if(alarm) - for(var/datum/alarm_source/alarm_source in alarm.sources) - var/obj/machinery/alarm/air_alarm = alarm_source.source - if(istype(air_alarm)) - var/list/new_ref = list("atmos_reset" = 1) - air_alarm.Topic(href, new_ref, state = air_alarm_topic) - return 1 - - -var/datum/topic_state/air_alarm_topic/air_alarm_topic = new() - -/datum/topic_state/air_alarm_topic/href_list(var/mob/user) - var/list/extra_href = list() - extra_href["remote_connection"] = 1 - extra_href["remote_access"] = 1 - - return extra_href + switch(action) + if("clear") + var/datum/alarm/alarm = locate(params["ref"]) in atmosphere_alarm.alarms + if(alarm) + for(var/datum/alarm_source/alarm_source in alarm.sources) + var/obj/machinery/alarm/air_alarm = alarm_source.source + if(istype(air_alarm)) + // I have to leave a note here: + // Once upon a time, this called air_alarm.Topic() with a custom topic state + // in order to perform three lines of code. In other words, pure insanity. + // Whyyyyyyyyyyyyyyyyyyyyyyy. + air_alarm.atmos_reset() + . = TRUE + update_icon() diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 48f899ed0d..c38af8ae41 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -13,7 +13,7 @@ circuit = /obj/item/weapon/circuitboard/atmoscontrol req_access = list(access_ce) var/list/monitored_alarm_ids = null - var/datum/nano_module/atmos_control/atmos_control + var/datum/tgui_module/atmos_control/atmos_control /obj/machinery/computer/atmoscontrol/New() ..() @@ -27,12 +27,12 @@ density = 0 /obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob) - ui_interact(user) + tgui_interact(user) /obj/machinery/computer/atmoscontrol/attack_hand(mob/user) if(..()) return 1 - ui_interact(user) + tgui_interact(user) /obj/machinery/computer/atmoscontrol/emag_act(var/remaining_carges, var/mob/user) if(!emagged) @@ -42,7 +42,7 @@ atmos_control.emagged = 1 return 1 -/obj/machinery/computer/atmoscontrol/ui_interact(var/mob/user) +/obj/machinery/computer/atmoscontrol/tgui_interact(var/mob/user) if(!atmos_control) atmos_control = new(src, req_access, req_one_access, monitored_alarm_ids) - atmos_control.ui_interact(user) + atmos_control.tgui_interact(user) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 2416a0cd35..1dc0709ed3 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -12,23 +12,21 @@ //Sparks effect - For emag var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread //Messages - Saves me time if I want to change something. - var/noserver = "ALERT: No server detected." - var/incorrectkey = "ALERT: Incorrect decryption key!" - var/defaultmsg = "Welcome. Please select an option." - var/rebootmsg = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" + var/noserver = list("text" = "ALERT: No server detected.", "style" = "alert") + var/incorrectkey = list("text" = "ALERT: Incorrect decryption key!", "style" = "warning") + var/defaultmsg = list("text" = "Welcome. Please select an option.", "style" = "notice") + var/rebootmsg = list("text" = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!", "style" = "warning") //Computer properties - var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message var/hacking = 0 // Is it being hacked into by the AI/Cyborg var/emag = 0 // When it is emagged. - var/message = "System bootup complete. Please select an option." // The message that shows on the main menu. var/auth = 0 // Are they authenticated? var/optioncount = 8 - // Custom Message Properties + // Custom temp Properties var/customsender = "System Administrator" var/obj/item/device/pda/customrecepient = null var/customjob = "Admin" var/custommessage = "This is a test, please ignore." - + var/list/temp = null /obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob) if(stat & (NOPOWER|BROKEN)) @@ -48,17 +46,16 @@ // Will create sparks and print out the console's password. You will then have to wait a while for the console to be back online. // It'll take more time if there's more characters in the password.. if(!emag && operable()) - if(!isnull(src.linkedServer)) + if(!isnull(linkedServer)) emag = 1 - screen = 2 spark_system.set_up(5, 0, src) - src.spark_system.start() + spark_system.start() var/obj/item/weapon/paper/monitorkey/MK = new/obj/item/weapon/paper/monitorkey - MK.loc = src.loc + MK.loc = loc // Will help make emagging the console not so easy to get away with. MK.info += "

£%@%(*$%&(£&?*(%&£/{}" - spawn(100*length(src.linkedServer.decryptkey)) UnmagConsole() - message = rebootmsg + spawn(100*length(linkedServer.decryptkey)) UnmagConsole() + temp = rebootmsg update_icon() return 1 else @@ -78,201 +75,92 @@ linkedServer = message_servers[1] return ..() +/obj/machinery/computer/message_monitor/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "MessageMonitor", name) + ui.open() + +/obj/machinery/computer/message_monitor/tgui_data(mob/user) + var/list/data = list() + + data["customsender"] = customsender + data["customrecepient"] = "[customrecepient]" + data["customjob"] = customjob + data["custommessage"] = custommessage + + data["temp"] = temp + data["hacking"] = !!hacking + data["emag"] = !!emag + data["auth"] = !!auth + data["linkedServer"] = list() + if(linkedServer && auth) + data["linkedServer"]["active"] = linkedServer.active + data["linkedServer"]["broke"] = linkedServer.stat & (NOPOWER|BROKEN) + + data["linkedServer"]["pda_msgs"] = list() + for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs) + data["linkedServer"]["pda_msgs"].Add(list(list( + "ref" = "\ref[pda]", + "sender" = pda.sender, + "recipient" = pda.recipient, + "message" = pda.message, + ))) + + data["linkedServer"]["rc_msgs"] = list() + for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs) + data["linkedServer"]["rc_msgs"].Add(list(list( + "ref" = "\ref[rc]", + "sender" = rc.send_dpt, + "recipient" = rc.rec_dpt, + "message" = rc.message, + "stamp" = rc.stamp, + "id_auth" = rc.id_auth, + "priority" = rc.priority, + ))) + + var/spamIndex = 0 + data["linkedServer"]["spamFilter"] = list() + for(var/token in linkedServer.spamfilter) + spamIndex++ + data["linkedServer"]["spamFilter"].Add(list(list( + "index" = spamIndex, + "token" = token, + ))) + + //Get out list of viable PDAs + var/list/obj/item/device/pda/sendPDAs = list() + for(var/obj/item/device/pda/P in PDAs) + if(!P.owner || P.toff || P.hidden) + continue + sendPDAs["[P.name]"] = "\ref[P]" + data["possibleRecipients"] = sendPDAs + + data["isMalfAI"] = ((istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) && (user.mind.special_role && user.mind.original == user)) + + return data + /obj/machinery/computer/message_monitor/attack_hand(var/mob/living/user as mob) if(stat & (NOPOWER|BROKEN)) return if(!istype(user)) return - //If the computer is being hacked or is emagged, display the reboot message. - if(hacking || emag) - message = rebootmsg - var/dat = "Message Monitor Console" - dat += "

Message Monitor Console


" - dat += "

" - - if(auth) - dat += "

\[Authenticated\] /" - dat += " Server Power: [src.linkedServer && src.linkedServer.active ? "\[On\]":"\[Off\]"]

" - else - dat += "

\[Unauthenticated\] /" - dat += " Server Power: [src.linkedServer && src.linkedServer.active ? "\[On\]":"\[Off\]"]

" - - if(hacking || emag) - screen = 2 - else if(!auth || !linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) - if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) message = noserver - screen = 0 - - switch(screen) - //Main menu - if(0) - // = TAB - var/i = 0 - dat += "
[++i]. Link To A Server
" - if(auth) - if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) - dat += "
ERROR: Server not found!
" - else - dat += "
[++i]. View Message Logs
" - dat += "
[++i]. View Request Console Logs
" - dat += "
[++i]. Clear Message Logs
" - dat += "
[++i]. Clear Request Console Logs
" - dat += "
[++i]. Set Custom Key
" - dat += "
[++i]. Send Admin Message
" - dat += "
[++i]. Modify Spam Filter
" - else - for(var/n = ++i; n <= optioncount; n++) - dat += "
[n]. ---------------
" - if((istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) && (user.mind.special_role && user.mind.original == user)) - //Malf/Traitor AIs can bruteforce into the system to gain the Key. - dat += "
*&@#. Bruteforce Key
" - else - dat += "
" - - //Bottom message - if(!auth) - dat += "

Please authenticate with the server in order to show additional options." - else - dat += "

Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties." - - //Message Logs - if(1) - var/index = 0 - //var/recipient = "Unspecified" //name of the person - //var/sender = "Unspecified" //name of the sender - //var/message = "Blank" //transferred message - dat += "
Back - Refresh

" - dat += "" - for(var/datum/data_pda_msg/pda in src.linkedServer.pda_msgs) - index++ - if(index > 3000) - break - // Del - Sender - Recepient - Message - // X - Al Green - Your Mom - WHAT UP!? - dat += "" - dat += "
XSenderRecipientMessage
X
[pda.sender][pda.recipient][pda.message]
" - //Hacking screen. - if(2) - if(istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) - dat += "Brute-forcing for server key.
It will take 20 seconds for every character that the password has." - dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time." - else - //It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever. - dat += {"01000010011100100111010101110100011001010010110
- 10110011001101111011100100110001101101001011011100110011
- 10010000001100110011011110111001000100000011100110110010
- 10111001001110110011001010111001000100000011010110110010
- 10111100100101110001000000100100101110100001000000111011
- 10110100101101100011011000010000001110100011000010110101
- 10110010100100000001100100011000000100000011100110110010
- 10110001101101111011011100110010001110011001000000110011
- 00110111101110010001000000110010101110110011001010111001
- 00111100100100000011000110110100001100001011100100110000
- 10110001101110100011001010111001000100000011101000110100
- 00110000101110100001000000111010001101000011001010010000
- 00111000001100001011100110111001101110111011011110111001
- 00110010000100000011010000110000101110011001011100010000
- 00100100101101110001000000111010001101000011001010010000
- 00110110101100101011000010110111001110100011010010110110
- 10110010100101100001000000111010001101000011010010111001
- 10010000001100011011011110110111001110011011011110110110
- 00110010100100000011000110110000101101110001000000111001
- 00110010101110110011001010110000101101100001000000111100
- 10110111101110101011100100010000001110100011100100111010
- 10110010100100000011010010110111001110100011001010110111
- 00111010001101001011011110110111001110011001000000110100
- 10110011000100000011110010110111101110101001000000110110
- 00110010101110100001000000111001101101111011011010110010
- 10110111101101110011001010010000001100001011000110110001
- 10110010101110011011100110010000001101001011101000010111
- 00010000001001101011000010110101101100101001000000111001
- 10111010101110010011001010010000001101110011011110010000
- 00110100001110101011011010110000101101110011100110010000
- 00110010101101110011101000110010101110010001000000111010
- 00110100001100101001000000111001001101111011011110110110
- 10010000001100100011101010111001001101001011011100110011
- 10010000001110100011010000110000101110100001000000111010
- 001101001011011010110010100101110"} - - //Fake messages - if(3) - dat += "
Back - Reset

" - - dat += {" - - - - "} - //Sender - Sender's Job - Recepient - Message - //Al Green- Your Dad - Your Mom - WHAT UP!? - - dat += {" - - - "} - dat += "
SenderSender's JobRecipientMessage
[customsender][customjob][customrecepient ? customrecepient.owner : "NONE"][custommessage]

Send
" - - //Request Console Logs - if(4) - - var/index = 0 - /* data_rc_msg - X - 5% - var/rec_dpt = "Unspecified" //name of the person - 15% - var/send_dpt = "Unspecified" //name of the sender- 15% - var/message = "Blank" //transferred message - 300px - var/stamp = "Unstamped" - 15% - var/id_auth = "Unauthenticated" - 15% - var/priority = "Normal" - 10% - */ - dat += "
Back - Refresh

" - dat += {" - "} - for(var/datum/data_rc_msg/rc in src.linkedServer.rc_msgs) - index++ - if(index > 3000) - break - // Del - Sender - Recepient - Message - // X - Al Green - Your Mom - WHAT UP!? - dat += {" - "} - dat += "
XSending Dep.Receiving Dep.MessageStampID Auth.Priority.
X
[rc.send_dpt][rc.rec_dpt][rc.message][rc.stamp][rc.id_auth][rc.priority]
" - - //Spam filter modification - if(5) - dat += "
Back - Refresh

" - var/index = 0 - for(var/token in src.linkedServer.spamfilter) - index++ - if(index > 3000) - break - dat += "
[index] \[[token]\]
" - dat += "
" - if (linkedServer.spamfilter.len < linkedServer.spamfilter_limit) - dat += "Add token
" - - - dat += "" - message = defaultmsg - user << browse(dat, "window=message;size=700x700") - onclose(user, "message") - return + tgui_interact(user) /obj/machinery/computer/message_monitor/attack_ai(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/machinery/computer/message_monitor/proc/BruteForce(mob/user as mob) if(isnull(linkedServer)) to_chat(user, "Could not complete brute-force: Linked Server Disconnected!") else - var/currentKey = src.linkedServer.decryptkey + var/currentKey = linkedServer.decryptkey to_chat(user, "Brute-force completed! The key is '[currentKey]'.") - src.hacking = 0 + hacking = 0 update_icon() - src.screen = 0 // Return the screen back to normal /obj/machinery/computer/message_monitor/proc/UnmagConsole() - src.emag = 0 + emag = 0 update_icon() /obj/machinery/computer/message_monitor/proc/ResetMessage() @@ -281,227 +169,156 @@ custommessage = "This is a test, please ignore." customjob = "Admin" -/obj/machinery/computer/message_monitor/Topic(href, href_list) +/obj/machinery/computer/message_monitor/tgui_act(action, params) if(..()) - return 1 - if(stat & (NOPOWER|BROKEN)) - return - if(!istype(usr, /mob/living)) - return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + return TRUE + + switch(action) + if("cleartemp") + temp = null + . = TRUE //Authenticate - if (href_list["auth"]) - if(auth) - auth = 0 - screen = 0 - else - var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) - if(dkey && dkey != "") - if(src.linkedServer.decryptkey == dkey) - auth = 1 - else - message = incorrectkey - - //Turn the server on/off. - if (href_list["active"]) - if(auth) linkedServer.active = !linkedServer.active + if("auth") + var/dkey = params["key"] + if(dkey && dkey != "") + if(linkedServer.decryptkey == dkey) + auth = TRUE + else + temp = incorrectkey + . = TRUE + if("deauth") + auth = FALSE + . = TRUE //Find a server - if (href_list["find"]) + if("find") if(message_servers && message_servers.len > 1) - src.linkedServer = input(usr,"Please select a server.", "Select a server.", null) as null|anything in message_servers - message = "NOTICE: Server selected." + linkedServer = input(usr,"Please select a server.", "Select a server.", null) as null|anything in message_servers + set_temp("NOTICE: Server selected.", "alert") else if(message_servers && message_servers.len > 0) linkedServer = message_servers[1] - message = "NOTICE: Only Single Server Detected - Server selected." + set_temp("NOTICE: Only Single Server Detected - Server selected.", "average") else - message = noserver - - //View the logs - KEY REQUIRED - if (href_list["view"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - if(auth) - src.screen = 1 - - //Clears the logs - KEY REQUIRED - if (href_list["clear"]) - if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - if(auth) - src.linkedServer.pda_msgs = list() - message = "NOTICE: Logs cleared." - //Clears the request console logs - KEY REQUIRED - if (href_list["clearr"]) - if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - if(auth) - src.linkedServer.rc_msgs = list() - message = "NOTICE: Logs cleared." - //Change the password - KEY REQUIRED - if (href_list["pass"]) - if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - if(auth) - var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) - if(dkey && dkey != "") - if(src.linkedServer.decryptkey == dkey) - var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):")) - if(length(newkey) <= 3) - message = "NOTICE: Decryption key too short!" - else if(length(newkey) > 16) - message = "NOTICE: Decryption key too long!" - else if(newkey && newkey != "") - src.linkedServer.decryptkey = newkey - message = "NOTICE: Decryption key set." - else - message = incorrectkey - + temp = noserver //Hack the Console to get the password - if (href_list["hack"]) + if("hack") if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && (usr.mind.special_role && usr.mind.original == usr)) - src.hacking = 1 - src.screen = 2 + hacking = 1 update_icon() //Time it takes to bruteforce is dependant on the password length. - spawn(100*length(src.linkedServer.decryptkey)) - if(src && src.linkedServer && usr) + spawn(100*length(linkedServer.decryptkey)) + if(src && linkedServer && usr) BruteForce(usr) + + if(!auth) + return + + if(!linkedServer || linkedServer.stat & (NOPOWER|BROKEN)) + temp = noserver + return TRUE + + switch(action) + //Turn the server on/off. + if("active") + linkedServer.active = !linkedServer.active + . = TRUE + //Clears the logs - KEY REQUIRED + if("del_pda") + linkedServer.pda_msgs = list() + set_temp("NOTICE: Logs cleared.", "average") + . = TRUE + //Clears the request console logs - KEY REQUIRED + if("del_rc") + linkedServer.rc_msgs = list() + set_temp("NOTICE: Logs cleared.", "average") + . = TRUE + //Change the password - KEY REQUIRED + if("pass") + var/dkey = trim(input(usr, "Please enter the current decryption key.") as text|null) + if(dkey && dkey != "") + if(linkedServer.decryptkey == dkey) + var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):")) + if(length(newkey) <= 3) + set_temp("NOTICE: Decryption key too short!", "average") + else if(length(newkey) > 16) + set_temp("NOTICE: Decryption key too long!", "average") + else if(newkey && newkey != "") + linkedServer.decryptkey = newkey + set_temp("NOTICE: Decryption key set.", "average") + else + temp = incorrectkey + . = TRUE //Delete the log. - if (href_list["delete"]) - //Are they on the view logs screen? - if(screen == 1) - if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else //if(istype(href_list["delete"], /datum/data_pda_msg)) - src.linkedServer.pda_msgs -= locate(href_list["delete"]) - message = "NOTICE: Log Deleted!" - //Delete the request console log. - if (href_list["deleter"]) - //Are they on the view logs screen? - if(screen == 4) - if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else //if(istype(href_list["delete"], /datum/data_pda_msg)) - src.linkedServer.rc_msgs -= locate(href_list["deleter"]) - message = "NOTICE: Log Deleted!" - //Create a custom message - if (href_list["msg"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver + if("delete") + if(params["type"] == "pda") + linkedServer.pda_msgs -= locate(params["id"]) else - if(auth) - src.screen = 3 + linkedServer.rc_msgs -= locate(params["id"]) + set_temp("NOTICE: Log Deleted!", "average") + . = TRUE //Fake messaging selection - KEY REQUIRED - if (href_list["select"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - screen = 0 + if("set_sender") + customsender = sanitize(params["val"]) + . = TRUE + if("set_sender_job") + customjob = sanitize(params["val"]) + . = TRUE + if("set_recipient") + var/ref = params["val"] + var/obj/item/device/pda/P = locate(ref) + if(!istype(P) || !P.owner || P.toff || P.hidden) + return FALSE + customrecepient = P + . = TRUE + if("set_message") + custommessage = sanitize(params["val"]) + . = TRUE + if("send_message") + if(isnull(customsender) || customsender == "") + customsender = "UNKNOWN" + + if(isnull(customrecepient)) + set_temp("NOTICE: No recepient selected!", "average") + return TRUE + + if(isnull(custommessage) || custommessage == "") + set_temp("NOTICE: No message entered!", "average") + return TRUE + + var/obj/item/device/pda/PDARec = null + for(var/obj/item/device/pda/P in PDAs) + if(!P.owner || P.toff || P.hidden) continue + if(P.owner == customsender) + PDARec = P + //Sender isn't faking as someone who exists + if(isnull(PDARec)) + linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]") + customrecepient.new_message(customsender, customsender, customjob, custommessage) + //Sender is faking as someone who exists else - switch(href_list["select"]) + linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]") + customrecepient.tnote.Add(list(list("sent" = 0, "owner" = "[PDARec.owner]", "job" = "[customjob]", "message" = "[custommessage]", "target" ="\ref[PDARec]"))) - //Reset - if("Reset") - ResetMessage() + if(!customrecepient.conversations.Find("\ref[PDARec]")) + customrecepient.conversations.Add("\ref[PDARec]") - //Select Your Name - if("Sender") - customsender = sanitize(input(usr, "Please enter the sender's name.") as text|null) + customrecepient.new_message(PDARec, custommessage) + //Finally.. + ResetMessage() + . = TRUE - //Select Receiver - if("Recepient") - //Get out list of viable PDAs - var/list/obj/item/device/pda/sendPDAs = list() - for(var/obj/item/device/pda/P in PDAs) - if(!P.owner || P.toff || P.hidden) continue - sendPDAs += P - if(PDAs && PDAs.len > 0) - customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortAtom(sendPDAs) - else - customrecepient = null + if("addtoken") + linkedServer.spamfilter += input(usr,"Enter text you want to be filtered out","Token creation") as text|null + . = TRUE - //Enter custom job - if("RecJob") - customjob = sanitize(input(usr, "Please enter the sender's job.") as text|null) + if("deltoken") + var/tokennum = text2num(params["deltoken"]) + linkedServer.spamfilter.Cut(tokennum, tokennum + 1) + . = TRUE - //Enter message - if("Message") - custommessage = input(usr, "Please enter your message.") as text|null - custommessage = sanitize(custommessage) - - //Send message - if("Send") - - if(isnull(customsender) || customsender == "") - customsender = "UNKNOWN" - - if(isnull(customrecepient)) - message = "NOTICE: No recepient selected!" - return src.attack_hand(usr) - - if(isnull(custommessage) || custommessage == "") - message = "NOTICE: No message entered!" - return src.attack_hand(usr) - - var/obj/item/device/pda/PDARec = null - for (var/obj/item/device/pda/P in PDAs) - if (!P.owner || P.toff || P.hidden) continue - if(P.owner == customsender) - PDARec = P - //Sender isn't faking as someone who exists - if(isnull(PDARec)) - src.linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]") - customrecepient.new_message(customsender, customsender, customjob, custommessage) - //Sender is faking as someone who exists - else - - src.linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]") - customrecepient.tnote.Add(list(list("sent" = 0, "owner" = "[PDARec.owner]", "job" = "[customjob]", "message" = "[custommessage]", "target" ="\ref[PDARec]"))) - - if(!customrecepient.conversations.Find("\ref[PDARec]")) - customrecepient.conversations.Add("\ref[PDARec]") - - customrecepient.new_message(PDARec, custommessage) - //Finally.. - ResetMessage() - - //Request Console Logs - KEY REQUIRED - if(href_list["viewr"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - if(auth) - src.screen = 4 - - //to_chat(usr,href_list["select"]) - - if(href_list["spam"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - if(auth) - src.screen = 5 - - if(href_list["addtoken"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - src.linkedServer.spamfilter += input(usr,"Enter text you want to be filtered out","Token creation") as text|null - - if(href_list["deltoken"]) - if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN))) - message = noserver - else - var/tokennum = text2num(href_list["deltoken"]) - src.linkedServer.spamfilter.Cut(tokennum,tokennum+1) - - if (href_list["back"]) - src.screen = 0 - - return src.attack_hand(usr) +/obj/machinery/computer/message_monitor/proc/set_temp(text = "", style = "info", update_now = FALSE) + temp = list(text = text, style = style) + if(update_now) + SStgui.update_uis(src) /obj/item/weapon/paper/monitorkey name = "Monitor Decryption Key" diff --git a/code/game/machinery/computer/shutoff_monitor.dm b/code/game/machinery/computer/shutoff_monitor.dm index 89cd4127db..8cc101d804 100644 --- a/code/game/machinery/computer/shutoff_monitor.dm +++ b/code/game/machinery/computer/shutoff_monitor.dm @@ -5,23 +5,19 @@ icon_screen = "power_monitor" light_color = "#a97faa" circuit = /obj/item/weapon/circuitboard/shutoff_monitor - var/datum/nano_module/shutoff_monitor/monitor + var/datum/tgui_module/shutoff_monitor/monitor /obj/machinery/computer/shutoff_monitor/New() ..() monitor = new(src) /obj/machinery/computer/shutoff_monitor/Destroy() - qdel(monitor) - monitor = null + QDEL_NULL(monitor) ..() /obj/machinery/computer/shutoff_monitor/attack_hand(var/mob/user as mob) ..() - ui_interact(user) - -/obj/machinery/computer/shutoff_monitor/ui_interact(mob/user, ui_key = "shutoff_monitor", var/datum/nanoui/ui = null, var/force_open = 1) - monitor.ui_interact(user, ui_key, ui, force_open) + monitor.tgui_interact(user) /obj/machinery/computer/shutoff_monitor/update_icon() ..() diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 1a64db7389..bde923a217 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -1,5 +1,11 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 +#define GENERAL_RECORD_LIST 2 +#define GENERAL_RECORD_MAINT 3 +#define GENERAL_RECORD_DATA 4 + +#define FIELD(N, V, E) list(field = N, value = V, edit = E) + /obj/machinery/computer/skills//TODO:SANITY name = "employment records console" desc = "Used to view, edit and maintain employment records." @@ -16,20 +22,40 @@ var/screen = null var/datum/data/record/active1 = null var/a_id = null - var/temp = null + var/list/temp = null var/printing = null var/can_change_id = 0 - var/list/Perp - var/tempname = null - //Sorting Variables - var/sortBy = "name" - var/order = 1 // -1 = Descending - 1 = Ascending + // The below are used to make modal generation more convenient + var/static/list/field_edit_questions + var/static/list/field_edit_choices + +/obj/machinery/computer/skills/Initialize() + ..() + field_edit_questions = list( + // General + "name" = "Please input new name:", + "id" = "Please input new ID:", + "sex" = "Please select new sex:", + "age" = "Please input new age:", + "fingerprint" = "Please input new fingerprint hash:", + ) + field_edit_choices = list( + // General + "sex" = all_genders_text_list, + "p_stat" = list("*Deceased*", "*SSD*", "Active", "Physically Unfit", "Disabled"), + "m_stat" = list("*Insane*", "*Unstable*", "*Watch*", "Stable"), + ) + +/obj/machinery/computer/skills/Destroy() + active1 = null + return ..() /obj/machinery/computer/skills/attackby(obj/item/O as obj, var/mob/user) if(istype(O, /obj/item/weapon/card/id) && !scan && user.unEquip(O)) O.loc = src scan = O to_chat(user, "You insert [O].") + tgui_interact(user) else ..() @@ -43,380 +69,271 @@ if (using_map && !(src.z in using_map.contact_levels)) to_chat(user, "Unable to establish a connection: You're too far away from the station!") return - var/dat + tgui_interact(user) - if (temp) - dat = text("[]

Clear Screen", temp, src) - else - dat = text("Confirm Identity: []
", src, (scan ? text("[]", scan.name) : "----------")) - if (authenticated) - switch(screen) - if(1.0) - dat += {" -

"} - dat += text("Search Records
", src) - dat += text("New Record
", src) - dat += {" -

- - - - -
Records:
- - - - - - -"} - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) - for(var/datum/data/record/E in data_core.security) - var/background - dat += text("", background, src, R, R.fields["name"]) - dat += text("", R.fields["id"]) - dat += text("", R.fields["rank"]) - dat += text("", R.fields["fingerprint"]) - dat += "
NameIDRankFingerprints
[][][][]

" - dat += text("Record Maintenance

", src) - dat += text("{Log Out}",src) - if(2.0) - dat += "Records Maintenance
" - dat += "
Delete All Records

Back" - if(3.0) - dat += "
Employment Record

" - if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - var/icon/front = active1.fields["photo_front"] - var/icon/side = active1.fields["photo_side"] - user << browse_rsc(front, "front.png") - user << browse_rsc(side, "side.png") - dat += "" - - dat += "
" - dat += "Name: [active1.fields["name"]]
" - dat += "ID: [active1.fields["id"]]
\n" - dat += "Entity Classification: [active1.fields["brain_type"]]
\n" - dat += "Sex: [active1.fields["sex"]]
\n" - dat += "Age: [active1.fields["age"]]
\n" - dat += "Rank: [active1.fields["rank"]]
\n" - dat += "Fingerprint: [active1.fields["fingerprint"]]
\n" - dat += "Physical Status: [active1.fields["p_stat"]]
\n" - dat += "Mental Status: [active1.fields["m_stat"]]

\n" +/obj/machinery/computer/skills/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GeneralRecords", "Employee Records") // 800, 380 + ui.open() + ui.set_autoupdate(FALSE) - dat += "Employment/skills summary:
" - dat += decode(active1.fields["notes"]) - dat += "


" - var/counter = 1 - while(src.active1.fields[text("com_[]", counter)]) - dat += text("[]
Delete Entry

", src.active1.fields[text("com_[]", counter)], src, counter) - counter++ - dat += "Add Entry

Photo:
" - dat += "
" - else - dat += "General Record Lost!
" - dat += text("\nDelete Record (ALL)

\nPrint Record
\nBack
", src, src, src) - if(4.0) - if(!Perp.len) - dat += text("ERROR. String could not be located.

Back", src) - else - dat += {" - - "} - dat += text("", tempname) - dat += {" - -
Search Results for '[]':
- - - - - - - "} - for(var/i=1, i<=Perp.len, i += 2) - var/crimstat = "" - var/datum/data/record/R = Perp[i] - if(istype(Perp[i+1],/datum/data/record/)) - var/datum/data/record/E = Perp[i+1] - crimstat = E.fields["criminal"] - var/background - background = "'background-color:#00FF7F;'" - dat += text("", background, src, R, R.fields["name"]) - dat += text("", R.fields["id"]) - dat += text("", R.fields["rank"]) - dat += text("", R.fields["fingerprint"]) - dat += text("", crimstat) - dat += "
NameIDRankFingerprints
[][][][][]

" - dat += text("
Return to index.", src) +/obj/machinery/computer/skills/tgui_data(mob/user) + var/data[0] + data["temp"] = temp + data["scan"] = scan ? scan.name : null + data["authenticated"] = authenticated + data["rank"] = rank + data["screen"] = screen + data["printing"] = printing + data["isAI"] = isAI(user) + data["isRobot"] = isrobot(user) + if(authenticated) + switch(screen) + if(GENERAL_RECORD_LIST) + if(!isnull(data_core.general)) + var/list/records = list() + data["records"] = records + for(var/datum/data/record/R in sortRecord(data_core.general)) + records[++records.len] = list( + "ref" = "\ref[R]", + "id" = R.fields["id"], + "name" = R.fields["name"], + "b_dna" = R.fields["b_dna"]) + if(GENERAL_RECORD_DATA) + var/list/general = list() + data["general"] = general + if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + var/list/fields = list() + general["fields"] = fields + fields[++fields.len] = FIELD("Name", active1.fields["name"], "name") + fields[++fields.len] = FIELD("ID", active1.fields["id"], "id") + fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex") + fields[++fields.len] = FIELD("Age", active1.fields["age"], "age") + fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint") + fields[++fields.len] = FIELD("Physical Status", active1.fields["p_stat"], null) + fields[++fields.len] = FIELD("Mental Status", active1.fields["m_stat"], null) + var/list/photos = list() + general["photos"] = photos + photos[++photos.len] = active1.fields["photo-south"] + photos[++photos.len] = active1.fields["photo-west"] + general["has_photos"] = (active1.fields["photo-south"] || active1.fields["photo-west"] ? 1 : 0) + if(!active1.fields["comments"] || !islist(active1.fields["comments"])) + active1.fields["comments"] = list() + general["skills"] = active1.fields["notes"] + general["comments"] = active1.fields["comments"] + general["empty"] = 0 else - else - dat += text("{Log In}", src) - user << browse(text("Employment Records[]", dat), "window=secure_rec;size=600x400") - onclose(user, "secure_rec") - return + general["empty"] = 1 -/*Revised /N -I can't be bothered to look more of the actual code outside of switch but that probably needs revising too. -What a mess.*/ -/obj/machinery/computer/skills/Topic(href, href_list) + data["modal"] = tgui_modal_data(src) + return data + +/obj/machinery/computer/skills/tgui_act(action, params) if(..()) - return 1 - if (!( data_core.general.Find(active1) )) + return TRUE + + add_fingerprint(usr) + + if(!data_core.general.Find(active1)) active1 = null - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - switch(href_list["choice"]) -// SORTING! - if("Sorting") - // Reverse the order if clicked twice - if(sortBy == href_list["sort"]) - if(order == 1) - order = -1 - else - order = 1 - else - // New sorting order! - sortBy = href_list["sort"] - order = initial(order) -//BASIC FUNCTIONS - if("Clear Screen") - temp = null - if ("Return") - screen = 1 + . = TRUE + if(tgui_act_modal(action, params)) + return + + switch(action) + if("scan") + if(scan) + scan.forceMove(loc) + if(ishuman(usr) && !usr.get_active_hand()) + usr.put_in_hands(scan) + scan = null + else + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/weapon/card/id)) + usr.drop_item() + I.forceMove(src) + scan = I + if("cleartemp") + temp = null + if("login") + var/login_type = text2num(params["login_type"]) + if(login_type == LOGIN_TYPE_NORMAL && istype(scan)) + if(check_access(scan)) + authenticated = scan.registered_name + rank = scan.assignment + else if(login_type == LOGIN_TYPE_AI && isAI(usr)) + authenticated = usr.name + rank = "AI" + else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr)) + authenticated = usr.name + var/mob/living/silicon/robot/R = usr + rank = "[R.modtype] [R.braintype]" + if(authenticated) active1 = null + screen = GENERAL_RECORD_LIST + else + . = FALSE + + if(.) + return - if("Confirm Identity") - if (scan) - if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + if(authenticated) + . = TRUE + switch(action) + if("logout") + if(scan) + scan.forceMove(loc) + if(ishuman(usr) && !usr.get_active_hand()) usr.put_in_hands(scan) - else - scan.loc = get_turf(src) scan = null - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I)) - I.loc = src - scan = I - - if("Log Out") authenticated = null screen = null active1 = null - - if("Log In") - if (istype(usr, /mob/living/silicon/ai)) - src.active1 = null - src.authenticated = usr.name - src.rank = "AI" - src.screen = 1 - else if (istype(usr, /mob/living/silicon/robot)) - src.active1 = null - src.authenticated = usr.name - var/mob/living/silicon/robot/R = usr - src.rank = R.braintype - src.screen = 1 - else if (istype(scan, /obj/item/weapon/card/id)) - active1 = null - if(check_access(scan)) - authenticated = scan.registered_name - rank = scan.assignment - screen = 1 -//RECORD FUNCTIONS - if("Search Records") - var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text - if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr))) - return - Perp = new/list() - t1 = lowertext(t1) - var/list/components = splittext(t1, " ") - if(components.len > 5) - return //Lets not let them search too greedily. - for(var/datum/data/record/R in data_core.general) - var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"] - for(var/i = 1, i<=components.len, i++) - if(findtext(temptext,components[i])) - var/prelist = new/list(2) - prelist[1] = R - Perp += prelist - for(var/i = 1, i<=Perp.len, i+=2) - for(var/datum/data/record/E in data_core.security) - var/datum/data/record/R = Perp[i] - if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) - Perp[i+1] = E - tempname = t1 - screen = 4 - - if("Record Maintenance") - screen = 2 + if("screen") + screen = clamp(text2num(params["screen"]) || 0, GENERAL_RECORD_LIST, GENERAL_RECORD_MAINT) active1 = null - - if ("Browse Record") - var/datum/data/record/R = locate(href_list["d_rec"]) - if (!( data_core.general.Find(R) )) - temp = "Record Not Found!" - else - for(var/datum/data/record/E in data_core.security) - active1 = R - screen = 3 - -/* if ("Search Fingerprints") - var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text - if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!istype(usr, /mob/living/silicon)))) - return - active1 = null - t1 = lowertext(t1) - for(var/datum/data/record/R in data_core.general) - if (lowertext(R.fields["fingerprint"]) == t1) - active1 = R - if (!( active1 )) - temp = text("Could not locate record [].", t1) - else - for(var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"])) - screen = 3 */ - - if ("Print Record") - if (!( printing )) - printing = 1 - sleep(50) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) - P.info = "
Employment Record

" - if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
\nEmployment/Skills Summary:
\n[]
", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"], active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"], decode(active1.fields["notes"])) - else - P.info += "General Record Lost!
" - P.info += "" - if(active1) - P.name = "Employment Record ([active1.fields["name"]])" - else - P.name = "Employment Record (Unknown/Invald Entry)" - log_debug("[usr] ([usr.ckey]) attempted to print a null employee record, this should be investigated.") - printing = null -// Add comment - if ("add_c") - if (!( istype(src.active1, /datum/data/record) )) - return - var/a1 = src.active1 - var/t1 = sanitize(input("Add Comment:", "Emp. records", null, null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - var/counter = 1 - while(src.active1.fields[text("com_[]", counter)]) - counter++ - src.active1.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [stationtime2text()], [game_year]
[t1]") -// Delete comment - if ("del_c") - var/target = href_list["del_c"] - if (istype(src.active1, /datum/data/record) && src.active1.fields["com_[target]"]) - src.active1.fields["com_[target]"] = "Deleted" - - -//RECORD DELETE - if ("Delete All Records") - temp = "" - temp += "Are you sure you wish to delete all Employment records?
" - temp += "Yes
" - temp += "No" - - if ("Purge All Records") - if(PDA_Manifest.len) + if("del_all") + if(PDA_Manifest) PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in data_core.general) qdel(R) - temp = "All Employment records deleted." + set_temp("All employment records deleted.") + if("del_r") + if(PDA_Manifest) + PDA_Manifest.Cut() + if(active1) + for(var/datum/data/record/R in data_core.medical) + if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) + qdel(R) + set_temp("Employment record deleted.") + QDEL_NULL(active1) + if("d_rec") + var/datum/data/record/general_record = locate(params["d_rec"] || "") + if(!data_core.general.Find(general_record)) + set_temp("Record not found.", "danger") + return - if ("Delete Record (ALL)") - if (active1) - temp = "
Are you sure you wish to delete the record (ALL)?
" - temp += "Yes
" - temp += "No" -//RECORD CREATE - if ("New Record (General)") - if(PDA_Manifest.len) + active1 = general_record + screen = GENERAL_RECORD_DATA + if("new") + if(PDA_Manifest) PDA_Manifest.Cut() active1 = data_core.CreateGeneralRecord() + screen = GENERAL_RECORD_DATA + set_temp("Employment record created.", "success") + if("del_c") + var/index = text2num(params["del_c"] || "") + if(!index || !istype(active1, /datum/data/record)) + return -//FIELD FUNCTIONS - if ("Edit Field") - var/a1 = active1 - switch(href_list["field"]) - if("name") - if (istype(active1, /datum/data/record)) - var/t1 = sanitizeName(input("Please input name:", "Secure. records", active1.fields["name"], null) as text) - if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon)))) || active1 != a1) - return - active1.fields["name"] = t1 - if("id") - if (istype(active1, /datum/data/record)) - var/t1 = sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["id"] = t1 - if("fingerprint") - if (istype(active1, /datum/data/record)) - var/t1 = sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["fingerprint"] = t1 - if("sex") - if (istype(active1, /datum/data/record)) - if (active1.fields["sex"] == "Male") - active1.fields["sex"] = "Female" - else - active1.fields["sex"] = "Male" - if("age") - if (istype(active1, /datum/data/record)) - var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["age"] = t1 - if("rank") - var/list/L = list( "Head of Personnel", "Colony Director", "AI" ) - //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N - if ((istype(active1, /datum/data/record) && L.Find(rank))) - temp = "
Rank:
" - temp += "" - else - alert(usr, "You do not have the required rank to do this!") - if("species") - if (istype(active1, /datum/data/record)) - var/t1 = sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["species"] = t1 + var/list/comments = active1.fields["comments"] + index = clamp(index, 1, length(comments)) + if(comments[index]) + comments.Cut(index, index + 1) + if("print_p") + if(!printing) + printing = TRUE + // playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE) + SStgui.update_uis(src) + addtimer(CALLBACK(src, .proc/print_finish), 5 SECONDS) + else + return FALSE -//TEMPORARY MENU FUNCTIONS - else//To properly clear as per clear screen. - temp=null - switch(href_list["choice"]) - if ("Change Rank") - if (active1) - if(PDA_Manifest.len) - PDA_Manifest.Cut() - active1.fields["rank"] = href_list["rank"] - if(href_list["rank"] in joblist) - active1.fields["real_rank"] = href_list["real_rank"] - - if ("Delete Record (ALL) Execute") - if (active1) - if(PDA_Manifest.len) - PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.medical) - if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) - qdel(R) - else - qdel(active1) +/** + * Called in tgui_act() to process modal actions + * + * Arguments: + * * action - The action passed by tgui + * * params - The params passed by tgui + */ +/obj/machinery/computer/skills/proc/tgui_act_modal(action, params) + . = TRUE + var/id = params["id"] // The modal's ID + var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"] + switch(tgui_modal_act(src, action, params)) + if(TGUI_MODAL_OPEN) + switch(id) + if("edit") + var/field = arguments["field"] + if(!length(field) || !field_edit_questions[field]) + return + var/question = field_edit_questions[field] + var/choices = field_edit_choices[field] + if(length(choices)) + tgui_modal_choice(src, id, question, arguments = arguments, value = arguments["value"], choices = choices) else - temp = "This function does not appear to be working at the moment. Our apologies." + tgui_modal_input(src, id, question, arguments = arguments, value = arguments["value"]) + if("add_c") + tgui_modal_input(src, id, "Please enter your message:") + else + return FALSE + if(TGUI_MODAL_ANSWER) + var/answer = params["answer"] + switch(id) + if("edit") + var/field = arguments["field"] + if(!length(field) || !field_edit_questions[field]) + return + var/list/choices = field_edit_choices[field] + if(length(choices) && !(answer in choices)) + return - add_fingerprint(usr) - updateUsrDialog() - return + if(field == "age") + answer = text2num(answer) + + if(istype(active1) && (field in active1.fields)) + active1.fields[field] = answer + . = TRUE + if("add_c") + if(!length(answer) || !istype(active1) || !length(authenticated)) + return + active1.fields["comments"] += list(list( + header = "Made by [authenticated] ([rank]) at [worldtime2stationtime(world.time)]", + text = answer + )) + else + return FALSE + else + return FALSE + +/** + * Called when the print timer finishes + */ +/obj/machinery/computer/skills/proc/print_finish() + var/obj/item/weapon/paper/P = new(loc) + P.info = "
Medical Record

" + if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]] +
\nSex: [active1.fields["sex"]] +
\nAge: [active1.fields["age"]] +
\nFingerprint: [active1.fields["fingerprint"]] +
\nPhysical Status: [active1.fields["p_stat"]] +
\nMental Status: [active1.fields["m_stat"]]
+
\nEmployment/Skills Summary: [active1.fields["notes"]] +
\n +
Comments/Log

"} + for(var/c in active1.fields["comments"]) + P.info += "[c]
" + else + P.info += "General Record Lost!
" + P.info += "" + P.name = "paper - 'Employment Record: [active1.fields["name"]]'" + printing = FALSE + SStgui.update_uis(src) + +/** + * Sets a temporary message to display to the user + * + * Arguments: + * * text - Text to display, null/empty to clear the message from the UI + * * style - The style of the message: (color name), info, success, warning, danger, virus + */ +/obj/machinery/computer/skills/proc/set_temp(text = "", style = "info", update_now = FALSE) + temp = list(text = text, style = style) + if(update_now) + SStgui.update_uis(src) /obj/machinery/computer/skills/emp_act(severity) if(stat & (BROKEN|NOPOWER)) diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 8bd2f91f89..5cb000484d 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -6,15 +6,15 @@ icon_screen = "alert:0" light_color = "#e6ffff" circuit = /obj/item/weapon/circuitboard/stationalert_engineering - var/datum/nano_module/alarm_monitor/alarm_monitor - var/monitor_type = /datum/nano_module/alarm_monitor/engineering + var/datum/tgui_module/alarm_monitor/alarm_monitor + var/monitor_type = /datum/tgui_module/alarm_monitor/engineering /obj/machinery/computer/station_alert/security - monitor_type = /datum/nano_module/alarm_monitor/security + monitor_type = /datum/tgui_module/alarm_monitor/security circuit = /obj/item/weapon/circuitboard/stationalert_security /obj/machinery/computer/station_alert/all - monitor_type = /datum/nano_module/alarm_monitor/all + monitor_type = /datum/tgui_module/alarm_monitor/all circuit = /obj/item/weapon/circuitboard/stationalert_all /obj/machinery/computer/station_alert/Initialize() @@ -31,18 +31,18 @@ add_fingerprint(user) if(stat & (BROKEN|NOPOWER)) return - interact(user) + tgui_interact(user) return /obj/machinery/computer/station_alert/attack_hand(mob/user) add_fingerprint(user) if(stat & (BROKEN|NOPOWER)) return - interact(user) + tgui_interact(user) return -/obj/machinery/computer/station_alert/interact(mob/user) - alarm_monitor.ui_interact(user) +/obj/machinery/computer/station_alert/tgui_interact(mob/user) + alarm_monitor.tgui_interact(user) /obj/machinery/computer/station_alert/update_icon() if(!(stat & (BROKEN|NOPOWER))) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 2ec9c0043b..73ed4dc72e 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -740,32 +740,52 @@ About the new airlock wires panel: return /obj/machinery/door/airlock/attack_ai(mob/user as mob) - ui_interact(user) + tgui_interact(user) -/obj/machinery/door/airlock/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/data[0] +/obj/machinery/door/airlock/attack_ghost(mob/user) + tgui_interact(user) - data["main_power_loss"] = round(main_power_lost_until > 0 ? max(main_power_lost_until - world.time, 0) / 10 : main_power_lost_until, 1) - data["backup_power_loss"] = round(backup_power_lost_until > 0 ? max(backup_power_lost_until - world.time, 0) / 10 : backup_power_lost_until, 1) - data["electrified"] = round(electrified_until > 0 ? max(electrified_until - world.time, 0) / 10 : electrified_until, 1) - data["open"] = !density - - var/commands[0] - commands[++commands.len] = list("name" = "IdScan", "command"= "idscan", "active" = !aiDisabledIdScanner, "enabled" = "Enabled", "disabled" = "Disable", "danger" = 0, "act" = 1) - commands[++commands.len] = list("name" = "Bolts", "command"= "bolts", "active" = !locked, "enabled" = "Raised ", "disabled" = "Dropped", "danger" = 0, "act" = 0) - commands[++commands.len] = list("name" = "Bolt Lights", "command"= "lights", "active" = lights, "enabled" = "Enabled", "disabled" = "Disable", "danger" = 0, "act" = 1) - commands[++commands.len] = list("name" = "Safeties", "command"= "safeties", "active" = safe, "enabled" = "Nominal", "disabled" = "Overridden", "danger" = 1, "act" = 0) - commands[++commands.len] = list("name" = "Timing", "command"= "timing", "active" = normalspeed, "enabled" = "Nominal", "disabled" = "Overridden", "danger" = 1, "act" = 0) - commands[++commands.len] = list("name" = "Door State", "command"= "open", "active" = density, "enabled" = "Closed", "disabled" = "Opened", "danger" = 0, "act" = 0) - - data["commands"] = commands - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "door_control.tmpl", "Door Controls", 450, 350, state = state) - ui.set_initial_data(data) +/obj/machinery/door/airlock/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AiAirlock", name) ui.open() - ui.set_auto_update(1) + return TRUE + +/obj/machinery/door/airlock/tgui_data(mob/user) + var/list/data = list() + + var/list/power = list() + power["main"] = main_power_lost_until > 0 ? 0 : 2 + power["main_timeleft"] = round(main_power_lost_until > 0 ? max(main_power_lost_until - world.time, 0) / 10 : main_power_lost_until, 1) + power["backup"] = backup_power_lost_until > 0 ? 0 : 2 + power["backup_timeleft"] = round(backup_power_lost_until > 0 ? max(backup_power_lost_until - world.time, 0) / 10 : backup_power_lost_until, 1) + data["power"] = power + + data["shock"] = (electrified_until == 0) ? 2 : 0 + data["shock_timeleft"] = round(electrified_until > 0 ? max(electrified_until - world.time, 0) / 10 : electrified_until, 1) + data["id_scanner"] = !aiDisabledIdScanner + data["locked"] = locked // bolted + data["lights"] = lights // bolt lights + data["safe"] = safe // safeties + data["speed"] = normalspeed // safe speed + data["welded"] = welded // welded + data["opened"] = !density // opened + + var/list/wire = list() + wire["main_1"] = !wires.is_cut(WIRE_MAIN_POWER1) + wire["main_2"] = !wires.is_cut(WIRE_MAIN_POWER2) + wire["backup_1"] = !wires.is_cut(WIRE_BACKUP_POWER1) + wire["backup_2"] = !wires.is_cut(WIRE_BACKUP_POWER2) + wire["shock"] = !wires.is_cut(WIRE_ELECTRIFY) + wire["id_scanner"] = !wires.is_cut(WIRE_IDSCAN) + wire["bolts"] = !wires.is_cut(WIRE_DOOR_BOLTS) + wire["lights"] = !wires.is_cut(WIRE_BOLT_LIGHT) + wire["safe"] = !wires.is_cut(WIRE_SAFETY) + wire["timing"] = !wires.is_cut(WIRE_SPEED) + + data["wires"] = wire + return data /obj/machinery/door/airlock/proc/hack(mob/user as mob) if(src.aiHacking==0) @@ -844,80 +864,106 @@ About the new airlock wires panel: ..(user) return -/obj/machinery/door/airlock/CanUseTopic(var/mob/user) - if(operating < 0) //emagged - to_chat(user, "Unable to interface: Internal error.") - return STATUS_CLOSE - if(issilicon(user) && !src.canAIControl()) - if(src.canAIHack(user)) - src.hack(user) - else - if (src.isAllPowerLoss()) //don't really like how this gets checked a second time, but not sure how else to do it. - to_chat(user, "Unable to interface: Connection timed out.") - else - to_chat(user, "Unable to interface: Connection refused.") - return STATUS_CLOSE - - return ..() - -/obj/machinery/door/airlock/Topic(href, href_list) +/obj/machinery/door/airlock/tgui_act(action, params) if(..()) - return 1 + return TRUE + if(!user_allowed(usr)) + return TRUE - var/activate = text2num(href_list["activate"]) - switch (href_list["command"]) - if("idscan") - set_idscan(activate, 1) - if("main_power") + switch(action) + if("disrupt-main") if(!main_power_lost_until) - src.loseMainPower() - if("backup_power") + loseMainPower() + update_icon() + else + to_chat(usr, "Main power is already offline.") + . = TRUE + if("disrupt-backup") if(!backup_power_lost_until) - src.loseBackupPower() - if("bolts") - if(wires.is_cut(WIRE_DOOR_BOLTS)) - to_chat(usr, "The door bolt control wire is cut - Door bolts permanently dropped.") - else if(activate && src.lock()) - to_chat(usr, "The door bolts have been dropped.") - else if(!activate && src.unlock()) - to_chat(usr, "The door bolts have been raised.") - if("electrify_temporary") - electrify(30 * activate, 1) - if("electrify_permanently") - electrify(-1 * activate, 1) - if("open") - if(src.welded) - to_chat(usr, "The airlock has been welded shut!") - else if(src.locked) - to_chat(usr, "The door bolts are down!") - else if(activate && density) - open() - else if(!activate && !density) - close() - if("safeties") - set_safeties(!activate, 1) - if("timing") - // Door speed control - if(wires.is_cut(WIRE_SPEED)) - to_chat(usr, "The timing wire is cut - Cannot alter timing.") - else if (activate && src.normalspeed) - normalspeed = 0 - else if (!activate && !src.normalspeed) - normalspeed = 1 - if("lights") - // Bolt lights + loseBackupPower() + update_icon() + else + to_chat(usr, "Backup power is already offline.") + . = TRUE + if("shock-restore") + electrify(0, 1) + . = TRUE + if("shock-temp") + electrify(30, 1) + . = TRUE + if("shock-perm") + electrify(-1, 1) + . = TRUE + if("idscan-toggle") + set_idscan(aiDisabledIdScanner, 1) + . = TRUE + // if("emergency-toggle") + // toggle_emergency(usr) + // . = TRUE + if("bolt-toggle") + toggle_bolt(usr) + . = TRUE + if("light-toggle") if(wires.is_cut(WIRE_BOLT_LIGHT)) to_chat(usr, "The bolt lights wire is cut - The door bolt lights are permanently disabled.") - else if (!activate && src.lights) - lights = 0 - to_chat(usr, "The door bolt lights have been disabled.") - else if (activate && !src.lights) - lights = 1 - to_chat(usr, "The door bolt lights have been enabled.") + return + lights = !lights + update_icon() + . = TRUE + if("safe-toggle") + set_safeties(!safe, 1) + . = TRUE + if("speed-toggle") + if(wires.is_cut(WIRE_SPEED)) + to_chat(usr, "The timing wire is cut - Cannot alter timing.") + return + normalspeed = !normalspeed + . = TRUE + if("open-close") + user_toggle_open(usr) + . = TRUE update_icon() return 1 +/obj/machinery/door/airlock/proc/user_allowed(mob/user) + var/allowed = (issilicon(user) && canAIControl(user)) + if(!allowed && isobserver(user)) + var/mob/observer/dead/D = user + if(D.can_admin_interact()) + allowed = TRUE + return allowed + +/obj/machinery/door/airlock/proc/toggle_bolt(mob/user) + if(!user_allowed(user)) + return + if(wires.is_cut(WIRE_DOOR_BOLTS)) + to_chat(user, "The door bolt drop wire is cut - you can't toggle the door bolts.") + return + if(locked) + if(!arePowerSystemsOn()) + to_chat(user, "The door has no power - you can't raise the door bolts.") + else + unlock() + to_chat(user, "The door bolts have been raised.") + // log_combat(user, src, "unbolted") + else + lock() + to_chat(user, "The door bolts have been dropped.") + // log_combat(user, src, "bolted") + +/obj/machinery/door/airlock/proc/user_toggle_open(mob/user) + if(!user_allowed(user)) + return + if(welded) + to_chat(user, text("The airlock has been welded shut!")) + else if(locked) + to_chat(user, text("The door bolts are down!")) + else if(!density) + close() + else + open() + /obj/machinery/door/airlock/proc/can_remove_electronics() return src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm index b15d5afd97..262ffacf41 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers.dm @@ -14,6 +14,7 @@ var/tag_secure = 0 var/list/dummy_terminals = list() var/cycle_to_external_air = 0 + valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure") /obj/machinery/embedded_controller/radio/airlock/Destroy() // TODO - Leshana - Implement dummy terminals @@ -23,90 +24,42 @@ //dummy_terminals.Cut() return ..() -/obj/machinery/embedded_controller/radio/airlock/CanUseTopic(var/mob/user) +/obj/machinery/embedded_controller/radio/airlock/tgui_status(mob/user, datum/tgui_state/state) + . = ..() if(!allowed(user)) - return min(STATUS_UPDATE, ..()) - else - return ..() + return min(STATUS_UPDATE, .) //Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks /obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller name = "Advanced Airlock Controller" -/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( +/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/tgui_data(mob/user) + . = list( "chamber_pressure" = round(program.memory["chamber_sensor_pressure"]), "external_pressure" = round(program.memory["external_sensor_pressure"]), "internal_pressure" = round(program.memory["internal_sensor_pressure"]), "processing" = program.memory["processing"], "purge" = program.memory["purge"], - "secure" = program.memory["secure"] + "secure" = program.memory["secure"], + "internalTemplateName" = "AirlockConsoleAdvanced", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "advanced_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/Topic(href, href_list) - if((. = ..())) - return - - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure") - program.receive_user_command(href_list["command"]) - - return 1 //Airlock controller for airlock control - most airlocks on the station use this /obj/machinery/embedded_controller/radio/airlock/airlock_controller name = "Airlock Controller" tag_secure = 1 + valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort") -/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( +/obj/machinery/embedded_controller/radio/airlock/airlock_controller/tgui_data(mob/user) + . = list( "chamber_pressure" = round(program.memory["chamber_sensor_pressure"]), "exterior_status" = program.memory["exterior_status"], "interior_status" = program.memory["interior_status"], "processing" = program.memory["processing"], + "internalTemplateName" = "AirlockConsoleSimple", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "simple_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/airlock_controller/Topic(href, href_list) - if((. = ..())) - return - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext") - clean = 1 - if("cycle_int") - clean = 1 - if("force_ext") - clean = 1 - if("force_int") - clean = 1 - if("abort") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 - //Access controller for door control - used in virology and the like /obj/machinery/embedded_controller/radio/airlock/access_controller icon = 'icons/obj/airlock_machines.dmi' @@ -114,6 +67,7 @@ name = "Access Controller" tag_secure = 1 + valid_actions = list("cycle_ext_door", "cycle_int_door", "force_ext", "force_int") /obj/machinery/embedded_controller/radio/airlock/access_controller/update_icon() @@ -125,40 +79,10 @@ else icon_state = "access_control_off" -/obj/machinery/embedded_controller/radio/airlock/access_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( +/obj/machinery/embedded_controller/radio/airlock/access_controller/tgui_data(mob/user) + . = list( "exterior_status" = program.memory["exterior_status"], "interior_status" = program.memory["interior_status"], - "processing" = program.memory["processing"] + "processing" = program.memory["processing"], + "internalTemplateName" = "DoorAccessConsole", ) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "door_access_console.tmpl", name, 330, 220) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/access_controller/Topic(href, href_list) - if((. = ..())) - return - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext_door") - clean = 1 - if("cycle_int_door") - clean = 1 - if("force_ext") - if(program.memory["interior_status"]["state"] == "closed") - clean = 1 - if("force_int") - if(program.memory["exterior_status"]["state"] == "closed") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 \ No newline at end of file diff --git a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm index d2f9a410a2..ef6367758f 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm @@ -1,4 +1,5 @@ // Provides remote access to a controller (since they must be unique). +// TGUITODO: Actually make these weird things work... well, as much as possible. /obj/machinery/dummy_airlock_controller name = "airlock control terminal" icon = 'icons/obj/airlock_machines.dmi' diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller.dm b/code/game/machinery/embedded_controller/airlock_docking_controller.dm index 4d5048ad6d..080fa7d357 100644 --- a/code/game/machinery/embedded_controller/airlock_docking_controller.dm +++ b/code/game/machinery/embedded_controller/airlock_docking_controller.dm @@ -13,6 +13,7 @@ var/datum/computer/file/embedded_program/docking/airlock/docking_program var/display_name // For mappers to override docking_program.display_name (how would it show up on docking monitoring program) tag_secure = 1 + valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "toggle_override") /obj/machinery/embedded_controller/radio/airlock/docking_port/Initialize() . = ..() @@ -34,12 +35,11 @@ else ..() -/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/embedded_controller/radio/airlock/docking_port/tgui_data(mob/user) var/datum/computer/file/embedded_program/docking/airlock/docking_program = program var/datum/computer/file/embedded_program/airlock/docking/airlock_program = docking_program.airlock_program - data = list( + . = list( "chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]), "exterior_status" = airlock_program.memory["exterior_status"], "interior_status" = airlock_program.memory["interior_status"], @@ -48,49 +48,16 @@ "airlock_disabled" = !(docking_program.undocked() || docking_program.override_enabled), "override_enabled" = docking_program.override_enabled, "docking_codes" = docking_program.docking_codes, - "name" = docking_program.get_name() + "name" = docking_program.get_name(), + "internalTemplateName" = "AirlockConsoleDocking", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "docking_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/docking_port/Topic(href, href_list) - if((. = ..())) - return - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext") - clean = 1 - if("cycle_int") - clean = 1 - if("force_ext") - clean = 1 - if("force_int") - clean = 1 - if("abort") - clean = 1 - if("toggle_override") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 - - /////////////////////////////////////////////////////////////////////////////// //A docking controller for an airlock based docking port // /datum/computer/file/embedded_program/docking/airlock var/datum/computer/file/embedded_program/airlock/docking/airlock_program - /datum/computer/file/embedded_program/docking/airlock/New(var/obj/machinery/embedded_controller/M, var/datum/computer/file/embedded_program/airlock/docking/A) ..(M) airlock_program = A diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm index 55182aaaa6..b153437ca6 100644 --- a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm +++ b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm @@ -15,9 +15,7 @@ for (var/i = 1; i <= tags.len; i++) child_names[tags[i]] = names[i] - -/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/embedded_controller/radio/docking_port_multi/tgui_data(mob/user) var/datum/computer/file/embedded_program/docking/multi/docking_program = program // Cast to proper type var/list/airlocks[child_names.len] @@ -25,23 +23,14 @@ for (var/child_tag in child_names) airlocks[i++] = list("name"=child_names[child_tag], "override_enabled"=(docking_program.children_override[child_tag] == "enabled")) - data = list( + . = list( "docking_status" = docking_program.get_docking_status(), "airlocks" = airlocks, + "internalTemplateName" = "DockingConsoleMulti", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "multi_docking_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/docking_port_multi/Topic(href, href_list) - return 1 // Apparently we swallow all input (this is corrected legacy code) - - +/obj/machinery/embedded_controller/radio/docking_port_multi/tgui_act(action, params) + return // Apparently we swallow all input (this is corrected legacy code) //a docking port based on an airlock // This is the actual controller that will be commanded by the master defined above @@ -50,12 +39,13 @@ program = /datum/computer/file/embedded_program/airlock/multi_docking var/master_tag //for mapping tag_secure = 1 + valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "toggle_override") + -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/tgui_data(mob/user) var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program = program // Cast to proper type - data = list( + . = list( "chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]), "exterior_status" = airlock_program.memory["exterior_status"], "interior_status" = airlock_program.memory["interior_status"], @@ -63,42 +53,9 @@ "docking_status" = airlock_program.master_status, "airlock_disabled" = (airlock_program.docking_enabled && !airlock_program.override_enabled), "override_enabled" = airlock_program.override_enabled, + "internalTemplateName" = "AirlockConsoleDocking", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "docking_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Topic(href, href_list) - if((. = ..())) - return - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext") - clean = 1 - if("cycle_int") - clean = 1 - if("force_ext") - clean = 1 - if("force_int") - clean = 1 - if("abort") - clean = 1 - if("toggle_override") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 - - - /*** DEBUG VERBS *** /datum/computer/file/embedded_program/docking/multi/proc/print_state() diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 714d27d560..58db9782da 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -4,6 +4,7 @@ use_power = USE_POWER_IDLE idle_power_usage = 10 var/datum/computer/file/embedded_program/program //the currently executing program + var/list/valid_actions = list() var/on = 1 /obj/machinery/embedded_controller/Initialize() @@ -24,18 +25,19 @@ if(program) program.receive_signal(signal, receive_method, receive_param) - //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0 -/obj/machinery/embedded_controller/Topic(href, href_list) - if((. = ..())) - return +/obj/machinery/embedded_controller/Topic() + . = ..() + stack_trace("WARNING: Embedded controller [src] ([type]) had Topic() called unexpectedly. Please report this.") + +/obj/machinery/embedded_controller/tgui_act(action, params) + if(..()) + return TRUE + if(LAZYLEN(valid_actions)) + if(action in valid_actions) + program.receive_user_command(action) if(usr) - usr.set_machine(src) - src.add_fingerprint(usr) - // We would now pass it to the program, except that some of our embedded controller types want to block certain commands. - // Until/unless that is refactored differently, we rely on subtypes to pass it on. - //if(program) - // return program.receive_user_command(href_list["command"]) + add_fingerprint(usr) /obj/machinery/embedded_controller/process() if(program) @@ -44,19 +46,23 @@ update_icon() /obj/machinery/embedded_controller/attack_ai(mob/user as mob) - src.ui_interact(user) + tgui_interact(user) /obj/machinery/embedded_controller/attack_hand(mob/user as mob) - if(!user.IsAdvancedToolUser()) return 0 - src.ui_interact(user) + tgui_interact(user) + +/obj/machinery/embedded_controller/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "EmbeddedController", src) + ui.open() // // Embedded controller with a radio! (Most things (All things?) use this) // - /obj/machinery/embedded_controller/radio icon = 'icons/obj/airlock_machines.dmi' icon_state = "airlock_control_standby" diff --git a/code/game/machinery/embedded_controller/simple_docking_controller.dm b/code/game/machinery/embedded_controller/simple_docking_controller.dm index d2e04a3330..df94c21d5c 100644 --- a/code/game/machinery/embedded_controller/simple_docking_controller.dm +++ b/code/game/machinery/embedded_controller/simple_docking_controller.dm @@ -3,42 +3,18 @@ name = "docking hatch controller" program = /datum/computer/file/embedded_program/docking/simple var/tag_door + valid_actions = list("force_door", "toggle_override") -/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/embedded_controller/radio/simple_docking_controller/tgui_data(mob/user) var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type - data = list( + . = list( "docking_status" = docking_program.get_docking_status(), "override_enabled" = docking_program.override_enabled, - "door_state" = docking_program.memory["door_status"]["state"], - "door_lock" = docking_program.memory["door_status"]["lock"], + "exterior_status" = docking_program.memory["door_status"], + "internalTemplateName" = "DockingConsoleSimple", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "simple_docking_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/simple_docking_controller/Topic(href, href_list) - if((. = ..())) - return - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("force_door") - clean = 1 - if("toggle_override") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return - //A docking controller program for a simple door based docking port /datum/computer/file/embedded_program/docking/simple var/tag_door diff --git a/code/game/machinery/exonet_node.dm b/code/game/machinery/exonet_node.dm index b9b95e103c..a8f6a38734 100644 --- a/code/game/machinery/exonet_node.dm +++ b/code/game/machinery/exonet_node.dm @@ -94,17 +94,25 @@ // Proc: attack_hand() // Parameters: 1 (user - the person clicking on the machine) -// Description: Opens the NanoUI interface with ui_interact() +// Description: Opens the TGUI interface with tgui_interact() /obj/machinery/exonet_node/attack_hand(mob/user) - ui_interact(user) + tgui_interact(user) -// Proc: ui_interact() -// Parameters: 4 (standard NanoUI arguments) +// Proc: tgui_interact() +// Parameters: 2 (user - person interacting with the UI, ui - the UI itself, in a refresh) +// Description: Handles opening the TGUI interface +/obj/machinery/exonet_node/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ExonetNode", src) + ui.open() + +// Proc: tgui_data() +// Parameters: 1 (user - the person using the interface) // Description: Allows the user to turn the machine on or off, or open or close certain 'ports' for things like external PDA messages, newscasters, etc. -/obj/machinery/exonet_node/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/exonet_node/tgui_data(mob/user) // this is the data which will be sent to the ui - var/data[0] - + var/list/data = list() data["on"] = toggle ? 1 : 0 data["allowPDAs"] = allow_external_PDAs @@ -112,53 +120,46 @@ data["allowNewscasters"] = allow_external_newscasters data["logs"] = logs + return data - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "exonet_node.tmpl", "Exonet Node #157", 400, 400) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -// Proc: Topic() -// Parameters: 2 (standard Topic arguments) -// Description: Responds to button presses on the NanoUI interface. -/obj/machinery/exonet_node/Topic(href, href_list) +// Proc: tgui_act() +// Parameters: 2 (standard tgui_act arguments) +// Description: Responds to button presses on the TGUI interface. +/obj/machinery/exonet_node/tgui_act(action, params) if(..()) - return 1 - if(href_list["toggle_power"]) - toggle = !toggle - update_power() - if(!toggle) - var/msg = "[usr.client.key] ([usr]) has turned [src] off, at [x],[y],[z]." - message_admins(msg) - log_game(msg) + return TRUE - if(href_list["toggle_PDA_port"]) - allow_external_PDAs = !allow_external_PDAs + switch(action) + if("toggle_power") + . = TRUE + toggle = !toggle + update_power() + if(!toggle) + var/msg = "[usr.client.key] ([usr]) has turned [src] off, at [x],[y],[z]." + message_admins(msg) + log_game(msg) - if(href_list["toggle_communicator_port"]) - allow_external_communicators = !allow_external_communicators - if(!allow_external_communicators) - var/msg = "[usr.client.key] ([usr]) has turned [src]'s communicator port off, at [x],[y],[z]." - message_admins(msg) - log_game(msg) + if("toggle_PDA_port") + . = TRUE + allow_external_PDAs = !allow_external_PDAs - if(href_list["toggle_newscaster_port"]) - allow_external_newscasters = !allow_external_newscasters - if(!allow_external_newscasters) - var/msg = "[usr.client.key] ([usr]) has turned [src]'s newscaster port off, at [x],[y],[z]." - message_admins(msg) - log_game(msg) + if("toggle_communicator_port") + . = TRUE + allow_external_communicators = !allow_external_communicators + if(!allow_external_communicators) + var/msg = "[usr.client.key] ([usr]) has turned [src]'s communicator port off, at [x],[y],[z]." + message_admins(msg) + log_game(msg) + + if("toggle_newscaster_port") + . = TRUE + allow_external_newscasters = !allow_external_newscasters + if(!allow_external_newscasters) + var/msg = "[usr.client.key] ([usr]) has turned [src]'s newscaster port off, at [x],[y],[z]." + message_admins(msg) + log_game(msg) update_icon() - SSnanoui.update_uis(src) add_fingerprint(usr) // Proc: get_exonet_node() diff --git a/code/game/machinery/fire_alarm.dm b/code/game/machinery/fire_alarm.dm index 388b834e82..3ed93f79b3 100644 --- a/code/game/machinery/fire_alarm.dm +++ b/code/game/machinery/fire_alarm.dm @@ -27,6 +27,10 @@ FIRE ALARM /obj/machinery/firealarm/alarms_hidden alarms_hidden = TRUE +/obj/machinery/firealarm/examine() + . = ..() + . += "Current security level: [seclevel]" + /obj/machinery/firealarm/Initialize() . = ..() if(z in using_map.contact_levels) @@ -127,81 +131,24 @@ FIRE ALARM if(user.stat || stat & (NOPOWER | BROKEN)) return - user.set_machine(src) - var/area/A = src.loc - var/d1 - var/d2 - if(istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon)) - A = A.loc - - if(A.fire) - d1 = text("Reset - Lockdown", src) - else - d1 = text("Alarm - Lockdown", src) - if(timing) - d2 = text("Stop Time Lock", src) - else - d2 = text("Initiate Time Lock", src) - var/second = round(time) % 60 - var/minute = (round(time) - second) / 60 - var/dat = "Fire alarm [d1]\n
The current alert level is: [get_security_level()]

\nTimer System: [d2]
\nTime Left: [(minute ? "[minute]:" : null)][second] - - + +\n
" - user << browse(dat, "window=firealarm") - onclose(user, "firealarm") + add_fingerprint(user) + var/area/A = get_area(src) + if(A.fire) + reset(user) else - A = A.loc - if(A.fire) - d1 = text("[]", src, stars("Reset - Lockdown")) - else - d1 = text("[]", src, stars("Alarm - Lockdown")) - if(timing) - d2 = text("[]", src, stars("Stop Time Lock")) - else - d2 = text("[]", src, stars("Initiate Time Lock")) - var/second = round(time) % 60 - var/minute = (round(time) - second) / 60 - var/dat = "[stars("Fire alarm")] [d1]\n
The current alert level is: [stars(get_security_level())]

\nTimer System: [d2]
\nTime Left: [(minute ? text("[]:", minute) : null)][second] - - + +\n
" - user << browse(dat, "window=firealarm") - onclose(user, "firealarm") - return + alarm(0, user) -/obj/machinery/firealarm/Topic(href, href_list) - ..() - if(usr.stat || stat & (BROKEN | NOPOWER)) - return - - if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - if(href_list["reset"]) - reset() - else if(href_list["alarm"]) - alarm() - else if(href_list["time"]) - timing = text2num(href_list["time"]) - last_process = world.timeofday - START_PROCESSING(SSobj, src) - else if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 120) - - updateUsrDialog() - - add_fingerprint(usr) - else - usr << browse(null, "window=firealarm") - return - return - -/obj/machinery/firealarm/proc/reset() +/obj/machinery/firealarm/proc/reset(mob/user) if(!(working)) return var/area/area = get_area(src) for(var/obj/machinery/firealarm/FA in area) fire_alarm.clearAlarm(src.loc, FA) update_icon() - return + if(user) + log_game("[user] reset a fire alarm at [COORD(src)]") -/obj/machinery/firealarm/proc/alarm(var/duration = 0) +/obj/machinery/firealarm/proc/alarm(var/duration = 0, mob/user) if(!(working)) return var/area/area = get_area(src) @@ -209,7 +156,8 @@ FIRE ALARM fire_alarm.triggerAlarm(loc, FA, duration, hidden = alarms_hidden) update_icon() playsound(src, 'sound/machines/airalarm.ogg', 25, 0, 4) - return + if(user) + log_game("[user] triggered a fire alarm at [COORD(src)]") /obj/machinery/firealarm/proc/set_security_level(var/newlevel) if(seclevel != newlevel) diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index 4c4d3ce914..2e728775da 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -15,69 +15,94 @@ "Fuel" = PIPING_LAYER_FUEL, "Aux" = PIPING_LAYER_AUX ) + var/disposals = FALSE // TODO - Its about time to make this NanoUI don't we think? /obj/machinery/pipedispenser/attack_hand(var/mob/user as mob) if((. = ..())) return - src.interact(user) + tgui_interact(user) -/obj/machinery/pipedispenser/interact(mob/user) - user.set_machine(src) +/obj/machinery/pipedispenser/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/pipes), + ) - var/list/lines = list() - for(var/category in atmos_pipe_recipes) - lines += "[category]:
" - if(category == "Pipes") - for(var/pipename in pipe_layers) - var/pipelayer = pipe_layers[pipename] - lines += "[pipename] " - lines += "
" - for(var/datum/pipe_recipe/PI in atmos_pipe_recipes[category]) - lines += PI.Render(src) - var/dat = lines.Join() - var/datum/browser/popup = new(user, "pipedispenser", name, 300, 800, src) - popup.set_content("[dat]") - popup.open() - return +/obj/machinery/pipedispenser/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PipeDispenser", name) + ui.open() -/obj/machinery/pipedispenser/Topic(href, href_list) +/obj/machinery/pipedispenser/tgui_data(mob/user) + var/list/data = list( + "disposals" = disposals, + "p_layer" = p_layer, + "pipe_layers" = pipe_layers, + ) + + var/list/recipes + if(disposals) + recipes = GLOB.disposal_pipe_recipes + else + recipes = GLOB.atmos_pipe_recipes + + for(var/c in recipes) + var/list/cat = recipes[c] + var/list/r = list() + for(var/i in 1 to cat.len) + var/datum/pipe_recipe/info = cat[i] + r += list(list("pipe_name" = info.name, "pipe_index" = i)) + data["categories"] += list(list("cat_name" = c, "recipes" = r)) + + return data + +/obj/machinery/pipedispenser/tgui_act(action, params) if(..()) - return + return TRUE if(unwrenched || !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=pipedispenser") - usr.unset_machine(src) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(href_list["setlayer"]) - var/new_pipe_layer = text2num(href_list["setlayer"]) - if(isnum(new_pipe_layer)) - p_layer = new_pipe_layer - updateDialog() - else if(href_list["makepipe"]) - if(!wait) - var/obj/machinery/atmospherics/p_type = text2path(href_list["makepipe"]) - var/p_dir = text2num(href_list["dir"]) - var/pi_type = initial(p_type.construction_type) - var/obj/item/pipe/P = new pi_type(src.loc, p_type, p_dir) - P.setPipingLayer(p_layer) - P.add_fingerprint(usr) - wait = 1 - spawn(10) - wait = 0 - else if(href_list["makemeter"]) - if(!wait) - new /obj/item/pipe_meter(/*usr.loc*/ src.loc) - wait = 1 - spawn(15) - wait = 0 - return + return TRUE + + . = TRUE + switch(action) + if("p_layer") + p_layer = text2num(params["p_layer"]) + if("dispense_pipe") + if(!wait) + var/list/recipes + if(disposals) + recipes = GLOB.disposal_pipe_recipes + else + recipes = GLOB.atmos_pipe_recipes + + var/datum/pipe_recipe/recipe = recipes[params["category"]][text2num(params["pipe_type"])] + + var/obj/created_object = null + if(istype(recipe, /datum/pipe_recipe/pipe)) + var/datum/pipe_recipe/pipe/R = recipe + created_object = new R.construction_type(loc, recipe.pipe_type, NORTH) + var/obj/item/pipe/P = created_object + P.setPipingLayer(p_layer) + else if(istype(recipe, /datum/pipe_recipe/disposal)) + var/datum/pipe_recipe/disposal/D = recipe + var/obj/structure/disposalconstruct/C = new(loc, D.pipe_type, NORTH, 0, D.subtype ? D.subtype : 0) + C.update() + created_object = C + else if(istype(recipe, /datum/pipe_recipe/meter)) + created_object = new recipe.pipe_type(loc) + else + log_runtime(EXCEPTION("Warning: [usr] attempted to spawn pipe recipe type by params [json_encode(params)] ([recipe] [recipe?.type]), but it was not allowed by this machine ([src] [type])")) + return + + created_object.add_fingerprint(usr) + wait = TRUE + VARSET_IN(src, wait, FALSE, 15) + /obj/machinery/pipedispenser/attackby(var/obj/item/W as obj, var/mob/user as mob) src.add_fingerprint(usr) if (istype(W, /obj/item/pipe) || istype(W, /obj/item/pipe_meter)) - to_chat(usr, "You put [W] back to [src].") + to_chat(usr, "You put [W] back in [src].") user.drop_item() qdel(W) return @@ -117,15 +142,7 @@ icon_state = "pipe_d" density = 1 anchored = 1.0 - -/* -//Allow you to push disposal pipes into it (for those with density 1) -/obj/machinery/pipedispenser/disposal/Crossed(var/obj/structure/disposalconstruct/pipe as obj) - if(istype(pipe) && !pipe.anchored) - qdel(pipe) - -Nah -*/ + disposals = TRUE //Allow you to drag-drop disposal pipes into it /obj/machinery/pipedispenser/disposal/MouseDrop_T(var/obj/structure/disposalconstruct/pipe as obj, mob/usr as mob) @@ -138,43 +155,9 @@ Nah if (pipe.anchored) return + to_chat(usr, "You shove [pipe] back in [src].") qdel(pipe) -/obj/machinery/pipedispenser/disposal/interact(mob/user) - user.set_machine(src) - - var/list/lines = list() - for(var/category in disposal_pipe_recipes) - lines += "[category]:
" - for(var/datum/pipe_recipe/PI in disposal_pipe_recipes[category]) - lines += PI.Render(src) - var/dat = lines.Join() - var/datum/browser/popup = new(user, "pipedispenser", name, 300, 500, src) - popup.set_content("[dat]") - popup.open() - return - -/obj/machinery/pipedispenser/disposal/Topic(href, href_list) - if(href_list["makepipe"] || href_list["setlayer"] || href_list["makemeter"]) // Asking the disposal machine to do atmos stuff? - return // That's a no no. - if((. = ..())) - return - if(href_list["dmake"]) - if(unwrenched || !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=pipedispenser") - return - if(!wait) - var/ptype = text2num(href_list["dmake"]) - var/pdir = (href_list["dir"] ? text2num(href_list["dir"]) : NORTH) - var/psub = (href_list["sort"] ? text2num(href_list["sort"]) : 0) - var/obj/structure/disposalconstruct/C = new (src.loc, ptype, pdir, 0, psub) - - C.add_fingerprint(usr) - C.update() - wait = 1 - VARSET_IN(src, wait, FALSE, 15) - return - // adding a pipe dispensers that spawn unhooked from the ground /obj/machinery/pipedispenser/orderable anchored = 0 diff --git a/code/game/machinery/pipe/pipe_recipes.dm b/code/game/machinery/pipe/pipe_recipes.dm index 14dbfc2603..e5db17f4b1 100644 --- a/code/game/machinery/pipe/pipe_recipes.dm +++ b/code/game/machinery/pipe/pipe_recipes.dm @@ -2,75 +2,69 @@ // Recipies for Pipe Dispenser and (someday) the RPD // -var/global/list/atmos_pipe_recipes = null -var/global/list/disposal_pipe_recipes = null -var/global/list/all_pipe_recipes = null // VOREStation Add +GLOBAL_LIST_INIT(atmos_pipe_recipes, list( + "Pipes" = list( + new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple), + new /datum/pipe_recipe/pipe("Manifold", /obj/machinery/atmospherics/pipe/manifold), + new /datum/pipe_recipe/pipe("Manual Valve", /obj/machinery/atmospherics/valve), + new /datum/pipe_recipe/pipe("Digital Valve", /obj/machinery/atmospherics/valve/digital), + new /datum/pipe_recipe/pipe("Pipe cap", /obj/machinery/atmospherics/pipe/cap), + new /datum/pipe_recipe/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/manifold4w), + new /datum/pipe_recipe/pipe("Manual T-Valve", /obj/machinery/atmospherics/tvalve), + new /datum/pipe_recipe/pipe("Digital T-Valve", /obj/machinery/atmospherics/tvalve/digital), + new /datum/pipe_recipe/pipe("Upward Pipe", /obj/machinery/atmospherics/pipe/zpipe/up), + new /datum/pipe_recipe/pipe("Downward Pipe", /obj/machinery/atmospherics/pipe/zpipe/down), + new /datum/pipe_recipe/pipe("Universal Pipe Adaptor",/obj/machinery/atmospherics/pipe/simple/visible/universal), + ), + "Devices" = list( + new /datum/pipe_recipe/pipe("Connector", /obj/machinery/atmospherics/portables_connector), + new /datum/pipe_recipe/pipe("Unary Vent", /obj/machinery/atmospherics/unary/vent_pump), + new /datum/pipe_recipe/pipe("Aux Vent", /obj/machinery/atmospherics/unary/vent_pump/aux), + new /datum/pipe_recipe/pipe("Passive Vent", /obj/machinery/atmospherics/pipe/vent), + new /datum/pipe_recipe/pipe("Injector", /obj/machinery/atmospherics/unary/outlet_injector), + new /datum/pipe_recipe/pipe("Gas Pump", /obj/machinery/atmospherics/binary/pump), + new /datum/pipe_recipe/pipe("Fuel Pump", /obj/machinery/atmospherics/binary/pump/fuel), + new /datum/pipe_recipe/pipe("Aux Pump", /obj/machinery/atmospherics/binary/pump/aux), + new /datum/pipe_recipe/pipe("Pressure Regulator", /obj/machinery/atmospherics/binary/passive_gate), + new /datum/pipe_recipe/pipe("High Power Gas Pump", /obj/machinery/atmospherics/binary/pump/high_power), + new /datum/pipe_recipe/pipe("Automatic Shutoff Valve",/obj/machinery/atmospherics/valve/shutoff), + new /datum/pipe_recipe/pipe("Scrubber", /obj/machinery/atmospherics/unary/vent_scrubber), + new /datum/pipe_recipe/meter("Meter"), + new /datum/pipe_recipe/pipe("Gas Filter", /obj/machinery/atmospherics/trinary/atmos_filter), + new /datum/pipe_recipe/pipe("Gas Mixer", /obj/machinery/atmospherics/trinary/mixer), + new /datum/pipe_recipe/pipe("Gas Mixer 'T'", /obj/machinery/atmospherics/trinary/mixer/t_mixer), + new /datum/pipe_recipe/pipe("Omni Gas Mixer", /obj/machinery/atmospherics/omni/mixer), + new /datum/pipe_recipe/pipe("Omni Gas Filter", /obj/machinery/atmospherics/omni/atmos_filter), + ), + "Heat Exchange" = list( + new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/heat_exchanging), + new /datum/pipe_recipe/pipe("Junction", /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction), + new /datum/pipe_recipe/pipe("Heat Exchanger", /obj/machinery/atmospherics/unary/heat_exchanger), + ), + "Insulated pipes" = list( + new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/insulated), + ) +)) -/hook/startup/proc/init_pipe_recipes() - global.atmos_pipe_recipes = list( - "Pipes" = list( - new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple), - new /datum/pipe_recipe/pipe("Manifold", /obj/machinery/atmospherics/pipe/manifold), - new /datum/pipe_recipe/pipe("Manual Valve", /obj/machinery/atmospherics/valve), - new /datum/pipe_recipe/pipe("Digital Valve", /obj/machinery/atmospherics/valve/digital), - new /datum/pipe_recipe/pipe("Pipe cap", /obj/machinery/atmospherics/pipe/cap), - new /datum/pipe_recipe/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/manifold4w), - new /datum/pipe_recipe/pipe("Manual T-Valve", /obj/machinery/atmospherics/tvalve), - new /datum/pipe_recipe/pipe("Digital T-Valve", /obj/machinery/atmospherics/tvalve/digital), - new /datum/pipe_recipe/pipe("Upward Pipe", /obj/machinery/atmospherics/pipe/zpipe/up), - new /datum/pipe_recipe/pipe("Downward Pipe", /obj/machinery/atmospherics/pipe/zpipe/down), - new /datum/pipe_recipe/pipe("Universal Pipe Adaptor",/obj/machinery/atmospherics/pipe/simple/visible/universal), - ), - "Devices" = list( - new /datum/pipe_recipe/pipe("Connector", /obj/machinery/atmospherics/portables_connector), - new /datum/pipe_recipe/pipe("Unary Vent", /obj/machinery/atmospherics/unary/vent_pump), - new /datum/pipe_recipe/pipe("Aux Vent", /obj/machinery/atmospherics/unary/vent_pump/aux), - new /datum/pipe_recipe/pipe("Passive Vent", /obj/machinery/atmospherics/pipe/vent), - new /datum/pipe_recipe/pipe("Injector", /obj/machinery/atmospherics/unary/outlet_injector), - new /datum/pipe_recipe/pipe("Gas Pump", /obj/machinery/atmospherics/binary/pump), - new /datum/pipe_recipe/pipe("Fuel Pump", /obj/machinery/atmospherics/binary/pump/fuel), - new /datum/pipe_recipe/pipe("Aux Pump", /obj/machinery/atmospherics/binary/pump/aux), - new /datum/pipe_recipe/pipe("Pressure Regulator", /obj/machinery/atmospherics/binary/passive_gate), - new /datum/pipe_recipe/pipe("High Power Gas Pump", /obj/machinery/atmospherics/binary/pump/high_power), - new /datum/pipe_recipe/pipe("Automatic Shutoff Valve",/obj/machinery/atmospherics/valve/shutoff), - new /datum/pipe_recipe/pipe("Scrubber", /obj/machinery/atmospherics/unary/vent_scrubber), - new /datum/pipe_recipe/meter("Meter"), - new /datum/pipe_recipe/pipe("Gas Filter", /obj/machinery/atmospherics/trinary/atmos_filter), - new /datum/pipe_recipe/pipe("Gas Mixer", /obj/machinery/atmospherics/trinary/mixer), - new /datum/pipe_recipe/pipe("Gas Mixer 'T'", /obj/machinery/atmospherics/trinary/mixer/t_mixer), - new /datum/pipe_recipe/pipe("Omni Gas Mixer", /obj/machinery/atmospherics/omni/mixer), - new /datum/pipe_recipe/pipe("Omni Gas Filter", /obj/machinery/atmospherics/omni/atmos_filter), - ), - "Heat Exchange" = list( - new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/heat_exchanging), - new /datum/pipe_recipe/pipe("Junction", /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction), - new /datum/pipe_recipe/pipe("Heat Exchanger", /obj/machinery/atmospherics/unary/heat_exchanger), - ), - "Insulated pipes" = list( - new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/insulated), - ) +GLOBAL_LIST_INIT(disposal_pipe_recipes, list( + "Disposal Pipes" = list( + new /datum/pipe_recipe/disposal("Pipe", DISPOSAL_PIPE_STRAIGHT, "conpipe-s", PIPE_STRAIGHT), + new /datum/pipe_recipe/disposal("Bent Pipe", DISPOSAL_PIPE_CORNER, "conpipe-c"), + new /datum/pipe_recipe/disposal("Junction", DISPOSAL_PIPE_JUNCTION, "conpipe-j1", PIPE_TRIN_M), + new /datum/pipe_recipe/disposal("Y-Junction", DISPOSAL_PIPE_JUNCTION_Y, "conpipe-y"), + new /datum/pipe_recipe/disposal("Sort Junction", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_NORMAL), + new /datum/pipe_recipe/disposal("Sort Junction (Wildcard)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_WILDCARD), + new /datum/pipe_recipe/disposal("Sort Junction (Untagged)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_UNTAGGED), + new /datum/pipe_recipe/disposal("Tagger", DISPOSAL_PIPE_TAGGER, "pipe-tagger", PIPE_STRAIGHT), + new /datum/pipe_recipe/disposal("Tagger (Partial)", DISPOSAL_PIPE_TAGGER_PARTIAL, "pipe-tagger-partial", PIPE_STRAIGHT), + new /datum/pipe_recipe/disposal("Trunk", DISPOSAL_PIPE_TRUNK, "conpipe-t"), + new /datum/pipe_recipe/disposal("Upwards", DISPOSAL_PIPE_UPWARD, "pipe-u"), + new /datum/pipe_recipe/disposal("Downwards", DISPOSAL_PIPE_DOWNWARD, "pipe-d"), + new /datum/pipe_recipe/disposal("Bin", DISPOSAL_PIPE_BIN, "disposal", PIPE_ONEDIR), + new /datum/pipe_recipe/disposal("Outlet", DISPOSAL_PIPE_OUTLET, "outlet"), + new /datum/pipe_recipe/disposal("Chute", DISPOSAL_PIPE_CHUTE, "intake"), ) - global.disposal_pipe_recipes = list( - "Disposal Pipes" = list( - new /datum/pipe_recipe/disposal("Pipe", DISPOSAL_PIPE_STRAIGHT, "conpipe-s", PIPE_STRAIGHT), - new /datum/pipe_recipe/disposal("Bent Pipe", DISPOSAL_PIPE_CORNER, "conpipe-c"), - new /datum/pipe_recipe/disposal("Junction", DISPOSAL_PIPE_JUNCTION, "conpipe-j1", PIPE_TRIN_M), - new /datum/pipe_recipe/disposal("Y-Junction", DISPOSAL_PIPE_JUNCTION_Y, "conpipe-y"), - new /datum/pipe_recipe/disposal("Sort Junction", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_NORMAL), - new /datum/pipe_recipe/disposal("Sort Junction (Wildcard)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_WILDCARD), - new /datum/pipe_recipe/disposal("Sort Junction (Untagged)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_UNTAGGED), - new /datum/pipe_recipe/disposal("Tagger", DISPOSAL_PIPE_TAGGER, "pipe-tagger", PIPE_STRAIGHT), - new /datum/pipe_recipe/disposal("Tagger (Partial)", DISPOSAL_PIPE_TAGGER_PARTIAL, "pipe-tagger-partial", PIPE_STRAIGHT), - new /datum/pipe_recipe/disposal("Trunk", DISPOSAL_PIPE_TRUNK, "conpipe-t"), - new /datum/pipe_recipe/disposal("Upwards", DISPOSAL_PIPE_UPWARD, "pipe-u"), - new /datum/pipe_recipe/disposal("Downwards", DISPOSAL_PIPE_DOWNWARD, "pipe-d"), - new /datum/pipe_recipe/disposal("Bin", DISPOSAL_PIPE_BIN, "disposal", PIPE_ONEDIR), - new /datum/pipe_recipe/disposal("Outlet", DISPOSAL_PIPE_OUTLET, "outlet"), - new /datum/pipe_recipe/disposal("Chute", DISPOSAL_PIPE_CHUTE, "intake"), - ) - ) - global.all_pipe_recipes = disposal_pipe_recipes + atmos_pipe_recipes // VOREStation Add - return TRUE +)) // // New method of handling pipe construction. Instead of numeric constants and a giant switch statement of doom @@ -83,11 +77,52 @@ var/global/list/all_pipe_recipes = null // VOREStation Add var/icon_state = null // This tells the RPD what kind of pipe icon to render for the preview. var/icon_state_m = null // This stores the mirrored version of the regular state (if available). var/dirtype // If using an RPD, this tells more about what previews to show. + var/pipe_type // Render an HTML link to select this pipe type. Returns text. /datum/pipe_recipe/proc/Render(dispenser) return "[name]
" +// Get preview for UIs +/datum/pipe_recipe/proc/get_preview(selected_dir) + var/list/dirs + switch(dirtype) + if(PIPE_STRAIGHT, PIPE_BENDABLE) + dirs = list("[NORTH]" = "Vertical", "[EAST]" = "Horizontal") + if(dirtype == PIPE_BENDABLE) + dirs += list("[NORTHWEST]" = "West to North", "[NORTHEAST]" = "North to East", + "[SOUTHWEST]" = "South to West", "[SOUTHEAST]" = "East to South") + if(PIPE_TRINARY) + dirs = list("[NORTH]" = "West South East", "[SOUTH]" = "East North West", + "[EAST]" = "North West South", "[WEST]" = "South East North") + if(PIPE_TRIN_M) + dirs = list("[NORTH]" = "North East South", "[SOUTHWEST]" = "North West South", + "[NORTHEAST]" = "South East North", "[SOUTH]" = "South West North", + "[WEST]" = "West North East", "[SOUTHEAST]" = "West South East", + "[NORTHWEST]" = "East North West", "[EAST]" = "East South West",) + if(PIPE_DIRECTIONAL) + dirs = list("[NORTH]" = "North", "[SOUTH]" = "South", "[WEST]" = "West", "[EAST]" = "East") + if(PIPE_ONEDIR) + dirs = list("[SOUTH]" = name) + if(PIPE_UNARY_FLIPPABLE) + dirs = list("[NORTH]" = "North", "[EAST]" = "East", "[SOUTH]" = "South", "[WEST]" = "West", + "[NORTHEAST]" = "North Flipped", "[SOUTHEAST]" = "East Flipped", "[SOUTHWEST]" = "South Flipped", "[NORTHWEST]" = "West Flipped") + + + var/list/rows = list() + var/list/row = list("previews" = list()) + var/i = 0 + for(var/dir in dirs) + var/numdir = text2num(dir) + var/flipped = ((dirtype == PIPE_TRIN_M) || (dirtype == PIPE_UNARY_FLIPPABLE)) && (numdir in GLOB.cornerdirs) + row["previews"] += list(list("selected" = (numdir == selected_dir), "dir" = dir2text(numdir), "dir_name" = dirs[dir], "icon_state" = icon_state, "flipped" = flipped)) + if(i++ || dirtype == PIPE_ONEDIR) + rows += list(row) + row = list("previews" = list()) + i = 0 + + return rows + // Parameters for the Topic link returned by Render(). Returns text. /datum/pipe_recipe/proc/Params() return "" @@ -97,7 +132,6 @@ var/global/list/all_pipe_recipes = null // VOREStation Add // /datum/pipe_recipe/pipe var/obj/item/pipe/construction_type // The type PATH to the type of pipe fitting object the recipe makes. - var/obj/machinery/atmospherics/pipe_type // The type PATH of what actual pipe the fitting becomes. var/paintable = FALSE // If TRUE, allow the RPD to paint this pipe. // VOREStation Add /datum/pipe_recipe/pipe/New(var/label, var/obj/machinery/atmospherics/path) @@ -129,6 +163,7 @@ var/global/list/all_pipe_recipes = null // VOREStation Add /datum/pipe_recipe/meter dirtype = PIPE_ONEDIR icon_state = "meter" + pipe_type = /obj/item/pipe_meter /datum/pipe_recipe/meter/New(label) name = label @@ -140,7 +175,6 @@ var/global/list/all_pipe_recipes = null // VOREStation Add // Subtype for disposal pipes // /datum/pipe_recipe/disposal - var/pipe_type // pipe_type is one of the DISPOSAL_PIPE_ ptype constants. var/subtype // subtype is one of the DISPOSAL_SORT_ constants. /datum/pipe_recipe/disposal/New(var/label, var/ptype, var/state, dt=PIPE_DIRECTIONAL, var/sort=0) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 77a35d2829..54aac0a5ff 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -11,6 +11,7 @@ var/set_temperature = T0C + 20 //K var/heating_power = 40000 clicksound = "switch" + interact_offline = TRUE /obj/machinery/space_heater/New() ..() @@ -88,75 +89,74 @@ interact(user) /obj/machinery/space_heater/interact(mob/user as mob) - if(panel_open) - - var/dat - dat = "Power cell: " - if(cell) - dat += "Installed
" - else - dat += "Removed
" - - dat += "Power Level: [cell ? round(cell.percent(),1) : 0]%

" - - dat += "Set Temperature: " - - dat += "-" - - dat += " [set_temperature]K ([set_temperature-T0C]°C)" - dat += "+
" - - user.set_machine(src) - user << browse("Space Heater Control Panel[dat]", "window=spaceheater") - onclose(user, "spaceheater") + tgui_interact(user) else on = !on user.visible_message("[user] switches [on ? "on" : "off"] the [src].","You switch [on ? "on" : "off"] the [src].") update_icon() return +/obj/machinery/space_heater/tgui_state(mob/user) + return GLOB.tgui_physical_state -/obj/machinery/space_heater/Topic(href, href_list) - if(usr.stat) - return - if((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) +/obj/machinery/space_heater/tgui_status(mob/user) + if(!panel_open) + return STATUS_CLOSE + return ..() - switch(href_list["op"]) +/obj/machinery/space_heater/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SpaceHeater", name) + ui.open() - if("temp") - var/value = text2num(href_list["val"]) +/obj/machinery/space_heater/tgui_data(mob/user) + var/list/data = list() - // limit to 0-90 degC - set_temperature = dd_range(T0C, T0C + 90, set_temperature + value) + data["cell"] = !!cell + data["power"] = round(cell?.percent(), 1) + data["temp"] = set_temperature + data["minTemp"] = T0C + data["maxTemp"] = T0C + 90 - if("cellremove") - if(panel_open && cell && !usr.get_active_hand()) - usr.visible_message("\The [usr] removes \the [cell] from \the [src].", "You remove \the [cell] from \the [src].") - cell.update_icon() - usr.put_in_hands(cell) - cell.add_fingerprint(usr) - cell = null + return data + +/obj/machinery/space_heater/tgui_act(action, params) + if(..()) + return TRUE + + if(!panel_open) + return FALSE + + switch(action) + if("temp") + // limit to 0-90 degC + set_temperature = clamp(text2num(params["newtemp"]), T0C, T0C + 90) + . = TRUE + + if("cellremove") + if(cell && !usr.get_active_hand()) + usr.visible_message("[usr] removes [cell] from [src].", "You remove [cell] from [src].") + cell.update_icon() + usr.put_in_hands(cell) + cell.add_fingerprint(usr) + cell = null + power_change() + . = TRUE + + + if("cellinstall") + if(!cell) + var/obj/item/weapon/cell/C = usr.get_active_hand() + if(istype(C)) + usr.drop_item() + cell = C + C.loc = src + C.add_fingerprint(usr) power_change() - - - if("cellinstall") - if(panel_open && !cell) - var/obj/item/weapon/cell/C = usr.get_active_hand() - if(istype(C)) - usr.drop_item() - cell = C - C.loc = src - C.add_fingerprint(usr) - power_change() - usr.visible_message("[usr] inserts \the [C] into \the [src].", "You insert \the [C] into \the [src].") - - updateDialog() - else - usr << browse(null, "window=spaceheater") - usr.unset_machine() - return + usr.visible_message("[usr] inserts \the [C] into \the [src].", "You insert \the [C] into \the [src].") + . = TRUE /obj/machinery/space_heater/process() if(on) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 718b71b644..6304820087 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -83,114 +83,93 @@ return return -/obj/machinery/suit_storage_unit/attack_hand(mob/user as mob) - var/dat +/obj/machinery/suit_storage_unit/attack_hand(mob/user) if(..()) return if(stat & NOPOWER) return if(!user.IsAdvancedToolUser()) return 0 - if(panelopen) //The maintenance panel is open. Time for some shady stuff - dat+= "Suit storage unit: Maintenance panel" - dat+= "Maintenance panel controls
" - dat+= "The panel is ridden with controls, button and meters, labeled in strange signs and symbols that
you cannot understand. Probably the manufactoring world's language.
Among other things, a few controls catch your eye.


" - dat+= text("A small dial with a small lambda symbol on it. It's pointing towards a gauge that reads [].
Turn towards []
",(issuperUV ? "15nm" : "185nm"),src,(issuperUV ? "185nm" : "15nm")) - dat+= text("A thick old-style button, with 2 grimy LED lights next to it. The [] LED is on.
Press button",(safetieson? "GREEN" : "RED"),src) - dat+= text("

Close panel", user) - //user << browse(dat, "window=ssu_m_panel;size=400x500") - //onclose(user, "ssu_m_panel") - else if(isUV) //The thing is running its cauterisation cycle. You have to wait. - dat += "Suit storage unit" - dat+= "Unit is cauterising contents with selected UV ray intensity. Please wait.
" - //dat+= "Cycle end in: [cycletimeleft()] seconds. " - //user << browse(dat, "window=ssu_cycling_panel;size=400x500") - //onclose(user, "ssu_cycling_panel") + tgui_interact(user) +/obj/machinery/suit_storage_unit/tgui_state(mob/user) + return GLOB.tgui_notcontained_state + +/obj/machinery/suit_storage_unit/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SuitStorageUnit", name) + ui.open() + +/obj/machinery/suit_storage_unit/tgui_data() + var/list/data = list() + + data["broken"] = isbroken + data["panelopen"] = panelopen + + data["locked"] = islocked + data["open"] = isopen + data["safeties"] = safetieson + data["uv_active"] = isUV + data["uv_super"] = issuperUV + if(HELMET) + data["helmet"] = HELMET.name else - if(!isbroken) - dat+= "Suit storage unit" - dat+= "U-Stor-It Suit Storage Unit, model DS1900
" - dat+= "Welcome to the Unit control panel.

" - dat+= text("Helmet storage compartment: []
",(HELMET ? HELMET.name : "No helmet detected.")) - if(HELMET && isopen) - dat+=text("Dispense helmet
",src) - dat+= text("Suit storage compartment: []
",(SUIT ? SUIT.name : "
No exosuit detected.")) - if(SUIT && isopen) - dat+=text("Dispense suit
",src) - dat+= text("Breathmask storage compartment: []
",(MASK ? MASK.name : "
No breathmask detected.")) - if(MASK && isopen) - dat+=text("Dispense mask
",src) - if(OCCUPANT) - dat+= "
WARNING: Biological entity detected inside the Unit's storage. Please remove.
" - dat+= "Eject extra load" - dat+= text("
Unit is: [] - [] Unit ",(isopen ? "Open" : "Closed"),src,(isopen ? "Close" : "Open")) - if(isopen) - dat+="
" - else - dat+= text(" - *[] Unit*
",src,(islocked ? "Unlock" : "Lock")) - dat+= text("Unit status: []",(islocked? "**LOCKED**
" : "**UNLOCKED**
")) - dat+= text("Start Disinfection cycle
",src) - dat += text("

Close control panel", user) - //user << browse(dat, "window=Suit Storage Unit;size=400x500") - //onclose(user, "Suit Storage Unit") - else //Ohhhh shit it's dirty or broken! Let's inform the guy. - dat+= "Suit storage unit" - dat+= "Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.

" - dat+= text("
Close control panel", user) - //user << browse(dat, "window=suit_storage_unit;size=400x500") - //onclose(user, "suit_storage_unit") + data["helmet"] = null + if(SUIT) + data["suit"] = SUIT.name + else + data["suit"] = null + if(MASK) + data["mask"] = MASK.name + else + data["mask"] = null + data["storage"] = null + if(OCCUPANT) + data["occupied"] = TRUE + else + data["occupied"] = FALSE + return data - user << browse(dat, "window=suit_storage_unit;size=400x500") - onclose(user, "suit_storage_unit") - return +/obj/machinery/suit_storage_unit/tgui_act(action, params) //I fucking HATE this proc + if(..() || isUV || isbroken) + return TRUE - -/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc - if(..()) - return - if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) - usr.set_machine(src) - if(href_list["toggleUV"]) - toggleUV(usr) - updateUsrDialog() - update_icon() - if(href_list["togglesafeties"]) - togglesafeties(usr) - updateUsrDialog() - update_icon() - if(href_list["dispense_helmet"]) - dispense_helmet(usr) - updateUsrDialog() - update_icon() - if(href_list["dispense_suit"]) - dispense_suit(usr) - updateUsrDialog() - update_icon() - if(href_list["dispense_mask"]) - dispense_mask(usr) - updateUsrDialog() - update_icon() - if(href_list["toggle_open"]) + switch(action) + if("door") toggle_open(usr) - updateUsrDialog() - update_icon() - if(href_list["toggle_lock"]) - toggle_lock(usr) - updateUsrDialog() - update_icon() - if(href_list["start_UV"]) + . = TRUE + if("dispense") + switch(params["item"]) + if("helmet") + dispense_helmet(usr) + if("mask") + dispense_mask(usr) + if("suit") + dispense_suit(usr) + . = TRUE + if("uv") start_UV(usr) - updateUsrDialog() - update_icon() - if(href_list["eject_guy"]) + . = TRUE + if("lock") + toggle_lock(usr) + . = TRUE + if("eject_guy") eject_occupant(usr) - updateUsrDialog() - update_icon() - /*if(href_list["refresh"]) - updateUsrDialog()*/ + . = TRUE + + // Panel Open stuff + if(!. && panelopen) + switch(action) + if("toggleUV") + toggleUV(usr) + . = TRUE + if("togglesafeties") + togglesafeties(usr) + . = TRUE + + update_icon() add_fingerprint(usr) - return /obj/machinery/suit_storage_unit/proc/toggleUV(mob/user as mob) @@ -847,9 +826,7 @@ return 1 /obj/machinery/suit_cycler/attack_hand(mob/user as mob) - add_fingerprint(user) - if(..() || stat & (BROKEN|NOPOWER)) return @@ -860,116 +837,134 @@ if(shock(user, 100)) return - user.set_machine(src) + tgui_interact(user) - var/dat = "Suit Cycler Interface" +/obj/machinery/suit_cycler/tgui_state(mob/user) + return GLOB.tgui_notcontained_state - if(active) - dat+= "
The [model_text ? "[model_text] " : ""]suit cycler is currently in use. Please wait..." +/obj/machinery/suit_cycler/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SuitCycler", name) + ui.open() - else if(locked) - dat += "
The [model_text ? "[model_text] " : ""]suit cycler is currently locked. Please contact your system administrator." - if(allowed(user)) - dat += "
\[unlock unit\]" +/obj/machinery/suit_cycler/tgui_data(mob/user) + var/list/data = list() + + data["departments"] = departments + data["species"] = species + data["model_text"] = model_text + data["can_repair"] = can_repair + data["userHasAccess"] = allowed(user) + + data["locked"] = locked + data["active"] = active + data["safeties"] = safeties + data["uv_active"] = (active && irradiating > 0) + data["uv_level"] = radiation_level + data["max_uv_level"] = emagged ? 5 : 3 + if(helmet) + data["helmet"] = helmet.name else - dat += "

Suit cycler

" - dat += "Welcome to the [model_text ? "[model_text] " : ""]suit cycler control panel. \[lock unit\]
" + data["helmet"] = null + if(suit) + data["suit"] = suit.name + if(istype(suit) && can_repair) + data["damage"] = suit.damage + else + data["suit"] = null + data["damage"] = null + if(occupant) + data["occupied"] = TRUE + else + data["occupied"] = FALSE - dat += "

Maintenance

" - dat += "Helmet: [helmet ? "\the [helmet]" : "no helmet stored" ]. \[eject\]
" - dat += "Suit: [suit ? "\the [suit]" : "no suit stored" ]. \[eject\]" + return data - if(can_repair && suit && istype(suit)) - dat += "[(suit.damage ? " \[repair\]" : "")]" +/obj/machinery/suit_cycler/tgui_act(action, params) + if(..()) + return TRUE - dat += "
UV decontamination systems: SYSTEM ERROR" : "green'>READY"]
" - dat += "Output level: [radiation_level]
" - dat += "\[select power level\] \[begin decontamination cycle\]

" + switch(action) + if("dispense") + switch(params["item"]) + if("helmet") + helmet.forceMove(get_turf(src)) + helmet = null + if("suit") + suit.forceMove(get_turf(src)) + suit = null + . = TRUE + + if("department") + var/choice = params["department"] + if(choice in departments) + target_department = choice + . = TRUE + + if("species") + var/choice = params["species"] + if(choice in species) + target_species = choice + . = TRUE + + if("radlevel") + radiation_level = clamp(params["radlevel"], 1, emagged ? 5 : 3) + . = TRUE + + if("repair_suit") + if(!suit || !can_repair) + return + active = 1 + spawn(100) + repair_suit() + finished_job() + . = TRUE - dat += "

Customisation

" - dat += "Target product: [target_department], [target_species]." - dat += "
\[apply customisation routine\]


" + if("apply_paintjob") + if(!suit && !helmet) + return + active = 1 + spawn(100) + apply_paintjob() + finished_job() + . = TRUE - if(panel_open) - wires.Interact(user) + if("lock") + if(allowed(usr)) + locked = !locked + to_chat(usr, "You [locked ? "" : "un"]lock \the [src].") + else + to_chat(usr, "Access denied.") + . = TRUE - user << browse(dat, "window=suit_cycler") - onclose(user, "suit_cycler") - return + if("eject_guy") + eject_occupant(usr) + . = TRUE -/obj/machinery/suit_cycler/Topic(href, href_list) - if(href_list["eject_suit"]) - if(!suit) return - suit.loc = get_turf(src) - suit = null - else if(href_list["eject_helmet"]) - if(!helmet) return - helmet.loc = get_turf(src) - helmet = null - else if(href_list["select_department"]) - var/choice = input("Please select the target department paintjob.","Suit cycler",null) as null|anything in departments - if(choice) target_department = choice - else if(href_list["select_species"]) - var/choice = input("Please select the target species configuration.","Suit cycler",null) as null|anything in species - if(choice) target_species = choice - else if(href_list["select_rad_level"]) - var/choices = list(1,2,3) - if(emagged) - choices = list(1,2,3,4,5) - radiation_level = input("Please select the desired radiation level.","Suit cycler",null) as null|anything in choices - else if(href_list["repair_suit"]) + if("uv") + if(safeties && occupant) + to_chat(usr, "The cycler has detected an occupant. Please remove the occupant before commencing the decontamination cycle.") + return - if(!suit || !can_repair) return - active = 1 - spawn(100) - repair_suit() - finished_job() + active = 1 + irradiating = 10 - else if(href_list["apply_paintjob"]) + sleep(10) - if(!suit && !helmet) return - active = 1 - spawn(100) - apply_paintjob() - finished_job() + if(helmet) + if(radiation_level > 2) + helmet.decontaminate() + if(radiation_level > 1) + helmet.clean_blood() - else if(href_list["toggle_safties"]) - safeties = !safeties + if(suit) + if(radiation_level > 2) + suit.decontaminate() + if(radiation_level > 1) + suit.clean_blood() - else if(href_list["toggle_lock"]) - - if(allowed(usr)) - locked = !locked - to_chat(usr, "You [locked ? "" : "un"]lock \the [src].") - else - to_chat(usr, "Access denied.") - - else if(href_list["begin_decontamination"]) - - if(safeties && occupant) - to_chat(usr, "The cycler has detected an occupant. Please remove the occupant before commencing the decontamination cycle.") - return - - active = 1 - irradiating = 10 - updateUsrDialog() - - sleep(10) - - if(helmet) - if(radiation_level > 2) - helmet.decontaminate() - if(radiation_level > 1) - helmet.clean_blood() - - if(suit) - if(radiation_level > 2) - suit.decontaminate() - if(radiation_level > 1) - suit.clean_blood() - - updateUsrDialog() - return + . = TRUE /obj/machinery/suit_cycler/process() diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm index 8cd1d8811e..b5dd077efa 100644 --- a/code/game/machinery/telecomms/logbrowser.dm +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -8,187 +8,138 @@ desc = "View communication logs here. Translation not guaranteed." icon_screen = "comm_logs" - var/screen = 0 // the screen number: var/list/servers = list() // the servers located by the computer var/obj/machinery/telecomms/server/SelectedServer circuit = /obj/item/weapon/circuitboard/comm_server var/network = "NULL" // the network to probe - var/temp = "" // temporary feedback messages + var/list/temp = null // temporary feedback messages var/universal_translate = 0 // set to 1 if it can translate nonhuman speech req_access = list(access_tcomsat) - attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/dat = "Telecommunication Server Monitor
Telecommunications Server Monitor
" +/obj/machinery/computer/telecomms/server/tgui_data(mob/user) + var/list/data = list() - switch(screen) + data["universal_translate"] = universal_translate + data["network"] = network + data["temp"] = temp + data["servers"] = list() + for(var/obj/machinery/telecomms/T in servers) + data["servers"].Add(list(list( + "id" = T.id, + "name" = T.name, + ))) - // --- Main Menu --- + data["selectedServer"] = null + if(SelectedServer) + data["selectedServer"] = list( + "id" = SelectedServer.id, + "totalTraffic" = SelectedServer.totaltraffic, + "logs" = list() + ) - if(0) - dat += "
[temp]
" - dat += "
Current Network: [network]
" - if(servers.len) - dat += "
Detected Telecommunication Servers:
    " - for(var/obj/machinery/telecomms/T in servers) - dat += "
  • \ref[T] [T.name] ([T.id])
  • " - dat += "
" - dat += "
\[Flush Buffer\]" + var/i = 0 + for(var/c in SelectedServer.log_entries) + i++ + var/datum/comm_log_entry/C = c + + // This is necessary to prevent leaking information to the clientside + var/static/list/acceptable_params = list("uspeech", "intelligible", "message", "name", "race", "job", "timecode") + var/list/parameters = list() + for(var/log_param in acceptable_params) + parameters["[log_param]"] = C.parameters["[log_param]"] - else - dat += "
No servers detected. Scan for servers: \[Scan\]" + data["selectedServer"]["logs"].Add(list(list( + "name" = C.name, + "input_type" = C.input_type, + "id" = i, + "parameters" = parameters, + ))) + return data - // --- Viewing Server --- - - if(1) - dat += "
[temp]
" - dat += "
\[Main Menu\] \[Refresh\]
" - dat += "
Current Network: [network]" - dat += "
Selected Server: [SelectedServer.id]" - - if(SelectedServer.totaltraffic >= 1024) - dat += "
Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes

" - else - dat += "
Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes

" - - dat += "Stored Logs:
    " - - var/i = 0 - for(var/datum/comm_log_entry/C in SelectedServer.log_entries) - i++ - - - // If the log is a speech file - if(C.input_type == "Speech File") - - dat += "
  1. [C.name] \[X\]
    " - - // -- Determine race of orator -- - - var/race = C.parameters["race"] // The actual race of the mob - var/language = C.parameters["language"] // The language spoken, or null/"" - - // -- If the orator is a human, or universal translate is active, OR mob has universal speech on -- - - if(universal_translate || C.parameters["uspeech"] || C.parameters["intelligible"]) - dat += "Data type: [C.input_type]
    " - dat += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]])
    " - dat += "Class: [race]
    " - dat += "Contents: \"[C.parameters["message"]]\"
    " - if(language) - dat += "Language: [language]
    " - - // -- Orator is not human and universal translate not active -- - - else - dat += "Data type: Audio File
    " - dat += "Source: Unidentifiable
    " - dat += "Class: [race]
    " - dat += "Contents: Unintelligble
    " - - dat += "

  2. " - - else if(C.input_type == "Execution Error") - - dat += "
  3. [C.name] \[X\]
    " - dat += "Output: \"[C.parameters["message"]]\"
    " - dat += "

  4. " - - - dat += "
" - - - - user << browse(dat, "window=comm_monitor;size=575x400") - onclose(user, "server_control") - - temp = "" +/obj/machinery/computer/telecomms/server/attack_hand(mob/user) + if(stat & (BROKEN|NOPOWER)) return + tgui_interact(user) +/obj/machinery/computer/telecomms/server/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TelecommsLogBrowser", name) + ui.open() + +/obj/machinery/computer/telecomms/server/tgui_act(action, params) + if(..()) + return TRUE - Topic(href, href_list) - if(..()) - return + add_fingerprint(usr) - - add_fingerprint(usr) - usr.set_machine(src) - - if(href_list["viewserver"]) - screen = 1 + switch(action) + if("view") for(var/obj/machinery/telecomms/T in servers) - if(T.id == href_list["viewserver"]) + if(T.id == params["id"]) SelectedServer = T break + . = TRUE - if(href_list["operation"]) - switch(href_list["operation"]) + if("mainmenu") + SelectedServer = null + . = TRUE - if("release") - servers = list() - screen = 0 + if("release") + servers = list() + SelectedServer = null + . = TRUE - if("mainmenu") - screen = 0 + if("scan") + if(servers.len > 0) + set_temp("FAILED: CANNOT PROBE WHEN BUFFER FULL", "bad") + return TRUE - if("scan") - if(servers.len > 0) - temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" + for(var/obj/machinery/telecomms/server/T in range(25, src)) + if(T.network == network) + servers.Add(T) - else - for(var/obj/machinery/telecomms/server/T in range(25, src)) - if(T.network == network) - servers.Add(T) + if(!servers.len) + set_temp("FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\]", "bad") + else + set_temp("[servers.len] SERVERS PROBED & BUFFERED", "good") + . = TRUE - if(!servers.len) - temp = "- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -" - else - temp = "- [servers.len] SERVERS PROBED & BUFFERED -" - - screen = 0 - - if(href_list["delete"]) - - if(!src.allowed(usr) && !emagged) + if("delete") + if(!allowed(usr) && !emagged) to_chat(usr, "ACCESS DENIED.") return if(SelectedServer) - - var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])] - - temp = "- DELETED ENTRY: [D.name] -" - + var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(params["id"])] + set_temp("DELETED ENTRY: [D.name]", "bad") SelectedServer.log_entries.Remove(D) qdel(D) - else - temp = "- FAILED: NO SELECTED MACHINE -" - - if(href_list["network"]) + set_temp("FAILED: NO SELECTED MACHINE", "bad") + . = TRUE + if("network") var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text if(newnet && ((usr in range(1, src) || issilicon(usr)))) if(length(newnet) > 15) - temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + set_temp("FAILED: NETWORK TAG STRING TOO LENGTHY", "bad") + return TRUE + network = newnet + servers = list() + set_temp("NEW NETWORK TAG SET IN ADDRESS \[[network]\]", "good") - else - - network = newnet - screen = 0 - servers = list() - temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" - - updateUsrDialog() - return + . = TRUE + + if("cleartemp") + temp = null + . = TRUE /obj/machinery/computer/telecomms/server/emag_act(var/remaining_charges, var/mob/user) if(!emagged) @@ -197,3 +148,6 @@ to_chat(user, "You you disable the security protocols") src.updateUsrDialog() return 1 + +/obj/machinery/computer/telecomms/server/proc/set_temp(var/text, var/color = "average") + temp = list("color" = color, "text" = text) \ No newline at end of file diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index d1449882af..7a14fa2023 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -11,8 +11,7 @@ #define TELECOMM_Z 3 /obj/machinery/telecomms - var/temp = "" // output message - + var/list/temp = null // output message /obj/machinery/telecomms/attackby(obj/item/P as obj, mob/user as mob) @@ -40,74 +39,72 @@ /obj/machinery/telecomms/attack_ai(var/mob/user as mob) attack_hand(user) -/obj/machinery/telecomms/attack_hand(var/mob/user as mob) +/obj/machinery/telecomms/tgui_data(mob/user) + var/list/data = list() + + data["temp"] = temp + data["on"] = on - // You need a multitool to use this, or be silicon - if(!issilicon(user)) - // istype returns false if the value is null - if(!istype(user.get_active_hand(), /obj/item/device/multitool)) - return + data["id"] = null + data["network"] = null + data["autolinkers"] = FALSE + data["shadowlink"] = FALSE + data["options"] = list() + data["linked"] = list() + data["filter"] = list() + data["multitool"] = FALSE + data["multitool_buffer"] = null - if(stat & (BROKEN|NOPOWER)) - return + if(on || interact_offline) + data["id"] = id + data["network"] = network + data["autolinkers"] = !!LAZYLEN(autolinkers) + data["shadowlink"] = !!hide - var/obj/item/device/multitool/P = get_multitool(user) + data["options"] = Options_Menu() - user.set_machine(src) - var/dat - dat = "[src.name]

[src.name] Access

" - dat += "
[temp]
" - dat += "
Power Status: [src.toggled ? "On" : "Off"]" - if(on && toggled) - if(id != "" && id) - dat += "
Identification String: [id]" - else - dat += "
Identification String: NULL" - dat += "
Network: [network]" - dat += "
Prefabrication: [autolinkers.len ? "TRUE" : "FALSE"]" - if(hide) dat += "
Shadow Link: ACTIVE" - - //Show additional options for certain machines. - dat += Options_Menu() - - dat += "
Linked Network Entities:
    " + var/obj/item/device/multitool/P = get_multitool(user) + data["multitool"] = !!P + data["multitool_buffer"] = null + if(P && P.buffer) + P.update_icon() + data["multitool_buffer"] = list("name" = "[P.buffer]", "id" = "[P.buffer.id]") var/i = 0 + data["linked"] = list() for(var/obj/machinery/telecomms/T in links) i++ - if(T.hide && !src.hide) - continue - dat += "
  1. \ref[T] [T.name] ([T.id]) \[X\]
  2. " - dat += "
" - - dat += "
Filtering Frequencies: " - - i = 0 - if(length(freq_listening)) + data["linked"].Add(list(list( + "ref" = "\ref[T]", + "name" = "[T]", + "id" = T.id, + "index" = i, + ))) + + data["filter"] = list() + if(LAZYLEN(freq_listening)) for(var/x in freq_listening) - i++ - if(i < length(freq_listening)) - dat += "[format_frequency(x)] GHz\[X\]; " - else - dat += "[format_frequency(x)] GHz\[X\]" - else - dat += "NONE" + data["filter"].Add(list(list( + "name" = "[format_frequency(x)]", + "freq" = x, + ))) - dat += "
\[Add Filter\]" - dat += "
" + return data - if(P) - if(P.buffer) - dat += "

MULTITOOL BUFFER: [P.buffer] ([P.buffer.id]) \[Link\] \[Flush\]" - else - dat += "

MULTITOOL BUFFER:
\[Add Machine\]" - P.update_icon() +/obj/machinery/telecomms/tgui_status(mob/user) + if(!issilicon(user)) + if(!istype(user.get_active_hand(), /obj/item/device/multitool)) + return STATUS_CLOSE + . = ..() - dat += "
" - temp = "" - user << browse(dat, "window=tcommachine;size=520x500;can_resize=0") - onclose(user, "dormitory") +/obj/machinery/telecomms/attack_hand(var/mob/user as mob) + tgui_interact(user) +/obj/machinery/telecomms/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TelecommsMultitoolMenu", name) + ui.open() // Off-Site Relays // @@ -148,7 +145,7 @@ // Example of how to use below. /obj/machinery/telecomms/proc/Options_Menu() - return "" + return list() /* // Add an option to the processor to switch processing mode. (COMPRESS -> UNCOMPRESS or UNCOMPRESS -> COMPRESS) @@ -158,213 +155,230 @@ */ // The topic for Additional Options. Use this for checking href links for your specific option. // Example of how to use below. -/obj/machinery/telecomms/proc/Options_Topic(href, href_list) +/obj/machinery/telecomms/proc/Options_Act(action, params) return /* -/obj/machinery/telecomms/processor/Options_Topic(href, href_list) +/obj/machinery/telecomms/processor/Options_Act(action, params) if(href_list["process"]) - temp = "-% Processing mode changed. %-" + set_temp("-% Processing mode changed. %-", "average") src.process_mode = !src.process_mode */ // RELAY /obj/machinery/telecomms/relay/Options_Menu() - var/dat = "" - if(src.z == TELECOMM_Z) - dat += "
Signal Locked to Station: [listening_level == STATION_Z ? "TRUE" : "FALSE"]" - dat += "
Broadcasting: [broadcasting ? "YES" : "NO"]" - dat += "
Receiving: [receiving ? "YES" : "NO"]" - return dat + var/list/data = ..() + data["use_listening_level"] = TRUE + data["use_broadcasting"] = TRUE + data["use_receiving"] = TRUE + data["listening_level"] = (listening_level == STATION_Z) + data["broadcasting"] = broadcasting + data["receiving"] = receiving + return data -/obj/machinery/telecomms/relay/Options_Topic(href, href_list) +/obj/machinery/telecomms/relay/Options_Act(action, params) + if(..()) + return TRUE - if(href_list["receive"]) - receiving = !receiving - temp = "-% Receiving mode changed. %-" - if(href_list["broadcast"]) - broadcasting = !broadcasting - temp = "-% Broadcasting mode changed. %-" - if(href_list["change_listening"]) - //Lock to the station OR lock to the current position! - //You need at least two receivers and two broadcasters for this to work, this includes the machine. - var/result = toggle_level() - if(result) - temp = "-% [src]'s signal has been successfully changed." - else - temp = "-% [src] could not lock it's signal onto the station. Two broadcasters or receivers required." + switch(action) + if("receive") + . = TRUE + receiving = !receiving + set_temp("-% Receiving mode changed. %-", "average") + if("broadcast") + . = TRUE + broadcasting = !broadcasting + set_temp("-% Broadcasting mode changed. %-", "average") + if("change_listening") + . = TRUE + //Lock to the station OR lock to the current position! + //You need at least two receivers and two broadcasters for this to work, this includes the machine. + var/result = toggle_level() + if(result) + set_temp("-% [src]'s signal has been successfully changed.", "average") + else + set_temp("-% [src] could not lock it's signal onto the station. Two broadcasters or receivers required.", "average") // BUS /obj/machinery/telecomms/bus/Options_Menu() - var/dat = "
Change Signal Frequency: [change_frequency ? "YES ([change_frequency])" : "NO"]" - return dat + var/list/data = ..() + data["use_change_freq"] = TRUE + data["change_freq"] = change_frequency + return data -/obj/machinery/telecomms/bus/Options_Topic(href, href_list) - - if(href_list["change_freq"]) - - var/newfreq = input(usr, "Specify a new frequency for new signals to change to. Enter null to turn off frequency changing. Decimals assigned automatically.", src, network) as null|num - if(canAccess(usr)) - if(newfreq) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - change_frequency = newfreq - temp = "-% New frequency to change to assigned: \"[newfreq] GHz\" %-" - else - change_frequency = 0 - temp = "-% Frequency changing deactivated %-" +/obj/machinery/telecomms/bus/Options_Act(action, params) + if(..()) + return TRUE + + switch(action) + if("change_freq") + . = TRUE + var/newfreq = input(usr, "Specify a new frequency for new signals to change to. Enter null to turn off frequency changing. Decimals assigned automatically.", src, network) as null|num + if(canAccess(usr)) + if(newfreq) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(newfreq < 10000) + change_frequency = newfreq + set_temp("-% New frequency to change to assigned: \"[newfreq] GHz\" %-", "average") + else + change_frequency = 0 + set_temp("-% Frequency changing deactivated %-", "average") // BROADCASTER /obj/machinery/telecomms/broadcaster/Options_Menu() - // Note the machine 'displays' 1 higher than overmap_range to save users from the abstraction that range '0' is valid and everything on the same turf. - var/dat = "
Broadcast Range (affects power usage)
- [overmap_range+1] gigameter\s +" - return dat + var/list/data = ..() + data["use_broadcast_range"] = TRUE + data["range"] = overmap_range + data["minRange"] = overmap_range_min + data["maxRange"] = overmap_range_max + return data -/obj/machinery/telecomms/broadcaster/Options_Topic(href, href_list) - if(href_list["range_down"]) - if(overmap_range > overmap_range_min) - overmap_range-- - update_idle_power_usage(initial(idle_power_usage)**(overmap_range+1)) - if(href_list["range_up"]) - if(overmap_range < overmap_range_max) - overmap_range++ +/obj/machinery/telecomms/broadcaster + interact_offline = TRUE // because you can accidentally nuke power grids with these, need to be able to fix mistake + +/obj/machinery/telecomms/broadcaster/Options_Act(action, params) + if(..()) + return TRUE + + switch(action) + if("range") + var/new_range = params["range"] + overmap_range = clamp(new_range, overmap_range_min, overmap_range_max) update_idle_power_usage(initial(idle_power_usage)**(overmap_range+1)) // RECEIVER /obj/machinery/telecomms/receiver/Options_Menu() - // Note the machine 'displays' 1 higher than overmap_range to save users from the abstraction that range '0' is valid and everything on the same turf. - var/dat = "
Receive Range (affects power usage)
- [overmap_range+1] gigameter\s +" - return dat + var/list/data = ..() + data["use_receive_range"] = TRUE + data["range"] = overmap_range + data["minRange"] = overmap_range_min + data["maxRange"] = overmap_range_max + return data -/obj/machinery/telecomms/receiver/Options_Topic(href, href_list) - if(href_list["range_down"]) - if(overmap_range > overmap_range_min) - overmap_range-- - update_idle_power_usage(initial(idle_power_usage)**(overmap_range+1)) - if(href_list["range_up"]) - if(overmap_range < overmap_range_max) - overmap_range++ +/obj/machinery/telecomms/receiver + interact_offline = TRUE // because you can accidentally nuke power grids with these, need to be able to fix mistake + +/obj/machinery/telecomms/receiver/Options_Act(action, params) + if(..()) + return TRUE + + switch(action) + if("range") + var/new_range = params["range"] + overmap_range = clamp(new_range, overmap_range_min, overmap_range_max) update_idle_power_usage(initial(idle_power_usage)**(overmap_range+1)) -/obj/machinery/telecomms/Topic(href, href_list) - - if(!issilicon(usr)) - if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) - return - - if(stat & (BROKEN|NOPOWER)) - return +/obj/machinery/telecomms/tgui_act(action, params) + if(..()) + return TRUE var/obj/item/device/multitool/P = get_multitool(usr) - if(href_list["input"]) - switch(href_list["input"]) + switch(action) + if("toggle") + src.toggled = !src.toggled + set_temp("-% [src] has been [src.toggled ? "activated" : "deactivated"].", "average") + update_power() + . = TRUE - if("toggle") + if("id") + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID for this machine", src, id) as null|text),1,MAX_MESSAGE_LEN) + if(newid && canAccess(usr)) + id = newid + set_temp("-% New ID assigned: \"[id]\" %-", "average") + . = TRUE - src.toggled = !src.toggled - temp = "-% [src] has been [src.toggled ? "activated" : "deactivated"]." - update_power() + if("network") + var/newnet = input(usr, "Specify the new network for this machine. This will break all current links.", src, network) as null|text + if(newnet && canAccess(usr)) - /* - if("hide") - src.hide = !hide - temp = "-% Shadow Link has been [src.hide ? "activated" : "deactivated"]." - */ + if(length(newnet) > 15) + set_temp("-% Too many characters in new network tag %-", "average") - if("id") - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID for this machine", src, id) as null|text),1,MAX_MESSAGE_LEN) - if(newid && canAccess(usr)) - id = newid - temp = "-% New ID assigned: \"[id]\" %-" + else + for(var/obj/machinery/telecomms/T in links) + T.links.Remove(src) - if("network") - var/newnet = input(usr, "Specify the new network for this machine. This will break all current links.", src, network) as null|text - if(newnet && canAccess(usr)) - - if(length(newnet) > 15) - temp = "-% Too many characters in new network tag %-" - - else - for(var/obj/machinery/telecomms/T in links) - T.links.Remove(src) - - network = newnet - links = list() - temp = "-% New network tag assigned: \"[network]\" %-" + network = newnet + links = list() + set_temp("-% New network tag assigned: \"[network]\" %-", "average") + . = TRUE - if("freq") - var/newfreq = input(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, network) as null|num - if(newfreq && canAccess(usr)) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(!(newfreq in freq_listening) && newfreq < 10000) - freq_listening.Add(newfreq) - temp = "-% New frequency filter assigned: \"[newfreq] GHz\" %-" + if("freq") + var/newfreq = input(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, network) as null|num + if(newfreq && canAccess(usr)) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(!(newfreq in freq_listening) && newfreq < 10000) + freq_listening.Add(newfreq) + set_temp("-% New frequency filter assigned: \"[newfreq] GHz\" %-", "average") + . = TRUE - if(href_list["delete"]) + if("delete") + var/x = text2num(params["delete"]) + set_temp("-% Removed frequency filter [x] %-", "average") + freq_listening.Remove(x) + . = TRUE - // changed the layout about to workaround a pesky runtime -- Doohl + if("unlink") + if(text2num(params["unlink"]) <= length(links)) + var/obj/machinery/telecomms/T = links[text2num(params["unlink"])] + set_temp("-% Removed \ref[T] [T.name] from linked entities. %-", "average") - var/x = text2num(href_list["delete"]) - temp = "-% Removed frequency filter [x] %-" - freq_listening.Remove(x) + // Remove link entries from both T and src. - if(href_list["unlink"]) + if(src in T.links) + T.links.Remove(src) + links.Remove(T) + . = TRUE - if(text2num(href_list["unlink"]) <= length(links)) - var/obj/machinery/telecomms/T = links[text2num(href_list["unlink"])] - temp = "-% Removed \ref[T] [T.name] from linked entities. %-" + if("link") + if(P) + if(P.buffer && P.buffer != src) + if(!(src in P.buffer.links)) + P.buffer.links.Add(src) - // Remove link entries from both T and src. + if(!(P.buffer in src.links)) + src.links.Add(P.buffer) - if(src in T.links) - T.links.Remove(src) - links.Remove(T) + set_temp("-% Successfully linked with \ref[P.buffer] [P.buffer.name] %-", "average") - if(href_list["link"]) + else + set_temp("-% Unable to acquire buffer %-", "average") + . = TRUE - if(P) - if(P.buffer && P.buffer != src) - if(!(src in P.buffer.links)) - P.buffer.links.Add(src) + if("buffer") + P.buffer = src + set_temp("-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-", "average") + . = TRUE - if(!(P.buffer in src.links)) - src.links.Add(P.buffer) + if("flush") + set_temp("-% Buffer successfully flushed. %-", "average") + P.buffer = null + . = TRUE - temp = "-% Successfully linked with \ref[P.buffer] [P.buffer.name] %-" + if("cleartemp") + temp = null + . = TRUE - else - temp = "-% Unable to acquire buffer %-" + if(Options_Act(action, params)) + . = TRUE - if(href_list["buffer"]) - - P.buffer = src - temp = "-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-" - - - if(href_list["flush"]) - - temp = "-% Buffer successfully flushed. %-" - P.buffer = null - - src.Options_Topic(href, href_list) - - usr.set_machine(src) - src.add_fingerprint(usr) - - updateUsrDialog() + add_fingerprint(usr) /obj/machinery/telecomms/proc/canAccess(var/mob/user) if(issilicon(user) || in_range(user, src)) return 1 return 0 +/obj/machinery/telecomms/proc/set_temp(var/text, var/color = "average") + temp = list("color" = color, "text" = text) + #undef TELECOMM_Z #undef STATION_Z diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 3799d06b07..6f2e626a00 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -593,6 +593,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() log.parameters["message"] = multilingual_to_message(signal.data["message"]) log.parameters["name"] = signal.data["name"] log.parameters["realname"] = signal.data["realname"] + log.parameters["timecode"] = worldtime2stationtime(world.time) var/race = "unknown" if(ishuman(M)) @@ -672,6 +673,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() log.name = "[input] ([md5(identifier)])" log.input_type = input log.parameters["message"] = content + log.parameters["timecode"] = stationtime2text() log_entries.Add(log) update_logs() diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm index 51a6ebf991..7107e0ff5d 100644 --- a/code/game/machinery/telecomms/telemonitor.dm +++ b/code/game/machinery/telecomms/telemonitor.dm @@ -6,7 +6,6 @@ and displays a heirarchy of linked machines. */ - /obj/machinery/computer/telecomms/monitor name = "Telecommunications Monitor" desc = "Used to traverse a telecommunication network. Helpful for debugging connection issues." @@ -19,111 +18,103 @@ var/network = "NULL" // the network to probe - var/temp = "" // temporary feedback messages + var/list/temp = null // temporary feedback messages - attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/dat = "Telecommunications Monitor
Telecommunications Monitor
" +/obj/machinery/computer/telecomms/monitor/tgui_data(mob/user) + var/list/data = list() - switch(screen) + data["network"] = network + data["temp"] = temp + data["machinelist"] = list() + for(var/obj/machinery/telecomms/T in machinelist) + data["machinelist"].Add(list(list( + "id" = T.id, + "name" = T.name, + ))) - // --- Main Menu --- + data["selectedMachine"] = null + if(SelectedMachine) + data["selectedMachine"] = list( + "id" = SelectedMachine.id, + "name" = SelectedMachine.name, + "links" = list(), + ) - if(0) - dat += "
[temp]

" - dat += "
Current Network: [network]
" - if(machinelist.len) - dat += "
Detected Network Entities:
    " - for(var/obj/machinery/telecomms/T in machinelist) - dat += "
  • \ref[T] [T.name] ([T.id])
  • " - dat += "
" - dat += "
\[Flush Buffer\]" - else - dat += "\[Probe Network\]" + for(var/obj/machinery/telecomms/T in SelectedMachine.links) + if(!T.hide) + data["selectedMachine"]["links"].Add(list(list( + "id" = T.id, + "name" = T.name + ))) + return data - // --- Viewing Machine --- - - if(1) - dat += "
[temp]
" - dat += "
\[Main Menu\]
" - dat += "
Current Network: [network]
" - dat += "Selected Network Entity: [SelectedMachine.name] ([SelectedMachine.id])
" - dat += "Linked Entities:
    " - for(var/obj/machinery/telecomms/T in SelectedMachine.links) - if(!T.hide) - dat += "
  1. \ref[T.id] [T.name] ([T.id])
  2. " - dat += "
" - - - - user << browse(dat, "window=comm_monitor;size=575x400") - onclose(user, "server_control") - - temp = "" +/obj/machinery/computer/telecomms/monitor/attack_hand(mob/user) + if(stat & (BROKEN|NOPOWER)) return + tgui_interact(user) +/obj/machinery/computer/telecomms/monitor/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TelecommsMachineBrowser", name) + ui.open() - Topic(href, href_list) - if(..()) - return +/obj/machinery/computer/telecomms/monitor/tgui_act(action, params) + if(..()) + return TRUE + add_fingerprint(usr) - add_fingerprint(usr) - usr.set_machine(src) - - if(href_list["viewmachine"]) - screen = 1 + switch(action) + if("view") for(var/obj/machinery/telecomms/T in machinelist) - if(T.id == href_list["viewmachine"]) + if(T.id == params["id"]) SelectedMachine = T break + . = TRUE - if(href_list["operation"]) - switch(href_list["operation"]) + if("mainmenu") + SelectedMachine = null + . = TRUE - if("release") - machinelist = list() - screen = 0 + if("release") + machinelist = list() + SelectedMachine = null + . = TRUE - if("mainmenu") - screen = 0 + if("scan") + if(machinelist.len > 0) + set_temp("FAILED: CANNOT PROBE WHEN BUFFER FULL", "bad") + return TRUE - if("probe") - if(machinelist.len > 0) - temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" + for(var/obj/machinery/telecomms/T in range(25, src)) + if(T.network == network) + machinelist.Add(T) - else - for(var/obj/machinery/telecomms/T in range(25, src)) - if(T.network == network) - machinelist.Add(T) - - if(!machinelist.len) - temp = "- FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\] -" - else - temp = "- [machinelist.len] ENTITIES LOCATED & BUFFERED -" - - screen = 0 - - - if(href_list["network"]) + if(!machinelist.len) + set_temp("FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\]", "bad") + else + set_temp("[machinelist.len] ENTITIES LOCATED & BUFFERED", "good") + . = TRUE + if("network") var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text if(newnet && ((usr in range(1, src) || issilicon(usr)))) if(length(newnet) > 15) - temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + set_temp("FAILED: NETWORK TAG STRING TOO LENGTHY", "bad") + return TRUE + network = newnet + machinelist = list() + set_temp("NEW NETWORK TAG SET IN ADDRESS \[[network]\]", "good") + + . = TRUE - else - network = newnet - screen = 0 - machinelist = list() - temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" + if("cleartemp") + temp = null + . = TRUE - updateUsrDialog() - return /obj/machinery/computer/telecomms/monitor/emag_act(var/remaining_charges, var/mob/user) if(!emagged) @@ -132,3 +123,6 @@ to_chat(user, "You you disable the security protocols") src.updateUsrDialog() return 1 + +/obj/machinery/computer/telecomms/monitor/proc/set_temp(var/text, var/color = "average") + temp = list("color" = color, "text" = text) \ No newline at end of file diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 5ff60979d0..dcdd8d88fe 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -26,6 +26,7 @@ var/vend_delay = 10 //How long does it take to vend? var/categories = CAT_NORMAL // Bitmask of cats we're currently showing var/datum/stored_item/vending_product/currently_vending = null // What we're requesting payment for right now + var/tmp/actively_vending = null // Used to allow TGUI to display normal items in-progress being vended var/status_message = "" // Status screen messages like "insufficient funds", displayed in NanoUI var/status_error = 0 // Set to 1 if status_message is an error var/vending_sound = "machines/vending/vending_drop.ogg" @@ -173,7 +174,7 @@ vend(currently_vending, usr) return else if(handled) - SSnanoui.update_uis(src) + SStgui.update_uis(src) return // don't smack that machine with your 2 thalers if(I || istype(W, /obj/item/weapon/spacecash)) @@ -184,11 +185,12 @@ to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") playsound(src, W.usesound, 50, 1) if(panel_open) + wires.Interact(user) add_overlay("[initial(icon_state)]-panel") else cut_overlay("[initial(icon_state)]-panel") - SSnanoui.update_uis(src) // Speaker switch is on the main UI, not wires UI + SStgui.update_uis(src) // Speaker switch is on the main UI, not wires UI return else if(istype(W, /obj/item/device/multitool) || W.is_wirecutter()) if(panel_open) @@ -200,7 +202,7 @@ coin = W categories |= CAT_COIN to_chat(user, "You insert \the [W] into \the [src].") - SSnanoui.update_uis(src) + SStgui.update_uis(src) return else if(W.is_wrench()) playsound(src, W.usesound, 100, 1) @@ -348,6 +350,9 @@ T.time = stationtime2text() vendor_account.transaction_log.Add(T) +/obj/machinery/vending/attack_ghost(mob/user) + return attack_hand(user) + /obj/machinery/vending/attack_ai(mob/user as mob) return attack_hand(user) @@ -360,24 +365,23 @@ return wires.Interact(user) - ui_interact(user) + tgui_interact(user) -/** - * Display the NanoUI window for the vending machine. - * - * See NanoUI documentation for details. - */ -/obj/machinery/vending/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/vending/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Vending", name) + ui.open() +/obj/machinery/vending/tgui_data(mob/user) var/list/data = list() if(currently_vending) data["mode"] = 1 data["product"] = currently_vending.item_name data["price"] = currently_vending.price - data["message_err"] = 0 data["message"] = status_message data["message_err"] = status_error + data["products"] = null else data["mode"] = 0 var/list/listed_products = list() @@ -399,6 +403,13 @@ if(coin) data["coin"] = coin.name + else + data["coin"] = FALSE + + if(actively_vending) + data["actively_vending"] = actively_vending + else + data["actively_vending"] = null if(panel_open) data["panel"] = 1 @@ -406,19 +417,20 @@ else data["panel"] = 0 - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "vending_machine.tmpl", name, 440, 600) - ui.set_initial_data(data) - ui.open() + return data -/obj/machinery/vending/Topic(href, href_list) +/obj/machinery/vending/tgui_act(action, params) if(stat & (BROKEN|NOPOWER)) return if(usr.stat || usr.restrained()) return + if(..()) + return TRUE + + if(action == "remove_coin") + if(issilicon(usr)) + return FALSE - if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) if(!coin) to_chat(usr, "There is no coin in this machine.") return @@ -426,19 +438,27 @@ coin.forceMove(src.loc) if(!usr.get_active_hand()) usr.put_in_hands(coin) - to_chat(usr, "You remove \the [coin] from \the [src]") + + to_chat(usr, "You remove \the [coin] from \the [src].") coin = null categories &= ~CAT_COIN + return TRUE - if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) - if((href_list["vend"]) && (vend_ready) && (!currently_vending)) - if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH + if(!usr.contents.Find(src) && (!in_range(src, usr) && isturf(loc))) + return FALSE + + . = TRUE + switch(action) + if("vend") + if(!vend_ready || currently_vending) + return + if(!allowed(usr) && !emagged && scan_id) to_chat(usr, "Access denied.") //Unless emagged of course flick("[icon_state]-deny",src) playsound(src, 'sound/machines/deniedbeep.ogg', 50, 0) return - var/key = text2num(href_list["vend"]) + var/key = text2num(params["vend"]) var/datum/stored_item/vending_product/R = product_records[key] // This should not happen unless the request from NanoUI was bad @@ -447,7 +467,7 @@ if(R.price <= 0) vend(R, usr) - else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something. + else if(issilicon(usr)) //If the item is not free, provide feedback if a synth is trying to buy something. to_chat(usr, "Lawed unit recognized. Lawed units cannot complete this transaction. Purchase canceled.") return else @@ -459,15 +479,14 @@ status_message = "Please swipe a card or insert cash to pay for the item." status_error = 0 - else if(href_list["cancelpurchase"]) + if("cancelpurchase") currently_vending = null - else if((href_list["togglevoice"]) && (panel_open)) + if("togglevoice") + if(!panel_open) + return FALSE shut_up = !shut_up - add_fingerprint(usr) - SSnanoui.update_uis(src) - /obj/machinery/vending/proc/vend(datum/stored_item/vending_product/R, mob/user) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH to_chat(usr, "Access denied.") //Unless emagged of course @@ -475,9 +494,10 @@ playsound(src, 'sound/machines/deniedbeep.ogg', 50, 0) return vend_ready = 0 //One thing at a time!! + actively_vending = R.item_name status_message = "Vending..." status_error = 0 - SSnanoui.update_uis(src) + SStgui.update_uis(src) if(R.category & CAT_COIN) if(!coin) @@ -516,8 +536,9 @@ status_message = "" status_error = 0 vend_ready = 1 + actively_vending = null currently_vending = null - SSnanoui.update_uis(src) + SStgui.update_uis(src) return 1 @@ -589,7 +610,7 @@ if(has_logs) do_logging(R, user) - SSnanoui.update_uis(src) + SStgui.update_uis(src) /obj/machinery/vending/process() if(stat & (BROKEN|NOPOWER)) diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index f20e340f34..fd9767dd87 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -22,15 +22,26 @@ to_chat(user, "ERROR ERROR ERROR") /obj/item/device/aicard/attack_self(mob/user) + tgui_interact(user) - ui_interact(user) +/obj/item/device/aicard/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui_state/custom_state) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AICard", "[name]") // 600, 394 + ui.open() + if(custom_state) + ui.set_state(custom_state) -/obj/item/device/aicard/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/device/aicard/tgui_state(mob/user) + return GLOB.tgui_inventory_state + +/obj/item/device/aicard/tgui_data(mob/user) var/data[0] + data["has_ai"] = carded_ai != null if(carded_ai) data["name"] = carded_ai.name - data["hardware_integrity"] = carded_ai.hardware_integrity() + data["integrity"] = carded_ai.hardware_integrity() data["backup_capacitor"] = carded_ai.backup_capacitor() data["radio"] = !carded_ai.aiRadio.disabledAi data["wireless"] = !carded_ai.control_disabled @@ -38,52 +49,42 @@ data["flushing"] = flush var/laws[0] - for(var/datum/ai_law/AL in carded_ai.laws.all_laws()) - laws[++laws.len] = list("index" = AL.get_index(), "law" = sanitize(AL.law)) + for(var/datum/ai_law/law in carded_ai.laws.all_laws()) + if(law in carded_ai.laws.ion_laws) // If we're an ion law, give it an ion index code + laws.Add(ionnum() + ". " + law.law) + else + laws.Add(num2text(law.get_index()) + ". " + law.law) data["laws"] = laws - data["has_laws"] = laws.len + data["has_laws"] = length(carded_ai.laws.all_laws()) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "aicard.tmpl", "[name]", 600, 400, state = state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data -/obj/item/device/aicard/Topic(href, href_list, state) +/obj/item/device/aicard/tgui_act(action, params) if(..()) - return 1 + return TRUE if(!carded_ai) - return 1 + return var/user = usr - if (href_list["wipe"]) - var/confirm = alert("Are you sure you want to disable this core's power? This cannot be undone once started.", "Confirm Shutdown", "No", "Yes") - if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE)) + switch(action) + if("wipe") + msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].") add_attack_logs(user,carded_ai,"Purged from AI Card") - flush = 1 - carded_ai.suiciding = 1 - to_chat(carded_ai, "Your power has been disabled!") - while (carded_ai && carded_ai.stat != DEAD) - if(carded_ai.deployed_shell && prob(carded_ai.oxyloss)) //You feel it creeping? Eventually will reach 100, resulting in the second half of the AI's remaining life being lonely. - carded_ai.disconnect_shell("Disconnecting from remote shell due to insufficent power.") - carded_ai.adjustOxyLoss(2) - carded_ai.updatehealth() - sleep(10) - flush = 0 - if (href_list["radio"]) - carded_ai.aiRadio.disabledAi = text2num(href_list["radio"]) - to_chat(carded_ai, "Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!") - to_chat(user, "You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.") - if (href_list["wireless"]) - carded_ai.control_disabled = text2num(href_list["wireless"]) - to_chat(carded_ai, "Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!") - to_chat(user, "You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.") - if(carded_ai.control_disabled && carded_ai.deployed_shell) - carded_ai.disconnect_shell("Disconnecting from remote shell due to [src] wireless access interface being disabled.") - update_icon() - return 1 + INVOKE_ASYNC(src, .proc/wipe_ai) + if("radio") + carded_ai.aiRadio.disabledAi = !carded_ai.aiRadio.disabledAi + to_chat(carded_ai, "Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!") + to_chat(user, "You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.") + if("wireless") + carded_ai.control_disabled = !carded_ai.control_disabled + to_chat(carded_ai, "Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!") + to_chat(user, "You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.") + if(carded_ai.control_disabled && carded_ai.deployed_shell) + carded_ai.disconnect_shell("Disconnecting from remote shell due to [src] wireless access interface being disabled.") + update_icon() + + return TRUE /obj/item/device/aicard/update_icon() overlays.Cut() @@ -168,3 +169,17 @@ var/obj/item/weapon/rig/rig = src.get_rig() if(istype(rig)) rig.forced_move(direction, user) + +/obj/item/device/aicard/proc/wipe_ai() + var/mob/living/silicon/ai/AI = carded_ai + flush = TRUE + AI.suiciding = TRUE + to_chat(AI, "Your power has been disabled!") + while(AI && AI.stat != DEAD) + // This is absolutely evil and I love it. + if(AI.deployed_shell && prob(AI.oxyloss)) //You feel it creeping? Eventually will reach 100, resulting in the second half of the AI's remaining life being lonely. + AI.disconnect_shell("Disconnecting from remote shell due to insufficent power.") + AI.adjustOxyLoss(2) + AI.updatehealth() + sleep(10) + flush = FALSE \ No newline at end of file diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 47de7ff7dd..f5c3918fc9 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -382,7 +382,7 @@ return -/obj/item/device/radio/headset/proc/recalculateChannels(var/setDescription = 0) +/obj/item/device/radio/headset/recalculateChannels(var/setDescription = 0) src.channels = list() src.translate_binary = 0 src.translate_hive = 0 diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 47e71092cf..210b93f1b0 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -37,12 +37,14 @@ var/global/list/default_medbay_channels = list( var/frequency = PUB_FREQ //common chat var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies var/canhear_range = 3 // the range which mobs can hear this radio from + var/loudspeaker = TRUE // Allows borgs to disable canhear_range. var/datum/wires/radio/wires = null var/b_stat = 0 var/broadcasting = 0 var/listening = 1 var/list/channels = list() //see communications.dm for full list. First channel is a "default" for :h var/subspace_transmission = 0 + var/subspace_switchable = FALSE var/adhoc_fallback = FALSE //Falls back to 'radio' mode if subspace not available var/syndie = 0//Holder to see if it's a syndicate encrypted radio var/centComm = 0//Holder to see if it's a CentCom encrypted radio @@ -133,6 +135,8 @@ var/global/list/default_medbay_channels = list( if(!found) testing("A radio [src] at [x],[y],[z] specified bluespace prelink IDs, but the machines with corresponding IDs ([bs_tx_preload_id], [bs_rx_preload_id]) couldn't be found.") +/obj/item/device/radio/proc/recalculateChannels() + return /obj/item/device/radio/attack_self(mob/user as mob) user.set_machine(src) @@ -145,15 +149,31 @@ var/global/list/default_medbay_channels = list( if(b_stat) wires.Interact(user) - return ui_interact(user) + return tgui_interact(user) -/obj/item/device/radio/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/item/device/radio/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nano_ui/master_ui, datum/topic_state/state) + log_runtime(EXCEPTION("Warning: [user] attempted to call ui_interact on radio [src] [type]. This is deprecated. Please update the caller to tgui_interact.")) + +/obj/item/device/radio/Topic(href, href_list) + if(href_list["track"]) + log_runtime(EXCEPTION("Warning: Topic() was improperly called on radio [src] [type], with the track href and \[[href] [json_encode(href_list)]]. Please update the caller to use tgui_act.")) + . = ..() + +/obj/item/device/radio/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Radio", name) + ui.open() + +/obj/item/device/radio/tgui_data(mob/user) var/data[0] - data["mic_status"] = broadcasting - data["speaker"] = listening - data["freq"] = format_frequency(frequency) data["rawfreq"] = num2text(frequency) + data["listening"] = listening + data["broadcasting"] = broadcasting + data["subspace"] = subspace_transmission + data["subspaceSwitchable"] = subspace_switchable + data["loudspeaker"] = loudspeaker data["mic_cut"] = (wires.is_cut(WIRE_RADIO_TRANSMIT) || wires.is_cut(WIRE_RADIO_SIGNAL)) data["spk_cut"] = (wires.is_cut(WIRE_RADIO_RECEIVER) || wires.is_cut(WIRE_RADIO_SIGNAL)) @@ -161,21 +181,16 @@ var/global/list/default_medbay_channels = list( var/list/chanlist = list_channels(user) if(islist(chanlist) && chanlist.len) data["chan_list"] = chanlist - data["chan_list_len"] = chanlist.len + else + data["chan_list"] = null if(syndie) data["useSyndMode"] = 1 - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 430) - ui.set_initial_data(data) - ui.open() + data["minFrequency"] = PUBLIC_LOW_FREQ + data["maxFrequency"] = PUBLIC_HIGH_FREQ -/obj/item/device/radio/CouldUseTopic(var/mob/user) - ..() - if(iscarbon(user)) - playsound(src, "button", 10) + return data /obj/item/device/radio/proc/list_channels(var/mob/user) return list_internal_channels(user) @@ -187,7 +202,7 @@ var/global/list/default_medbay_channels = list( var/chan_stat = channels[ch_name] var/listening = !!(chan_stat & FREQ_LISTENING) != 0 - dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = frequency_span_class(radiochannels[ch_name])))) + dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "freq" = radiochannels[ch_name]))) return dat @@ -195,7 +210,7 @@ var/global/list/default_medbay_channels = list( var/dat[0] for(var/internal_chan in internal_channels) if(has_channel_access(user, internal_chan)) - dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan))))) + dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "freq" = text2num(internal_chan)))) return dat @@ -233,50 +248,61 @@ var/global/list/default_medbay_channels = list( return STATUS_CLOSE return ..() -/obj/item/device/radio/Topic(href, href_list) +/obj/item/device/radio/tgui_act(action, params) if(..()) return TRUE - usr.set_machine(src) - if (href_list["track"]) - var/mob/target = locate(href_list["track"]) - var/mob/living/silicon/ai/A = locate(href_list["track2"]) - if(A && target) - A.ai_actual_track(target) - . = 1 - - else if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if ((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)) - new_frequency = sanitize_frequency(new_frequency) - set_frequency(new_frequency) - if(hidden_uplink) - if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) - usr << browse(null, "window=radio") - . = 1 - else if (href_list["talk"]) - ToggleBroadcast() - . = 1 - else if (href_list["listen"]) - var/chan_name = href_list["ch_name"] - if (!chan_name) + switch(action) + if("setFrequency") + var/new_frequency = (text2num(params["freq"])) + if((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)) + new_frequency = sanitize_frequency(new_frequency) + set_frequency(new_frequency) + if(hidden_uplink) + if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) + usr << browse(null, "window=radio") + . = TRUE + if("broadcast") + ToggleBroadcast() + . = TRUE + if("listen") ToggleReception() - else - if (channels[chan_name] & FREQ_LISTENING) + . = TRUE + if("channel") + var/chan_name = params["channel"] + if(channels[chan_name] & FREQ_LISTENING) channels[chan_name] &= ~FREQ_LISTENING else channels[chan_name] |= FREQ_LISTENING - . = 1 - else if(href_list["spec_freq"]) - var freq = href_list["spec_freq"] - if(has_channel_access(usr, freq)) - set_frequency(text2num(freq)) - . = 1 - if(href_list["nowindow"]) // here for pAIs, maybe others will want it, idk - return TRUE + . = TRUE + if("specFreq") + var/freq = params["channel"] + if(has_channel_access(usr, freq)) + set_frequency(text2num(freq)) + . = TRUE + if("subspace") + if(subspace_switchable) + subspace_transmission = !subspace_transmission + if(!subspace_transmission) + channels = list() + to_chat(usr, "Subspace Transmission is disabled") + else + recalculateChannels() + to_chat(usr, "Subspace Transmission is enabled") + . = TRUE + if("toggleLoudspeaker") + if(!subspace_switchable) + return + loudspeaker = !loudspeaker - if(.) - SSnanoui.update_uis(src) + if(loudspeaker) + to_chat(usr, "Loadspeaker enabled.") + else + to_chat(usr, "Loadspeaker disabled.") + . = TRUE + + if(. && iscarbon(usr)) + playsound(src, "button", 10) GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) /obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/list/zlevels) //BS12 EDIT @@ -569,10 +595,9 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) return canhear_range /obj/item/device/radio/proc/send_hear(freq, level) - var/range = receive_range(freq, level) - if(range > -1) - return get_mobs_or_objects_in_view(canhear_range, src) + if(range > -1 && loudspeaker) + return get_mobs_or_objects_in_view(range, src) /obj/item/device/radio/examine(mob/user) @@ -616,11 +641,11 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) /obj/item/device/radio/borg var/mob/living/silicon/robot/myborg = null // Cyborg which owns this radio. Used for power checks var/obj/item/device/encryptionkey/keyslot = null//Borg radios can handle a single encryption key - var/shut_up = 1 icon = 'icons/obj/robot_component.dmi' // Cyborgs radio icons should look like the component. icon_state = "radio" canhear_range = 0 - subspace_transmission = 1 + subspace_transmission = TRUE + subspace_switchable = TRUE /obj/item/device/radio/borg/Destroy() myborg = null @@ -678,7 +703,7 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) return -/obj/item/device/radio/borg/proc/recalculateChannels() +/obj/item/device/radio/borg/recalculateChannels() src.channels = list() src.syndie = 0 @@ -710,71 +735,6 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) return -/obj/item/device/radio/borg/Topic(href, href_list) - if(..()) - return TRUE - if (href_list["mode"]) - var/enable_subspace_transmission = text2num(href_list["mode"]) - if(enable_subspace_transmission != subspace_transmission) - subspace_transmission = !subspace_transmission - if(subspace_transmission) - to_chat(usr, "Subspace Transmission is enabled") - else - to_chat(usr, "Subspace Transmission is disabled") - - if(subspace_transmission == 0)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled - channels = list() - else - recalculateChannels() - . = 1 - if (href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio. - var/do_shut_up = text2num(href_list["shutup"]) - if(do_shut_up != shut_up) - shut_up = !shut_up - if(shut_up) - canhear_range = 0 - to_chat(usr, "Loadspeaker disabled.") - else - canhear_range = 3 - to_chat(usr, "Loadspeaker enabled.") - . = 1 - - if(.) - SSnanoui.update_uis(src) - -/obj/item/device/radio/borg/interact(mob/user as mob) - if(!on) - return - - . = ..() - -/obj/item/device/radio/borg/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data["mic_status"] = broadcasting - data["speaker"] = listening - data["freq"] = format_frequency(frequency) - data["rawfreq"] = num2text(frequency) - - var/list/chanlist = list_channels(user) - if(islist(chanlist) && chanlist.len) - data["chan_list"] = chanlist - data["chan_list_len"] = chanlist.len - - if(syndie) - data["useSyndMode"] = 1 - - data["has_loudspeaker"] = 1 - data["loudspeaker"] = !shut_up - data["has_subspace"] = 1 - data["subspace"] = subspace_transmission - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 430) - ui.set_initial_data(data) - ui.open() - /obj/item/device/radio/proc/config(op) if(radio_controller) for (var/ch_name in channels) diff --git a/code/game/objects/items/weapons/RPD_vr.dm b/code/game/objects/items/weapons/RPD_vr.dm index 9ae806f63c..b3b3507586 100644 --- a/code/game/objects/items/weapons/RPD_vr.dm +++ b/code/game/objects/items/weapons/RPD_vr.dm @@ -1,8 +1,11 @@ -#define PAINT_MODE -2 -#define EATING_MODE -1 -#define ATMOS_MODE 0 -#define DISPOSALS_MODE 1 -#define TRANSIT_MODE 2 +#define ATMOS_CATEGORY 0 +#define DISPOSALS_CATEGORY 1 +#define TRANSIT_CATEGORY 2 + +#define BUILD_MODE (1<<0) +#define WRENCH_MODE (1<<1) +#define DESTROY_MODE (1<<2) +#define PAINT_MODE (1<<3) /obj/item/weapon/pipe_dispenser name = "Rapid Piping Device (RPD)" @@ -22,18 +25,16 @@ w_class = ITEMSIZE_NORMAL matter = list(MAT_STEEL = 50000, MAT_GLASS = 25000) var/datum/effect/effect/system/spark_spread/spark_system - var/mode = ATMOS_MODE var/p_dir = NORTH // Next pipe will be built with this dir var/p_flipped = FALSE // If the next pipe should be built flipped var/paint_color = "grey" // Pipe color index for next pipe painted/built. - var/screen = ATMOS_MODE // Starts on the atmos tab. + var/category = ATMOS_CATEGORY var/piping_layer = PIPING_LAYER_DEFAULT - var/wrench_mode = FALSE var/obj/item/weapon/tool/wrench/tool var/datum/pipe_recipe/recipe // pipe recipie selected for display/construction var/static/datum/pipe_recipe/first_atmos var/static/datum/pipe_recipe/first_disposal - var/static/datum/asset/spritesheet/pipes/icon_assets + var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE var/static/list/pipe_layers = list( "Regular" = PIPING_LAYER_REGULAR, "Supply" = PIPING_LAYER_SUPPLY, @@ -51,10 +52,10 @@ /obj/item/weapon/pipe_dispenser/proc/SetupPipes() if(!first_atmos) - first_atmos = atmos_pipe_recipes[atmos_pipe_recipes[1]][1] + first_atmos = GLOB.atmos_pipe_recipes[GLOB.atmos_pipe_recipes[1]][1] recipe = first_atmos if(!first_disposal) - first_disposal = disposal_pipe_recipes[disposal_pipe_recipes[1]][1] + first_disposal = GLOB.disposal_pipe_recipes[GLOB.disposal_pipe_recipes[1]][1] /obj/item/weapon/pipe_dispenser/Destroy() qdel_null(spark_system) @@ -69,170 +70,97 @@ return(BRUTELOSS) /obj/item/weapon/pipe_dispenser/attack_self(mob/user) - src.interact(user) + tgui_interact(user) -// TODO - Wouldn't it be nice to have nanoui? -/obj/item/weapon/pipe_dispenser/interact(mob/user) +/obj/item/weapon/pipe_dispenser/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/pipes), + ) + +/obj/item/weapon/pipe_dispenser/tgui_interact(mob/user, datum/tgui/ui) SetupPipes() - if(!icon_assets) - icon_assets = get_asset_datum(/datum/asset/spritesheet/pipes) - icon_assets.send(user) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "RapidPipeDispenser", name) + ui.open() - var/list/lines = list() - if(mode >= ATMOS_MODE) - lines += "

Direction:

" - switch(recipe.dirtype) +/obj/item/weapon/pipe_dispenser/tgui_data(mob/user) + var/list/data = list( + "category" = category, + "piping_layer" = piping_layer, + "pipe_layers" = pipe_layers, + "preview_rows" = recipe.get_preview(p_dir), + "categories" = list(), + "selected_color" = paint_color, + "paint_colors" = pipe_colors, + "mode" = mode + ) - if(PIPE_STRAIGHT) // Straight, N-S, W-E - lines += render_dir_img(recipe.icon_state,user,NORTH,"Vertical","↕") - lines += render_dir_img(recipe.icon_state,user,EAST,"Horizontal","↔") + var/list/recipes + switch(category) + if(ATMOS_CATEGORY) + recipes = GLOB.atmos_pipe_recipes + if(DISPOSALS_CATEGORY) + recipes = GLOB.disposal_pipe_recipes + // if(TRANSIT_CATEGORY) + // recipes = transit_tube_recipes + for(var/c in recipes) + var/list/cat = recipes[c] + var/list/r = list() + for(var/i in 1 to cat.len) + var/datum/pipe_recipe/info = cat[i] + r += list(list("pipe_name" = info.name, "pipe_index" = i, "selected" = (info == recipe))) + data["categories"] += list(list("cat_name" = c, "recipes" = r)) - if(PIPE_BENDABLE) // Bent, N-W, N-E etc - lines += render_dir_img(recipe.icon_state,user,NORTH,"Vertical","↕") - lines += render_dir_img(recipe.icon_state,user,EAST,"Horizontal","↔") - lines += "
" - lines += render_dir_img(recipe.icon_state,user,NORTHWEST,"West to North","╝") - lines += render_dir_img(recipe.icon_state,user,NORTHEAST,"North to East","╚") - lines += render_dir_img(recipe.icon_state,user,SOUTHWEST,"South to West","╗") - lines += render_dir_img(recipe.icon_state,user,SOUTHEAST,"East to South","╔") + return data - if(PIPE_TRINARY) // Manifold - lines += render_dir_img(recipe.icon_state,user,NORTH,"West South East","╦") - lines += render_dir_img(recipe.icon_state,user,EAST,"North West South","╣") - lines += render_dir_img(recipe.icon_state,user,SOUTH,"East North West","╩") - lines += render_dir_img(recipe.icon_state,user,WEST,"South East North","╠") - - if(PIPE_TRIN_M) // Mirrored ones - //each mirror icon is 45 anticlockwise from it's real direction - lines += render_dir_img(recipe.icon_state,user,NORTH,"West South East","╦") - lines += render_dir_img(recipe.icon_state,user,EAST,"North West South","╣") - lines += render_dir_img(recipe.icon_state,user,SOUTH,"East North West","╩") - lines += render_dir_img(recipe.icon_state,user,WEST,"South East North","╠") - lines += "
" - lines += render_dir_img(recipe.icon_state_m,user,SOUTH,"West South East","╦", 1) - lines += render_dir_img(recipe.icon_state_m,user,WEST,"South East North","╠", 1) - lines += render_dir_img(recipe.icon_state_m,user,NORTH,"East North West","╩", 1) - lines += render_dir_img(recipe.icon_state_m,user,EAST,"North West South","╣", 1) - - if(PIPE_DIRECTIONAL) // Stuff with four directions - includes pumps etc. - lines += render_dir_img(recipe.icon_state,user,NORTH,"North","↑") - lines += render_dir_img(recipe.icon_state,user,EAST,"East","→") - lines += render_dir_img(recipe.icon_state,user,SOUTH,"South","↓") - lines += render_dir_img(recipe.icon_state,user,WEST,"West","←") - - if(PIPE_ONEDIR) // Single icon_state (eg 4-way manifolds) - lines += render_dir_img(recipe.icon_state,user,SOUTH,"Pipe","↕") - lines += "
" - - if(mode == ATMOS_MODE || mode == PAINT_MODE) - lines += "

Color:

" - var/i = 0 - for(var/c in pipe_colors) - ++i - lines += "[c]" - if(i == 4) - lines += "
" - i = 0 - lines += "
" - - lines += "

Mode:

" - lines += "Lay Pipes" - lines += "Eat Pipes" - lines += "Paint Pipes" - lines += "
" - - lines += "

Category:

" - lines += "Atmospherics" - lines += "Disposals" - //lines += "Transit Tube" - lines += "
Wrench Mode" - lines += "
" - - if(screen == ATMOS_MODE) - for(var/category in atmos_pipe_recipes) - lines += "

[category]:

" - - if(category == "Pipes") - lines += "
" - for(var/pipename in pipe_layers) - var/pipelayer = pipe_layers[pipename] - lines += "[pipename] " - lines += "
" - lines += "
" - for(var/i in 1 to atmos_pipe_recipes[category].len) - var/datum/pipe_recipe/PI = atmos_pipe_recipes[category][i] - lines += "
" - lines += "[PI.name]" - lines += "
" - lines += "
" - else if(screen == DISPOSALS_MODE) - for(var/category in disposal_pipe_recipes) - lines += "

[category]:

" - for(var/i in 1 to disposal_pipe_recipes[category].len) - var/datum/pipe_recipe/PI = disposal_pipe_recipes[category][i] - lines += "
" - lines += "[PI.name]" - lines += "
" - lines += "
" - - var/dat = lines.Join() - var/datum/browser/popup = new(user, "rpd", name, 300, 800, src) - popup.set_content("[dat]") - popup.add_head_content(icon_assets.css_tag()) - popup.open() - -/obj/item/weapon/pipe_dispenser/Topic(href, href_list, state = global.inventory_state) +/obj/item/weapon/pipe_dispenser/tgui_act(action, params) SetupPipes() if(..()) - return 1 + return TRUE if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - return 1 - var/playeffect = TRUE // Do we spark the device - var/anyclicked = FALSE // Tells us if we need to refresh the window. - if(href_list["paint_color"]) - paint_color = href_list["paint_color"] - playeffect = FALSE - anyclicked = TRUE - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - anyclicked = TRUE - if(href_list["screen"]) - if(mode == screen) - mode = text2num(href_list["screen"]) - screen = text2num(href_list["screen"]) - switch(screen) - if(DISPOSALS_MODE) - recipe = first_disposal - if(ATMOS_MODE) - recipe = first_atmos - p_dir = NORTH - playeffect = FALSE - anyclicked = TRUE - if(href_list["piping_layer"]) - piping_layer = text2num(href_list["piping_layer"]) - playeffect = FALSE - anyclicked = TRUE - if(href_list["pipe_type"]) - recipe = all_pipe_recipes[href_list["category"]][text2num(href_list["pipe_type"])] - if(recipe.dirtype == PIPE_ONEDIR) // One hell of a hack for the fact that the image previews for the onedir types only show on the south, but the default pipe type is north. - p_dir = SOUTH // Did I fuck this up? Maybe. Or maybe it's just the icon files not being ready for an RPD. - else // If going to try and fix this hack, be aware the pipe dispensers might rely on pipes defaulting south instead of north. + return TRUE + var/playeffect = TRUE + switch(action) + if("color") + paint_color = params["paint_color"] + if("category") + category = text2num(params["category"]) + switch(category) + if(DISPOSALS_CATEGORY) + recipe = first_disposal + if(ATMOS_CATEGORY) + recipe = first_atmos + // if(TRANSIT_CATEGORY) + // recipe = first_transit p_dir = NORTH - p_flipped = FALSE - anyclicked = TRUE - if(href_list["dir"]) - p_dir = text2dir(href_list["dir"]) - p_flipped = text2num(href_list["flipped"]) - playeffect = FALSE - anyclicked = TRUE - if(href_list["switch_wrench"]) - wrench_mode = text2num(href_list["wrench_mode"]) - anyclicked = TRUE - if(anyclicked) - if(playeffect) - spark_system.start() - playsound(src, 'sound/effects/pop.ogg', 50, 0) - src.interact(usr) + playeffect = FALSE + if("piping_layer") + piping_layer = text2num(params["piping_layer"]) + playeffect = FALSE + // if("ducting_layer") + // ducting_layer = text2num(params["ducting_layer"]) + // playeffect = FALSE + if("pipe_type") + var/static/list/recipes + if(!recipes) + recipes = GLOB.disposal_pipe_recipes + GLOB.atmos_pipe_recipes + recipe = recipes[params["category"]][text2num(params["pipe_type"])] + p_dir = NORTH + if("setdir") + p_dir = text2dir(params["dir"]) + p_flipped = text2num(params["flipped"]) + playeffect = FALSE + if("mode") + var/n = text2num(params["mode"]) + if(mode & n) + mode &= ~n + else + mode |= n + if(playeffect) + spark_system.start() + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE) + return TRUE /obj/item/weapon/pipe_dispenser/afterattack(atom/A, mob/user as mob, proximity) if(!user.IsAdvancedToolUser() || istype(A, /turf/space/transit) || !proximity) @@ -249,88 +177,89 @@ make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe)) var/can_make_pipe = (isturf(A) || is_type_in_typecache(A, make_pipe_whitelist)) - . = FALSE - switch(mode) //if we've gotten this var, the target is valid - if(PAINT_MODE) //Paint pipes - if(!istype(A, /obj/machinery/atmospherics/pipe)) - return ..() + var/can_destroy_pipe = istype(A, /obj/item/pipe) || istype(A, /obj/item/pipe_meter) || istype(A, /obj/structure/disposalconstruct) + + . = TRUE + if((mode & DESTROY_MODE) && can_destroy_pipe) + to_chat(user, "You start destroying a pipe...") + playsound(src, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 2, target = A)) + activate() + animate_deletion(A) + return + + if((mode & PAINT_MODE)) //Paint pipes + if(istype(A, /obj/machinery/atmospherics/pipe)) var/obj/machinery/atmospherics/pipe/P = A playsound(src, 'sound/machines/click.ogg', 50, 1) P.change_color(pipe_colors[paint_color]) user.visible_message("[user] paints \the [P] [paint_color].", "You paint \the [P] [paint_color].") return - if(EATING_MODE) //Eating pipes - if(!(istype(A, /obj/item/pipe) || istype(A, /obj/item/pipe_meter) || istype(A, /obj/structure/disposalconstruct))) - return ..() - to_chat(user, "You start destroying a pipe...") - playsound(src, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 2, target = A)) - activate() - animate_deletion(A) + if(mode & BUILD_MODE) //Making pipes + switch(category) + if(ATMOS_CATEGORY) + if(!can_make_pipe) + return ..() + playsound(src, 'sound/machines/click.ogg', 50, 1) + if(istype(recipe, /datum/pipe_recipe/meter)) + to_chat(user, "You start building a meter...") + if(do_after(user, 2, target = A)) + activate() + var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(get_turf(A)) + PM.setAttachLayer(queued_piping_layer) + if(mode & WRENCH_MODE) + do_wrench(PM, user) + else if(istype(recipe, /datum/pipe_recipe/pipe)) + var/datum/pipe_recipe/pipe/R = recipe + to_chat(user, "You start building a pipe...") + if(do_after(user, 2, target = A)) + activate() + var/obj/machinery/atmospherics/path = R.pipe_type + var/pipe_item_type = initial(path.construction_type) || /obj/item/pipe + var/obj/item/pipe/P = new pipe_item_type(get_turf(A), path, queued_p_dir) - if(ATMOS_MODE) //Making pipes - if(!can_make_pipe) - return ..() - playsound(src, 'sound/machines/click.ogg', 50, 1) - if (istype(recipe, /datum/pipe_recipe/meter)) - to_chat(user, "You start building a meter...") - if(do_after(user, 2, target = A)) - activate() - var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(get_turf(A)) - PM.setAttachLayer(queued_piping_layer) - if(wrench_mode) - do_wrench(PM, user) - else if(istype(recipe, /datum/pipe_recipe/pipe)) - var/datum/pipe_recipe/pipe/R = recipe - to_chat(user, "You start building a pipe...") - if(do_after(user, 2, target = A)) - activate() - var/obj/machinery/atmospherics/path = R.pipe_type - var/pipe_item_type = initial(path.construction_type) || /obj/item/pipe - var/obj/item/pipe/P = new pipe_item_type(get_turf(A), path, queued_p_dir) + P.update() + P.add_fingerprint(usr) + if(R.paintable) + P.color = pipe_colors[paint_color] + P.setPipingLayer(queued_piping_layer) + if(queued_p_flipped) + P.do_a_flip() + if(mode & WRENCH_MODE) + do_wrench(P, user) + else + build_effect(P) - P.update() - P.add_fingerprint(usr) - if (R.paintable) - P.color = pipe_colors[paint_color] - P.setPipingLayer(queued_piping_layer) - if(queued_p_flipped) - P.do_a_flip() - if(wrench_mode) - do_wrench(P, user) - else - build_effect(P) - - if(DISPOSALS_MODE) //Making disposals pipes - var/datum/pipe_recipe/disposal/R = recipe - if(!istype(R) || !can_make_pipe) - return ..() - A = get_turf(A) - if(istype(A, /turf/unsimulated)) - to_chat(user, "[src]'s error light flickers; there's something in the way!") - return - to_chat(user, "You start building a disposals pipe...") - playsound(src, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 4, target = A)) - var/obj/structure/disposalconstruct/C = new(A, R.pipe_type, queued_p_dir, queued_p_flipped, R.subtype) - - if(!C.can_place()) - to_chat(user, "There's not enough room to build that here!") - qdel(C) + if(DISPOSALS_CATEGORY) //Making disposals pipes + var/datum/pipe_recipe/disposal/R = recipe + if(!istype(R) || !can_make_pipe) + return ..() + A = get_turf(A) + if(istype(A, /turf/unsimulated)) + to_chat(user, "[src]'s error light flickers; there's something in the way!") return + to_chat(user, "You start building a disposals pipe...") + playsound(src, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 4, target = A)) + var/obj/structure/disposalconstruct/C = new(A, R.pipe_type, queued_p_dir, queued_p_flipped, R.subtype) - activate() + if(!C.can_place()) + to_chat(user, "There's not enough room to build that here!") + qdel(C) + return - C.add_fingerprint(usr) - C.update_icon() - if(wrench_mode) - do_wrench(C, user) - else - build_effect(C) + activate() - else - return ..() + C.add_fingerprint(usr) + C.update_icon() + if(mode & WRENCH_MODE) + do_wrench(C, user) + else + build_effect(C) + + else + return ..() /obj/item/weapon/pipe_dispenser/proc/build_effect(var/obj/P, var/time = 1.5) set waitfor = FALSE @@ -359,19 +288,11 @@ if(!resolved && tool && target) tool.afterattack(target,user,1) -/obj/item/weapon/pipe_dispenser/proc/render_dir_img(icon_state, user, _dir, title, noimg, flipped = FALSE) - var/dirtext = dir2text(_dir) - var/attrs = " style=\"height:34px;width:34px;display:inline-block\"" - if(_dir == p_dir && flipped == p_flipped) - attrs += " class=\"linkOn\"" - if(icon_state) - var/img_tag = icon_assets.icon_tag("[dirtext]-[icon_state]") - return "[img_tag]" - else - return "[noimg]" +#undef ATMOS_CATEGORY +#undef DISPOSALS_CATEGORY +#undef TRANSIT_CATEGORY - -#undef PAINT_MODE -#undef EATING_MODE -#undef ATMOS_MODE -#undef DISPOSALS_MODE +#undef BUILD_MODE +#undef WRENCH_MODE +#undef DESTROY_MODE +#undef PAINT_MODE \ No newline at end of file diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm index 5b1f6752ae..d701070aca 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -17,8 +17,7 @@ var/dna_hash = "\[UNSET\]" var/fingerprint_hash = "\[UNSET\]" var/sex = "\[UNSET\]" - var/icon/front - var/icon/side + var/front var/primary_color = rgb(0,0,0) // Obtained by eyedroppering the stripe in the middle of the card var/secondary_color = rgb(0,0,0) // Likewise for the oval in the top-left corner @@ -34,30 +33,27 @@ /obj/item/weapon/card/id/examine(mob/user) . = ..() if(in_range(user, src)) - show(user) //Not chat related + tgui_interact(user) //Not chat related else . += "It is too far away to read." /obj/item/weapon/card/id/proc/prevent_tracking() return 0 -/obj/item/weapon/card/id/proc/show(mob/user as mob) - if(front && side) - user << browse_rsc(front, "front.png") - user << browse_rsc(side, "side.png") - var/datum/browser/popup = new(user, "idcard", name, 600, 250) - popup.set_content(dat()) - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return +/obj/item/weapon/card/id/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "IDCard", name) + ui.open() /obj/item/weapon/card/id/proc/update_name() name = "[src.registered_name]'s ID Card ([src.assignment])" /obj/item/weapon/card/id/proc/set_id_photo(var/mob/M) - var/icon/charicon = cached_character_icon(M) - front = icon(charicon,dir = SOUTH) - side = icon(charicon,dir = WEST) + COMPILE_OVERLAYS(M) + SSoverlays.queue -= M + var/icon/F = getFlatIcon(M, defdir = SOUTH, no_anim = TRUE) + front = "'data:image/png;base64,[icon2base64(F)]'" /mob/proc/set_id_info(var/obj/item/weapon/card/id/id_card) id_card.age = 0 @@ -75,19 +71,19 @@ ..() id_card.age = age -/obj/item/weapon/card/id/proc/dat() - var/dat = ("" - dat += "
") - dat += text("Name: []
", registered_name) - dat += text("Sex: []
\n", sex) - dat += text("Age: []
\n", age) - dat += text("Rank: []
\n", assignment) - dat += text("Fingerprint: []
\n", fingerprint_hash) - dat += text("Blood Type: []
\n", blood_type) - dat += text("DNA Hash: []

\n", dna_hash) - if(front && side) - dat +="
Photo:
" - return dat +/obj/item/weapon/card/id/tgui_data(mob/user) + var/list/data = list() + + data["registered_name"] = registered_name + data["sex"] = sex + data["age"] = age + data["assignment"] = assignment + data["fingerprint_hash"] = fingerprint_hash + data["blood_type"] = blood_type + data["dna_hash"] = dna_hash + data["photo_front"] = front + + return data /obj/item/weapon/card/id/attack_self(mob/user as mob) user.visible_message("\The [user] shows you: [bicon(src)] [src.name]. The assignment on the card: [src.assignment]",\ diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 25c08c725a..f267ac3654 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -1,5 +1,5 @@ #define TANK_MAX_RELEASE_PRESSURE (3*ONE_ATMOSPHERE) -#define TANK_DEFAULT_RELEASE_PRESSURE 24 +#define TANK_DEFAULT_RELEASE_PRESSURE 21 #define TANK_IDEAL_PRESSURE 1015 //Arbitrary. var/list/global/tank_gauge_cache = list() @@ -217,90 +217,73 @@ var/list/global/tank_gauge_cache = list() add_fingerprint(user) if (!(src.air_contents)) return - ui_interact(user) + tgui_interact(user) // There's GOT to be a better way to do this if (src.proxyassembly.assembly) src.proxyassembly.assembly.attack_self(user) -/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/mob/living/carbon/location = null +/obj/item/weapon/tank/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Tank", name) + ui.open() - if(istype(loc, /obj/item/weapon/rig)) // check for tanks in rigs - if(istype(loc.loc, /mob/living/carbon)) - location = loc.loc - else if(istype(loc, /mob/living/carbon)) - location = loc - - var/using_internal - if(istype(location)) - if(location.internal==src) - using_internal = 1 - - // this is the data which will be sent to the ui - var/data[0] +/obj/item/weapon/tank/tgui_data(mob/user) + var/list/data = list() data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0) data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) + data["minReleasePressure"] = 0 data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) - data["valveOpen"] = using_internal ? 1 : 0 - data["maskConnected"] = 0 - if(istype(location)) - var/mask_check = 0 + var/mob/living/carbon/C = user + if(!istype(C)) + C = loc.loc + if(!istype(C)) + return data - if(location.internal == src) // if tank is current internal - mask_check = 1 - else if(src in location) // or if tank is in the mobs possession - if(!location.internal) // and they do not have any active internals - mask_check = 1 - else if(istype(src.loc, /obj/item/weapon/rig) && src.loc in location) // or the rig is in the mobs possession - if(!location.internal) // and they do not have any active internals - mask_check = 1 + if(C.internal == src) + data["connected"] = TRUE + else + data["connected"] = FALSE - if(mask_check) - if(location.wear_mask && (location.wear_mask.item_flags & AIRTIGHT)) - data["maskConnected"] = 1 - else if(istype(location, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = location - if(H.head && (H.head.item_flags & AIRTIGHT)) - data["maskConnected"] = 1 + data["maskConnected"] = FALSE + if(C.wear_mask && (C.wear_mask.item_flags & AIRTIGHT)) + data["maskConnected"] = TRUE + else if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(H.head && (H.head.item_flags & AIRTIGHT)) + data["maskConnected"] = TRUE - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "tanks.tmpl", "Tank", 500, 300) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data -/obj/item/weapon/tank/Topic(href, href_list) - ..() - if (usr.stat|| usr.restrained()) - return 0 - if (src.loc != usr) - return 0 +/obj/item/weapon/tank/tgui_act(action, params) + if(..()) + return TRUE + switch(action) + if("pressure") + var/pressure = params["pressure"] + if(pressure == "reset") + pressure = TANK_DEFAULT_RELEASE_PRESSURE + . = TRUE + else if(pressure == "min") + pressure = 0 + . = TRUE + else if(pressure == "max") + pressure = TANK_MAX_RELEASE_PRESSURE + . = TRUE + else if(text2num(pressure) != null) + pressure = text2num(pressure) + . = TRUE + if(.) + distribute_pressure = clamp(round(pressure), 0, TANK_MAX_RELEASE_PRESSURE) + if("toggle") + toggle_valve(usr) + . = TRUE - if (href_list["dist_p"]) - if (href_list["dist_p"] == "reset") - src.distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE - else if (href_list["dist_p"] == "max") - src.distribute_pressure = TANK_MAX_RELEASE_PRESSURE - else - var/cp = text2num(href_list["dist_p"]) - src.distribute_pressure += cp - src.distribute_pressure = min(max(round(src.distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE) - if (href_list["stat"]) - toggle_valve(usr) - - src.add_fingerprint(usr) - return 1 + add_fingerprint(usr) /obj/item/weapon/tank/proc/toggle_valve(var/mob/user) if(istype(loc,/mob/living/carbon)) diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index e994e1b760..c75186f923 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -1,3 +1,5 @@ +#define TANK_DISPENSER_CAPACITY 10 + /obj/structure/dispenser name = "tank storage unit" desc = "A simple yet bulky storage device for gas tanks. Has room for up to ten oxygen tanks, and ten phoron tanks." @@ -6,10 +8,8 @@ density = 1 anchored = 1.0 w_class = ITEMSIZE_HUGE - var/oxygentanks = 10 - var/phorontanks = 10 - var/list/oxytanks = list() //sorry for the similar var names - var/list/platanks = list() + var/oxygentanks = TANK_DISPENSER_CAPACITY + var/phorontanks = TANK_DISPENSER_CAPACITY /obj/structure/dispenser/oxygen @@ -19,10 +19,14 @@ oxygentanks = 0 -/obj/structure/dispenser/New() +/obj/structure/dispenser/Initialize() + . = ..() + for(var/i in 1 to oxygentanks) + new /obj/item/weapon/tank/oxygen(src) + for(var/i in 1 to phorontanks) + new /obj/item/weapon/tank/phoron(src) update_icon() - /obj/structure/dispenser/update_icon() overlays.Cut() switch(oxygentanks) @@ -32,49 +36,44 @@ if(1 to 4) overlays += "phoron-[phorontanks]" if(5 to INFINITY) overlays += "phoron-5" -/obj/structure/dispenser/attack_ai(mob/user as mob) +/obj/structure/dispenser/attack_ai(mob/user) + // This looks silly, but robots also call attack_ai, and they're allowed physical state stuff. if(user.Adjacent(src)) return attack_hand(user) ..() -/obj/structure/dispenser/attack_hand(mob/user as mob) - user.set_machine(src) - var/dat = "[src]

" - dat += "Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
" - dat += "Phoron tanks: [phorontanks] - [phorontanks ? "Dispense" : "empty"]" - user << browse(dat, "window=dispenser") - onclose(user, "dispenser") - return +/obj/structure/dispenser/attack_hand(mob/user) + tgui_interact(user) +/obj/structure/dispenser/tgui_state(mob/user) + return GLOB.tgui_physical_state -/obj/structure/dispenser/attackby(obj/item/I as obj, mob/user as mob) +/obj/structure/dispenser/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TankDispenser", name) + ui.open() + +/obj/structure/dispenser/tgui_data(mob/user) + var/list/data = list() + data["oxygen"] = oxygentanks + data["plasma"] = phorontanks + + return data + +/obj/structure/dispenser/attackby(obj/item/I, mob/user) + var/full if(istype(I, /obj/item/weapon/tank/oxygen) || istype(I, /obj/item/weapon/tank/air) || istype(I, /obj/item/weapon/tank/anesthetic)) - if(oxygentanks < 10) - user.drop_item() - I.loc = src - oxytanks.Add(I) + if(oxygentanks < TANK_DISPENSER_CAPACITY) oxygentanks++ - to_chat(user, "You put [I] in [src].") - if(oxygentanks < 5) - update_icon() else - to_chat(user, "[src] is full.") - updateUsrDialog() - return - if(istype(I, /obj/item/weapon/tank/phoron)) - if(phorontanks < 10) - user.drop_item() - I.loc = src - platanks.Add(I) + full = TRUE + else if(istype(I, /obj/item/weapon/tank/phoron)) + if(phorontanks < TANK_DISPENSER_CAPACITY) phorontanks++ - to_chat(user, "You put [I] in [src].") - if(oxygentanks < 6) - update_icon() else - to_chat(user, "[src] is full.") - updateUsrDialog() - return - if(I.is_wrench()) + full = TRUE + else if(I.is_wrench()) if(anchored) to_chat(user, "You lean down and unwrench [src].") anchored = 0 @@ -82,39 +81,42 @@ to_chat(user, "You wrench [src] into place.") anchored = 1 return - -/obj/structure/dispenser/Topic(href, href_list) - if(usr.stat || usr.restrained()) + else if(user.a_intent != I_HURT) + to_chat(user, "[I] does not fit into [src].") return - if(Adjacent(usr)) - usr.set_machine(src) - if(href_list["oxygen"]) - if(oxygentanks > 0) - var/obj/item/weapon/tank/oxygen/O - if(oxytanks.len == oxygentanks) - O = oxytanks[1] - oxytanks.Remove(O) - else - O = new /obj/item/weapon/tank/oxygen(loc) - O.loc = loc - to_chat(usr, "You take [O] out of [src].") - oxygentanks-- - update_icon() - if(href_list["phoron"]) - if(phorontanks > 0) - var/obj/item/weapon/tank/phoron/P - if(platanks.len == phorontanks) - P = platanks[1] - platanks.Remove(P) - else - P = new /obj/item/weapon/tank/phoron(loc) - P.loc = loc - to_chat(usr, "You take [P] out of [src].") - phorontanks-- - update_icon() - add_fingerprint(usr) - updateUsrDialog() else - usr << browse(null, "window=dispenser") + return ..() + + if(full) + to_chat(user, "[src] can't hold any more of [I].") return - return + + if(!user.unEquip(I, target = src)) + return + to_chat(user, "You put [I] in [src].") + update_icon() + + +/obj/structure/dispenser/tgui_act(action, params) + if(..()) + return + switch(action) + if("plasma") + var/obj/item/weapon/tank/phoron/tank = locate() in src + if(tank && Adjacent(usr)) + usr.put_in_hands(tank) + phorontanks-- + . = TRUE + playsound(src, 'sound/machines/vending/vending_drop.ogg', 100, 1, 1) + if("oxygen") + var/obj/item/weapon/tank/tank = null + for(var/obj/item/weapon/tank/T in src) + if(istype(T, /obj/item/weapon/tank/oxygen) || istype(T, /obj/item/weapon/tank/air) || istype(T, /obj/item/weapon/tank/anesthetic)) + tank = T + break + if(tank && Adjacent(usr)) + usr.put_in_hands(tank) + oxygentanks-- + . = TRUE + playsound(src, 'sound/machines/vending/vending_drop.ogg', 100, 1, 1) + update_icon() \ No newline at end of file diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index ffc0f97738..cf32d9ad4d 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -31,58 +31,53 @@ if(holder) holder.update_icon() -/obj/item/device/assembly/signaler/interact(var/mob/user) - var/t1 = "-------" - var/dat = {" - +/obj/item/device/assembly/signaler/interact(mob/user) + if(..()) + return TRUE + tgui_interact(user) -Send Signal
-Frequency/Code for signaler:
-Frequency: -- -- -[format_frequency(src.frequency)] -+ -+
+/obj/item/device/assembly/signaler/tgui_state(mob/user) + return GLOB.tgui_deep_inventory_state -Code: -- -- -[src.code] -+ -+
-[t1] -
"} - user << browse(dat, "window=radio") - onclose(user, "radio") +/obj/item/device/assembly/signaler/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Signaler", name) + ui.open() -/obj/item/device/assembly/signaler/Topic(href, href_list, state = deep_inventory_state) +/obj/item/device/assembly/signaler/tgui_data(mob/user) + var/list/data = list() + data["frequency"] = frequency + data["code"] = code + data["minFrequency"] = RADIO_LOW_FREQ + data["maxFrequency"] = RADIO_HIGH_FREQ + return data + +/obj/item/device/assembly/signaler/tgui_act(action, params) if(..()) return TRUE - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=radio") - onclose(usr, "radio") - return + switch(action) + if("signal") + INVOKE_ASYNC(src, .proc/signal) + . = TRUE + if("freq") + frequency = unformat_frequency(params["freq"]) + frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + set_frequency(frequency) + . = TRUE + if("code") + code = text2num(params["code"]) + code = clamp(round(code), 1, 100) + . = TRUE + if("reset") + if(params["reset"] == "freq") + set_frequency(initial(frequency)) + else + code = initial(code) + . = TRUE - if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if(new_frequency < RADIO_LOW_FREQ || new_frequency > RADIO_HIGH_FREQ) - new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) - set_frequency(new_frequency) - - if(href_list["code"]) - src.code += text2num(href_list["code"]) - src.code = round(src.code) - src.code = min(100, src.code) - src.code = max(1, src.code) - - if(href_list["send"]) - spawn( 0 ) - signal() - - if(usr) - attack_self(usr) + update_icon() /obj/item/device/assembly/signaler/attackby(var/obj/item/weapon/W, mob/user, params) if(issignaler(W)) diff --git a/code/modules/clothing/glasses/hud_vr.dm b/code/modules/clothing/glasses/hud_vr.dm index ce49c88949..09e2af254d 100644 --- a/code/modules/clothing/glasses/hud_vr.dm +++ b/code/modules/clothing/glasses/hud_vr.dm @@ -100,12 +100,12 @@ mode = "sec" flash_protection = FLASH_PROTECTION_MAJOR action_button_name = "AR Console (Security Alerts)" - arscreen_path = /datum/nano_module/alarm_monitor/security + tgarscreen_path = /datum/tgui_module/alarm_monitor/security/glasses enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_WANTED,VIS_AUGMENTED) ar_interact(var/mob/living/carbon/human/user) - if(arscreen) - arscreen.ui_interact(user,"main",null,1,glasses_state) + if(tgarscreen) + tgarscreen.tgui_interact(user) return 1 /obj/item/clothing/glasses/omnihud/eng @@ -115,11 +115,11 @@ mode = "eng" flash_protection = FLASH_PROTECTION_MAJOR action_button_name = "AR Console (Station Alerts)" - arscreen_path = /datum/nano_module/alarm_monitor/engineering + tgarscreen_path = /datum/tgui_module/alarm_monitor/engineering/glasses ar_interact(var/mob/living/carbon/human/user) - if(arscreen) - arscreen.ui_interact(user,"main",null,1,glasses_state) + if(tgarscreen) + tgarscreen.tgui_interact(user) return 1 /obj/item/clothing/glasses/omnihud/rnd diff --git a/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm b/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm index 6dc5fc4f01..e6848a66d0 100644 --- a/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm +++ b/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm @@ -15,7 +15,7 @@ to_chat(usr, "Your module is not installed in a hardsuit.") return - module.holder.ui_interact(usr, nano_state = contained_state) + module.holder.tgui_interact(usr, custom_state = GLOB.tgui_contained_state) /obj/item/rig_module/ai_container @@ -134,7 +134,7 @@ if(!target) if(ai_card) if(istype(ai_card,/obj/item/device/aicard)) - ai_card.ui_interact(H, state = deep_inventory_state) + ai_card.tgui_interact(H, custom_state = deep_inventory_state) else eject_ai(H) update_verb_holder() diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 1afd78dee0..2a8cef9991 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -28,8 +28,8 @@ var/suit_state //The string used for the suit's icon_state. - var/interface_path = "hardsuit.tmpl" - var/ai_interface_path = "hardsuit.tmpl" + var/interface_path = "RIGSuit" + var/ai_interface_path = "RIGSuit" var/interface_title = "Hardsuit Controller" var/wearer_move_delay //Used for AI moving. var/ai_controlled_move_delay = 10 @@ -576,81 +576,6 @@ cell.use(cost*10) return 1 -/obj/item/weapon/rig/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/nano_state = inventory_state) - if(!user) - return - - var/list/data = list() - - if(selected_module) - data["primarysystem"] = "[selected_module.interface_name]" - - if(src.loc != user) - data["ai"] = 1 - - data["seals"] = "[src.canremove]" - data["sealing"] = "[src.sealing]" - data["helmet"] = (helmet ? "[helmet.name]" : "None.") - data["gauntlets"] = (gloves ? "[gloves.name]" : "None.") - data["boots"] = (boots ? "[boots.name]" : "None.") - data["chest"] = (chest ? "[chest.name]" : "None.") - - data["charge"] = cell ? round(cell.charge,1) : 0 - data["maxcharge"] = cell ? cell.maxcharge : 0 - data["chargestatus"] = cell ? FLOOR((cell.charge/cell.maxcharge)*50, 1) : 0 - - data["emagged"] = subverted - data["coverlock"] = locked - data["interfacelock"] = interface_locked - data["aicontrol"] = control_overridden - data["aioverride"] = ai_override_enabled - data["securitycheck"] = security_check_enabled - data["malf"] = malfunction_delay - - - var/list/module_list = list() - var/i = 1 - for(var/obj/item/rig_module/module in installed_modules) - var/list/module_data = list( - "index" = i, - "name" = "[module.interface_name]", - "desc" = "[module.interface_desc]", - "can_use" = "[module.usable]", - "can_select" = "[module.selectable]", - "can_toggle" = "[module.toggleable]", - "is_active" = "[module.active]", - "engagecost" = module.use_power_cost*10, - "activecost" = module.active_power_cost*10, - "passivecost" = module.passive_power_cost*10, - "engagestring" = module.engage_string, - "activatestring" = module.activate_string, - "deactivatestring" = module.deactivate_string, - "damage" = module.damage - ) - - if(module.charges && module.charges.len) - - module_data["charges"] = list() - var/datum/rig_charge/selected = module.charges[module.charge_selected] - module_data["chargetype"] = selected ? "[selected.display_name]" : "none" - - for(var/chargetype in module.charges) - var/datum/rig_charge/charge = module.charges[chargetype] - module_data["charges"] += list(list("caption" = "[chargetype] ([charge.charges])", "index" = "[chargetype]")) - - module_list += list(module_data) - i++ - - if(module_list.len) - data["modules"] = module_list - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, ((src.loc != user) ? ai_interface_path : interface_path), interface_title, 480, 550, state = nano_state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - /obj/item/weapon/rig/update_icon(var/update_mob_icon) //TODO: Maybe consider a cache for this (use mob_icon as blank canvas, use suit icon overlay). @@ -698,44 +623,6 @@ return 1 -//TODO: Fix Topic vulnerabilities for malfunction and AI override. -/obj/item/weapon/rig/Topic(href,href_list) - if(!check_suit_access(usr)) - return 0 - - if(href_list["toggle_piece"]) - if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying)) - return 0 - toggle_piece(href_list["toggle_piece"], usr) - else if(href_list["toggle_seals"]) - toggle_seals(usr) - else if(href_list["interact_module"]) - - var/module_index = text2num(href_list["interact_module"]) - - if(module_index > 0 && module_index <= installed_modules.len) - var/obj/item/rig_module/module = installed_modules[module_index] - switch(href_list["module_mode"]) - if("activate") - module.activate() - if("deactivate") - module.deactivate() - if("engage") - module.engage() - if("select") - selected_module = module - if("select_charge_type") - module.charge_selected = href_list["charge_type"] - else if(href_list["toggle_ai_control"]) - ai_override_enabled = !ai_override_enabled - notify_ai("Synthetic suit control has been [ai_override_enabled ? "enabled" : "disabled"].") - else if(href_list["toggle_suit_lock"]) - locked = !locked - - usr.set_machine(src) - src.add_fingerprint(usr) - return 0 - /obj/item/weapon/rig/proc/notify_ai(var/message) for(var/obj/item/rig_module/ai_container/module in installed_modules) if(module.integrated_ai && module.integrated_ai.client && !module.integrated_ai.stat) diff --git a/code/modules/clothing/spacesuits/rig/rig_tgui.dm b/code/modules/clothing/spacesuits/rig/rig_tgui.dm new file mode 100644 index 0000000000..5fc1e17380 --- /dev/null +++ b/code/modules/clothing/spacesuits/rig/rig_tgui.dm @@ -0,0 +1,164 @@ +/* + * This defines the global UI for RIGSuits. + * It has all of the relevant TGUI procs, but it's entry point is in rig_verbs.dm + * as part of rig/proc/hardsuit_interface(). + */ + +/* + * tgui_interact() is the proc that opens the UI. It doesn't really do anything else, unlike NanoV1. + * We add an extra argument, custom_state, for the things that want a custom state for their UI. + */ +/obj/item/weapon/rig/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, datum/tgui_state/custom_state) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, (loc != usr ? ai_interface_path : interface_path), interface_title) + ui.open() + if(custom_state) + ui.set_state(custom_state) + +/* + * tgui_state() gives the UI the state to use by default. + */ +/obj/item/weapon/rig/tgui_state() + return GLOB.tgui_inventory_state + +/* + * tgui_status() is middlewere for objects to add little exceptions or special cases to the state they use. + * In this case, we're using it in order to make the UI refuse to let the user press any buttons if they're + * not authorized to do so. + * This saves us two lines of code in tgui_act(). + */ +/obj/item/weapon/rig/tgui_status(mob/user, datum/tgui_state/state) + . = ..() + if(!check_suit_access(user)) + // Forces the UI to never go interactive, + // but doesn't interfere with state saying to close. + . = min(., STATUS_UPDATE) + +/* + * tgui_data() is the heavy lifter, it gives the UI it's relevant datastructure every SStgui tick. + */ +/obj/item/weapon/rig/tgui_data(mob/user) + var/list/data = list() + + if(selected_module) + data["primarysystem"] = "[selected_module.interface_name]" + else + data["primarysystem"] = null + + if(loc != user) + data["ai"] = TRUE + else + data["ai"] = FALSE + + data["sealed"] = !canremove + data["sealing"] = sealing + data["helmet"] = (helmet ? "[helmet.name]" : "None.") + data["gauntlets"] = (gloves ? "[gloves.name]" : "None.") + data["boots"] = (boots ? "[boots.name]" : "None.") + data["chest"] = (chest ? "[chest.name]" : "None.") + + data["helmetDeployed"] = (helmet && helmet.loc == loc) + data["gauntletsDeployed"] = (gloves && gloves.loc == loc) + data["bootsDeployed"] = (boots && boots.loc == loc) + data["chestDeployed"] = (chest && chest.loc == loc) + + data["charge"] = cell ? round(cell.charge,1) : 0 + data["maxcharge"] = cell ? cell.maxcharge : 0 + data["chargestatus"] = cell ? FLOOR((cell.charge/cell.maxcharge)*50, 1) : 0 + + data["emagged"] = subverted + data["coverlock"] = locked + data["interfacelock"] = interface_locked + data["aicontrol"] = control_overridden + data["aioverride"] = ai_override_enabled + data["securitycheck"] = security_check_enabled + data["malf"] = malfunction_delay + + var/list/module_list = list() + if(!canremove && !sealing) + var/i = 1 + for(var/obj/item/rig_module/module in installed_modules) + var/list/module_data = list( + "index" = i, + "name" = "[module.interface_name]", + "desc" = "[module.interface_desc]", + "can_use" = module.usable, + "can_select" = module.selectable, + "can_toggle" = module.toggleable, + "is_active" = module.active, + "engagecost" = module.use_power_cost*10, + "activecost" = module.active_power_cost*10, + "passivecost" = module.passive_power_cost*10, + "engagestring" = module.engage_string, + "activatestring" = module.activate_string, + "deactivatestring" = module.deactivate_string, + "damage" = module.damage + ) + + if(module.charges && module.charges.len) + module_data["charges"] = list() + var/datum/rig_charge/selected = module.charges[module.charge_selected] + module_data["chargetype"] = selected ? "[selected.display_name]" : "none" + + for(var/chargetype in module.charges) + var/datum/rig_charge/charge = module.charges[chargetype] + module_data["charges"] += list(list("caption" = "[chargetype] ([charge.charges])", "index" = "[chargetype]")) + + module_list += list(module_data) + i++ + + if(module_list.len) + data["modules"] = module_list + else + data["modules"] = list() + + return data + +/* + * tgui_act() is the TGUI equivelent of Topic(). It's responsible for all of the "actions" you can take in the UI. + */ +/obj/item/weapon/rig/tgui_act(action, params) + // This parent call is very important, as it's responsible for invoking tgui_status and checking our state's rules. + if(..()) + return TRUE + + add_fingerprint(usr) + + switch(action) + if("toggle_seals") + toggle_seals(usr) + . = TRUE + if("toggle_ai_control") + ai_override_enabled = !ai_override_enabled + notify_ai("Synthetic suit control has been [ai_override_enabled ? "enabled" : "disabled"].") + . = TRUE + if("toggle_suit_lock") + locked = !locked + . = TRUE + if("toggle_piece") + if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying)) + return FALSE + toggle_piece(params["piece"], usr) + . = TRUE + if("interact_module") + var/module_index = text2num(params["module"]) + + if(module_index > 0 && module_index <= installed_modules.len) + var/obj/item/rig_module/module = installed_modules[module_index] + switch(params["module_mode"]) + if("select") + selected_module = module + . = TRUE + if("engage") + module.engage() + . = TRUE + if("toggle") + if(module.active) + module.deactivate() + else + module.activate() + . = TRUE + if("select_charge_type") + module.charge_selected = params["charge_type"] + . = TRUE \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/rig/rig_verbs.dm b/code/modules/clothing/spacesuits/rig/rig_verbs.dm index 9f832ec911..ea56adb1e6 100644 --- a/code/modules/clothing/spacesuits/rig/rig_verbs.dm +++ b/code/modules/clothing/spacesuits/rig/rig_verbs.dm @@ -7,7 +7,7 @@ set src = usr.contents if(wearer && (wearer.back == src || wearer.belt == src)) - ui_interact(usr) + tgui_interact(usr) /obj/item/weapon/rig/verb/toggle_vision() diff --git a/code/modules/mob/living/silicon/robot/drone/drone_console.dm b/code/modules/mob/living/silicon/robot/drone/drone_console.dm index c2e6ca48f5..94b8bb2e2c 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_console.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_console.dm @@ -14,111 +14,107 @@ /obj/machinery/computer/drone_control/attack_ai(var/mob/user as mob) return src.attack_hand(user) +/obj/machinery/computer/drone_control/tgui_status(mob/user) + if(!allowed(user)) + return STATUS_CLOSE + return ..() + /obj/machinery/computer/drone_control/attack_hand(var/mob/user as mob) if(..()) return - if(!allowed(user)) - to_chat(user, "Access denied.") - return + tgui_interact(user) - user.set_machine(src) - var/dat - dat += "Maintenance Units
" +/obj/machinery/computer/drone_control/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "DroneConsole", name) + ui.open() +/obj/machinery/computer/drone_control/tgui_data(mob/user) + var/list/data = list() + + data["drones"] = list() for(var/mob/living/silicon/robot/drone/D in mob_list) - if(D.z != src.z) + if(D.z != z) continue if(D.foreign_droid) continue + + data["drones"].Add(list(list( + "name" = D.real_name, + "active" = D.stat != 2, + "charge" = D.cell.charge, + "maxCharge" = D.cell.maxcharge, + "loc" = "[get_area(D)]", + "ref" = "\ref[D]", + ))) - dat += "
[D.real_name] ([D.stat == 2 ? "INACTIVE" : "ACTIVE"])" - dat += "
Cell charge: [D.cell.charge]/[D.cell.maxcharge]." - dat += "
Currently located in: [get_area(D)]." - dat += "
Resync | Shutdown
" + data["fabricator"] = dronefab + data["fabPower"] = dronefab?.produce_drones - dat += "

Request drone presence in area: [drone_call_area] (Send ping)" + data["areas"] = tagger_locations + data["selected_area"] = "[drone_call_area]" - dat += "

Drone fabricator: " - dat += "[dronefab ? "[(dronefab.produce_drones && !(dronefab.stat & NOPOWER)) ? "ACTIVE" : "INACTIVE"]" : "FABRICATOR NOT DETECTED. (search)"]" - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return + return data - -/obj/machinery/computer/drone_control/Topic(href, href_list) +/obj/machinery/computer/drone_control/tgui_act(action, params) if(..()) - return + return TRUE - if(!allowed(usr)) - to_chat(usr, "Access denied.") - return + switch(action) + if("set_dcall_area") + var/t_area = params["area"] + if(!t_area || !(t_area in tagger_locations)) + return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) + drone_call_area = t_area + to_chat(usr, "You set the area selector to [drone_call_area].") - if (href_list["setarea"]) + if("ping") + to_chat(usr, "You issue a maintenance request for all active drones, highlighting [drone_call_area].") + for(var/mob/living/silicon/robot/drone/D in player_list) + if(D.stat == 0) + to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].") - //Probably should consider using another list, but this one will do. - var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in tagger_locations + if("resync") + var/mob/living/silicon/robot/drone/D = locate(params["ref"]) - if(!t_area) - return + if(D.stat != 2) + to_chat(usr, "You issue a law synchronization directive for the drone.") + D.law_resync() - drone_call_area = t_area - to_chat(usr, "You set the area selector to [drone_call_area].") + if("shutdown") + var/mob/living/silicon/robot/drone/D = locate(params["ref"]) - else if (href_list["ping"]) + if(D.stat != 2) + to_chat(usr, "You issue a kill command for the unfortunate drone.") + message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.") + log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.") + D.shut_down() - to_chat(usr, "You issue a maintenance request for all active drones, highlighting [drone_call_area].") - for(var/mob/living/silicon/robot/drone/D in player_list) - if(D.stat == 0) - to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].") + if("search_fab") + if(dronefab) + return - else if (href_list["resync"]) + for(var/obj/machinery/drone_fabricator/fab in oview(3,src)) + if(fab.stat & NOPOWER) + continue - var/mob/living/silicon/robot/drone/D = locate(href_list["resync"]) + dronefab = fab + to_chat(usr, "Drone fabricator located.") + return - if(D.stat != 2) - to_chat(usr, "You issue a law synchronization directive for the drone.") - D.law_resync() - - else if (href_list["shutdown"]) - - var/mob/living/silicon/robot/drone/D = locate(href_list["shutdown"]) - - if(D.stat != 2) - to_chat(usr, "You issue a kill command for the unfortunate drone.") - message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.") - log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.") - D.shut_down() - - else if (href_list["search_fab"]) - if(dronefab) - return - - for(var/obj/machinery/drone_fabricator/fab in oview(3,src)) - - if(fab.stat & NOPOWER) - continue - - dronefab = fab - to_chat(usr, "Drone fabricator located.") - return - - to_chat(usr, "Unable to locate drone fabricator.") - - else if (href_list["toggle_fab"]) - - if(!dronefab) - return - - if(get_dist(src,dronefab) > 3) - dronefab = null to_chat(usr, "Unable to locate drone fabricator.") - return - dronefab.produce_drones = !dronefab.produce_drones - to_chat(usr, "You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.") + if("toggle_fab") + if(!dronefab) + return - src.updateUsrDialog() \ No newline at end of file + if(get_dist(src,dronefab) > 3) + dronefab = null + to_chat(usr, "Unable to locate drone fabricator.") + return + + dronefab.produce_drones = !dronefab.produce_drones + to_chat(usr, "You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.") diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm index e5d50d5824..bb84ed3ce3 100644 --- a/code/modules/mob/living/silicon/subystems.dm +++ b/code/modules/mob/living/silicon/subystems.dm @@ -1,11 +1,11 @@ /mob/living/silicon var/register_alarms = 1 - var/datum/nano_module/alarm_monitor/all/alarm_monitor - var/datum/nano_module/atmos_control/atmos_control + var/datum/tgui_module/alarm_monitor/all/robot/alarm_monitor + var/datum/tgui_module/atmos_control/robot/atmos_control var/datum/tgui_module/crew_monitor/robot/crew_monitor var/datum/nano_module/law_manager/law_manager - var/datum/nano_module/power_monitor/power_monitor - var/datum/nano_module/rcon/rcon + var/datum/tgui_module/power_monitor/robot/power_monitor + var/datum/tgui_module/rcon/robot/rcon /mob/living/silicon var/list/silicon_subsystems = list( @@ -49,7 +49,7 @@ set name = "Alarm Monitor" set category = "Subystems" - alarm_monitor.ui_interact(usr, state = self_state) + alarm_monitor.tgui_interact(usr) /******************** * Atmos Control * @@ -58,7 +58,7 @@ set category = "Subystems" set name = "Atmospherics Control" - atmos_control.ui_interact(usr, state = self_state) + atmos_control.tgui_interact(usr) /******************** * Crew Monitor * @@ -85,7 +85,7 @@ set category = "Subystems" set name = "Power Monitor" - power_monitor.ui_interact(usr, state = self_state) + power_monitor.tgui_interact(usr) /************ * RCON * @@ -94,4 +94,4 @@ set category = "Subystems" set name = "RCON" - rcon.ui_interact(usr, state = self_state) + rcon.tgui_interact(usr) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index e6fd555d8d..94c69622c4 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -582,7 +582,6 @@ // Do the initial caching of the player's body icons. new_character.force_update_limbs() new_character.update_icons_body() - new_character.update_eyes() new_character.key = key //Manually transfer the key to log them in diff --git a/code/modules/modular_computers/NTNet/NTNet_relay.dm b/code/modules/modular_computers/NTNet/NTNet_relay.dm index 85daf5d03d..9e39fe8e2e 100644 --- a/code/modules/modular_computers/NTNet/NTNet_relay.dm +++ b/code/modules/modular_computers/NTNet/NTNet_relay.dm @@ -57,41 +57,43 @@ ntnet_global.add_log("Quantum relay switched from overload recovery mode to normal operation mode.") ..() -/obj/machinery/ntnet_relay/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) +/obj/machinery/ntnet_relay/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "NTNetRelay", src) + ui.open() + +/obj/machinery/ntnet_relay/tgui_data(mob/user) var/list/data = list() data["enabled"] = enabled data["dos_capacity"] = dos_capacity data["dos_overload"] = dos_overload data["dos_crashed"] = dos_failure - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "ntnet_relay.tmpl", "NTNet Quantum Relay", 500, 300, state = state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data /obj/machinery/ntnet_relay/attack_hand(var/mob/living/user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/ntnet_relay/Topic(href, href_list) +/obj/machinery/ntnet_relay/tgui_act(action, params) if(..()) - return 1 - if(href_list["restart"]) - dos_overload = 0 - dos_failure = 0 - update_icon() - ntnet_global.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.") - return 1 - else if(href_list["toggle"]) - enabled = !enabled - ntnet_global.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].") - update_icon() - return 1 - else if(href_list["purge"]) - ntnet_global.banned_nids.Cut() - ntnet_global.add_log("Manual override: Network blacklist cleared.") - return 1 + return TRUE + + switch(action) + if("restart") + dos_overload = 0 + dos_failure = 0 + update_icon() + ntnet_global.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.") + . = TRUE + if("toggle") + enabled = !enabled + ntnet_global.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].") + update_icon() + . = TRUE + if("purge") + ntnet_global.banned_nids.Cut() + ntnet_global.add_log("Manual override: Network blacklist cleared.") + . = TRUE /obj/machinery/ntnet_relay/New() ..() diff --git a/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm index 8c03238bff..d7f13fcbc5 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/alarm_monitor filename = "alarmmonitoreng" filedesc = "Alarm Monitoring (Engineering)" - nanomodule_path = /datum/nano_module/alarm_monitor/engineering + tguimodule_path = /datum/tgui_module/alarm_monitor/engineering/ntos ui_header = "alarm_green.gif" program_icon_state = "alert-green" program_key_state = "atmos_key" @@ -15,8 +15,8 @@ /datum/computer_file/program/alarm_monitor/process_tick() ..() - var/datum/nano_module/alarm_monitor/NMA = NM - if(istype(NMA) && NMA.has_major_alarms()) + var/datum/tgui_module/alarm_monitor/TMA = TM + if(istype(TMA) && TMA.has_major_alarms()) if(!has_alert) program_icon_state = "alert-red" ui_header = "alarm_red.gif" @@ -29,112 +29,3 @@ update_computer_icon() has_alert = 0 return 1 - -/datum/nano_module/alarm_monitor - name = "Alarm monitor" - var/list_cameras = 0 // Whether or not to list camera references. A future goal would be to merge this with the enginering/security camera console. Currently really only for AI-use. - var/list/datum/alarm_handler/alarm_handlers // The particular list of alarm handlers this alarm monitor should present to the user. - //available_to_ai = FALSE - -/datum/nano_module/alarm_monitor/New() - ..() - alarm_handlers = list() - -/datum/nano_module/alarm_monitor/all/New() - ..() - alarm_handlers = SSalarm.all_handlers - -/datum/nano_module/alarm_monitor/engineering/New() - ..() - alarm_handlers = list(atmosphere_alarm, fire_alarm, power_alarm) - -/datum/nano_module/alarm_monitor/security/New() - ..() - alarm_handlers = list(camera_alarm, motion_alarm) - -/datum/nano_module/alarm_monitor/proc/register_alarm(var/object, var/procName) - for(var/datum/alarm_handler/AH in alarm_handlers) - AH.register_alarm(object, procName) - -/datum/nano_module/alarm_monitor/proc/unregister_alarm(var/object) - for(var/datum/alarm_handler/AH in alarm_handlers) - AH.unregister_alarm(object) - -/datum/nano_module/alarm_monitor/proc/all_alarms() - var/z = get_z(nano_host()) - var/list/all_alarms = new() - for(var/datum/alarm_handler/AH in alarm_handlers) - all_alarms += AH.visible_alarms(z) - - return all_alarms - -/datum/nano_module/alarm_monitor/proc/major_alarms() - var/z = get_z(nano_host()) - var/list/all_alarms = new() - for(var/datum/alarm_handler/AH in alarm_handlers) - all_alarms += AH.major_alarms(z) - - return all_alarms - -// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise. -/datum/nano_module/alarm_monitor/proc/has_major_alarms() - var/z = get_z(nano_host()) - for(var/datum/alarm_handler/AH in alarm_handlers) - if(AH.has_major_alarms(z)) - return 1 - - return 0 - -/datum/nano_module/alarm_monitor/proc/minor_alarms() - var/z = get_z(nano_host()) - var/list/all_alarms = new() - for(var/datum/alarm_handler/AH in alarm_handlers) - all_alarms += AH.minor_alarms(z) - - return all_alarms - -/datum/nano_module/alarm_monitor/Topic(ref, href_list) - if(..()) - return 1 - if(href_list["switchTo"]) - var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras - if(!C) - return - - usr.switch_to_camera(C) - return 1 - -/datum/nano_module/alarm_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - - var/categories[0] - var/z = get_z(nano_host()) - for(var/datum/alarm_handler/AH in alarm_handlers) - categories[++categories.len] = list("category" = AH.category, "alarms" = list()) - for(var/datum/alarm/A in AH.visible_alarms(z)) - var/cameras[0] - var/lost_sources[0] - - if(isAI(user)) - for(var/obj/machinery/camera/C in A.cameras()) - cameras[++cameras.len] = C.nano_structure() - for(var/datum/alarm_source/AS in A.sources) - if(!AS.source) - lost_sources[++lost_sources.len] = AS.source_name - - categories[categories.len]["alarms"] += list(list( - "name" = sanitize("[A.alarm_name()]" + "[A.max_severity() > 1 ? "(MAJOR)" : ""]"), - "origin_lost" = A.origin == null, - "has_cameras" = cameras.len, - "cameras" = cameras, - "lost_sources" = lost_sources.len ? sanitize(english_list(lost_sources, nothing_text = "", and_text = ", ")) : "")) - data["categories"] = categories - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "alarm_monitor.tmpl", "Alarm Monitoring Console", 800, 800, state = state) - if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI. - ui.auto_update_layout = 1 - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm b/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm index bfcaadee3e..5c25ed8315 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/atmos_control filename = "atmoscontrol" filedesc = "Atmosphere Control" - nanomodule_path = /datum/nano_module/atmos_control + tguimodule_path = /datum/tgui_module/atmos_control/ntos program_icon_state = "atmos_control" program_key_state = "atmos_key" program_menu_icon = "shuffle" @@ -12,96 +12,3 @@ requires_ntnet_feature = NTNET_SYSTEMCONTROL usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE size = 17 - -/datum/nano_module/atmos_control - name = "Atmospherics Control" - var/obj/access = new() - var/emagged = 0 - var/ui_ref - var/list/monitored_alarms = list() - -/datum/nano_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids) - ..() - access.req_access = req_access - access.req_one_access = req_one_access - - if(monitored_alarm_ids) - for(var/obj/machinery/alarm/alarm in machines) - if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids) - monitored_alarms += alarm - // machines may not yet be ordered at this point - monitored_alarms = dd_sortedObjectList(monitored_alarms) - -/datum/nano_module/atmos_control/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["alarm"]) - if(ui_ref) - var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms.len ? monitored_alarms : machines) - if(alarm) - var/datum/topic_state/TS = generate_state(alarm) - alarm.ui_interact(usr, master_ui = ui_ref, state = TS) - return 1 - -/datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - var/alarms[0] - - var/z = get_z(nano_host()) - var/list/map_levels = using_map.get_map_levels(z) - data["map_levels"] = map_levels - - // TODO: Move these to a cache, similar to cameras - for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines)) - if(!monitored_alarms.len && alarm.alarms_hidden) - continue - if(!(alarm.z in map_levels)) - continue - alarms[++alarms.len] = list( - "name" = sanitize(alarm.name), - "ref"= "\ref[alarm]", - "danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm), - "x" = alarm.x, - "y" = alarm.y, - "z" = alarm.z) - data["alarms"] = alarms - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 625, 625, state = state) - if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI. - ui.auto_update_layout = 1 - // adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "atmos_control_map_content.tmpl") - // adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "atmos_control_map_header.tmpl") - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(0) - ui_ref = ui - -/datum/nano_module/atmos_control/proc/generate_state(air_alarm) - var/datum/topic_state/air_alarm/state = new() - state.atmos_control = src - state.air_alarm = air_alarm - return state - -/datum/topic_state/air_alarm - var/datum/nano_module/atmos_control/atmos_control = null - var/obj/machinery/alarm/air_alarm = null - -/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user) - if(has_access(user)) - return STATUS_INTERACTIVE - return STATUS_UPDATE - -/datum/topic_state/air_alarm/href_list(var/mob/user) - var/list/extra_href = list() - extra_href["remote_connection"] = 1 - extra_href["remote_access"] = has_access(user) - - return extra_href - -/datum/topic_state/air_alarm/proc/has_access(var/mob/user) - return user && (isAI(user) || atmos_control.access.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO) || (access_ce in user.GetAccess())) diff --git a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm index b5c086dc26..5df437790b 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/power_monitor filename = "powermonitor" filedesc = "Power Monitoring" - nanomodule_path = /datum/nano_module/power_monitor/ + tguimodule_path = /datum/tgui_module/power_monitor/ntos program_icon_state = "power_monitor" program_key_state = "power_key" program_menu_icon = "battery-3" @@ -15,8 +15,8 @@ /datum/computer_file/program/power_monitor/process_tick() ..() - var/datum/nano_module/power_monitor/NMA = NM - if(istype(NMA) && NMA.has_alarm()) + var/datum/tgui_module/power_monitor/TMA = TM + if(istype(TMA) && TMA.has_alarm()) if(!has_alert) program_icon_state = "power_monitor_warn" ui_header = "power_warn.gif" @@ -28,90 +28,3 @@ ui_header = "power_norm.gif" update_computer_icon() has_alert = 0 - -/datum/nano_module/power_monitor - name = "Power monitor" - var/list/grid_sensors - var/active_sensor = null //name_tag of the currently selected sensor - -/datum/nano_module/power_monitor/New() - ..() - refresh_sensors() - -// Checks whether there is an active alarm, if yes, returns 1, otherwise returns 0. -/datum/nano_module/power_monitor/proc/has_alarm() - for(var/obj/machinery/power/sensor/S in grid_sensors) - if(S.check_grid_warning()) - return 1 - return 0 - -// If PC is not null header template is loaded. Use PC.get_header_data() to get relevant nanoui data from it. All data entries begin with "PC_...." -// In future it may be expanded to other modular computer devices. -/datum/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - - var/list/sensors = list() - // Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading. - var/obj/machinery/power/sensor/focus = null - - var/z = get_z(nano_host()) - var/list/map_levels = using_map.get_map_levels(z) - data["map_levels"] = map_levels - - // Build list of data from sensor readings. - for(var/obj/machinery/power/sensor/S in grid_sensors) - if(!(S.z in map_levels)) - continue - sensors.Add(list(list( - "name" = S.name_tag, - "alarm" = S.check_grid_warning() - ))) - if(S.name_tag == active_sensor) - focus = S - - data["all_sensors"] = sensors - if(focus) - data["focus"] = focus.return_reading_data() - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 500, state = state) - if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI. - ui.auto_update_layout = 1 - // adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "power_monitor_map_content.tmpl") - // adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "power_monitor_map_header.tmpl") - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -// Refreshes list of active sensors kept on this computer. -/datum/nano_module/power_monitor/proc/refresh_sensors() - grid_sensors = list() - var/turf/T = get_turf(nano_host()) - var/list/levels = list() - if(!T) // Safety check - return - if(T) - levels += using_map.get_map_levels(T.z, FALSE) - for(var/obj/machinery/power/sensor/S in machines) - if(T && (S.loc.z == T.z) || (S.loc.z in levels) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels. - if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen! - warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z") - else - grid_sensors += S - -// Allows us to process UI clicks, which are relayed in form of hrefs. -/datum/nano_module/power_monitor/Topic(href, href_list) - if(..()) - return 1 - if( href_list["clear"] ) - active_sensor = null - . = 1 - if( href_list["refresh"] ) - refresh_sensors() - . = 1 - else if( href_list["setsensor"] ) - active_sensor = href_list["setsensor"] - . = 1 diff --git a/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm b/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm index 03f69cd949..ded2e3922f 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/rcon_console filename = "rconconsole" filedesc = "RCON Remote Control" - nanomodule_path = /datum/nano_module/rcon + tguimodule_path = /datum/tgui_module/rcon/ntos program_icon_state = "generic" program_key_state = "rd_key" program_menu_icon = "power" @@ -12,129 +12,3 @@ requires_ntnet_feature = NTNET_SYSTEMCONTROL usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE size = 19 - -/datum/nano_module/rcon - name = "Power RCON" - var/list/known_SMESs = null - var/list/known_breakers = null - // Allows you to hide specific parts of the UI - var/hide_SMES = 0 - var/hide_SMES_details = 0 - var/hide_breakers = 0 - -/datum/nano_module/rcon/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1, var/datum/topic_state/state = default_state) - FindDevices() // Update our devices list - var/list/data = host.initial_data() - - // SMES DATA (simplified view) - var/list/smeslist[0] - for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs) - smeslist.Add(list(list( - "charge" = round(SMES.Percentage()), - "input_set" = SMES.input_attempt, - "input_val" = round(SMES.input_level/1000, 0.1), - "output_set" = SMES.output_attempt, - "output_val" = round(SMES.output_level/1000, 0.1), - "output_load" = round(SMES.output_used/1000, 0.1), - "RCON_tag" = SMES.RCon_tag - ))) - - data["smes_info"] = sortByKey(smeslist, "RCON_tag") - - // BREAKER DATA (simplified view) - var/list/breakerlist[0] - for(var/obj/machinery/power/breakerbox/BR in known_breakers) - breakerlist.Add(list(list( - "RCON_tag" = BR.RCon_tag, - "enabled" = BR.on - ))) - data["breaker_info"] = breakerlist - data["hide_smes"] = hide_SMES - data["hide_smes_details"] = hide_SMES_details - data["hide_breakers"] = hide_breakers - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "rcon.tmpl", "RCON Console", 600, 400, state = state) - if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI. - ui.auto_update_layout = 1 - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -// Proc: Topic() -// Parameters: 2 (href, href_list - allows us to process UI clicks) -// Description: Allows us to process UI clicks, which are relayed in form of hrefs. -/datum/nano_module/rcon/Topic(href, href_list) - if(..()) - return - - if(href_list["smes_in_toggle"]) - var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_toggle"]) - if(SMES) - SMES.toggle_input() - if(href_list["smes_out_toggle"]) - var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_toggle"]) - if(SMES) - SMES.toggle_output() - if(href_list["smes_in_set"]) - var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_set"]) - if(SMES) - var/inputset = (input(usr, "Enter new input level (0-[SMES.input_level_max/1000] kW)", "SMES Input Power Control", SMES.input_level/1000) as num) * 1000 - SMES.set_input(inputset) - if(href_list["smes_out_set"]) - var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_set"]) - if(SMES) - var/outputset = (input(usr, "Enter new output level (0-[SMES.output_level_max/1000] kW)", "SMES Output Power Control", SMES.output_level/1000) as num) * 1000 - SMES.set_output(outputset) - - if(href_list["toggle_breaker"]) - var/obj/machinery/power/breakerbox/toggle = null - for(var/obj/machinery/power/breakerbox/breaker in known_breakers) - if(breaker.RCon_tag == href_list["toggle_breaker"]) - toggle = breaker - if(toggle) - if(toggle.update_locked) - to_chat(usr, "The breaker box was recently toggled. Please wait before toggling it again.") - else - toggle.auto_toggle() - if(href_list["hide_smes"]) - hide_SMES = !hide_SMES - if(href_list["hide_smes_details"]) - hide_SMES_details = !hide_SMES_details - if(href_list["hide_breakers"]) - hide_breakers = !hide_breakers - - -// Proc: GetSMESByTag() -// Parameters: 1 (tag - RCON tag of SMES we want to look up) -// Description: Looks up and returns SMES which has matching RCON tag -/datum/nano_module/rcon/proc/GetSMESByTag(var/tag) - if(!tag) - return - - for(var/obj/machinery/power/smes/buildable/S in known_SMESs) - if(S.RCon_tag == tag) - return S - -// Proc: FindDevices() -// Parameters: None -// Description: Refreshes local list of known devices. -/datum/nano_module/rcon/proc/FindDevices() - known_SMESs = new /list() - - var/z = get_z(nano_host()) - var/list/map_levels = using_map.get_map_levels(z) - - for(var/obj/machinery/power/smes/buildable/SMES in GLOB.smeses) - if(!(SMES.z in map_levels)) - continue - if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon) - known_SMESs.Add(SMES) - - known_breakers = new /list() - for(var/obj/machinery/power/breakerbox/breaker in machines) - if(!(breaker.z in map_levels)) - continue - if(breaker.RCon_tag != "NO_TAG") - known_breakers.Add(breaker) diff --git a/code/modules/modular_computers/file_system/programs/engineering/shutoff_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/shutoff_monitor.dm index c46bb9c667..e87991041e 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/shutoff_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/shutoff_monitor.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/shutoff_monitor filename = "shutoffmonitor" filedesc = "Shutoff Valve Monitoring" - nanomodule_path = /datum/nano_module/shutoff_monitor + tguimodule_path = /datum/tgui_module/shutoff_monitor/ntos program_icon_state = "atmos_control" program_key_state = "atmos_key" program_menu_icon = "wrench" @@ -11,53 +11,3 @@ network_destination = "shutoff valve control computer" size = 5 var/has_alert = 0 - -/datum/nano_module/shutoff_monitor - name = "Shutoff Valve Monitoring" - -/datum/nano_module/shutoff_monitor/Topic(ref, href_list) - if(..()) - return 1 - - if(href_list["toggle_enable"]) - var/obj/machinery/atmospherics/valve/shutoff/S = locate(href_list["toggle_enable"]) - if(!istype(S)) - return 0 - S.close_on_leaks = !S.close_on_leaks - return 1 - - if(href_list["toggle_open"]) - var/obj/machinery/atmospherics/valve/shutoff/S = locate(href_list["toggle_open"]) - if(!istype(S)) - return 0 - if(S.open) - S.close() - else - S.open() - return 1 - -/datum/nano_module/shutoff_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - var/list/valves = list() - - for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves) - valves.Add(list(list( - "name" = S.name, - "enabled" = S.close_on_leaks, - "open" = S.open, - "x" = S.x, - "y" = S.y, - "z" = S.z, - "ref" = "\ref[S]" - ))) - - data["valves"] = valves - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "shutoff_monitor.tmpl", "Shutoff Valve Monitoring", 627, 700, state = state) - if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI. - ui.auto_update_layout = 1 - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm index 421bb65047..9c3cabd3f7 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/supermatter_monitor filename = "supmon" filedesc = "Supermatter Monitoring" - nanomodule_path = /datum/nano_module/supermatter_monitor/ + tguimodule_path = /datum/tgui_module/supermatter_monitor/ntos program_icon_state = "smmon_0" program_key_state = "tech_key" program_menu_icon = "notice" @@ -15,119 +15,11 @@ /datum/computer_file/program/supermatter_monitor/process_tick() ..() - var/datum/nano_module/supermatter_monitor/NMS = NM - var/new_status = istype(NMS) ? NMS.get_status() : 0 + var/datum/tgui_module/supermatter_monitor/TMS = TM + var/new_status = istype(TMS) ? TMS.get_status() : 0 if(last_status != new_status) last_status = new_status ui_header = "smmon_[last_status].gif" program_icon_state = "smmon_[last_status]" if(istype(computer)) computer.update_icon() - -/datum/nano_module/supermatter_monitor - name = "Supermatter monitor" - var/list/supermatters - var/obj/machinery/power/supermatter/active = null // Currently selected supermatter crystal. - -/datum/nano_module/supermatter_monitor/Destroy() - . = ..() - active = null - supermatters = null - -/datum/nano_module/supermatter_monitor/New() - ..() - refresh() - -// Refreshes list of active supermatter crystals -/datum/nano_module/supermatter_monitor/proc/refresh() - supermatters = list() - var/z = get_z(nano_host()) - if(!z) - return - var/valid_z_levels = using_map.get_map_levels(z) - for(var/obj/machinery/power/supermatter/S in machines) - // Delaminating, not within coverage, not on a tile. - if(S.grav_pulling || S.exploded || !(S.z in valid_z_levels) || !istype(S.loc, /turf/)) - continue - supermatters.Add(S) - - if(!(active in supermatters)) - active = null - -/datum/nano_module/supermatter_monitor/proc/get_status() - . = SUPERMATTER_INACTIVE - for(var/obj/machinery/power/supermatter/S in supermatters) - . = max(., S.get_status()) - -/datum/nano_module/supermatter_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - - if(istype(active)) - var/turf/T = get_turf(active) - if(!T) - active = null - return - var/datum/gas_mixture/air = T.return_air() - if(!istype(air)) - active = null - return - - data["active"] = 1 - data["SM_integrity"] = active.get_integrity() - data["SM_power"] = active.power - data["SM_ambienttemp"] = air.temperature - data["SM_ambientpressure"] = air.return_pressure() - data["SM_EPR"] = active.get_epr() - //data["SM_EPR"] = active.get_epr() - if(air.total_moles) - data["SM_gas_O2"] = round(100*air.gas["oxygen"]/air.total_moles,0.01) - data["SM_gas_CO2"] = round(100*air.gas["carbon_dioxide"]/air.total_moles,0.01) - data["SM_gas_N2"] = round(100*air.gas["nitrogen"]/air.total_moles,0.01) - data["SM_gas_PH"] = round(100*air.gas["phoron"]/air.total_moles,0.01) - data["SM_gas_N2O"] = round(100*air.gas["sleeping_agent"]/air.total_moles,0.01) - else - data["SM_gas_O2"] = 0 - data["SM_gas_CO2"] = 0 - data["SM_gas_N2"] = 0 - data["SM_gas_PH"] = 0 - data["SM_gas_N2O"] = 0 - else - var/list/SMS = list() - for(var/obj/machinery/power/supermatter/S in supermatters) - var/area/A = get_area(S) - if(!A) - continue - - SMS.Add(list(list( - "area_name" = A.name, - "integrity" = S.get_integrity(), - "uid" = S.uid - ))) - - data["active"] = 0 - data["supermatters"] = SMS - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "supermatter_monitor.tmpl", "Supermatter Monitoring", 600, 400, state = state) - if(host.update_layout()) - ui.auto_update_layout = 1 - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/datum/nano_module/supermatter_monitor/Topic(href, href_list) - if(..()) - return 1 - if( href_list["clear"] ) - active = null - return 1 - if( href_list["refresh"] ) - refresh() - return 1 - if( href_list["set"] ) - var/newuid = text2num(href_list["set"]) - for(var/obj/machinery/power/supermatter/S in supermatters) - if(S.uid == newuid) - active = S - return 1 \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm b/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm index 2254cc1dae..a833573be6 100644 --- a/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm @@ -2,5 +2,5 @@ filename = "alarmmonitorsec" filedesc = "Alarm Monitoring (Security)" extended_desc = "This program provides visual interface for the security alarm system." - nanomodule_path = /datum/nano_module/alarm_monitor/security + tguimodule_path = /datum/tgui_module/alarm_monitor/security/ntos required_access = access_security \ No newline at end of file diff --git a/code/modules/nifsoft/software/06_screens.dm b/code/modules/nifsoft/software/06_screens.dm index 64a1faac5c..8dadc88192 100644 --- a/code/modules/nifsoft/software/06_screens.dm +++ b/code/modules/nifsoft/software/06_screens.dm @@ -34,19 +34,19 @@ access = access_engine cost = 625 p_drain = 0.025 - var/datum/nano_module/alarm_monitor/engineering/arscreen + var/datum/tgui_module/alarm_monitor/engineering/nif/tgarscreen New() ..() - arscreen = new(nif) + tgarscreen = new(nif) Destroy() - QDEL_NULL(arscreen) + QDEL_NULL(tgarscreen) return ..() activate() if((. = ..())) - arscreen.ui_interact(nif.human,"main",null,1,nif_state) + tgarscreen.tgui_interact(nif.human) return TRUE deactivate() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 1dd8e6a133..90ba2d1a36 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -27,9 +27,19 @@ GLOBAL_LIST_EMPTY(apcs) #define APC_UPOVERLAY_LOCKED 4096 #define APC_UPOVERLAY_OPERATING 8192 - #define APC_UPDATE_ICON_COOLDOWN 100 // 10 seconds +// main_status var +#define APC_EXTERNAL_POWER_NOTCONNECTED 0 +#define APC_EXTERNAL_POWER_NOENERGY 1 +#define APC_EXTERNAL_POWER_GOOD 2 + +// has_electronics var +#define APC_HAS_ELECTRONICS_NONE 0 +#define APC_HAS_ELECTRONICS_WIRED 1 +#define APC_HAS_ELECTRONICS_SECURED 2 + + // the Area Power Controller (APC), formerly Power Distribution Unit (PDU) // one per area, needs wire conection to power network through a terminal @@ -101,13 +111,13 @@ GLOBAL_LIST_EMPTY(apcs) var/lastused_environ = 0 var/lastused_charging = 0 var/lastused_total = 0 - var/main_status = 0 + var/main_status = APC_EXTERNAL_POWER_NOTCONNECTED var/mob/living/silicon/ai/hacker = null // Malfunction var. If set AI hacked the APC and has full control. var/wiresexposed = 0 powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :( var/debug= 0 var/autoflag= 0 // 0 = off, 1= eqp and lights off, 2 = eqp off, 3 = all on. - var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver + var/has_electronics = APC_HAS_ELECTRONICS_NONE // 0 - none, 1 - plugged in, 2 - secured by screwdriver var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment var/longtermpower = 10 var/datum/wires/apc/wires = null @@ -131,7 +141,7 @@ GLOBAL_LIST_EMPTY(apcs) var/last_nightshift_switch = 0 /obj/machinery/power/apc/updateDialog() - if (stat & (BROKEN|MAINT)) + if(stat & (BROKEN|MAINT)) return ..() @@ -175,12 +185,12 @@ GLOBAL_LIST_EMPTY(apcs) // offset 24 pixels in direction of dir // this allows the APC to be embedded in a wall, yet still inside an area - if (building) + if(building) set_dir(ndir) - pixel_x = (src.dir & 3)? 0 : (src.dir == 4 ? 26 : -26) //VOREStation Edit -> 24 to 26 - pixel_y = (src.dir & 3)? (src.dir ==1 ? 26 : -26) : 0 //VOREStation Edit -> 24 to 26 - if (building==0) + pixel_x = (dir & 3)? 0 : (dir == 4 ? 26 : -26) //VOREStation Edit -> 24 to 26 + pixel_y = (dir & 3)? (dir ==1 ? 26 : -26) : 0 //VOREStation Edit -> 24 to 26 + if(building==0) init() else area = get_area(src) @@ -189,11 +199,11 @@ GLOBAL_LIST_EMPTY(apcs) operating = 0 name = "[area.name] APC" stat |= MAINT - src.update_icon() + update_icon() /obj/machinery/power/apc/Destroy() GLOB.apcs -= src - src.update() + update() area.apc = null area.power_light = 0 area.power_equip = 0 @@ -216,11 +226,11 @@ GLOBAL_LIST_EMPTY(apcs) // APCs are pixel-shifted, so they need to be updated. /obj/machinery/power/apc/set_dir(new_dir) ..() - pixel_x = (src.dir & 3)? 0 : (src.dir == 4 ? 24 : -24) - pixel_y = (src.dir & 3)? (src.dir ==1 ? 24 : -24) : 0 + pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) + pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 if(terminal) terminal.disconnect_from_network() - terminal.set_dir(src.dir) // Terminal has same dir as master + terminal.set_dir(dir) // Terminal has same dir as master terminal.connect_to_network() // Refresh the network the terminal is connected to. return @@ -230,25 +240,25 @@ GLOBAL_LIST_EMPTY(apcs) /obj/machinery/power/apc/proc/make_terminal() // create a terminal object at the same position as original turf loc // wires will attach to this - terminal = new/obj/machinery/power/terminal(src.loc) + terminal = new/obj/machinery/power/terminal(loc) terminal.set_dir(dir) terminal.master = src /obj/machinery/power/apc/proc/init() - has_electronics = 2 //installed and secured + has_electronics = APC_HAS_ELECTRONICS_SECURED //installed and secured // is starting with a power cell installed, create it and set its charge level if(cell_type) - src.cell = new cell_type(src) + cell = new cell_type(src) cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value) - var/area/A = src.loc.loc + var/area/A = loc.loc //if area isn't specified use current - if(isarea(A) && src.areastring == null) - src.area = A + if(isarea(A) && !areastring) + area = A name = "\improper [area.name] APC" else - src.area = get_area_name(areastring) + area = get_area_name(areastring) name = "\improper [area.name] APC" area.apc = src @@ -260,7 +270,7 @@ GLOBAL_LIST_EMPTY(apcs) make_terminal() spawn(5) - src.update() + update() /obj/machinery/power/apc/examine(mob/user) . = ..() @@ -271,17 +281,17 @@ GLOBAL_LIST_EMPTY(apcs) else if(opened) if(has_electronics && terminal) . += "The cover is [opened == 2 ? "removed" : "open"] and [ cell ? "a power cell is installed" : "the power cell is missing"]." - else if (!has_electronics && terminal) + else if(!has_electronics && terminal) . += "The frame is wired, but the electronics are missing." - else if (has_electronics && !terminal) + else if(has_electronics && !terminal) . += "The electronics are installed, but not wired." - else /* if (!has_electronics && !terminal) */ + else /* if(!has_electronics && !terminal) */ . += "It's just an empty metal frame." else - if (wiresexposed) + if(wiresexposed) . += "The cover is closed and the wires are exposed." - else if ((locked && emagged) || hacker) //Some things can cause locked && emagged. Malf AI causes hacker. + else if((locked && emagged) || hacker) //Some things can cause locked && emagged. Malf AI causes hacker. . += "The cover is closed, but the panel is unresponsive." else if(!locked && emagged) //Normal emag does this. . += "The cover is closed, but the panel is flashing an error." @@ -292,7 +302,7 @@ GLOBAL_LIST_EMPTY(apcs) // update the APC icon to show the three base states // also add overlays for indicator lights /obj/machinery/power/apc/update_icon() - if (!status_overlays) + if(!status_overlays) status_overlays = 1 status_overlays_lock = new status_overlays_charging = new @@ -424,7 +434,7 @@ GLOBAL_LIST_EMPTY(apcs) else if(charging == 2) update_overlay |= APC_UPOVERLAY_CHARGEING2 - if (!equipment) + if(!equipment) update_overlay |= APC_UPOVERLAY_EQUIPMENT0 else if(equipment == 1) update_overlay |= APC_UPOVERLAY_EQUIPMENT1 @@ -468,35 +478,34 @@ GLOBAL_LIST_EMPTY(apcs) //attack with an item - open/close cover, insert cell, or (un)lock interface /obj/machinery/power/apc/attackby(obj/item/W, mob/user) - - if (istype(user, /mob/living/silicon) && get_dist(src,user)>1) - return src.attack_hand(user) - src.add_fingerprint(user) - if (W.is_crowbar() && opened) - if (has_electronics==1) - if (terminal) + if(issilicon(user) && get_dist(src,user) > 1) + return attack_hand(user) + add_fingerprint(user) + if(W.is_crowbar() && opened) + if(has_electronics == APC_HAS_ELECTRONICS_WIRED) + if(terminal) to_chat(user, "Disconnect the wires first.") return playsound(src, W.usesound, 50, 1) to_chat(user, "You begin to remove the power control board...") //lpeters - fixed grammar issues //Ner - grrrrrr if(do_after(user, 50 * W.toolspeed)) - if (has_electronics==1) - has_electronics = 0 - if ((stat & BROKEN)) + if(has_electronics == APC_HAS_ELECTRONICS_WIRED) + has_electronics = APC_HAS_ELECTRONICS_NONE + if((stat & BROKEN)) user.visible_message(\ - "[user.name] has broken the charred power control board inside [src.name]!",\ + "[user.name] has broken the charred power control board inside [name]!",\ "You broke the charred power control board and remove the remains.", "You hear a crack!") //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0 else user.visible_message(\ - "[user.name] has removed the power control board from [src.name]!",\ + "[user.name] has removed the power control board from [name]!",\ "You remove the power control board.") new /obj/item/weapon/module/power_control(loc) - else if (opened!=2) //cover isn't removed + else if(opened != 2) //cover isn't removed opened = 0 update_icon() - else if (W.is_crowbar() && !(stat & BROKEN) ) + else if(W.is_crowbar() && !(stat & BROKEN) ) if(coverlocked && !(stat & MAINT)) to_chat(user, "The cover is locked and cannot be opened.") return @@ -505,9 +514,9 @@ GLOBAL_LIST_EMPTY(apcs) update_icon() else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside if(cell) - to_chat(user, "The [src.name] already has a power cell installed.") + to_chat(user, "The [name] already has a power cell installed.") return - if (stat & MAINT) + if(stat & MAINT) to_chat(user, "You need to install the wiring and electronics first.") return if(W.w_class != ITEMSIZE_NORMAL) @@ -518,27 +527,27 @@ GLOBAL_LIST_EMPTY(apcs) W.forceMove(src) cell = W user.visible_message(\ - "[user.name] has inserted a power cell into [src.name]!",\ + "[user.name] has inserted a power cell into [name]!",\ "You insert the power cell.") chargecount = 0 update_icon() else if (W.is_screwdriver()) // haxing if(opened) - if (cell) + if(cell) to_chat(user, "Remove the power cell first.") return else - if (has_electronics==1 && terminal) - has_electronics = 2 + if(has_electronics == APC_HAS_ELECTRONICS_WIRED && terminal) + has_electronics = APC_HAS_ELECTRONICS_SECURED stat &= ~MAINT playsound(src, W.usesound, 50, 1) to_chat(user, "You screw the circuit electronics into place.") - else if (has_electronics==2) - has_electronics = 1 + else if(has_electronics == APC_HAS_ELECTRONICS_SECURED) + has_electronics = APC_HAS_ELECTRONICS_WIRED stat |= MAINT playsound(src, W.usesound, 50, 1) to_chat(user, "You unfasten the electronics.") - else /* has_electronics==0 */ + else /* has_electronics == APC_HAS_ELECTRONICS_NONE */ to_chat(user, "There is nothing to secure.") return update_icon() @@ -548,10 +557,10 @@ GLOBAL_LIST_EMPTY(apcs) playsound(src, W.usesound, 50, 1) update_icon() - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card - togglelock() + else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card + togglelock(user) - else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics!=2) + else if(istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED) var/turf/T = loc if(istype(T) && !T.is_plating()) to_chat(user, "You must remove the floor plating in front of the APC first.") @@ -564,9 +573,9 @@ GLOBAL_LIST_EMPTY(apcs) "You start adding cables to the APC frame...") playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, 20)) - if (C.amount >= 10 && !terminal && opened && has_electronics != 2) + if(C.amount >= 10 && !terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED) var/obj/structure/cable/N = T.get_cable_node() - if (prob(50) && electrocute_mob(usr, N, N)) + if(prob(50) && electrocute_mob(usr, N, N)) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) s.start() @@ -578,7 +587,7 @@ GLOBAL_LIST_EMPTY(apcs) "You add cables to the APC frame.") make_terminal() terminal.connect_to_network() - else if (W.is_wirecutter() && terminal && opened && has_electronics!=2) + else if(W.is_wirecutter() && terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED) var/turf/T = loc if(istype(T) && !T.is_plating()) to_chat(user, "You must remove the floor plating in front of the APC first.") @@ -587,8 +596,8 @@ GLOBAL_LIST_EMPTY(apcs) "You begin to cut the cables...") playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, 50 * W.toolspeed)) - if(terminal && opened && has_electronics!=2) - if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal)) + if(terminal && opened && has_electronics != APC_HAS_ELECTRONICS_SECURED) + if(prob(50) && electrocute_mob(usr, terminal.powernet, terminal)) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) s.start() @@ -597,22 +606,22 @@ GLOBAL_LIST_EMPTY(apcs) new /obj/item/stack/cable_coil(loc,10) to_chat(user, "You cut the cables and dismantle the power terminal.") qdel(terminal) - else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN))) + else if(istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics == APC_HAS_ELECTRONICS_NONE && !((stat & BROKEN))) user.visible_message("[user.name] inserts the power control board into [src].", \ "You start to insert the power control board into the frame...") playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, 10)) - if(has_electronics==0) - has_electronics = 1 + if(has_electronics == APC_HAS_ELECTRONICS_NONE) + has_electronics = APC_HAS_ELECTRONICS_WIRED reboot() to_chat(user, "You place the power control board inside the frame.") qdel(W) - else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN))) + else if(istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics == APC_HAS_ELECTRONICS_NONE && ((stat & BROKEN))) to_chat(user, "The [src] is too broken for that. Repair it first.") return - else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal) + else if(istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics == APC_HAS_ELECTRONICS_NONE && !terminal) var/obj/item/weapon/weldingtool/WT = W - if (WT.get_fuel() < 3) + if(WT.get_fuel() < 3) to_chat(user, "You need more welding fuel to complete this task.") return user.visible_message("[user.name] begins cutting apart [src] with the [WT.name].", \ @@ -621,7 +630,7 @@ GLOBAL_LIST_EMPTY(apcs) playsound(src, WT.usesound, 25, 1) if(do_after(user, 50 * WT.toolspeed)) if(!src || !WT.remove_fuel(3, user)) return - if (emagged || (stat & BROKEN) || opened==2) + if(emagged || (stat & BROKEN) || opened==2) new /obj/item/stack/material/steel(loc) user.visible_message(\ "[src] has been cut apart by [user.name] with the [WT.name].",\ @@ -635,8 +644,8 @@ GLOBAL_LIST_EMPTY(apcs) "You hear welding.") qdel(src) return - else if (opened && ((stat & BROKEN) || hacker || emagged)) - if (istype(W, /obj/item/frame/apc) && (stat & BROKEN)) + else if(opened && ((stat & BROKEN) || hacker || emagged)) + if(istype(W, /obj/item/frame/apc) && (stat & BROKEN)) if(cell) to_chat(user, "You need to remove the power cell first.") return @@ -648,10 +657,10 @@ GLOBAL_LIST_EMPTY(apcs) qdel(W) stat &= ~BROKEN reboot() - if (opened==2) + if(opened==2) opened = 1 update_icon() - else if (istype(W, /obj/item/device/multitool) && (hacker || emagged)) + else if(istype(W, /obj/item/device/multitool) && (hacker || emagged)) if(cell) to_chat(user, "You need to remove the power cell first.") return @@ -663,12 +672,12 @@ GLOBAL_LIST_EMPTY(apcs) playsound(src, 'sound/machines/chime.ogg', 25, 1) reboot() else - if ((stat & BROKEN) \ + if((stat & BROKEN) \ && !opened \ && W.force >= 5 \ && W.w_class >= ITEMSIZE_SMALL ) - user.visible_message("The [src.name] has been hit with the [W.name] by [user.name]!", \ - "You hit the [src.name] with your [W.name]!", \ + user.visible_message("The [name] has been hit with the [W.name] by [user.name]!", \ + "You hit the [name] with your [W.name]!", \ "You hear a bang!") if(prob(20)) opened = 2 @@ -677,12 +686,12 @@ GLOBAL_LIST_EMPTY(apcs) "You hear a bang!") update_icon() else - if (istype(user, /mob/living/silicon)) - return src.attack_hand(user) - if (!opened && wiresexposed && (istype(W, /obj/item/device/multitool) || W.is_wirecutter() || istype(W, /obj/item/device/assembly/signaler))) - return src.attack_hand(user) + if(istype(user, /mob/living/silicon)) + return attack_hand(user) + if(!opened && wiresexposed && (istype(W, /obj/item/device/multitool) || W.is_wirecutter() || istype(W, /obj/item/device/assembly/signaler))) + return attack_hand(user) //Placeholder until someone can do take_damage() for APCs or something. - to_chat(user, "The [src.name] looks too sturdy to bash open with \the [W.name].") + to_chat(user, "The [name] looks too sturdy to bash open with \the [W.name].") // attack with hand - remove cell (if cover open) or interact with the APC @@ -698,7 +707,7 @@ GLOBAL_LIST_EMPTY(apcs) else if(hacker) to_chat(user, "Access denied.") else - if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN)) + if(allowed(user) && !wires.is_cut(WIRE_IDSCAN)) locked = !locked to_chat(user, "You [ locked ? "lock" : "unlock"] the APC interface.") update_icon() @@ -707,10 +716,10 @@ GLOBAL_LIST_EMPTY(apcs) /obj/machinery/power/apc/AltClick(mob/user) ..() - togglelock() + togglelock(user) /obj/machinery/power/apc/emag_act(var/remaining_charges, var/mob/user) - if (!(emagged || hacker)) // trying to unlock with an emag card + if(!(emagged || hacker)) // trying to unlock with an emag card if(opened) to_chat(user, "You must close the cover to do that.") else if(wiresexposed) @@ -719,7 +728,7 @@ GLOBAL_LIST_EMPTY(apcs) to_chat(user, "The [src] isn't working.") else flick("apc-spark", src) - if (do_after(user,6)) + if(do_after(user,6)) emagged = 1 locked = 0 to_chat(user, "You emag the APC interface.") @@ -733,11 +742,9 @@ GLOBAL_LIST_EMPTY(apcs) update_icon() /obj/machinery/power/apc/attack_hand(mob/user) -// if (!can_use(user)) This already gets called in interact() and in topic() -// return if(!user) return - src.add_fingerprint(user) + add_fingerprint(user) //Human mob special interaction goes here. if(istype(user,/mob/living/carbon/human)) @@ -745,20 +752,20 @@ GLOBAL_LIST_EMPTY(apcs) if(H.species.can_shred(H)) user.setClickCooldown(user.get_attack_speed()) - user.visible_message("[user.name] slashes at the [src.name]!", "You slash at the [src.name]!") + user.visible_message("[user.name] slashes at the [name]!", "You slash at the [name]!") playsound(src, 'sound/weapons/slash.ogg', 100, 1) var/allcut = wires.is_all_cut() if(beenhit >= pick(3, 4) && wiresexposed != 1) wiresexposed = 1 - src.update_icon() - src.visible_message("The [src.name]'s cover flies open, exposing the wires!") + update_icon() + visible_message("The [name]'s cover flies open, exposing the wires!") else if(wiresexposed == 1 && allcut == 0) wires.cut_all() - src.update_icon() - src.visible_message("The [src.name]'s wires are shredded!") + update_icon() + visible_message("The [name]'s wires are shredded!") else beenhit += 1 return @@ -769,16 +776,21 @@ GLOBAL_LIST_EMPTY(apcs) cell.add_fingerprint(user) cell.update_icon() - src.cell = null - user.visible_message("[user.name] removes the power cell from [src.name]!",\ + cell = null + user.visible_message("[user.name] removes the power cell from [name]!",\ "You remove the power cell.") charging = 0 - src.update_icon() + update_icon() return if(stat & (BROKEN|MAINT)) return // do APC interaction - src.interact(user) + interact(user) + +/obj/machinery/power/apc/attack_ghost(mob/user) + if(panel_open) + return wires.Interact(user) + return tgui_interact(user) /obj/machinery/power/apc/interact(mob/user) if(!user) @@ -788,15 +800,18 @@ GLOBAL_LIST_EMPTY(apcs) wires.Interact(user) return //The panel is visibly dark when the wires are exposed, so we shouldn't be able to interact with it. - return ui_interact(user) + return tgui_interact(user) +/obj/machinery/power/apc/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "APC", name) // 510, 460 + ui.open() -/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(!user) - return - +/obj/machinery/power/apc/tgui_data(mob/user) var/list/data = list( "locked" = locked, + "normallyLocked" = locked, "emagged" = emagged, "isOperating" = operating, "externalPower" = main_status, @@ -808,7 +823,7 @@ GLOBAL_LIST_EMPTY(apcs) "failTime" = failure_timer * 2, "gridCheck" = grid_check, "coverLocked" = coverlocked, - "siliconUser" = issilicon(user) || isobserver(user), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate. + "siliconUser" = issilicon(user) || (isobserver(user) && is_admin(user)), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate. "emergencyLights" = !emergency_lights, "nightshiftLights" = nightshift_lights, "nightshiftSetting" = nightshift_setting, @@ -847,18 +862,7 @@ GLOBAL_LIST_EMPTY(apcs) ) ) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 490 : 465) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data /obj/machinery/power/apc/proc/report() return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" @@ -868,23 +872,23 @@ GLOBAL_LIST_EMPTY(apcs) area.power_light = (lighting >= POWERCHAN_ON) area.power_equip = (equipment >= POWERCHAN_ON) area.power_environ = (environ >= POWERCHAN_ON) -// if (area.name == "AI Chamber") +// if(area.name == "AI Chamber") // spawn(10) // to_world(" [area.name] [area.power_equip]") else area.power_light = 0 area.power_equip = 0 area.power_environ = 0 -// if (area.name == "AI Chamber") +// if(area.name == "AI Chamber") // to_world("[area.power_equip]") area.power_change() /obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic() if(!user.client) return 0 - if(isobserver(user) && is_admin(user) ) //This is to allow nanoUI interaction by ghost admins. + if(isobserver(user) && is_admin(user)) //This is to allow nanoUI interaction by ghost admins. return 1 - if (user.stat) + if(user.stat) return 0 if(inoperable()) return 0 @@ -897,7 +901,7 @@ GLOBAL_LIST_EMPTY(apcs) to_chat(user, "You must stand to use [src]!") return 0 autoflag = 5 - if (istype(user, /mob/living/silicon)) + if(istype(user, /mob/living/silicon)) var/permit = 0 // Malfunction variable. If AI hacks APC it can control it even without AI control wire. var/mob/living/silicon/ai/AI = user var/mob/living/silicon/robot/robot = user @@ -912,122 +916,90 @@ GLOBAL_LIST_EMPTY(apcs) to_chat(user, "\The AI control for [src] has been disabled!") return 0 else - if (!in_range(src, user) || !istype(src.loc, /turf)) + if(!in_range(src, user) || !istype(loc, /turf)) return 0 var/mob/living/carbon/human/H = user - if (istype(H) && prob(H.getBrainLoss())) + if(istype(H) && prob(H.getBrainLoss())) to_chat(user, "You momentarily forget how to use [src].") return 0 return 1 -/obj/machinery/power/apc/Topic(href, href_list) - if(..()) - return 1 +/obj/machinery/power/apc/tgui_act(action, params) + if(..() || !can_use(usr, TRUE)) + return TRUE - if(!can_use(usr, 1)) - return 1 + // There's a handful of cases where we want to allow users to bypass the `locked` variable. + // If can_admin_interact() wasn't only defined on observers, this could just be part of a single-line + // conditional. + var/locked_exception = FALSE + if(issilicon(usr) || action == "nightshift") + locked_exception = TRUE + if(isobserver(usr)) + var/mob/observer/dead/D = usr + if(D.can_admin_interact()) + locked_exception = TRUE - if(href_list["nightshift"]) - if(last_nightshift_switch > world.time - 10 SECONDS) // don't spam... - to_chat(usr, "[src]'s night lighting circuit breaker is still cycling!") - return 0 - last_nightshift_switch = world.time - nightshift_setting = text2num(href_list["nightshift"]) - update_nightshift() - return 1 + if(locked && !locked_exception) + return - if(locked && !issilicon(usr) ) - if(isobserver(usr) ) - var/mob/observer/dead/O = usr //Added to allow admin nanoUI interactions. - if(!O.can_admin_interact() ) //NanoUI /should/ make this not needed, but better safe than sorry. - to_chat(usr, "Try as you might, your ghostly fingers can't press the buttons.") - return 1 - else - to_chat(usr, "You must unlock the panel to use this!") - return 1 - - if (href_list["lock"]) - coverlocked = !coverlocked - - else if (href_list["reboot"]) - failure_timer = 0 - update_icon() - update() - - else if (href_list["emergency_lighting"]) - emergency_lights = !emergency_lights - for(var/obj/machinery/light/L in area) - if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override - L.no_emergency = emergency_lights - INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) - CHECK_TICK - - else if (href_list["breaker"]) - toggle_breaker() - - else if (href_list["cmode"]) - chargemode = !chargemode - if(!chargemode) - charging = 0 + . = TRUE + switch(action) + if("lock") + if(locked_exception) // Yay code reuse + if(emagged || (stat & (BROKEN|MAINT))) + to_chat(usr, "The APC does not respond to the command.") + return + locked = !locked + update_icon() + if("cover") + coverlocked = !coverlocked + if("breaker") + toggle_breaker() + if("nightshift") + if(last_nightshift_switch > world.time - 10 SECONDS) // don't spam... + to_chat(usr, "[src]'s night lighting circuit breaker is still cycling!") + return 0 + last_nightshift_switch = world.time + nightshift_setting = params["nightshift"] + update_nightshift() + if("charge") + chargemode = !chargemode + if(!chargemode) + charging = 0 + update_icon() + if("channel") + if(params["eqp"]) + equipment = setsubsystem(text2num(params["eqp"])) + update_icon() + update() + else if(params["lgt"]) + lighting = setsubsystem(text2num(params["lgt"])) + update_icon() + update() + else if(params["env"]) + environ = setsubsystem(text2num(params["env"])) + update_icon() + update() + if("reboot") + failure_timer = 0 update_icon() - - else if (href_list["eqp"]) - var/val = text2num(href_list["eqp"]) - equipment = setsubsystem(val) - update_icon() - update() - - else if (href_list["lgt"]) - var/val = text2num(href_list["lgt"]) - lighting = setsubsystem(val) - update_icon() - update() - - else if (href_list["env"]) - var/val = text2num(href_list["env"]) - environ = setsubsystem(val) - update_icon() - update() - - else if (href_list["overload"]) - if(istype(usr, /mob/living/silicon)) - src.overload_lighting() - - else if (href_list["toggleaccess"]) - if(istype(usr, /mob/living/silicon)) - if(emagged || (stat & (BROKEN|MAINT))) - to_chat(usr, "The APC does not respond to the command.") - return - locked = !locked - update_icon() - - return 0 + update() + if("emergency_lighting") + emergency_lights = !emergency_lights + for(var/obj/machinery/light/L in area) + if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override + L.no_emergency = emergency_lights + INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) + CHECK_TICK + if("overload") + if(locked_exception) // Reusing for simplicity! + overload_lighting() /obj/machinery/power/apc/proc/toggle_breaker() operating = !operating - src.update() + update() update_icon() -//This isn't used for now, so might as well disable it -/* -/obj/machinery/power/apc/proc/ion_act() - if(prob(3)) - src.locked = 1 - if (src.cell.charge > 0) - src.cell.charge = 0 - cell.corrupt() - update_icon() - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(3, 0, src.loc) - smoke.attach(src) - smoke.start() - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - visible_message("The [src.name] suddenly lets out a blast of smoke and some sparks!", \ - "You hear sizzling electronics.") -*/ - /obj/machinery/power/apc/surplus() if(terminal) return terminal.surplus() @@ -1083,12 +1055,12 @@ GLOBAL_LIST_EMPTY(apcs) var/excess = surplus() - if(!src.avail()) - main_status = 0 + if(!avail()) + main_status = APC_EXTERNAL_POWER_NOTCONNECTED else if(excess < 0) - main_status = 1 + main_status = APC_EXTERNAL_POWER_NOENERGY else - main_status = 2 + main_status = APC_EXTERNAL_POWER_GOOD if(debug) log_debug("Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]") @@ -1122,7 +1094,7 @@ GLOBAL_LIST_EMPTY(apcs) // now trickle-charge the cell lastused_charging = 0 // Clear the variable for new use. - if(src.attempt_charging()) + if(attempt_charging()) if(excess > 0) // check to make sure we have enough to charge // Max charge is capped to % per second constant var/ch = min(excess*CELLRATE, cell.maxcharge*chargelevel) @@ -1170,7 +1142,7 @@ GLOBAL_LIST_EMPTY(apcs) force_update = 0 queue_icon_update() update() - else if (last_ch != charging) + else if(last_ch != charging) queue_icon_update() /obj/machinery/power/apc/proc/update_channels() @@ -1212,7 +1184,7 @@ GLOBAL_LIST_EMPTY(apcs) // val 0=off, 1=off(auto) 2=on 3=on(auto) // on 0=off, 1=on, 2=autooff // defines a state machine, returns the new state -obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) +/obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) switch(cur_state) //if(POWERCHAN_OFF); //autoset will never turn on a channel set to off if(POWERCHAN_OFF_AUTO) @@ -1253,24 +1225,24 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) switch(severity) if(1) //set_broken() //now qdel() do what we need - if (cell) + if(cell) cell.ex_act(1) // more lags woohoo qdel(src) return if(2) - if (prob(75)) + if(prob(75)) set_broken() - if (cell && prob(50)) + if(cell && prob(50)) cell.ex_act(2) if(3) - if (prob(50)) + if(prob(50)) set_broken() - if (cell && prob(50)) + if(cell && prob(50)) cell.ex_act(3) if(4) - if (prob(25)) + if(prob(25)) set_broken() - if (cell && prob(50)) + if(cell && prob(50)) cell.ex_act(3) return @@ -1282,7 +1254,7 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) /obj/machinery/power/apc/proc/set_broken() // Aesthetically much better! spawn(rand(2,5)) - src.visible_message("[src]'s screen flickers suddenly, then explodes in a rain of sparks and small debris!") + visible_message("[src]'s screen flickers suddenly, then explodes in a rain of sparks and small debris!") stat |= BROKEN operating = 0 update_icon() @@ -1314,7 +1286,7 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) /obj/machinery/power/apc/proc/ai_hack(var/mob/living/silicon/ai/A = null) if(!A || !A.hacked_apcs || hacker || aidisabled || A.stat == DEAD) return 0 - src.hacker = A + hacker = A A.hacked_apcs += src locked = 1 update_icon() @@ -1406,3 +1378,11 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) CHECK_TICK #undef APC_UPDATE_ICON_COOLDOWN + +#undef APC_EXTERNAL_POWER_NOTCONNECTED +#undef APC_EXTERNAL_POWER_NOENERGY +#undef APC_EXTERNAL_POWER_GOOD + +#undef APC_HAS_ELECTRONICS_NONE +#undef APC_HAS_ELECTRONICS_WIRED +#undef APC_HAS_ELECTRONICS_SECURED \ No newline at end of file diff --git a/code/modules/power/breaker_box.dm b/code/modules/power/breaker_box.dm index dc7cd0c519..5ebf482679 100644 --- a/code/modules/power/breaker_box.dm +++ b/code/modules/power/breaker_box.dm @@ -25,7 +25,7 @@ for(var/obj/structure/cable/C in src.loc) qdel(C) . = ..() - for(var/datum/nano_module/rcon/R in world) + for(var/datum/tgui_module/rcon/R in world) R.FindDevices() /obj/machinery/power/breakerbox/Initialize() diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 19ba3b8065..c6ad30ccc5 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -192,58 +192,48 @@ GLOBAL_LIST_EMPTY(all_turbines) if(stat & (BROKEN|NOPOWER) || !anchored) return if(!circ1 || !circ2) //Just incase the middle part of the TEG was not wrenched last. reconnect() - ui_interact(user) + tgui_interact(user) -/obj/machinery/power/generator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/power/generator/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TEGenerator", name) + ui.open() + +/obj/machinery/power/generator/tgui_data(mob/user) // this is the data which will be sent to the ui var/vertical = 0 if (dir == NORTH || dir == SOUTH) vertical = 1 - var/data[0] - data["totalOutput"] = effective_gen/1000 - data["maxTotalOutput"] = max_power/1000 - data["thermalOutput"] = last_thermal_gen/1000 - data["circConnected"] = 0 + var/list/data = list() + data["totalOutput"] = effective_gen + data["maxTotalOutput"] = max_power + data["thermalOutput"] = last_thermal_gen + data["primary"] = list() if(circ1) //The one on the left (or top) - data["primaryDir"] = vertical ? "top" : "left" - data["primaryOutput"] = last_circ1_gen/1000 - data["primaryFlowCapacity"] = circ1.volume_capacity_used*100 - data["primaryInletPressure"] = circ1.air1.return_pressure() - data["primaryInletTemperature"] = circ1.air1.temperature - data["primaryOutletPressure"] = circ1.air2.return_pressure() - data["primaryOutletTemperature"] = circ1.air2.temperature + data["primary"]["dir"] = vertical ? "top" : "left" + data["primary"]["output"] = last_circ1_gen + data["primary"]["flowCapacity"] = circ1.volume_capacity_used*100 + data["primary"]["inletPressure"] = circ1.air1.return_pressure() + data["primary"]["inletTemperature"] = circ1.air1.temperature + data["primary"]["outletPressure"] = circ1.air2.return_pressure() + data["primary"]["outletTemperature"] = circ1.air2.temperature + data["secondary"] = list() if(circ2) //Now for the one on the right (or bottom) - data["secondaryDir"] = vertical ? "bottom" : "right" - data["secondaryOutput"] = last_circ2_gen/1000 - data["secondaryFlowCapacity"] = circ2.volume_capacity_used*100 - data["secondaryInletPressure"] = circ2.air1.return_pressure() - data["secondaryInletTemperature"] = circ2.air1.temperature - data["secondaryOutletPressure"] = circ2.air2.return_pressure() - data["secondaryOutletTemperature"] = circ2.air2.temperature + data["secondary"]["dir"] = vertical ? "bottom" : "right" + data["secondary"]["output"] = last_circ2_gen + data["secondary"]["flowCapacity"] = circ2.volume_capacity_used*100 + data["secondary"]["inletPressure"] = circ2.air1.return_pressure() + data["secondary"]["inletTemperature"] = circ2.air1.temperature + data["secondary"]["outletPressure"] = circ2.air2.return_pressure() + data["secondary"]["outletTemperature"] = circ2.air2.temperature - if(circ1 && circ2) - data["circConnected"] = 1 - else - data["circConnected"] = 0 - - - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "generator.tmpl", "Thermoelectric Generator", 450, 500) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data /obj/machinery/power/generator/power_change() ..() diff --git a/code/modules/power/gravitygenerator_vr.dm b/code/modules/power/gravitygenerator_vr.dm index 6e3d784fe4..3e4767a9a9 100644 --- a/code/modules/power/gravitygenerator_vr.dm +++ b/code/modules/power/gravitygenerator_vr.dm @@ -240,11 +240,16 @@ GLOBAL_LIST_EMPTY(gravity_generators) /obj/machinery/gravity_generator/main/attack_hand(mob/user) if((. = ..())) return - if(CanUseTopic(user, global.default_state) > STATUS_CLOSE) - ui_interact(user) - return TRUE + tgui_interact(user) + return TRUE -/obj/machinery/gravity_generator/main/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/gravity_generator/main/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GravityGenerator", name) + ui.open() + +/obj/machinery/gravity_generator/main/tgui_data(mob/user) var/data[0] data["breaker"] = breaker @@ -253,22 +258,18 @@ GLOBAL_LIST_EMPTY(gravity_generators) data["on"] = on data["operational"] = (stat & BROKEN) ? FALSE : TRUE - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "gravity_generator.tmpl", src.name, 500, 400) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data -/obj/machinery/gravity_generator/main/Topic(href, href_list, datum/topic_state/state = default_state) - if((. = ..())) - return +/obj/machinery/gravity_generator/main/tgui_act(action, params) + if((..())) + return TRUE - if(href_list["gentoggle"]) - breaker = !breaker - investigate_log("was toggled [breaker ? "ON" : "OFF"] by [key_name(usr)].", "gravity") - set_power() - return TOPIC_REFRESH + switch(action) + if("gentoggle") + breaker = !breaker + investigate_log("was toggled [breaker ? "ON" : "OFF"] by [key_name(usr)].", "gravity") + set_power() + return TOPIC_REFRESH // Power and Icon States diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 3251aee2f9..dce52720b4 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -7,6 +7,7 @@ density = 1 anchored = 0 use_power = USE_POWER_OFF + interact_offline = TRUE var/active = 0 var/power_gen = 5000 @@ -28,13 +29,22 @@ /obj/machinery/power/port_gen/proc/handleInactive() return +/obj/machinery/power/port_gen/proc/TogglePower() + if(active) + active = FALSE + icon_state = "[initial(icon_state)]" + // soundloop.stop() + else if(HasFuel()) + active = TRUE + icon_state = "[initial(icon_state)]on" + // soundloop.start() + /obj/machinery/power/port_gen/process() if(active && HasFuel() && !IsBroken() && anchored && powernet) add_avail(power_gen * power_output) UseFuel() - src.updateDialog() else - active = 0 + active = FALSE icon_state = initial(icon_state) handleInactive() @@ -121,7 +131,7 @@ return ..() /obj/machinery/power/port_gen/pacman/dismantle() - while ( sheets > 0 ) + while( sheets > 0 ) DropFuel() return ..() @@ -212,16 +222,16 @@ /obj/machinery/power/port_gen/pacman/handleInactive() var/cooling_temperature = 20 var/datum/gas_mixture/environment = loc.return_air() - if (environment) + if(environment) var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1) var/ambient = environment.temperature - T20C cooling_temperature += ambient*ratio - if (temperature > cooling_temperature) + if(temperature > cooling_temperature) var/temp_loss = (temperature - cooling_temperature)/TEMPERATURE_DIVISOR temp_loss = between(2, round(temp_loss, 1), TEMPERATURE_CHANGE_MAX) temperature = max(temperature - temp_loss, cooling_temperature) - src.updateDialog() + updateDialog() if(overheating) overheating-- @@ -287,97 +297,77 @@ ..() if (!anchored) return - ui_interact(user) + tgui_interact(user) /obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob) - ui_interact(user) + tgui_interact(user) -/obj/machinery/power/port_gen/pacman/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/power/port_gen/tgui_status(mob/user, datum/tgui_state/state) if(IsBroken()) - return + return STATUS_CLOSE + return ..() + +/obj/machinery/power/port_gen/pacman/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableGenerator", name) + ui.open() + +/obj/machinery/power/port_gen/pacman/tgui_data(mob/user) + var/list/data = list() - var/data[0] data["active"] = active + if(istype(user, /mob/living/silicon/ai)) - data["is_ai"] = 1 + data["is_ai"] = TRUE else if(istype(user, /mob/living/silicon/robot) && !Adjacent(user)) - data["is_ai"] = 1 + data["is_ai"] = TRUE else - data["is_ai"] = 0 - data["output_set"] = power_output - data["output_max"] = max_power_output - data["output_safe"] = max_safe_output - data["output_watts"] = power_output * power_gen - data["temperature_current"] = src.temperature - data["temperature_max"] = src.max_temperature - data["temperature_overheat"] = overheating - // 1 sheet = 1000cm3? + data["is_ai"] = FALSE + + data["sheet_name"] = capitalize(sheet_name) data["fuel_stored"] = round((sheets * 1000) + (sheet_left * 1000)) data["fuel_capacity"] = round(max_sheets * 1000, 0.1) data["fuel_usage"] = active ? round((power_output / time_per_sheet) * 1000) : 0 - data["fuel_type"] = sheet_name + data["anchored"] = anchored + data["connected"] = (powernet == null ? 0 : 1) + data["ready_to_boot"] = anchored && HasFuel() + data["power_generated"] = DisplayPower(power_gen) + data["power_output"] = DisplayPower(power_gen * power_output) + data["unsafe_output"] = power_output > max_safe_output + data["power_available"] = (powernet == null ? 0 : DisplayPower(avail())) + data["temperature_current"] = temperature + data["temperature_max"] = max_temperature + data["temperature_overheat"] = overheating + // 1 sheet = 1000cm3? + return data - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "pacman.tmpl", src.name, 500, 560) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - - -/* -/obj/machinery/power/port_gen/pacman/interact(mob/user) - if (get_dist(src, user) > 1 ) - if (!istype(user, /mob/living/silicon/ai)) - user.unset_machine() - user << browse(null, "window=port_gen" - return - - user.set_machine(src) - - var/dat = text("[name]
") - if (active) - dat += text("Generator: On
") - else - dat += text("Generator: Off
") - dat += text("[capitalize(sheet_name)]: [sheets] - Eject
") - var/stack_percent = round(sheet_left * 100, 1) - dat += text("Current stack: [stack_percent]%
") - dat += text("Power output: - [power_gen * power_output] Watts+
") - dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]
") - - var/tempstr = "Temperature: [temperature]°C
" - dat += (overheating)? "[tempstr]" : tempstr - dat += "
Close" - user << browse("[dat]", "window=port_gen") - onclose(user, "port_gen") -*/ - -/obj/machinery/power/port_gen/pacman/Topic(href, href_list) +/obj/machinery/power/port_gen/pacman/tgui_act(action, params) if(..()) return - src.add_fingerprint(usr) - if(href_list["action"]) - if(href_list["action"] == "enable") - if(!active && HasFuel() && !IsBroken()) - active = 1 - icon_state = "[initial(icon_state)]on" //VOREStation Edit - if(href_list["action"] == "disable") - if (active) - active = 0 - icon_state = initial(icon_state) //VOREStation Edit - if(href_list["action"] == "eject") + add_fingerprint(usr) + switch(action) + if("toggle_power") + TogglePower() + . = TRUE + + if("eject") if(!active) DropFuel() - if(href_list["action"] == "lower_power") - if (power_output > 1) + . = TRUE + + if("lower_power") + if(power_output > 1) power_output-- - if (href_list["action"] == "higher_power") - if (power_output < max_power_output || (emagged && power_output < round(max_power_output*2.5))) + . = TRUE + + if("higher_power") + if(power_output < max_power_output || (emagged && power_output < round(max_power_output * 2.5))) power_output++ + . = TRUE /obj/machinery/power/port_gen/pacman/super name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator" diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index b08586a449..1747842df9 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -5,6 +5,7 @@ var/load = 0 // the current load on the powernet, increased by each machine at processing var/newavail = 0 // what available power was gathered last tick, then becomes... var/avail = 0 //...the current available power in the powernet + var/viewavail = 0 // the availability as it appears on the power console (gradually updated) var/viewload = 0 // the load as it appears on the power console (gradually updated) var/number = 0 // Unused //TODEL @@ -134,7 +135,8 @@ S.restore(perc) //updates the viewed load (as seen on power computers) - viewload = round(load) + viewavail = round(0.8 * viewavail + 0.2 * avail) + viewload = round(0.8 * viewload + 0.2 * load) //reset the powernet load = 0 diff --git a/code/modules/power/sensors/powernet_sensor.dm b/code/modules/power/sensors/powernet_sensor.dm index bc1298d201..6f1b53db05 100644 --- a/code/modules/power/sensors/powernet_sensor.dm +++ b/code/modules/power/sensors/powernet_sensor.dm @@ -19,12 +19,22 @@ var/name_tag = "#UNKN#" // ID tag displayed in list of powernet sensors. Each sensor should have it's own tag! var/long_range = 0 // If 1, sensor reading will show on all computers, regardless of Zlevel + var/list/history = list() + var/record_size = 60 + var/record_interval = 50 + var/next_record = 0 + var/is_secret_monitor = FALSE + // Proc: New() // Parameters: None // Description: Automatically assigns name according to ID tag. /obj/machinery/power/sensor/New() ..() auto_set_name() +/obj/machinery/power/sensor/Initialize() + . = ..() + history["supply"] = list() + history["demand"] = list() // Proc: auto_set_name() // Parameters: None @@ -38,6 +48,8 @@ for(var/obj/machinery/computer/power_monitor/PM in machines) if(PM.power_monitor) PM.power_monitor.refresh_sensors() + history.Cut() + history = null // Proc: check_grid_warning() // Parameters: None @@ -51,10 +63,67 @@ // Proc: process() // Parameters: None -// Description: This has to be here because we need sensors to remain in Machines list. +// Description: This tracks historical usage, for TGUI power monitors /obj/machinery/power/sensor/process() + if(!powernet) + use_power = USE_POWER_IDLE + connect_to_network() + else + use_power = USE_POWER_ACTIVE + record() return 1 +// This tracks historical usage, for TGUI power monitors +/obj/machinery/power/sensor/proc/record() + if(world.time >= next_record) + next_record = world.time + record_interval + + var/datum/powernet/connected_powernet = powernet + + var/list/supply = history["supply"] + if(connected_powernet) + supply += connected_powernet.viewavail + if(supply.len > record_size) + supply.Cut(1, 2) + + var/list/demand = history["demand"] + if(connected_powernet) + demand += connected_powernet.viewload + if(demand.len > record_size) + demand.Cut(1, 2) + +/obj/machinery/power/sensor/tgui_data() + var/list/data = list() + + data["name"] = name_tag + data["stored"] = record_size + data["interval"] = record_interval / 10 + data["attached"] = !!powernet + data["history"] = history + + data["areas"] = list() + if(powernet) + for(var/obj/machinery/power/terminal/term in powernet.nodes) + if(istype(term.master, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = term.master + if(istype(A)) + var/cell_charge + if(!A.cell) + cell_charge = 0 + else + cell_charge = A.cell.percent() + data["areas"] += list(list( + "name" = A.area.name, + "charge" = cell_charge, + "load" = DisplayPower(A.lastused_total), + "charging" = A.charging, + "eqp" = A.equipment, + "lgt" = A.lighting, + "env" = A.environ, + )) + + return data + // Proc: reading_to_text() // Parameters: 1 (amount - Power in Watts to be converted to W, kW or MW) // Description: Helper proc that converts reading in Watts to kW or MW (returns string version of amount parameter) @@ -178,7 +247,7 @@ APC_entry["total_load"] = reading_to_text(A.lastused_total) // Hopefully removes those goddamn \improper s which are screwing up the UI var/N = A.area.name - if(findtext(N, "ÿ")) + if(findtext(N, "�")) N = copytext(N, 3) APC_entry["name"] = N // Add data into main list of APC data. diff --git a/code/modules/power/sensors/sensor_monitoring.dm b/code/modules/power/sensors/sensor_monitoring.dm index e243b7f75b..4e6198f410 100644 --- a/code/modules/power/sensors/sensor_monitoring.dm +++ b/code/modules/power/sensors/sensor_monitoring.dm @@ -18,7 +18,7 @@ use_power = USE_POWER_IDLE idle_power_usage = 300 active_power_usage = 300 - var/datum/nano_module/power_monitor/power_monitor + var/datum/tgui_module/power_monitor/power_monitor // Checks the sensors for alerts. If change (alerts cleared or detected) occurs, calls for icon update. /obj/machinery/computer/power_monitor/process() @@ -47,12 +47,11 @@ if(stat & (BROKEN|NOPOWER)) return - ui_interact(user) + tgui_interact(user) // Uses dark magic to operate the NanoUI of this computer. -/obj/machinery/computer/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - power_monitor.ui_interact(user, ui_key, ui, force_open) - +/obj/machinery/computer/power_monitor/tgui_interact(mob/user, var/datum/tgui/ui = null) + power_monitor.tgui_interact(user, ui) // Verifies if any warnings were registered by connected sensors. /obj/machinery/computer/power_monitor/proc/check_warnings() diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index bcb72061f4..6beda2db15 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -36,7 +36,7 @@ /obj/machinery/particle_accelerator/control_box/attack_hand(mob/user as mob) if(construction_state >= 3) - interact(user) + tgui_interact(user) else if(construction_state == 2) // Wires exposed wires.Interact(user) @@ -77,36 +77,6 @@ else icon_state = "[reference]c" -/obj/machinery/particle_accelerator/control_box/Topic(href, href_list) - ..() - //Ignore input if we are broken, !silicon guy cant touch us, or nonai controlling from super far away - if(stat & (BROKEN|NOPOWER) || (get_dist(src, usr) > 1 && !istype(usr, /mob/living/silicon)) || (get_dist(src, usr) > 8 && !istype(usr, /mob/living/silicon/ai))) - usr.unset_machine() - usr << browse(null, "window=pacontrol") - return - - if( href_list["close"] ) - usr << browse(null, "window=pacontrol") - usr.unset_machine() - return - - if(href_list["togglep"]) - if(!wires.is_cut(WIRE_PARTICLE_POWER)) - toggle_power() - else if(href_list["scan"]) - part_scan() - - else if(href_list["strengthup"]) - if(!wires.is_cut(WIRE_PARTICLE_STRENGTH)) - add_strength() - - else if(href_list["strengthdown"]) - if(!wires.is_cut(WIRE_PARTICLE_STRENGTH)) - remove_strength() - - updateDialog() - update_icon() - /obj/machinery/particle_accelerator/control_box/proc/strength_change() for(var/obj/structure/particle_accelerator/part in connected_parts) part.strength = strength @@ -230,33 +200,54 @@ part.update_icon() return 1 +/obj/machinery/particle_accelerator/control_box/proc/is_interactive(mob/user) + if(!interface_control) + to_chat(user, "ERROR: Request timed out. Check wire contacts.") + return FALSE + if(construction_state != 3) + return FALSE + return TRUE -/obj/machinery/particle_accelerator/control_box/interact(mob/user) - if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) - if(!istype(user, /mob/living/silicon)) - user.unset_machine() - user << browse(null, "window=pacontrol") - return - user.set_machine(src) +/obj/machinery/particle_accelerator/control_box/tgui_status(mob/user) + if(is_interactive(user)) + return ..() + return STATUS_CLOSE - var/dat = "" - dat += "Particle Accelerator Control Panel
" - dat += "Close

" - dat += "Status:
" - if(!assembled) - dat += "Unable to detect all parts!
" - dat += "Run Scan

" - else - dat += "All parts in place.

" - dat += "Power:" - if(active) - dat += "On
" - else - dat += "Off
" - dat += "Toggle Power

" - dat += "Particle Strength: [src.strength] " - dat += "--|++

" +/obj/machinery/particle_accelerator/control_box/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ParticleAccelerator", name) + ui.open() - user << browse(dat, "window=pacontrol;size=420x500") - onclose(user, "pacontrol") - return +/obj/machinery/particle_accelerator/control_box/tgui_data(mob/user) + var/list/data = list() + data["assembled"] = assembled + data["power"] = active + data["strength"] = strength + return data + +/obj/machinery/particle_accelerator/control_box/tgui_act(action, params) + if(..()) + return + + switch(action) + if("power") + if(wires.is_cut(WIRE_POWER)) + return + toggle_power() + . = TRUE + if("scan") + part_scan() + . = TRUE + if("add_strength") + if(wires.is_cut(WIRE_PARTICLE_STRENGTH)) + return + add_strength() + . = TRUE + if("remove_strength") + if(wires.is_cut(WIRE_PARTICLE_STRENGTH)) + return + remove_strength() + . = TRUE + + update_icon() diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index c05c4e1523..365fda6b50 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -263,11 +263,11 @@ GLOBAL_LIST_EMPTY(smeses) /obj/machinery/power/smes/attack_ai(mob/user) add_hiddenprint(user) - ui_interact(user) + tgui_interact(user) /obj/machinery/power/smes/attack_hand(mob/user) add_fingerprint(user) - ui_interact(user) + tgui_interact(user) /obj/machinery/power/smes/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) @@ -344,78 +344,84 @@ GLOBAL_LIST_EMPTY(smeses) return FALSE return TRUE -/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - - if(stat & BROKEN) - return - - // this is the data which will be sent to the ui - var/data[0] - data["nameTag"] = name_tag - data["storedCapacity"] = round(100.0*charge/capacity, 0.1) - data["storedCapacityAbs"] = round(charge/(1000*60), 0.1) - data["storedCapacityMax"] = round(capacity/(1000*60)) - data["charging"] = inputting - data["chargeMode"] = input_attempt - data["chargeLevel"] = round(input_level/1000, 0.1) - data["chargeMax"] = round(input_level_max/1000) - data["chargeLoad"] = round(input_available/1000, 0.1) - data["outputOnline"] = output_attempt - data["outputLevel"] = round(output_level/1000, 0.1) - data["outputMax"] = round(output_level_max/1000) - data["outputLoad"] = round(output_used/1000, 0.1) - data["outputting"] = outputting - - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "smes.tmpl", "SMES Unit", 540, 380) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window +/obj/machinery/power/smes/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Smes", name) ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + +/obj/machinery/power/smes/tgui_data() + var/list/data = list( + "capacity" = capacity, + "capacityPercent" = round(100*charge/capacity, 0.1), + "charge" = charge, + "inputAttempt" = input_attempt, + "inputting" = inputting, + "inputLevel" = input_level, + "inputLevel_text" = DisplayPower(input_level), + "inputLevelMax" = input_level_max, + "inputAvailable" = input_available, + "outputAttempt" = output_attempt, + "outputting" = outputting, + "outputLevel" = output_level, + "outputLevel_text" = DisplayPower(output_level), + "outputLevelMax" = output_level_max, + "outputUsed" = output_used, + ) + return data /obj/machinery/power/smes/proc/Percentage() if(!capacity) return 0 return round(100.0*charge/capacity, 0.1) -/obj/machinery/power/smes/Topic(href, href_list) - if(..()) - return 1 - if( href_list["cmode"] ) - inputting(!input_attempt) - update_icon() - return 1 - else if( href_list["online"] ) - outputting(!output_attempt) - update_icon() - return 1 - else if( href_list["input"] ) - switch( href_list["input"] ) - if("min") - input_level = 0 - if("max") - input_level = input_level_max - if("set") - input_level = (input(usr, "Enter new input level (0-[input_level_max/1000] kW)", "SMES Input Power Control", input_level/1000) as num) * 1000 - input_level = max(0, min(input_level_max, input_level)) // clamp to range - return 1 - else if( href_list["output"] ) - switch( href_list["output"] ) - if("min") - output_level = 0 - if("max") - output_level = output_level_max - if("set") - output_level = (input(usr, "Enter new output level (0-[output_level_max/1000] kW)", "SMES Output Power Control", output_level/1000) as num) * 1000 - output_level = max(0, min(output_level_max, output_level)) // clamp to range - return 1 +/obj/machinery/power/smes/tgui_act(action, params) + if(..()) + return TRUE + switch(action) + if("tryinput") + inputting(!input_attempt) + update_icon() + . = TRUE + if("tryoutput") + outputting(!output_attempt) + update_icon() + . = TRUE + if("input") + var/target = params["target"] + var/adjust = text2num(params["adjust"]) + if(target == "min") + target = 0 + . = TRUE + else if(target == "max") + target = input_level_max + . = TRUE + else if(adjust) + target = input_level + adjust + . = TRUE + else if(text2num(target) != null) + target = text2num(target) + . = TRUE + if(.) + input_level = clamp(target, 0, input_level_max) + if("output") + var/target = params["target"] + var/adjust = text2num(params["adjust"]) + if(target == "min") + target = 0 + . = TRUE + else if(target == "max") + target = output_level_max + . = TRUE + else if(adjust) + target = output_level + adjust + . = TRUE + else if(text2num(target) != null) + target = text2num(target) + . = TRUE + if(.) + output_level = clamp(target, 0, output_level_max) /obj/machinery/power/smes/proc/inputting(var/do_input) input_attempt = do_input diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index f8bf16087e..45b44d64f8 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -84,7 +84,7 @@ /obj/machinery/power/smes/buildable/Destroy() qdel(wires) wires = null - for(var/datum/nano_module/rcon/R in world) + for(var/datum/tgui_module/rcon/R in world) R.FindDevices() return ..() diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 27f1953b32..850bb5807c 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -399,38 +399,32 @@ GLOBAL_LIST_EMPTY(solars_list) return /obj/machinery/power/solar_control/attack_hand(mob/user) - if(!..()) - interact(user) + if(..()) + return TRUE + tgui_interact(user) -/obj/machinery/power/solar_control/interact(mob/user) +/obj/machinery/power/solar_control/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SolarControl", name) + ui.open() - var/t = "Generated power : [round(lastgen)] W
" - t += "Star Orientation: [SSsun.sun.angle]° ([angle2text(SSsun.sun.angle)])
" - t += "Array Orientation: [rate_control(src,"cdir","[cdir]°",1,15)] ([angle2text(cdir)])
" - t += "Tracking:
" - switch(track) - if(0) - t += "Off Timed Auto
" - if(1) - t += "Off Timed Auto
" - if(2) - t += "Off Timed Auto
" +/obj/machinery/power/solar_control/tgui_data() + var/data = list() - t += "Tracking Rate: [rate_control(src,"tdir","[trackrate] deg/h ([trackrate<0 ? "CCW" : "CW"])",1,30,180)]

" + data["generated"] = round(lastgen) + data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * GLOB.solar_gen_rate) - t += "Connected devices:
" + data["sun_angle"] = SSsun.sun.angle + data["array_angle"] = cdir + data["rotation_rate"] = trackrate + data["max_rotation_rate"] = 7200 + data["tracking_state"] = track - t += "Search for devices
" - t += "Solar panels : [connected_panels.len] connected
" - t += "Solar tracker : [connected_tracker ? "Found" : "Not found"]

" + data["connected_panels"] = connected_panels.len + data["connected_tracker"] = (connected_tracker ? TRUE : FALSE) - t += "Close" - - var/datum/browser/popup = new(user, "solar", name) - popup.set_content(t) - popup.open() - - return + return data /obj/machinery/power/solar_control/attackby(obj/item/I, user as mob) if(I.is_screwdriver()) @@ -481,51 +475,52 @@ GLOBAL_LIST_EMPTY(solars_list) updateDialog() -/obj/machinery/power/solar_control/Topic(href, href_list) +/obj/machinery/power/solar_control/tgui_act(action, params) if(..()) - usr << browse(null, "window=solcon") - usr.unset_machine() - return 0 - if(href_list["close"] ) - usr << browse(null, "window=solcon") - usr.unset_machine() - return 0 + return TRUE - if(href_list["rate control"]) - if(href_list["cdir"]) - src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360) - src.targetdir = src.cdir - if(track == 2) //manual update, so losing auto-tracking - track = 0 - spawn(1) + switch(action) + if("azimuth") + var/adjust = text2num(params["adjust"]) + var/value = text2num(params["value"]) + if(adjust) + value = cdir + adjust + if(value != null) + cdir = value set_panels(cdir) - if(href_list["tdir"]) - src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"])) - if(src.trackrate) nexttime = world.time + 36000/abs(trackrate) + return TRUE + return FALSE + if("azimuth_rate") + var/adjust = text2num(params["adjust"]) + var/value = text2num(params["value"]) + if(adjust) + value = trackrate + adjust + if(value != null) + trackrate = round(clamp(value, -7200, 7200), 0.01) + if(trackrate) + nexttime = world.time + 36000 / abs(trackrate) + return TRUE + return TRUE + if("tracking") + var/mode = text2num(params["mode"]) + track = mode + if(track == 2) + if(connected_tracker) + connected_tracker.set_angle(SSsun.sun.angle) + set_panels(cdir) + else if(track == 1) //begin manual tracking + targetdir = cdir + if(trackrate) + nexttime = world.time + 36000/abs(trackrate) + set_panels(targetdir) + return TRUE - if(href_list["track"]) - track = text2num(href_list["track"]) - if(track == 2) - if(connected_tracker) - connected_tracker.set_angle(SSsun.sun.angle) - set_panels(cdir) - else if (track == 1) //begin manual tracking - src.targetdir = src.cdir - if(src.trackrate) nexttime = world.time + 36000/abs(trackrate) - set_panels(targetdir) - - if(href_list["search_connected"]) - src.search_for_connected() - if(connected_tracker && track == 2) - connected_tracker.set_angle(SSsun.sun.angle) - src.set_panels(cdir) - - interact(usr) - return 1 + if("refresh") + search_for_connected() + return TRUE //rotates the panel to the passed angle /obj/machinery/power/solar_control/proc/set_panels(var/cdir) - for(var/obj/machinery/power/solar/S in connected_panels) S.adir = cdir //instantly rotates the panel S.occlusion()//and @@ -547,7 +542,7 @@ GLOBAL_LIST_EMPTY(solars_list) /obj/machinery/power/solar_control/ex_act(severity) switch(severity) if(1.0) - //SN src = null + //SN = null qdel(src) return if(2.0) @@ -565,9 +560,3 @@ GLOBAL_LIST_EMPTY(solars_list) /obj/item/weapon/paper/solar name = "paper- 'Going green! Setup your own solar array instructions.'" info = "

Welcome

At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or phoron! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.

You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!

Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the SSsun.sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the SSsun.sun's movements and to send commands to the solar panels to change direction with the SSsun.sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.

Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.

That's all to it, be safe, be green!

" - -/proc/rate_control(var/S, var/V, var/C, var/Min=1, var/Max=5, var/Limit=null) //How not to name vars - var/href = "-[href]=-[Min]'>- [(C?C : 0)] [href]=[Min]'>+[href]=[Max]'>+" - if(Limit) return "[href]=-[Limit]'>-"+rate+"[href]=[Limit]'>+" - return rate diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 3d651a2a0f..4e6c5a6cb5 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -390,11 +390,11 @@ if(Adjacent(user)) return attack_hand(user) else - ui_interact(user) + tgui_interact(user) return /obj/machinery/power/supermatter/attack_ai(mob/user as mob) - ui_interact(user) + tgui_interact(user) /obj/machinery/power/supermatter/attack_hand(mob/user as mob) var/datum/gender/TU = gender_datums[user.get_visible_gender()] @@ -404,9 +404,15 @@ Consume(user) +/obj/machinery/power/supermatter/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AiSupermatter", name) + ui.open() + // This is purely informational UI that may be accessed by AIs or robots -/obj/machinery/power/supermatter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/power/supermatter/tgui_data(mob/user) + var/list/data = list() data["integrity_percentage"] = round(get_integrity()) var/datum/gas_mixture/env = null @@ -421,12 +427,7 @@ data["ambient_pressure"] = round(env.return_pressure()) data["detonating"] = grav_pulling - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "supermatter_crystal.tmpl", "Supermatter Crystal", 500, 300) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data /obj/machinery/power/supermatter/attackby(obj/item/weapon/W as obj, mob/living/user as mob) diff --git a/code/modules/resleeving/infomorph.dm b/code/modules/resleeving/infomorph.dm index 45c5d4193b..7fd716bc96 100644 --- a/code/modules/resleeving/infomorph.dm +++ b/code/modules/resleeving/infomorph.dm @@ -417,7 +417,7 @@ var/list/infomorph_emotions = list( desc = "Modify the settings on your integrated radio." if(radio) - radio.ui_interact(src,"main",null,1,conscious_state) + radio.tgui_interact(src) else to_chat(src, "You don't have a radio!") diff --git a/code/modules/shieldgen/shield_capacitor.dm b/code/modules/shieldgen/shield_capacitor.dm index 2ef3f17a85..d76a18045a 100644 --- a/code/modules/shieldgen/shield_capacitor.dm +++ b/code/modules/shieldgen/shield_capacitor.dm @@ -18,6 +18,7 @@ use_power = USE_POWER_OFF //doesn't use APC power var/charge_rate = 100000 //100 kW var/obj/machinery/shield_gen/owned_gen + interact_offline = TRUE /obj/machinery/shield_capacitor/advanced name = "advanced shield capacitor" @@ -67,36 +68,30 @@ /obj/machinery/shield_capacitor/attack_hand(mob/user) if(stat & (BROKEN)) return - interact(user) + tgui_interact(user) -/obj/machinery/shield_capacitor/interact(mob/user) - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN)) ) - if (!istype(user, /mob/living/silicon)) - user.unset_machine() - user << browse(null, "window=shield_capacitor") - return - var/t = "Shield Capacitor Control Console

" - if(locked) - t += "Swipe your ID card to begin." - else - t += "This capacitor is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
" - t += "Capacitor Status: [time_since_fail > 2 ? "OK." : "Discharging!"]
" - t += "Stored Energy: [format_SI(stored_charge, "J")] ([100 * round(stored_charge/max_charge, 0.01)]%)
" - t += "Charge Rate: \ - \[----\] \ - \[---\] \ - \[--\] \ - \[-\][format_SI(charge_rate, "W")]\ - \[+\] \ - \[++\] \ - \[+++\] \ - \[++++\]
" - t += "
" - t += "Refresh " - t += "Close
" +/obj/machinery/shield_capacitor/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ShieldCapacitor", name) + ui.open() - user << browse(t, "window=shield_capacitor;size=500x400") - user.set_machine(src) +/obj/machinery/shield_capacitor/tgui_status(mob/user) + if(stat & BROKEN) + return STATUS_CLOSE + return ..() + +/obj/machinery/shield_capacitor/tgui_data(mob/user) + var/list/data = list() + + data["active"] = active + data["time_since_fail"] = time_since_fail + data["stored_charge"] = stored_charge + data["max_charge"] = max_charge + data["charge_rate"] = charge_rate + data["max_charge_rate"] = max_charge_rate + + return data /obj/machinery/shield_capacitor/process() if (!anchored) @@ -119,21 +114,20 @@ time_since_fail = 0 //losing charge faster than we can draw from PN last_stored_charge = stored_charge -/obj/machinery/shield_capacitor/Topic(href, href_list[]) - ..() - if( href_list["close"] ) - usr << browse(null, "window=shield_capacitor") - usr.unset_machine() - return - if( href_list["toggle"] ) - if(!active && !anchored) - to_chat(usr, "The [src] needs to be firmly secured to the floor first.") - return - active = !active - if( href_list["charge_rate"] ) - charge_rate = between(10000, charge_rate + text2num(href_list["charge_rate"]), max_charge_rate) +/obj/machinery/shield_capacitor/tgui_act(action, params) + if(..()) + return TRUE - updateDialog() + switch(action) + if("toggle") + if(!active && !anchored) + to_chat(usr, "The [src] needs to be firmly secured to the floor first.") + return + active = !active + . = TRUE + if("charge_rate") + charge_rate = clamp(text2num(params["rate"]), 10000, max_charge_rate) + . = TRUE /obj/machinery/shield_capacitor/power_change() if(stat & BROKEN) diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index cdd16d2429..b87f66432f 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -23,6 +23,7 @@ var/energy_conversion_rate = 0.0006 //how many renwicks per watt? Higher numbers equals more effiency. var/z_range = 0 // How far 'up and or down' to extend the shield to, in z-levels. Only works on MultiZ supported z-levels. use_power = USE_POWER_OFF //doesn't use APC power + interact_offline = TRUE // don't check stat & NOPOWER|BROKEN for our UI. We check BROKEN ourselves. var/id //for button usage /obj/machinery/shield_gen/advanced @@ -95,59 +96,50 @@ /obj/machinery/shield_gen/attack_hand(mob/user) if(stat & (BROKEN)) return - interact(user) + tgui_interact(user) -/obj/machinery/shield_gen/interact(mob/user) - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN)) ) - if (!istype(user, /mob/living/silicon)) - user.unset_machine() - user << browse(null, "window=shield_generator") - return - var/t = "Shield Generator Control Console

" - if(locked) - t += "Swipe your ID card to begin." - else - t += "[capacitors.len ? "Charge capacitor(s) connected." : "Unable to locate charge capacitor!"]
" - var/i = 0 - for(var/obj/machinery/shield_capacitor/capacitor in capacitors) - i++ - t += "Capacitor #[i]: [capacitor.active ? "Online." : "Offline."] \ - Charge: [round(capacitor.stored_charge/1000, 0.1)] kJ ([100 * round(capacitor.stored_charge/capacitor.max_charge, 0.01)]%) \ - Status: [capacitor.time_since_fail > 2 ? "OK." : "Discharging!"]
" - t += "This generator is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
" - t += "Field Status: [time_since_fail > 2 ? "Stable" : "Unstable"]
" - t += "Coverage Radius (restart required): \ - --- \ - -- \ - - \ - [field_radius] m \ - + \ - ++ \ - +++
" - if(HasAbove(src.z) || HasBelow(src.z)) // Won't show up on maps lacking MultiZ support. - t += "Vertical Shielding (restart required): \ - - \ - [z_range] Vertical Range \ - +
" - t += "Overall Field Strength: [round(average_field_strength, 0.01)] Renwick ([target_field_strength ? round(100 * average_field_strength / target_field_strength, 0.1) : "NA"]%)
" - t += "Upkeep Power: [format_SI(round(field.len * max(average_field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate), "W")]
" - t += "Charge Rate: -- \ - [strengthen_rate] Renwick/s \ - ++
" - t += "Shield Generation Power: [format_SI(round(field.len * min(strengthen_rate, target_field_strength - average_field_strength) / energy_conversion_rate), "W")]
" - t += "Maximum Field Strength: \ - \[min\] \ - -- \ - - \ - [target_field_strength] Renwick \ - + \ - ++ \ - \[max\]
" - t += "
" - t += "Refresh " - t += "Close
" - user << browse(t, "window=shield_generator;size=500x400") - user.set_machine(src) +/obj/machinery/shield_gen/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ShieldGenerator", name) + ui.open() + +/obj/machinery/shield_gen/tgui_status(mob/user) + if(stat & BROKEN) + return STATUS_CLOSE + return ..() + +/obj/machinery/shield_gen/tgui_data(mob/user) + var/list/data = list() + + data["locked"] = locked + data["lockedData"] = list() + if(!locked) + data["lockedData"]["capacitors"] = list() + for(var/obj/machinery/shield_capacitor/C in capacitors) + data["lockedData"]["capacitors"].Add(list(list( + "active" = C.active, + "stored_charge" = C.stored_charge, + "max_charge" = C.max_charge, + "failing" = (C.time_since_fail <= 2), + ))) + + data["lockedData"]["active"] = active + data["lockedData"]["failing"] = (time_since_fail <= 2) + data["lockedData"]["radius"] = field_radius + data["lockedData"]["max_radius"] = max_field_radius + data["lockedData"]["z_range"] = z_range + data["lockedData"]["max_z_range"] = 10 + data["lockedData"]["average_field_strength"] = average_field_strength + data["lockedData"]["target_field_strength"] = target_field_strength + data["lockedData"]["max_field_strength"] = max_field_strength + data["lockedData"]["shields"] = LAZYLEN(field) + data["lockedData"]["upkeep"] = round(field.len * max(average_field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate) + data["lockedData"]["strengthen_rate"] = strengthen_rate + data["lockedData"]["max_strengthen_rate"] = max_strengthen_rate + data["lockedData"]["gen_power"] = round(field.len * min(strengthen_rate, target_field_strength - average_field_strength) / energy_conversion_rate) + + return data /obj/machinery/shield_gen/process() if (!anchored && active) @@ -206,30 +198,32 @@ else average_field_strength = 0 -/obj/machinery/shield_gen/Topic(href, href_list[]) - ..() - if( href_list["close"] ) - usr << browse(null, "window=shield_generator") - usr.unset_machine() - return - else if( href_list["toggle"] ) - if (!active && !anchored) - to_chat(usr, "The [src] needs to be firmly secured to the floor first.") - return - toggle() - else if( href_list["change_radius"] ) - field_radius = between(0, field_radius + text2num(href_list["change_radius"]), max_field_radius) - else if( href_list["strengthen_rate"] ) - strengthen_rate = between(0, strengthen_rate + text2num(href_list["strengthen_rate"]), max_strengthen_rate) - else if( href_list["target_field_strength"] ) - target_field_strength = between(1, target_field_strength + text2num(href_list["target_field_strength"]), max_field_strength) - else if( href_list["z_range"] ) - z_range = between(0, z_range + text2num(href_list["z_range"]), 10) // Max is extending ten z-levels up and down. Probably too big of a number but it shouldn't matter. +/obj/machinery/shield_gen/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("toggle") + if (!active && !anchored) + to_chat(usr, "The [src] needs to be firmly secured to the floor first.") + return + toggle() + . = TRUE + if("change_radius") + field_radius = clamp(text2num(params["val"]), 0, max_field_radius) + . = TRUE + if("strengthen_rate") + strengthen_rate = clamp(text2num(params["val"]), 0, max_strengthen_rate) + . = TRUE + if("target_field_strength") + target_field_strength = clamp(text2num(params["val"]), 1, max_field_strength) + . = TRUE + if("z_range") + z_range = clamp(text2num(params["val"]), 0, 10) + . = TRUE - updateDialog() /obj/machinery/shield_gen/ex_act(var/severity) - if(active) toggle() return ..() diff --git a/code/modules/shuttles/escape_pods.dm b/code/modules/shuttles/escape_pods.dm index 245b96e82e..b1d3efdc0c 100644 --- a/code/modules/shuttles/escape_pods.dm +++ b/code/modules/shuttles/escape_pods.dm @@ -46,73 +46,58 @@ name = "escape pod controller" program = /datum/computer/file/embedded_program/docking/simple var/datum/shuttle/autodock/ferry/escape_pod/pod + valid_actions = list("toggle_override", "force_door") -/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/tgui_data(mob/user) var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type - data = list( + . = list( "docking_status" = docking_program.get_docking_status(), "override_enabled" = docking_program.override_enabled, - "door_state" = docking_program.memory["door_status"]["state"], - "door_lock" = docking_program.memory["door_status"]["lock"], + "exterior_status" = docking_program.memory["door_status"], "can_force" = pod.can_force() || (emergency_shuttle.departed && pod.can_launch()), //allow players to manually launch ahead of time if the shuttle leaves - "is_armed" = pod.arming_controller.armed, + "armed" = pod.arming_controller.armed, + "internalTemplateName" = "EscapePodConsole", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "escape_pod_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/Topic(href, href_list) - if((. = ..())) - return - - if("manual_arm") - pod.arming_controller.arm() - return TOPIC_REFRESH - if("force_launch") - if (pod.can_force()) - pod.force_launch(src) - else if (emergency_shuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves - pod.launch(src) - return TOPIC_REFRESH - return 0 +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/tgui_act(action, params) + if(..()) + return TRUE + switch(action) + if("manual_arm") + pod.arming_controller.arm() + . = TRUE + if("force_launch") + if(pod.can_force()) + pod.force_launch(src) + else if(emergency_shuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves + pod.launch(src) + . = TRUE //This controller is for the escape pod berth (station side) /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth name = "escape pod berth controller" program = /datum/computer/file/embedded_program/docking/simple/escape_pod_berth + valid_actions = list("toggle_override", "force_door") -/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/tgui_data(mob/user) var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type var/armed = null - if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth)) + if(istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth)) var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/P = docking_program armed = P.armed - data = list( + . = list( "docking_status" = docking_program.get_docking_status(), "override_enabled" = docking_program.override_enabled, + "exterior_status" = docking_program.memory["door_status"], "armed" = armed, + "internalTemplateName" = "EscapePodBerthConsole", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "escape_pod_berth_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/emag_act(var/remaining_charges, var/mob/user) if (!emagged) to_chat(user, "You emag the [src], arming the escape pod!") diff --git a/code/modules/tgui/modules/alarm.dm b/code/modules/tgui/modules/alarm.dm new file mode 100644 index 0000000000..2c0c75a6e8 --- /dev/null +++ b/code/modules/tgui/modules/alarm.dm @@ -0,0 +1,138 @@ +/datum/tgui_module/alarm_monitor + name = "Alarm monitor" + tgui_id = "StationAlertConsole" + var/list_cameras = 0 // Whether or not to list camera references. A future goal would be to merge this with the enginering/security camera console. Currently really only for AI-use. + var/list/datum/alarm_handler/alarm_handlers // The particular list of alarm handlers this alarm monitor should present to the user. + +/datum/tgui_module/alarm_monitor/New() + ..() + alarm_handlers = list() + +/datum/tgui_module/alarm_monitor/all +/datum/tgui_module/alarm_monitor/all/New() + ..() + alarm_handlers = SSalarm.all_handlers + +/datum/tgui_module/alarm_monitor/all/robot +/datum/tgui_module/alarm_monitor/all/robot/tgui_state(mob/user) + return GLOB.tgui_self_state + +/datum/tgui_module/alarm_monitor/engineering +/datum/tgui_module/alarm_monitor/engineering/New() + ..() + alarm_handlers = list(atmosphere_alarm, fire_alarm, power_alarm) + +// Subtype for glasses_state +/datum/tgui_module/alarm_monitor/engineering/glasses +/datum/tgui_module/alarm_monitor/engineering/glasses/tgui_state(mob/user) + return GLOB.tgui_glasses_state + +// Subtype for nif_state +/datum/tgui_module/alarm_monitor/engineering/nif +/datum/tgui_module/alarm_monitor/engineering/nif/tgui_state(mob/user) + return GLOB.tgui_nif_state + +// Subtype for NTOS +/datum/tgui_module/alarm_monitor/engineering/ntos + ntos = TRUE + +/datum/tgui_module/alarm_monitor/security +/datum/tgui_module/alarm_monitor/security/New() + ..() + alarm_handlers = list(camera_alarm, motion_alarm) + +// Subtype for glasses_state +/datum/tgui_module/alarm_monitor/security/glasses +/datum/tgui_module/alarm_monitor/security/glasses/tgui_state(mob/user) + return GLOB.tgui_glasses_state + +// Subtype for NTOS +/datum/tgui_module/alarm_monitor/security/ntos + ntos = TRUE + +/datum/tgui_module/alarm_monitor/proc/register_alarm(var/object, var/procName) + for(var/datum/alarm_handler/AH in alarm_handlers) + AH.register_alarm(object, procName) + +/datum/tgui_module/alarm_monitor/proc/unregister_alarm(var/object) + for(var/datum/alarm_handler/AH in alarm_handlers) + AH.unregister_alarm(object) + +/datum/tgui_module/alarm_monitor/proc/all_alarms() + var/z = get_z(tgui_host()) + var/list/all_alarms = new() + for(var/datum/alarm_handler/AH in alarm_handlers) + all_alarms += AH.visible_alarms(z) + + return all_alarms + +/datum/tgui_module/alarm_monitor/proc/major_alarms() + var/z = get_z(tgui_host()) + var/list/all_alarms = new() + for(var/datum/alarm_handler/AH in alarm_handlers) + all_alarms += AH.major_alarms(z) + + return all_alarms + +// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise. +/datum/tgui_module/alarm_monitor/proc/has_major_alarms() + var/z = get_z(tgui_host()) + for(var/datum/alarm_handler/AH in alarm_handlers) + if(AH.has_major_alarms(z)) + return 1 + + return 0 + +/datum/tgui_module/alarm_monitor/proc/minor_alarms() + var/z = get_z(tgui_host()) + var/list/all_alarms = new() + for(var/datum/alarm_handler/AH in alarm_handlers) + all_alarms += AH.minor_alarms(z) + + return all_alarms + +/datum/tgui_module/alarm_monitor/tgui_act(action, params) + if(..()) + return TRUE + + // Camera stuff is AI only. + // If you're not an AI, this is a read-only UI. + if(!isAI(usr)) + return + + switch(action) + if("switchTo") + var/obj/machinery/camera/C = locate(params["camera"]) in cameranet.cameras + if(!C) + return + + usr.switch_to_camera(C) + return 1 + +/datum/tgui_module/alarm_monitor/tgui_data(mob/user) + var/list/data = list() + + var/categories[0] + var/z = get_z(tgui_host()) + for(var/datum/alarm_handler/AH in alarm_handlers) + categories[++categories.len] = list("category" = AH.category, "alarms" = list()) + for(var/datum/alarm/A in AH.visible_alarms(z)) + var/cameras[0] + var/lost_sources[0] + + if(isAI(user)) + for(var/obj/machinery/camera/C in A.cameras()) + cameras[++cameras.len] = C.tgui_structure() + for(var/datum/alarm_source/AS in A.sources) + if(!AS.source) + lost_sources[++lost_sources.len] = AS.source_name + + categories[categories.len]["alarms"] += list(list( + "name" = "[A.alarm_name()]" + "[A.max_severity() > 1 ? "(MAJOR)" : ""]", + "origin_lost" = A.origin == null, + "has_cameras" = cameras.len, + "cameras" = cameras, + "lost_sources" = lost_sources.len ? sanitize(english_list(lost_sources, nothing_text = "", and_text = ", ")) : "")) + data["categories"] = categories + + return data diff --git a/code/modules/tgui/modules/atmos_control.dm b/code/modules/tgui/modules/atmos_control.dm new file mode 100644 index 0000000000..83d3db4d1e --- /dev/null +++ b/code/modules/tgui/modules/atmos_control.dm @@ -0,0 +1,110 @@ +/datum/tgui_module/atmos_control + name = "Atmospherics Control" + tgui_id = "AtmosControl" + var/obj/access = new() + var/emagged = 0 + var/ui_ref + var/list/monitored_alarms = list() + +/datum/tgui_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids) + ..() + access.req_access = req_access + access.req_one_access = req_one_access + + if(monitored_alarm_ids) + for(var/obj/machinery/alarm/alarm in machines) + if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids) + monitored_alarms += alarm + // machines may not yet be ordered at this point + monitored_alarms = dd_sortedObjectList(monitored_alarms) + +/datum/tgui_module/atmos_control/tgui_act(action, params, datum/tgui/ui) + if(..()) + return TRUE + + switch(action) + if("alarm") + if(ui_ref) + var/obj/machinery/alarm/alarm = locate(params["alarm"]) in (monitored_alarms.len ? monitored_alarms : machines) + if(alarm) + var/datum/tgui_state/TS = generate_state(alarm) + alarm.tgui_interact(usr, parent_ui = ui_ref, state = TS) + return 1 + if("setZLevel") + ui.set_map_z_level(params["mapZLevel"]) + return TRUE + +/datum/tgui_module/atmos_control/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, tgui_id, name) + ui.autoupdate = TRUE + ui.open() + ui_ref = ui + +/datum/tgui_module/atmos_control/tgui_static_data(mob/user) + . = ..() + + var/z = get_z(user) + var/list/map_levels = using_map.get_map_levels(z) + + // TODO: Move these to a cache, similar to cameras + var/alarms[0] + for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines)) + if(!monitored_alarms.len && alarm.alarms_hidden) + continue + if(!(alarm.z in map_levels)) + continue + alarms[++alarms.len] = list( + "name" = sanitize(alarm.name), + "ref"= "\ref[alarm]", + "danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm), + "x" = alarm.x, + "y" = alarm.y, + "z" = alarm.z) + .["alarms"] = alarms + +/datum/tgui_module/atmos_control/tgui_data(mob/user) + var/list/data = list() + + var/z = get_z(user) + var/list/map_levels = using_map.get_map_levels(z) + data["map_levels"] = map_levels + + return data + +/datum/tgui_module/atmos_control/tgui_close() + . = ..() + ui_ref = null + +/datum/tgui_module/atmos_control/proc/generate_state(air_alarm) + var/datum/tgui_state/air_alarm_remote/state = new() + state.atmos_control = src + state.air_alarm = air_alarm + return state + +/datum/tgui_state/air_alarm_remote + var/datum/tgui_module/atmos_control/atmos_control = null + var/obj/machinery/alarm/air_alarm = null + +/datum/tgui_state/air_alarm_remote/can_use_topic(src_object, mob/user) + if(!atmos_control.ui_ref) + qdel(src) + return STATUS_CLOSE + if(has_access(user)) + return STATUS_INTERACTIVE + return STATUS_UPDATE + +/datum/tgui_state/air_alarm_remote/proc/has_access(var/mob/user) + return user && (isAI(user) || atmos_control.access.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO) || (access_ce in user.GetAccess())) + +/datum/tgui_state/air_alarm_remote/Destroy() + atmos_control = null + air_alarm = null + +/datum/tgui_module/atmos_control/ntos + ntos = TRUE + +/datum/tgui_module/atmos_control/robot +/datum/tgui_module/atmos_control/robot/tgui_state(mob/user) + return GLOB.tgui_self_state \ No newline at end of file diff --git a/code/modules/tgui/modules/power_monitor.dm b/code/modules/tgui/modules/power_monitor.dm new file mode 100644 index 0000000000..ec5c820598 --- /dev/null +++ b/code/modules/tgui/modules/power_monitor.dm @@ -0,0 +1,85 @@ +/datum/tgui_module/power_monitor + name = "Power monitor" + tgui_id = "PowerMonitor" + var/list/grid_sensors + var/active_sensor = null //name_tag of the currently selected sensor + +/datum/tgui_module/power_monitor/New() + . = ..() + refresh_sensors() + +/datum/tgui_module/power_monitor/tgui_data(mob/user) + var/list/data = list() + + var/list/sensors = list() + // Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading. + var/obj/machinery/power/sensor/focus = null + + var/z = get_z(user) + var/list/map_levels = using_map.get_map_levels(z) + + // Build list of data from sensor readings. + for(var/obj/machinery/power/sensor/S in grid_sensors) + if(!(S.z in map_levels)) + continue + sensors.Add(list(list( + "name" = S.name_tag, + "alarm" = S.check_grid_warning() + ))) + if(S.name_tag == active_sensor) + focus = S + + data["all_sensors"] = sensors + if(focus) + data["focus"] = focus.tgui_data(user) + else + data["focus"] = null + + return data + +/datum/tgui_module/power_monitor/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("clear") + active_sensor = null + . = TRUE + if("refresh") + refresh_sensors() + . = TRUE + if("setsensor") + active_sensor = params["id"] + . = TRUE + +/datum/tgui_module/power_monitor/proc/has_alarm() + for(var/obj/machinery/power/sensor/S in grid_sensors) + if(S.check_grid_warning()) + return TRUE + return FALSE + +/datum/tgui_module/power_monitor/proc/refresh_sensors() + grid_sensors = list() + + // Handle ultranested programs + var/turf/T = get_turf(tgui_host()) + + var/list/levels = list() + if(!T) // Safety check + return + if(T) + levels += using_map.get_map_levels(T.z, FALSE) + for(var/obj/machinery/power/sensor/S in machines) + if(T && (S.loc.z == T.z) || (S.loc.z in levels) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels. + if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen! + warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z") + else + grid_sensors += S + +/datum/tgui_module/power_monitor/ntos + ntos = TRUE + +// Subtype for self_state +/datum/tgui_module/power_monitor/robot +/datum/tgui_module/power_monitor/robot/tgui_state(mob/user) + return GLOB.tgui_self_state diff --git a/code/modules/tgui/modules/rcon.dm b/code/modules/tgui/modules/rcon.dm new file mode 100644 index 0000000000..62cf3e5d71 --- /dev/null +++ b/code/modules/tgui/modules/rcon.dm @@ -0,0 +1,118 @@ +/datum/tgui_module/rcon + name = "Power RCON" + tgui_id = "RCON" + + var/list/known_SMESs = null + var/list/known_breakers = null + +/datum/tgui_module/rcon/tgui_data(mob/user) + FindDevices() // Update our devices list + var/list/data = ..() + + // SMES DATA (simplified view) + var/list/smeslist[0] + for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs) + smeslist.Add(list(list( + "capacity" = SMES.capacity, + "capacityPercent" = round(100*SMES.charge/SMES.capacity, 0.1), + "charge" = SMES.charge, + "input_set" = SMES.input_attempt, + "input_val" = round(SMES.input_level/1000, 0.1), + "output_set" = SMES.output_attempt, + "output_val" = round(SMES.output_level/1000, 0.1), + "output_load" = round(SMES.output_used/1000, 0.1), + "RCON_tag" = SMES.RCon_tag + ))) + + data["smes_info"] = sortByKey(smeslist, "RCON_tag") + + // BREAKER DATA (simplified view) + var/list/breakerlist[0] + for(var/obj/machinery/power/breakerbox/BR in known_breakers) + breakerlist.Add(list(list( + "RCON_tag" = BR.RCon_tag, + "enabled" = BR.on + ))) + data["breaker_info"] = breakerlist + + return data + +/datum/tgui_module/rcon/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("smes_in_toggle") + var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"]) + if(SMES) + SMES.toggle_input() + . = TRUE + if("smes_out_toggle") + var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"]) + if(SMES) + SMES.toggle_output() + . = TRUE + if("smes_in_set") + var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"]) + if(SMES) + var/inputset = (input(usr, "Enter new input level (0-[SMES.input_level_max/1000] kW)", "SMES Input Power Control", SMES.input_level/1000) as num) * 1000 + SMES.set_input(inputset) + . = TRUE + if("smes_out_set") + var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"]) + if(SMES) + var/outputset = (input(usr, "Enter new output level (0-[SMES.output_level_max/1000] kW)", "SMES Output Power Control", SMES.output_level/1000) as num) * 1000 + SMES.set_output(outputset) + . = TRUE + if("toggle_breaker") + var/obj/machinery/power/breakerbox/toggle = null + for(var/obj/machinery/power/breakerbox/breaker in known_breakers) + if(breaker.RCon_tag == params["breaker"]) + toggle = breaker + if(toggle) + if(toggle.update_locked) + to_chat(usr, "The breaker box was recently toggled. Please wait before toggling it again.") + else + toggle.auto_toggle() + . = TRUE + + +// Proc: GetSMESByTag() +// Parameters: 1 (tag - RCON tag of SMES we want to look up) +// Description: Looks up and returns SMES which has matching RCON tag +/datum/tgui_module/rcon/proc/GetSMESByTag(var/tag) + if(!tag) + return + + for(var/obj/machinery/power/smes/buildable/S in known_SMESs) + if(S.RCon_tag == tag) + return S + +// Proc: FindDevices() +// Parameters: None +// Description: Refreshes local list of known devices. +/datum/tgui_module/rcon/proc/FindDevices() + known_SMESs = new /list() + + var/z = get_z(tgui_host()) + var/list/map_levels = using_map.get_map_levels(z) + + for(var/obj/machinery/power/smes/buildable/SMES in GLOB.smeses) + if(!(SMES.z in map_levels)) + continue + if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon) + known_SMESs.Add(SMES) + + known_breakers = new /list() + for(var/obj/machinery/power/breakerbox/breaker in machines) + if(!(breaker.z in map_levels)) + continue + if(breaker.RCon_tag != "NO_TAG") + known_breakers.Add(breaker) + +/datum/tgui_module/rcon/ntos + ntos = TRUE + +/datum/tgui_module/rcon/robot +/datum/tgui_module/rcon/robot/tgui_state(mob/user) + return GLOB.tgui_self_state \ No newline at end of file diff --git a/code/modules/tgui/modules/shutoff_monitor.dm b/code/modules/tgui/modules/shutoff_monitor.dm new file mode 100644 index 0000000000..ead6502dc4 --- /dev/null +++ b/code/modules/tgui/modules/shutoff_monitor.dm @@ -0,0 +1,46 @@ +/datum/tgui_module/shutoff_monitor + name = "Shutoff Valve Monitoring" + tgui_id = "ShutoffMonitor" + +/datum/tgui_module/shutoff_monitor/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("toggle_enable") + var/obj/machinery/atmospherics/valve/shutoff/S = locate(params["valve"]) + if(!istype(S)) + return 0 + S.close_on_leaks = !S.close_on_leaks + return 1 + + if("toggle_open") + var/obj/machinery/atmospherics/valve/shutoff/S = locate(params["valve"]) + if(!istype(S)) + return 0 + if(S.open) + S.close() + else + S.open() + return 1 + +/datum/tgui_module/shutoff_monitor/tgui_data(mob/user) + var/list/data = list() + var/list/valves = list() + + for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves) + valves.Add(list(list( + "name" = S.name, + "enabled" = S.close_on_leaks, + "open" = S.open, + "x" = S.x, + "y" = S.y, + "z" = S.z, + "ref" = "\ref[S]" + ))) + + data["valves"] = valves + return data + +/datum/tgui_module/shutoff_monitor/ntos + ntos = TRUE \ No newline at end of file diff --git a/code/modules/tgui/modules/supermatter_monitor.dm b/code/modules/tgui/modules/supermatter_monitor.dm new file mode 100644 index 0000000000..0e0aed4f1b --- /dev/null +++ b/code/modules/tgui/modules/supermatter_monitor.dm @@ -0,0 +1,108 @@ + +/datum/tgui_module/supermatter_monitor + name = "Supermatter monitor" + tgui_id = "SupermatterMonitor" + var/list/supermatters + var/obj/machinery/power/supermatter/active = null // Currently selected supermatter crystal. + +/datum/tgui_module/supermatter_monitor/Destroy() + . = ..() + active = null + supermatters = null + +/datum/tgui_module/supermatter_monitor/New() + ..() + refresh() + +// Refreshes list of active supermatter crystals +/datum/tgui_module/supermatter_monitor/proc/refresh() + supermatters = list() + var/z = get_z(tgui_host()) + if(!z) + return + var/valid_z_levels = using_map.get_map_levels(z) + for(var/obj/machinery/power/supermatter/S in machines) + // Delaminating, not within coverage, not on a tile. + if(S.grav_pulling || S.exploded || !(S.z in valid_z_levels) || !istype(S.loc, /turf/)) + continue + supermatters.Add(S) + + if(!(active in supermatters)) + active = null + +/datum/tgui_module/supermatter_monitor/proc/get_status() + . = SUPERMATTER_INACTIVE + for(var/obj/machinery/power/supermatter/S in supermatters) + . = max(., S.get_status()) + +/datum/tgui_module/supermatter_monitor/tgui_data(mob/user) + var/list/data = ..() + + if(istype(active)) + var/turf/T = get_turf(active) + if(!T) + active = null + return + var/datum/gas_mixture/air = T.return_air() + if(!istype(air)) + active = null + return + + data["active"] = 1 + data["SM_area"] = get_area(active) + data["SM_integrity"] = active.get_integrity() + data["SM_power"] = active.power + data["SM_ambienttemp"] = air.temperature + data["SM_ambientpressure"] = air.return_pressure() + data["SM_EPR"] = active.get_epr() + //data["SM_EPR"] = active.get_epr() + if(air.total_moles) + data["SM_gas_O2"] = round(100*air.gas["oxygen"]/air.total_moles,0.01) + data["SM_gas_CO2"] = round(100*air.gas["carbon_dioxide"]/air.total_moles,0.01) + data["SM_gas_N2"] = round(100*air.gas["nitrogen"]/air.total_moles,0.01) + data["SM_gas_PH"] = round(100*air.gas["phoron"]/air.total_moles,0.01) + data["SM_gas_N2O"] = round(100*air.gas["sleeping_agent"]/air.total_moles,0.01) + else + data["SM_gas_O2"] = 0 + data["SM_gas_CO2"] = 0 + data["SM_gas_N2"] = 0 + data["SM_gas_PH"] = 0 + data["SM_gas_N2O"] = 0 + else + var/list/SMS = list() + for(var/obj/machinery/power/supermatter/S in supermatters) + var/area/A = get_area(S) + if(!A) + continue + + SMS.Add(list(list( + "area_name" = A.name, + "integrity" = S.get_integrity(), + "uid" = S.uid + ))) + + data["active"] = 0 + data["supermatters"] = SMS + + return data + +/datum/tgui_module/supermatter_monitor/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("clear") + active = null + . = TRUE + if("refresh") + refresh() + . = TRUE + if("set") + var/newuid = text2num(params["set"]) + for(var/obj/machinery/power/supermatter/S in supermatters) + if(S.uid == newuid) + active = S + . = TRUE + +/datum/tgui_module/supermatter_monitor/ntos + ntos = TRUE \ No newline at end of file diff --git a/code/modules/turbolift/turbolift_console.dm b/code/modules/turbolift/turbolift_console.dm index d69a9b0a16..9d8b90f802 100644 --- a/code/modules/turbolift/turbolift_console.dm +++ b/code/modules/turbolift/turbolift_console.dm @@ -143,57 +143,56 @@ /obj/structure/lift/panel/interact(var/mob/user) if(!..()) return + + tgui_interact(user) - var/dat = list() - dat += "
Lift panel
" +/obj/structure/lift/panel/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Turbolift", name) + ui.open() - //the floors list stores levels in order of increasing Z - //therefore, to display upper levels at the top of the menu and - //lower levels at the bottom, we need to go through the list in reverse +/obj/structure/lift/panel/tgui_data(mob/user) + var/list/data = list() + + data["doors_open"] = lift.doors_are_open() + data["fire_mode"] = lift.fire_mode + + data["floors"] = list() for(var/i in lift.floors.len to 1 step -1) var/datum/turbolift_floor/floor = lift.floors[i] - var/label = floor.label? floor.label : "Level #[i]" - dat += "" - dat += "[label]: [floor.name]
" + data["floors"].Add(list(list( + "id" = i, + "ref" = "\ref[floor]", + "queued" = (floor in lift.queued_floors), + "target" = (lift.target_floor == floor), + "current" = (lift.current_floor == floor), + "label" = floor.label, + "name" = floor.name, + ))) + + return data - dat += "
" - if(lift.doors_are_open()) - dat += "Close Doors
" - else - dat += "Open Doors
" - dat += "Emergency Stop" - dat += "
" +/obj/structure/lift/panel/tgui_act(action, params) + if(..()) + return TRUE - user.set_machine(src) - var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 350, 320) //VOREStation Edit - Wider! - popup.set_content(jointext(dat, null)) - popup.open() - return + switch(action) + if("move_to_floor") + . = TRUE + lift.queue_move_to(locate(params["ref"])) + if("toggle_doors") + . = TRUE + if(lift.doors_are_open()) + lift.close_doors() + else + lift.open_doors() + if("emergency_stop") + . = TRUE + lift.emergency_stop() -/obj/structure/lift/panel/Topic(href, href_list) - . = ..() if(.) - return - - var/panel_interact - if(href_list["move_to_floor"]) - lift.queue_move_to(locate(href_list["move_to_floor"])) - panel_interact = 1 - if(href_list["open_doors"]) - panel_interact = 1 - lift.open_doors() - if(href_list["close_doors"]) - panel_interact = 1 - lift.close_doors() - if(href_list["emergency_stop"]) - panel_interact = 1 - lift.emergency_stop() - - if(panel_interact) pressed(usr) - updateDialog() - - return 0 /obj/structure/lift/panel/update_icon() if(lift.fire_mode) diff --git a/maps/tether/tether_phoronlock.dm b/maps/tether/tether_phoronlock.dm index 9118284285..3afc89ebce 100644 --- a/maps/tether/tether_phoronlock.dm +++ b/maps/tether/tether_phoronlock.dm @@ -126,49 +126,18 @@ obj/machinery/airlock_sensor/phoron/airlock_exterior //Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks /obj/machinery/embedded_controller/radio/airlock/phoron name = "Phoron Lock Controller" + valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "secure") -/obj/machinery/embedded_controller/radio/airlock/phoron/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data = list( +/obj/machinery/embedded_controller/radio/airlock/phoron/tgui_data(mob/user) + . = list( "chamber_pressure" = program.memory["chamber_sensor_pressure"], "chamber_phoron" = program.memory["chamber_sensor_phoron"], "exterior_status" = program.memory["exterior_status"], "interior_status" = program.memory["interior_status"], - "processing" = program.memory["processing"] + "processing" = program.memory["processing"], + "internalTemplateName" = "AirlockConsolePhoron", ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "phoron_airlock_console.tmpl", name, 470, 290) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/embedded_controller/radio/airlock/phoron/Topic(href, href_list) - if((. = ..())) - return - - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks - if("cycle_ext") - clean = 1 - if("cycle_int") - clean = 1 - if("force_ext") - clean = 1 - if("force_int") - clean = 1 - if("abort") - clean = 1 - if("secure") - clean = 1 - - if(clean) - program.receive_user_command(href_list["command"]) - - return 1 - // // PHORON LOCK CONTROLLER PROGRAM // diff --git a/nano/images/tether_nanomap_z1.png b/nano/images/tether_nanomap_z1.png index bd575097c3194981d5cde781969a667cd532100c..c463bd04b76144a712801775dd1d4a34988b685e 100644 GIT binary patch literal 23848 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

7{buo~XU0$lQ^Y3*RRtHYYU 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 NoJO9iK6&x_zX7sLdBXqz literal 24076 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¬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 Qb^ja2#p49)*!i3P0^j|9>i_@% diff --git a/nano/templates/advanced_airlock_console.tmpl b/nano/templates/advanced_airlock_console.tmpl deleted file mode 100644 index e60cf7c932..0000000000 --- a/nano/templates/advanced_airlock_console.tmpl +++ /dev/null @@ -1,60 +0,0 @@ -

-
-
- External Pressure: -
-
- {{:helper.displayBar(data.external_pressure, 0, 200, (data.external_pressure < 80 || data.external_pressure > 120) ? 'bad' : (data.external_pressure < 95 || data.external_pressure > 110) ? 'average' : 'good')}} -
- {{:data.external_pressure}} kPa -
-
-
-
-
- Chamber Pressure: -
-
- {{:helper.displayBar(data.chamber_pressure, 0, 200, (data.chamber_pressure < 80 || data.chamber_pressure > 120) ? 'bad' : (data.chamber_pressure < 95 || data.chamber_pressure > 110) ? 'average' : 'good')}} -
- {{:data.chamber_pressure}} kPa -
-
-
-
-
- Internal Pressure: -
-
- {{:helper.displayBar(data.internal_pressure, 0, 200, (data.internal_pressure < 80 || data.internal_pressure > 120) ? 'bad' : (data.internal_pressure < 95 || data.internal_pressure > 110) ? 'average' : 'good')}} -
- {{:data.internal_pressure}} kPa -
-
-
-
-
-
-
- {{:helper.link('Cycle to Exterior', 'arrowthickstop-1-w', {'command' : 'cycle_ext'}, data.processing ? 'disabled' : null)}} - {{:helper.link('Cycle to Interior', 'arrowthickstop-1-e', {'command' : 'cycle_int'}, data.processing ? 'disabled' : null)}} -
-
- {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, data.processing ? 'yellowButton' : null)}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, data.processing ? 'yellowButton' : null)}} -
-
-
-
-
- {{:helper.link('Purge', 'refresh', {'command' : 'purge'}, data.processing ? 'disabled' : null, data.purge ? 'linkOn' : null)}} -
-
- {{:helper.link('Secure', data.secure ? 'locked' : 'unlocked', {'command' : 'secure'}, data.processing ? 'disabled' : null, data.secure ? 'linkOn' : null)}} -
-
-
-
- {{:helper.link('Abort', 'cancel', {'command' : 'abort'}, data.processing ? null : 'disabled', data.processing ? 'redButton' : null)}} -
-
\ No newline at end of file diff --git a/nano/templates/aicard.tmpl b/nano/templates/aicard.tmpl deleted file mode 100644 index 40a192a165..0000000000 --- a/nano/templates/aicard.tmpl +++ /dev/null @@ -1,103 +0,0 @@ - - - - -{{if data.has_ai}} -
-
- Hardware Integrity: -
-
- {{:data.hardware_integrity}}% -
-
- Backup Capacitor: -
-
- {{:data.backup_capacitor}}% -
-
- - {{if data.has_laws}} - - - -
- Laws: -
- {{for data.laws}} - - {{/for}} -
IndexLaw
{{:value.index}}.{{:value.law}}
- {{else}} - No laws found. - {{/if}} - - {{if data.operational}} - - - - - - - - - - - {{if data.flushing}} - - {{else}} - - - - - {{/if}} -
Radio Subspace Transceiver{{:helper.link("Enabled", null, {'radio' : 0}, data.radio ? 'selected' : null)}}{{:helper.link("Disabled", null, {'radio' : 1}, data.radio ? null : 'redButton' )}}
Wireless Interface{{:helper.link("Enabled", null, {'wireless' : 0}, data.wireless ? 'selected' : null)}}{{:helper.link("Disabled", null, {'wireless' : 1}, data.wireless ? null : 'redButton' )}}
AI shutdown in progress...
AI Power{{:helper.link("Shutdown", 'radiation', {'wipe' : 1}, null, 'redButton')}}
- {{/if}} -{{else}} - Stored AI: No AI detected. -{{/if}} diff --git a/nano/templates/air_alarm.tmpl b/nano/templates/air_alarm.tmpl deleted file mode 100644 index 5914d32646..0000000000 --- a/nano/templates/air_alarm.tmpl +++ /dev/null @@ -1,217 +0,0 @@ - -

Air Status

-{{if data.has_environment}} - {{for data.environment}} - {{:value.name}}: - {{if value.danger_level == 2}} - - {{else value.danger_level == 1}} - - {{else}} - - {{/if}} - {{:helper.fixed(value.value, 1)}} - {{:value.unit}}
- {{/for}} - Local Status: {{if data.total_danger == 2}} - DANGER: Internals Required - {{else data.total_danger == 1}} - Caution - {{else}} - Optimal - {{/if}} -
- Area Status: {{if data.atmos_alarm}}Atmosphere alert in area{{else data.fire_alarm}}Fire alarm in area{{else}}No alerts{{/if}} -{{else}} - Warning: Cannot obtain air sample for analysis. -{{/if}} -
- - - - - - - - - - - - - -
-
-

Remote Control

-
-

Thermostat

-
-
-
-
- {{:helper.link('Off', null, { 'rcon' : 1}, data.remote_connection && !data.remote_access ? (data.rcon == 1 ? 'yellowButton' : 'disabled') : null, data.rcon == 1 ? 'selected' : null)}} - {{:helper.link('Auto', null, { 'rcon' : 2}, data.remote_connection && !data.remote_access ? (data.rcon == 2 ? 'yellowButton' : 'disabled') : null, data.rcon == 2 ? 'selected' : null)}} - {{:helper.link('On', null, { 'rcon' : 3}, data.remote_connection && !data.remote_access ? (data.rcon == 3 ? 'yellowButton' : 'disabled') : null, data.rcon == 3 ? 'selected' : null)}} -
-
-
- {{:helper.link(data.target_temperature, null, { 'temperature' : 1})}} -
-
-{{if (data.locked && !data.remote_connection) || (data.remote_connection && ! data.remote_access)}} - {{if data.remote_connection}} - (Current remote control settings and alarm status restricts access.) - {{else}} - (Swipe ID card to unlock interface.) - {{/if}} -{{else}} - {{if data.screen != 1}} -
{{:helper.link('Main Menu', null, { 'screen' : 1})}}
- {{/if}} - {{if data.screen == 1}} -
- {{if data.atmos_alarm}} - {{:helper.link('Reset - Area Atmospheric Alarm', null, { 'atmos_reset' : 1})}} - {{else}} - {{:helper.link('Activate - Area Atmospheric Alarm', null, { 'atmos_alarm' : 1})}} - {{/if}} -
-
-
- {{:helper.link('Scrubbers Control', null, { 'screen' : 3})}} -
-
- {{:helper.link('Vents Control', null, { 'screen' : 2})}} -
-
- {{:helper.link('Set Environmental Mode', null, { 'screen' : 4})}} -
-
- {{:helper.link('Sensor Settings', null, { 'screen' : 5})}} -
-
- {{if data.mode==3}} - {{:helper.link('PANIC SIPHON ACTIVE - Turn siphoning off', null, { 'mode' : 1}, null, 'redButton')}} - {{else}} - {{:helper.link('ACTIVATE PANIC SIPHON IN AREA', null, { 'mode' : 3}, null, 'yellowButton')}} - {{/if}} - {{else data.screen == 2}} - {{for data.vents}} -
- {{:value.long_name}}
-
-
- Operating: -
-
- {{:helper.link(value.power ? 'On' : 'Off', null, { 'id_tag' : value.id_tag, 'command' : 'power', 'val' : value.power ? 0 : 1}, null, value.power ? null : 'redButton')}} -
-
-
-
- Operation Mode: -
-
- {{:helper.link(value.direction == "siphon" ? 'Siphoning' : 'Pressurizing', null, { 'id_tag' : value.id_tag, 'command' : 'direction', 'val' : value.direction == "siphon" ? 1 : 0}, null, value.direction == "siphon" ? 'redButton' : null)}} -
-
-
-
- Pressure Checks: -
-
- {{:helper.link('External', null, { 'id_tag' : value.id_tag, 'command' : 'checks', 'val' : value.checks^1}, null, value.checks&1 ? 'selected' : null)}} - {{:helper.link('Internal', null, { 'id_tag' : value.id_tag, 'command' : 'checks', 'val' : value.checks^2}, null, value.checks&2 ? 'selected' : null)}} -
-
-
-
- External Pressure Bound: -
-
- {{:helper.link(helper.fixed(value.external,2), null, { 'id_tag' : value.id_tag, 'command' : 'set_external_pressure'})}} - {{:helper.link('Reset', null, { 'id_tag' : value.id_tag, 'command' : 'reset_external_pressure'})}} -
-
-
- {{empty}} - No vents connected. - {{/for}} - {{else data.screen == 3}} - {{for data.scrubbers}} -
- {{:value.long_name}}
-
-
- Operating: -
-
- {{:helper.link(value.power ? 'On' : 'Off', null, { 'id_tag' : value.id_tag, 'command' : 'power', 'val' : value.power ? 0 : 1}, null, value.power ? null : 'redButton')}} -
-
-
-
- Operation Mode: -
-
- {{:helper.link(value.scrubbing ? 'Scrubbing' : 'Siphoning', null, { 'id_tag' : value.id_tag, 'command' : 'scrubbing', 'val' : value.scrubbing ? 0 : 1}, null, value.scrubbing ? null : 'redButton')}} -
-
-
-
- Filters: -
-
- {{for value.filters :filterValue:filterIndex}} - {{:helper.link(filterValue.name, null, { 'id_tag' : value.id_tag, 'command' : filterValue.command, 'val' : filterValue.val ? 0 : 1}, null, filterValue.val ? 'selected' : null)}} - {{/for}} -
-
-
- {{empty}} - No scrubbers connected. - {{/for}} - {{else data.screen == 4}} -

Environmental Modes

- {{for data.modes}} -
- {{:helper.link(value.name, null, { 'mode' : value.mode }, null, value.selected ? (value.danger ? 'redButton' : 'selected') : null)}} -
- {{/for}} - {{else data.screen == 5}} -

Alarm Threshold

- Partial pressure for gases. - - - - - {{for data.thresholds}} - - - {{for value.settings :settingsValue:settingsIndex}} - - {{/for}} - - {{/for}} -
min2min1max1max2
{{:value.name}} - {{:helper.link(settingsValue.selected >= 0 ? helper.fixed(settingsValue.selected, 2) : "Off", null, { 'command' : 'set_threshold', 'env' : settingsValue.env, 'var' : settingsValue.val })}} -
- {{/if}} -{{/if}} - \ No newline at end of file diff --git a/nano/templates/alarm_monitor.tmpl b/nano/templates/alarm_monitor.tmpl deleted file mode 100644 index 2591763fc0..0000000000 --- a/nano/templates/alarm_monitor.tmpl +++ /dev/null @@ -1,38 +0,0 @@ - - -{{for data.categories}} -

{{:value.category}}

- {{for value.alarms :alarmValue:alarmIndex}} - {{if alarmValue.origin_lost}} - {{:alarmValue.name}} Alarm Origin Lost
- {{else}} - {{:alarmValue.name}}
- {{/if}} - {{if alarmValue.has_cameras || alarmValue.lost_sources != ""}} -
- {{if alarmValue.has_cameras}} -
- {{for alarmValue.cameras :cameraValue:cameraIndex}} - {{if cameraValue.deact}} - {{:helper.link(cameraValue.name + " (deactivated)", '', {}, 'inactive')}} - {{else}} - {{:helper.link(cameraValue.name, '', {'switchTo' : cameraValue.camera})}} - {{/if}} - {{/for}} -
- {{/if}} - {{if alarmValue.lost_sources != ""}} -
-

Lost Alarm Sources: {{:alarmValue.lost_sources}}

-
- {{/if}} -
- {{/if}} - {{empty}} - --All Systems Nominal - {{/for}} -{{/for}} diff --git a/nano/templates/algae_farm_vr.tmpl b/nano/templates/algae_farm_vr.tmpl deleted file mode 100644 index be730d9d65..0000000000 --- a/nano/templates/algae_farm_vr.tmpl +++ /dev/null @@ -1,70 +0,0 @@ - -{{if data.errorText }} -
{{:data.errorText}}

-{{/if}} - -
-
- {{if data.usePower==2}} - {{:helper.link('Deactivate Processing', 'power', {'deactivate' : 1})}} - {{else}} - {{:helper.link('Activate Processing', 'power', {'activate' : 1})}} - {{/if}} -
-
-
Flow Rate
-
{{:helper.fixed(data.last_flow_rate)}} L/s
-
-
-
Power Draw
-
{{:helper.formatNumber(data.last_power_draw)}} Watts
-
-
- -

Materials

-
- {{for data.materials }} -
-
{{:value.display.toTitleCase()}}
-
{{:helper.displayBar(value.percent, 0, 100, - (value.percent < 25) ? 'bad' : (value.percent < 50) ? 'average' : 'good', - value.qty + "/" + value.max )}}
-
{{:helper.link("Eject", 'eject', {'ejectMaterial' : value.name })}}
-
- {{/for}} -
- -

Gas Input ({{:data.inputDir}})

-
- {{if data.input}} -
-
Total Pressure
-
{{:data.input.pressure}} kPa
-
-
-
{{:data.input.name}}
-
{{:helper.fixed(data.input.percent)}}% ({{:helper.fixed(data.input.moles)}} moles)
-
- {{else}} -
Not Connected
- {{/if}} -
- -

Gas Output ({{:data.outputDir}})

-
- {{if data.output}} -
-
Total Pressure
-
{{:data.output.pressure}} kPa
-
-
-
{{:data.output.name}}
-
{{:helper.fixed(data.output.percent)}}% ({{:helper.fixed(data.output.moles)}} moles)
-
- {{else}} -
Not Connected
- {{/if}} -
diff --git a/nano/templates/apc.tmpl b/nano/templates/apc.tmpl deleted file mode 100644 index a26abef4a0..0000000000 --- a/nano/templates/apc.tmpl +++ /dev/null @@ -1,229 +0,0 @@ -{{if data.gridCheck}} -
-

SYSTEM FAILURE

- Power surge detected, grid check in effect...
-
-{{else data.failTime}} -
-

SYSTEM FAILURE

- I/O regulators malfunction detected! Waiting for system reboot...
- Automatic reboot in {{:data.failTime}} seconds...
- {{if !data.siliconUser}} - {{if data.locked}} - Swipe an ID card for manual reboot.


- {{else}} - {{:helper.link('Reboot Now', 'refresh', {'reboot' : 1})}}


- {{/if}} - {{else}} - {{:helper.link('Reboot Now', 'refresh', {'reboot' : 1})}}


- {{/if}} -
-{{else}} -
- {{if data.siliconUser}} -
- Interface Lock: -
-
- {{:helper.link('Engaged', 'locked', {'toggleaccess' : 1}, data.locked ? 'selected' : null)}}{{:helper.link('Disengaged', 'unlocked', {'toggleaccess' : 1}, data.malfStatus >= 2 ? 'linkOff' : (data.locked ? null : 'selected'))}} -
-
- {{else}} - {{if data.emagged}} -

Fault in ID authenticator

- Please contact maintenance for service. - {{else data.locked}} - Swipe an ID card to unlock this interface - {{else}} - Swipe an ID card to lock this interface - {{/if}} - {{/if}} -
- -
- -

Power Status

- -
-
- Main Breaker: -
-
- {{if data.locked && !data.siliconUser}} - {{if data.isOperating}} - On - {{else}} - Off - {{/if}} - {{else}} - {{:helper.link('On', 'power', {'breaker' : 1}, data.isOperating ? 'selected' : null)}}{{:helper.link('Off', 'close', {'breaker' : 1}, data.isOperating ? null : 'selected')}} - {{/if}} -
-
- -
-
- External Power: -
-
- {{if data.externalPower == 2}} - Good - {{else data.externalPower == 1}} - Low - {{else}} - None - {{/if}} -
-
- -
-
- Power Cell: -
- {{if data.powerCellStatus == null}} -
- Power cell removed. -
- {{else}} - - {{:helper.displayBar(data.powerCellStatus, 0, 100, (data.powerCellStatus >= 50) ? 'good' : (data.powerCellStatus >= 25) ? 'average' : 'bad')}} -
- {{:helper.round(data.powerCellStatus*10)/10}}% -
- {{/if}} -
- - {{if data.powerCellStatus != null}} -
-
- Charge Mode: -
-
- {{if data.locked && !data.siliconUser}} - {{if data.chargeMode}} - Auto - {{else}} - Off - {{/if}} - {{else}} - {{:helper.link('Auto', 'refresh', {'cmode' : 1}, data.chargeMode ? 'selected' : null)}}{{:helper.link('Off', 'close', {'cmode' : 1}, data.chargeMode ? null : 'selected')}} - {{/if}} -   - {{if data.chargingStatus > 1}} - [Fully Charged] - {{else data.chargingStatus == 1}} - [Charging] - {{else}} - [Not Charging] - {{/if}} -
-
- {{/if}} - - -

Power Channels

- - {{for data.powerChannels}} -
-
- {{:value.title}}: -
-
- {{:value.powerLoad}} W -
-
-    - {{if value.status <= 1}} - Off - {{else value.status >= 2}} - On - {{/if}} - {{if data.locked}} - {{if value.status == 1 || value.status == 3}} -   Auto - {{else}} -   Manual - {{/if}} - {{/if}} -
- {{if !data.locked || data.siliconUser}} -
- {{:helper.link('Auto', 'refresh', value.topicParams.auto, (value.status == 1 || value.status == 3) ? 'selected' : null)}} - {{:helper.link('On', 'power', value.topicParams.on, (value.status == 2) ? 'selected' : null)}} - {{:helper.link('Off', 'close', value.topicParams.off, (value.status == 0) ? 'selected' : null)}} -
- {{/if}} -
- {{/for}} - -
-
- Total Load: -
-
- {{if data.totalCharging}} - {{:data.totalLoad}}W (+ {{:data.totalCharging}}W Charging) - {{else}} - {{:data.totalLoad}}W - {{/if}} -
-
- -
 
- -
-
- Cover Lock: -
-
- {{if data.locked && !data.siliconUser}} - {{if data.coverLocked}} - Engaged - {{else}} - Disengaged - {{/if}} - {{else}} - {{:helper.link('Engaged', 'locked', {'lock' : 1}, data.coverLocked ? 'selected' : null)}}{{:helper.link('Disengaged', 'unlocked', {'lock' : 1}, data.coverLocked ? null : 'selected')}} - {{/if}} -
-
- -
-
- Emergency Lighting: -
-
- {{if data.locked && !data.siliconUser}} - {{:data.emergencyLights ? "Enabled" : "Disabled"}} - {{else}} - {{:helper.link(data.emergencyLights ? 'Enabled' : 'Disabled', data.emergencyLights ? 'power' : 'close', {'emergency_lighting' : 1}, null)}} - {{/if}} -
-
- -
-
- Night Lighting: -
-
- {{:helper.link('Disabled', null, {'nightshift' : 2}, data.nightshiftSetting == 2 ? 'selected' : null)}} - {{:helper.link('Automatic', null, {'nightshift' : 1}, data.nightshiftSetting == 1 ? 'selected' : null)}} - {{:helper.link('Enabled', null, {'nightshift' : 3}, data.nightshiftSetting == 3 ? 'selected' : null)}} -
-
- - {{if data.siliconUser}} -

System Overrides

- -
- {{:helper.link('Overload Lighting Circuit', 'lightbulb', {'overload' : 1})}} - {{if data.malfStatus == 1}} - {{:helper.link('Override Programming', 'script', {'malfhack' : 1})}} - {{else data.malfStatus > 1}} -
APC Hacked
- {{/if}} -
- {{/if}} - -
-{{/if}} \ No newline at end of file diff --git a/nano/templates/atmo_control.tmpl b/nano/templates/atmo_control.tmpl deleted file mode 100644 index d3c61758e7..0000000000 --- a/nano/templates/atmo_control.tmpl +++ /dev/null @@ -1,224 +0,0 @@ - -{{if data.sensors}} - {{for data.sensors}} - {{if value.sensor_data}} -
-
{{:value.long_name}}
- {{if value.sensor_data.pressure}} -
-
Pressure:
-
{{:value.sensor_data.pressure}} kPa
-
- {{/if}} - {{if value.sensor_data.temperature}} -
-
Temperature:
-
{{:value.sensor_data.temperature}} K
-
- {{/if}} - {{if value.sensor_data.oxygen || value.sensor_data.nitrogen || value.sensor_data.carbon_dioxide || value.sensor_data.phoron}} -
-
Gas Composition:
- {{if value.sensor_data.oxygen}} -
{{:value.sensor_data.oxygen}}% O2
- {{/if}} - {{if value.sensor_data.nitrogen}} -
{{:value.sensor_data.nitrogen}}% N
- {{/if}} - {{if value.sensor_data.carbon_dioxide}} -
{{:value.sensor_data.carbon_dioxide}}% CO2
- {{/if}} - {{if value.sensor_data.phoron}} -
{{:value.sensor_data.phoron}}% TX
- {{/if}} -
- {{/if}} -
- {{else}} -
-
{{:value.long_name}} can not be found!
-
- {{/if}} - {{/for}} -{{else}} -
- No sensors connected. -
-{{/if}} - -{{if data.tanks || data.core}} -

- {{if data.tanks}} - Tank Control System - {{else data.core}} - Core Cooling Control System - {{/if}} -

- - {{if data.input_info}} -
-
- {{if data.tanks}} - Input: - {{else data.core}} - Coolant Input: - {{/if}} -
-
- {{if data.input_info.power}} - Injecting - {{else}} - On Hold - {{/if}} -
-
-
-
Flow Rate Limit:
-
{{:data.input_info.volume_rate}} L/s
-
-
-
Command:
- {{:helper.link('Toggle Power', 'power', {'in_toggle_injector' : 1})}} - {{:helper.link('Set Flow Rate', 'pencil', {'in_set_flowrate' : 1})}} - {{:helper.link('Refresh', 'refresh', {'in_refresh_status' : 1})}} -
- {{else}} -
-
ERROR: Can not find input port
- {{:helper.link('Search', 'search', {'in_refresh_status' : 1})}} -
- {{/if}} -
-
- Flow Rate Limit: -
-
- {{:helper.link('100', 'minus', {'adj_input_flow_rate' : -100})}} - {{:helper.link('10', 'minus', {'adj_input_flow_rate' : -10})}} - {{:helper.link('1', 'minus', {'adj_input_flow_rate' : -1})}} - {{:helper.link('0.1', 'minus', {'adj_input_flow_rate' : -0.1})}} -
 {{:data.input_flow_setting}} L/s 
- {{:helper.link('0.1', 'plus', {'adj_input_flow_rate' : 0.1})}} - {{:helper.link('1', 'plus', {'adj_input_flow_rate' : 1})}} - {{:helper.link('10', 'plus', {'adj_input_flow_rate' : 10})}} - {{:helper.link('100', 'plus', {'adj_input_flow_rate' : 100})}} -
-
- - {{if data.output_info}} -
-
- {{if data.tanks}} - Output: - {{else data.core}} - Core Outpump: - {{/if}} -
-
- {{if data.output_info.power}} - Open - {{else}} - On Hold - {{/if}} -
-
-
- {{if data.tanks}} -
Max Output Pressure:
-
{{:data.output_info.output_pressure}} kPa
- {{else data.core}} -
Min Core Pressure:
-
{{:data.output_info.pressure_limit}} kPa
- {{/if}} -
-
-
Command:
- {{:helper.link('Toggle Power', 'power', {'out_toggle_power' : 1})}} - {{:helper.link('Set Pressure', 'pencil', {'out_set_pressure' : 1})}} - {{:helper.link('Refresh', 'refresh', {'out_refresh_status' : 1})}} -
- {{else}} -
-
ERROR: Can not find output port
- {{:helper.link('Search', 'search', {'out_refresh_status' : 1})}} -
- {{/if}} - -
- {{if data.tanks}} -
- Max Output Pressure Set: -
-
- {{:helper.link('1000', 'minus', {'adj_pressure' : -1000})}} - {{:helper.link('100', 'minus', {'adj_pressure' : -100})}} - {{:helper.link('10', 'minus', {'adj_pressure' : -10})}} - {{:helper.link('1', 'minus', {'adj_pressure' : -1})}} -
 {{:data.pressure_setting}} kPa 
- {{:helper.link('1', 'plus', {'adj_pressure' : 1})}} - {{:helper.link('10', 'plus', {'adj_pressure' : 10})}} - {{:helper.link('100', 'plus', {'adj_pressure' : 100})}} - {{:helper.link('1000', 'plus', {'adj_pressure' : 1000})}} -
- {{else data.core}} -
- Min Core Pressure Set: -
-
- {{:helper.link('100', 'minus', {'adj_pressure' : -100})}} - {{:helper.link('50', 'minus', {'adj_pressure' : -50})}} - {{:helper.link('10', 'minus', {'adj_pressure' : -10})}} - {{:helper.link('1', 'minus', {'adj_pressure' : -1})}} -
 {{:data.pressure_setting}} kPa 
- {{:helper.link('1', 'plus', {'adj_pressure' : 1})}} - {{:helper.link('10', 'plus', {'adj_pressure' : 10})}} - {{:helper.link('50', 'plus', {'adj_pressure' : 50})}} - {{:helper.link('100', 'plus', {'adj_pressure' : 100})}} -
- {{/if}} -
-{{/if}} - -{{if data.fuel}} -

Fuel Injection System

- - {{if data.device_info}} -
-
- Status: -
-
- {{if data.device_info.power}} - Injecting - {{else}} - On Hold - {{/if}} -
{{:helper.link('Refresh', 'refresh', {'refresh_status' : 1})}}
-
-
-
-
Rate:
-
{{:data.device_info.volume_rate}} L/s
-
-
-
Automated Fuel Injection:
- {{if data.automation}} - {{:helper.link('Engaged', 'check', {'toggle_automation' : 1})}} -
Injector Controls Locked Out
- {{else}} - {{:helper.link('Disengaged', 'close', {'toggle_automation' : 1})}} -
Injector:
- {{:helper.link('Toggle Power', 'power', {'toggle_injector' : 1})}} - {{:helper.link('Inject (1 Cycle)', 'syringe', {'injection' : 1})}} - {{/if}} -
- {{else}} -
-
ERROR: Can not find device
- {{:helper.link('Search', 'search', {'refresh_status' : 1})}} -
- {{/if}} -{{/if}} diff --git a/nano/templates/atmos_alert.tmpl b/nano/templates/atmos_alert.tmpl deleted file mode 100644 index 92946e8d31..0000000000 --- a/nano/templates/atmos_alert.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -

Priority Alerts

-{{for data.priority_alarms}} -
- {{:value.name}} {{:helper.link('Reset', null, {'clear_alarm' : value.ref})}} -
-{{empty}} - No priority alerts detected. -{{/for}} - -

Minor Alerts

-{{for data.minor_alarms}} -
- {{:value.name}} {{:helper.link('Reset', null, {'clear_alarm' : value.ref})}} -
-{{empty}} - No minor alerts detected. -{{/for}} - diff --git a/nano/templates/atmos_control.tmpl b/nano/templates/atmos_control.tmpl deleted file mode 100644 index ac50e3fbdf..0000000000 --- a/nano/templates/atmos_control.tmpl +++ /dev/null @@ -1,10 +0,0 @@ -{{if data.map_levels.length}} -
- {{:helper.link('Show Air Alarms On Map', 'pin-s', {'showMap' : 1})}} -
-{{/if}} -
- {{for data.alarms}} - {{:helper.link(value.name, null, {'alarm' : value.ref}, null, value.danger == 2 ? 'redButton' : (value.danger == 1 ? 'yellowButton' : null))}} - {{/for}} -
diff --git a/nano/templates/atmos_control_map_content.tmpl b/nano/templates/atmos_control_map_content.tmpl deleted file mode 100644 index 931ddb974c..0000000000 --- a/nano/templates/atmos_control_map_content.tmpl +++ /dev/null @@ -1,13 +0,0 @@ - -{{for data.alarms}} - {{if value.z == config.mapZLevel}} -
- -
- {{/if}} -{{/for}} diff --git a/nano/templates/atmos_control_map_header.tmpl b/nano/templates/atmos_control_map_header.tmpl deleted file mode 100644 index 7fea71a965..0000000000 --- a/nano/templates/atmos_control_map_header.tmpl +++ /dev/null @@ -1,20 +0,0 @@ - -{{:helper.link('Show List', 'script', {'showMap' : 0})}} -{{if data.map_levels.length > 1}} -
- Z Level:  - {{for data.map_levels }} - {{:helper.link(value, null, {'mapZLevel' : value}, null, config.mapZLevel == value ? 'selected' : null)}} - {{/for}} -
-{{/if}} -
- Zoom Level:  - - - - -
diff --git a/nano/templates/canister.tmpl b/nano/templates/canister.tmpl deleted file mode 100644 index e4033eb016..0000000000 --- a/nano/templates/canister.tmpl +++ /dev/null @@ -1,83 +0,0 @@ -

Tank Status

-
-
- Tank Label: -
-
-
{{:data.name}}
{{:helper.link('Relabel', 'pencil', {'relabel' : 1}, data.canLabel ? null : 'disabled')}} -
-
- -
-
- Tank Pressure: -
-
- {{:data.tankPressure}} kPa -
-
- -
-
- Port Status: -
-
- {{:data.portConnected ? 'Connected' : 'Disconnected'}} -
-
- -

Holding Tank Status

-{{if data.hasHoldingTank}} -
-
- Tank Label: -
-
-
{{:data.holdingTank.name}}
{{:helper.link('Eject', 'eject', {'remove_tank' : 1})}} -
-
- -
-
- Tank Pressure: -
-
- {{:data.holdingTank.tankPressure}} kPa -
-
-{{else}} -
No holding tank inserted.
-
 
-{{/if}} - - -

Release Valve Status

-
-
- Release Pressure: -
-
- {{:helper.displayBar(data.releasePressure, data.minReleasePressure, data.maxReleasePressure)}} -
- {{:helper.link('-', null, {'pressure_adj' : -1000}, (data.releasePressure > data.minReleasePressure) ? null : 'disabled')}} - {{:helper.link('-', null, {'pressure_adj' : -100}, (data.releasePressure > data.minReleasePressure) ? null : 'disabled')}} - {{:helper.link('-', null, {'pressure_adj' : -10}, (data.releasePressure > data.minReleasePressure) ? null : 'disabled')}} - {{:helper.link('-', null, {'pressure_adj' : -1}, (data.releasePressure > data.minReleasePressure) ? null : 'disabled')}} -
 {{:data.releasePressure}} kPa 
- {{:helper.link('+', null, {'pressure_adj' : 1}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'pressure_adj' : 10}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'pressure_adj' : 100}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'pressure_adj' : 1000}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} -
-
-
- -
-
- Release Valve: -
-
- {{:helper.link('Open', 'unlocked', {'toggle' : 1}, data.valveOpen ? 'selected' : null)}}{{:helper.link('Close', 'locked', {'toggle' : 1}, data.valveOpen ? null : 'selected')}} -
-
- diff --git a/nano/templates/crew_monitor.tmpl b/nano/templates/crew_monitor.tmpl deleted file mode 100644 index 2dbc65d36d..0000000000 --- a/nano/templates/crew_monitor.tmpl +++ /dev/null @@ -1,32 +0,0 @@ - - - -{{if data.map_levels.length}} - {{:helper.link('Show Tracker Map', 'pin-s', {'showMap' : 1})}} -{{/if}} -
- {{for data.crewmembers}} - {{if value.sensor_type == 1}} - {{if data.isAI}}{{/if}} - {{else value.sensor_type == 2}} - {{if data.isAI}}{{/if}} - {{else value.sensor_type == 3}} - {{if data.isAI}}{{/if}} - {{/if}} - {{/for}} -
{{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}}Not Available{{:helper.link('Track', null, {}, 'disabled')}}
{{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}})Not Available{{:helper.link('Track', null, {}, 'disabled')}}
{{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}}){{:value.area}}({{:value.x}}, {{:value.y}}, {{:value.z}}){{:helper.link('Track', null, {'track' : value.ref})}}
diff --git a/nano/templates/crew_monitor_map_content.tmpl b/nano/templates/crew_monitor_map_content.tmpl deleted file mode 100644 index 432649926c..0000000000 --- a/nano/templates/crew_monitor_map_content.tmpl +++ /dev/null @@ -1,13 +0,0 @@ - -{{for data.crewmembers}} - {{if value.sensor_type == 3 && value.z == config.mapZLevel}} -
- -
- {{/if}} -{{/for}} diff --git a/nano/templates/crew_monitor_map_header.tmpl b/nano/templates/crew_monitor_map_header.tmpl deleted file mode 100644 index 2ec9485491..0000000000 --- a/nano/templates/crew_monitor_map_header.tmpl +++ /dev/null @@ -1,20 +0,0 @@ - -{{:helper.link('Show Detail List', 'script', {'showMap' : 0})}} -{{if data.map_levels.length > 1}} -
- Z Level:  - {{for data.map_levels }} - {{:helper.link(value, null, {'mapZLevel' : value}, null, config.mapZLevel == value ? 'selected' : null)}} - {{/for}} -
-{{/if}} -
- Zoom Level:  - - - - -
\ No newline at end of file diff --git a/nano/templates/docking_airlock_console.tmpl b/nano/templates/docking_airlock_console.tmpl deleted file mode 100644 index 08d4dbf0e4..0000000000 --- a/nano/templates/docking_airlock_console.tmpl +++ /dev/null @@ -1,96 +0,0 @@ -
-
-
- Docking Port Status: -
- {{if data.docking_status == "docked"}} -
- {{if !data.override_enabled}} - DOCKED - {{else}} - DOCKED-OVERRIDE ENABLED - {{/if}} - - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - -
- {{else data.docking_status == "docking"}} -
- {{if !data.override_enabled}} - DOCKING - {{else}} - DOCKING-OVERRIDE ENABLED - {{/if}} - - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - -
- {{else data.docking_status == "undocking"}} -
- {{if !data.override_enabled}} - UNDOCKING - {{else}} - UNDOCKING-OVERRIDE ENABLED - {{/if}} - - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - -
- {{else data.docking_status == "undocked"}} -
- {{if !data.override_enabled}} - NOT IN USE - {{else}} - OVERRIDE ENABLED - {{/if}} - - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - -
- {{else}} - ERROR - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - {{/if}} -
-
-
-
-
- Chamber Pressure: -
-
- {{:helper.displayBar(data.chamber_pressure, 0, 200, (data.chamber_pressure < 80 || data.chamber_pressure > 120) ? 'bad' : (data.chamber_pressure < 95 || data.chamber_pressure > 110) ? 'average' : 'good')}} -
- {{:data.chamber_pressure}} kPa -
-
-
-
-
-
-
- {{:helper.link('Cycle to Exterior', 'arrowthickstop-1-w', {'command' : 'cycle_ext'}, (data.processing || data.airlock_disabled) ? 'disabled' : null)}} - {{:helper.link('Cycle to Interior', 'arrowthickstop-1-e', {'command' : 'cycle_int'}, (data.processing || data.airlock_disabled) ? 'disabled' : null)}} -
-
- {{if data.airlock_disabled}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, 'disabled', null)}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, 'disabled', null)}} - {{else}} - {{if data.interior_status.state == "open"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} - {{if data.exterior_status.state == "open"}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} - {{/if}} -
-
-
- {{:helper.link('Abort', 'cancel', {'command' : 'abort'}, (data.processing && !data.airlock_disabled) ? null : 'disabled', (data.processing && !data.airlock_disabled) ? 'redButton' : null)}} -
-
\ No newline at end of file diff --git a/nano/templates/door_access_console.tmpl b/nano/templates/door_access_console.tmpl deleted file mode 100644 index 2e5c81cb7e..0000000000 --- a/nano/templates/door_access_console.tmpl +++ /dev/null @@ -1,42 +0,0 @@ -
-
-
- Exterior Door Status: -
-
- {{if data.exterior_status.state == "closed"}} - Locked - {{else}} - Open - {{/if}} -
-
-
-
- Interior Door Status: -
-
- {{if data.interior_status.state == "closed"}} - Locked - {{else}} - Open - {{/if}} -
-
-
-
-
-
- {{if data.exterior_status.state == "open"}} - {{:helper.link('Lock Exterior Door', 'alert', {'command' : 'force_ext'}, data.processing ? 'disabled' : null)}} - {{else}} - {{:helper.link('Cycle to Exterior', 'arrowthickstop-1-w', {'command' : 'cycle_ext_door'}, data.processing ? 'disabled' : null)}} - {{/if}} - {{if data.interior_status.state == "open"}} - {{:helper.link('Lock Interior Door', 'alert', {'command' : 'force_int'}, data.processing ? 'disabled' : null)}} - {{else}} - {{:helper.link('Cycle to Interior', 'arrowthickstop-1-e', {'command' : 'cycle_int_door'}, data.processing ? 'disabled' : null)}} - {{/if}} -
-
-
\ No newline at end of file diff --git a/nano/templates/escape_pod_berth_console.tmpl b/nano/templates/escape_pod_berth_console.tmpl deleted file mode 100644 index 434fa386cf..0000000000 --- a/nano/templates/escape_pod_berth_console.tmpl +++ /dev/null @@ -1,42 +0,0 @@ -
-
-
- Escape Pod Status: -
-
- {{if data.docking_status == "docked"}} - {{if data.armed}} - ARMED - {{else}} - SYSTEMS OK - {{/if}} - {{else data.docking_status == "undocking"}} - EJECTING-STAND CLEAR! - {{else data.docking_status == "undocked"}} - POD EJECTED - {{else data.docking_status == "docking"}} - INITIALIZING... - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- {{if data.armed}} - {{if data.docking_status == "docked"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', data.override_enabled ? 'redButton' : null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : 'yellowButton')}} - {{/if}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, 'disabled', null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, 'disabled', null)}} - {{/if}} -
-
-
\ No newline at end of file diff --git a/nano/templates/escape_pod_console.tmpl b/nano/templates/escape_pod_console.tmpl deleted file mode 100644 index aa24d3a9ce..0000000000 --- a/nano/templates/escape_pod_console.tmpl +++ /dev/null @@ -1,95 +0,0 @@ -
-
-
- Escape Pod Status: -
-
- {{if data.docking_status == "docked"}} - {{if data.is_armed}} - ARMED - {{else}} - SYSTEMS OK - {{/if}} - {{else data.docking_status == "undocking"}} - EJECTING - {{else data.docking_status == "undocked"}} - POD EJECTED - {{else data.docking_status == "docking"}} - DOCKING - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- Docking Hatch: -
-
- {{if data.docking_status == "docked"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed"}} - CLOSED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "docking"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "undocking"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "undocked"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- {{if data.docking_status == "docked"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', data.override_enabled ? 'redButton' : null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : 'yellowButton')}} - {{/if}} -
-
-
-
-
-
- {{:helper.link('ARM', 'alert', {'command' : 'manual_arm'}, data.is_armed ? 'disabled' : null, data.is_armed ? 'redButton' : 'yellowButton')}} - {{:helper.link('MANUAL EJECT', 'alert', {'command' : 'force_launch'}, data.can_force ? null : 'disabled', data.can_force ? 'yellowButton' : null)}} -
-
-
diff --git a/nano/templates/exonet_node.tmpl b/nano/templates/exonet_node.tmpl deleted file mode 100644 index df075c8b89..0000000000 --- a/nano/templates/exonet_node.tmpl +++ /dev/null @@ -1,49 +0,0 @@ - - -

Status

-
-
- Power: -
-
- {{:helper.link('On', 'power', {'toggle_power' : 1}, data.on ? 'selected' : null)}}{{:helper.link('Off', 'close', {'toggle_power' : 1}, data.on ? null : 'selected', data.on ? 'redButton' : null)}} -
-
- -

Ports

-
-
- Incoming PDA Messages: -
-
- {{:helper.link('Open', 'check', {'toggle_PDA_port' : 1}, data.allowPDAs ? 'selected' : null)}}{{:helper.link('Close', 'close', {'toggle_PDA_port' : 1}, data.allowPDAs ? null : 'selected')}} -
-
-
-
- Incoming Communicators: -
-
- {{:helper.link('Open', 'check', {'toggle_communicator_port' : 1}, data.allowCommunicators ? 'selected' : null)}}{{:helper.link('Close', 'close', {'toggle_communicator_port' : 1}, data.allowCommunicators ? null : 'selected')}} -
-
-
-
- Incoming Newscaster Content: -
-
- {{:helper.link('Open', 'check', {'toggle_newscaster_port' : 1}, data.allowNewscasters ? 'selected' : null)}}{{:helper.link('Close', 'close', {'toggle_newscaster_port' : 1}, data.allowNewscasters ? null : 'selected')}} -
-
- -

Logging

-
- {{for data.logs}} -
- {{:value}} -
- {{/for}} -
diff --git a/nano/templates/freezer.tmpl b/nano/templates/freezer.tmpl deleted file mode 100644 index fad41bad9f..0000000000 --- a/nano/templates/freezer.tmpl +++ /dev/null @@ -1,62 +0,0 @@ -
-
- Status: -
-
- {{:helper.link('On', 'power', {'toggleStatus' : 1}, data.on ? 'selected' : null)}}{{:helper.link('Off', 'close', {'toggleStatus' : 1}, data.on ? null : 'selected')}} -
-
- -
-
- Power Level: -
-
- {{:helper.link('1', null, {'setPower' : 20}, (data.powerSetting == 20)? 'selected' : null)}} - {{:helper.link('2', null, {'setPower' : 40}, (data.powerSetting == 40)? 'selected' : null)}} - {{:helper.link('3', null, {'setPower' : 60}, (data.powerSetting == 60)? 'selected' : null)}} - {{:helper.link('4', null, {'setPower' : 80}, (data.powerSetting == 80)? 'selected' : null)}} - {{:helper.link('5', null, {'setPower' : 100}, (data.powerSetting == 100)? 'selected' : null)}} -
-
- -
-
- Gas Pressure: -
-
- {{:data.gasPressure}} kPa -
-
- -

Gas Temperature

-
-
- Current: -
-
- {{:helper.displayBar(data.gasTemperature, data.minGasTemperature, data.maxGasTemperature, data.gasTemperatureClass)}} -
- {{:data.gasTemperature}} K -
-
-
- -
-
- Target: -
-
- {{:helper.displayBar(data.targetGasTemperature, data.minGasTemperature, data.maxGasTemperature)}} -
- {{:helper.link('-', null, {'temp' : -100}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} - {{:helper.link('-', null, {'temp' : -10}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} - {{:helper.link('-', null, {'temp' : -1}, (data.targetGasTemperature > data.minGasTemperature) ? null : 'disabled')}} -
 {{:data.targetGasTemperature}} K 
- {{:helper.link('+', null, {'temp' : 1}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}} - {{:helper.link('+', null, {'temp' : 10}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}} - {{:helper.link('+', null, {'temp' : 100}, (data.targetGasTemperature < data.maxGasTemperature) ? null : 'disabled')}} -
-
-
- diff --git a/nano/templates/gas_pump.tmpl b/nano/templates/gas_pump.tmpl deleted file mode 100644 index a26d88a2cf..0000000000 --- a/nano/templates/gas_pump.tmpl +++ /dev/null @@ -1,44 +0,0 @@ -
-
- Power: -
-
- {{:helper.link(data.on? 'On' : 'Off', null, {'power' : 1})}} -
-
- -
-
- Desirable output pressure: -
-
-
- {{:helper.link('MAX', null, {'set_press' : 'max'}, null)}} - {{:helper.link('SET', null, {'set_press' : 'set'}, null)}} -
 {{:(data.pressure_set/100)}} kPa 
-
-
-
- -
-
- Load: -
-
- {{:helper.displayBar(data.last_power_draw, 0, data.max_power_draw, (data.last_power_draw < data.max_power_draw - 5) ? 'good' : 'average')}} -
- {{:data.last_power_draw}} W -
-
-
- -
-
- Flow Rate: -
-
-
- {{:(data.last_flow_rate/10)}} L/s -
-
-
\ No newline at end of file diff --git a/nano/templates/generator.tmpl b/nano/templates/generator.tmpl deleted file mode 100644 index 150884187f..0000000000 --- a/nano/templates/generator.tmpl +++ /dev/null @@ -1,142 +0,0 @@ -
-
- Total Output: -
-
- {{:helper.displayBar(data.totalOutput, 0, data.maxTotalOutput)}} -
-
- {{:helper.fixed(data.totalOutput, 1)}} kW -
-
-
-
- Thermal Output: -
-
- {{:helper.fixed(data.thermalOutput, 1)}} kW -
-
-
- -{{if data.circConnected}} - - - - - - -
-
-

Primary Circulator ({{:data.primaryDir}})

-
-
- Turbine Output: -
-
- {{:helper.fixed(data.primaryOutput, 1)}} kW -
-
-
-
- Flow Capacity: -
-
- {{:helper.fixed(data.primaryFlowCapacity, 1)}} % -
-
-
-
-
- Inlet Pressure: -
-
- {{:helper.fixed(data.primaryInletPressure, 1)}} kPa -
-
-
-
- Inlet Temperature: -
-
- {{:helper.fixed(data.primaryInletTemperature, 1)}} K -
-
-
-
-
- Outlet Pressure: -
-
- {{:helper.fixed(data.primaryOutletPressure, 1)}} kPa -
-
-
-
- Outlet Temperature: -
-
- {{:helper.fixed(data.primaryOutletTemperature, 1)}} K -
-
-
-
-
-

Secondary Circulator ({{:data.secondaryDir}})

-
-
- Turbine Output: -
-
- {{:helper.fixed(data.secondaryOutput, 1)}} kW -
-
-
-
- Flow Capacity: -
-
- {{:helper.fixed(data.secondaryFlowCapacity, 1)}} % -
-
-
-
-
- Inlet Pressure: -
-
- {{:helper.fixed(data.secondaryInletPressure, 1)}} kPa -
-
-
-
- Inlet Temperature: -
-
- {{:helper.fixed(data.secondaryInletTemperature, 1)}} K -
-
-
-
-
- Outlet Pressure: -
-
- {{:helper.fixed(data.secondaryOutletPressure, 1)}} kPa -
-
-
-
- Outlet Temperature: -
-
- {{:helper.fixed(data.secondaryOutletTemperature, 1)}} K -
-
-
-
-{{else}} -
- ERROR: Both circulators must be connected! -
-{{/if}} diff --git a/nano/templates/gravity_generator.tmpl b/nano/templates/gravity_generator.tmpl deleted file mode 100644 index ad8e686c49..0000000000 --- a/nano/templates/gravity_generator.tmpl +++ /dev/null @@ -1,45 +0,0 @@ -
-
-
- Breaker Setting: -
-
- {{if data.breaker}} - Generator Enabled - {{else}} - Generator Disabled - {{/if}} -
-
-
-
- Charge Mode: -
-
- {{if (data.breaker && data.charge_count < 100)}} - Generator CHARGING - {{else (data.breaker && data.charge_count >= 100)}} - Generator Running - {{else (!data.breaker && data.charge_count > 0)}} - Generator DISCHARGING - {{else}} - Generator Offline - {{/if}} -
-
-
-
- Charge Status: -
-
- {{:data.charge_count}}% -
-
-
-
-
-
- {{:helper.link('Toggle Breaker', 'alert', {'gentoggle' : 1}, null)}} -
-
-
\ No newline at end of file diff --git a/nano/templates/hardsuit.tmpl b/nano/templates/hardsuit.tmpl deleted file mode 100644 index deb906249b..0000000000 --- a/nano/templates/hardsuit.tmpl +++ /dev/null @@ -1,257 +0,0 @@ - - - - -{{if data.interfacelock || data.malf > 0}} -
-- HARDSUIT INTERFACE OFFLINE --
-{{else}} - {{if data.aicontrol && data.ai != 1}} -
-- HARDSUIT CONTROL OVERRIDDEN BY AI --
- {{else}} -
-
-
- Power supply -
-
- {{:helper.displayBar(data.chargestatus, 0, 50, (data.chargestatus >= 35) ? 'good' : (data.chargestatus >= 15) ? 'average' : 'bad')}} {{:data.charge}}/{{:data.maxcharge}} -
-
-
-
-
- AI control: -
-
- {{if data.aioverride}} -
ENABLED
- {{else}} -
DISABLED
- {{/if}} -
-
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_ai_control' : 1}, null)}} -
-
-
-
- Suit status: -
-
- {{if data.sealing == 1}} -
PROCESSING
- {{else}} - {{if data.seals == 1}} -
INACTIVE
- {{else}} -
ACTIVE
- {{/if}} - {{/if}} -
-
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_seals' : 1}, null)}} -
-
-
-
- Cover status: -
-
- {{if data.emagged || !data.securitycheck}} -
ERROR - MAINTENANCE LOCK CONTROL OFFLINE
- {{else}} - {{if data.coverlock}} -
LOCKED
- {{else}} -
UNLOCKED
- {{/if}} - {{/if}} -
-
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_suit_lock' : 1}, null)}} -
-
-
-
- -

Hardware

-

Suit pieces

- -
-
-
- Helmet: -
-
- {{:helper.capitalizeFirstLetter(data.helmet)}} -
- {{if data.sealing != 1}} -
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_piece' : 'helmet'}, null)}} -
- {{/if}} -
-
-
- Gauntlets: -
-
- {{:helper.capitalizeFirstLetter(data.gauntlets)}} -
- {{if data.sealing != 1}} -
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_piece' : 'gauntlets'}, null)}} -
- {{/if}} -
-
-
- Boots: -
-
- {{:helper.capitalizeFirstLetter(data.boots)}} -
- {{if data.sealing != 1}} -
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_piece' : 'boots'}, null)}} -
- {{/if}} -
-
-
- Chestpiece: -
-
- {{:helper.capitalizeFirstLetter(data.chest)}} -
- {{if data.sealing != 1}} -
- {{:helper.link('Toggle', 'circle-arrow-s', {'toggle_piece' : 'chest'}, null)}} -
- {{/if}} -
-
- -

System modules

- {{if data.seals == 1 || data.sealing == 1}} -

HARDSUIT SYSTEMS OFFLINE

- {{else}} -

Selected primary system: - {{if data.primarysystem}} - {{:helper.capitalizeFirstLetter(data.primarysystem)}} - {{else}} - None - {{/if}} -

- {{if data.modules}} -
- {{for data.modules}} -
-
-
-
{{:helper.capitalizeFirstLetter(value.name)}}
- {{if value.damage > 0}} -
- {{if value.damage == 1}} - (
damaged
) - {{else}} - (
destroyed
) - {{/if}} -
- {{/if}} -
-
- Engage: {{:value.engagecost}} - Activate: {{:value.activecost}} - Passive: {{:value.passivecost}} -
-
- {{:value.desc}} -
-
- {{if value.can_use == 1}} -
- {{:helper.link(value.engagestring, 'circle-arrow-s', {'interact_module' : value.index, 'module_mode' : 'engage'}, null)}} -
- {{/if}} - {{if value.can_select == 1}} -
- {{if value.name == data.primarysystem}} -
SELECTED
- {{else}} - {{:helper.link('Select', 'circle-arrow-s', {'interact_module' : value.index, 'module_mode' : 'select'}, null)}} - {{/if}} -
- {{/if}} - {{if value.can_toggle == 1}} -
- {{if value.is_active == 1}} - {{:helper.link(value.deactivatestring, 'circle-arrow-s', {'interact_module' : value.index, 'module_mode' : 'deactivate'}, null)}} - {{else}} - {{:helper.link(value.activatestring, 'circle-arrow-s', {'interact_module' : value.index, 'module_mode' : 'activate'}, null)}} - {{/if}} -
- {{/if}} -
-
-
-
- {{if value.charges}} -
Stored charges
-
Selected: {{:helper.capitalizeFirstLetter(value.chargetype)}}
- {{for value.charges :itemValue:itemIndex}} -
- {{:helper.link(helper.capitalizeFirstLetter(itemValue.caption), null, {'interact_module' : value.index, 'module_mode' : 'select_charge_type', 'charge_type' : itemValue.index}, null)}} -
- {{/for}} - {{/if}} -
-
-
- {{/for}} -
- {{else}} - None. - {{/if}} - {{/if}} - {{/if}} -{{/if}} \ No newline at end of file diff --git a/nano/templates/mod_sec_camera.tmpl b/nano/templates/mod_sec_camera.tmpl deleted file mode 100644 index 0afb80f4b8..0000000000 --- a/nano/templates/mod_sec_camera.tmpl +++ /dev/null @@ -1,36 +0,0 @@ -
- {{:helper.link('Show Map', 'pin-s', {'showMap' : 1})}} - {{:helper.link('Reset', 'refresh', {'reset' : 1})}} -
- -
-
Current Camera:
- {{if data.current_camera}} -
{{:data.current_camera.name}}
- {{else}} -
None
- {{/if}} -
- -
-
Networks:
-
-{{for data.networks}} - {{if value.has_access}} - {{:helper.link(value.tag, '', {'switch_network' : value.tag}, null, data.current_network == value.tag ? 'selected' : null)}} - {{else}} - {{:helper.link(value.tag, '', {}, null, data.current_network == value.tag ? 'selected' : 'redButton')}} - {{/if}} -{{/for}} -
-
Cameras:
-
-{{for data.cameras}} - {{if data.current_camera && value.name == data.current_camera.name}} - {{:helper.link(value.name, '', {'switch_camera' : value.camera}, 'selected')}} - {{else value.deact}} - {{:helper.link(value.name + " (deactivated)", '', {}, 'inactive')}} - {{else}} - {{:helper.link(value.name, '', {'switch_camera' : value.camera})}} - {{/if}} -{{/for}} diff --git a/nano/templates/mod_sec_camera_map_header.tmpl b/nano/templates/mod_sec_camera_map_header.tmpl deleted file mode 100644 index 459027797f..0000000000 --- a/nano/templates/mod_sec_camera_map_header.tmpl +++ /dev/null @@ -1,44 +0,0 @@ -
- {{:helper.link('Show Camera List', 'script', {'showMap' : 0})}} - {{:helper.link('Reset', 'refresh', {'reset' : 1})}} -
-
-
Current Camera:
- {{if data.current_camera}} -
{{:data.current_camera.name}}
- {{else}} -
None
- {{/if}} -
- -
-
- Z-Level: -
-
- {{for config.mapZLevels :zValue:zIndex}} - {{:helper.link(zValue, 'close', {'mapZLevel' : zValue}, null, config.mapZLevel == zValue ? 'selected' : null)}} - {{/for}} -
-
-
-
- Zoom Level: -
-
- - - - -
-
-
-
Networks:
-
-{{for data.networks}} - {{if value.has_access}} - {{:helper.link(value.tag, '', {'switch_network' : value.tag}, null, data.current_network == value.tag ? 'selected' : null)}} - {{else}} - {{:helper.link(value.tag, '', {}, null, data.current_network == value.tag ? 'selected' : 'redButton')}} - {{/if}} -{{/for}} \ No newline at end of file diff --git a/nano/templates/multi_docking_console.tmpl b/nano/templates/multi_docking_console.tmpl deleted file mode 100644 index 9515799644..0000000000 --- a/nano/templates/multi_docking_console.tmpl +++ /dev/null @@ -1,37 +0,0 @@ -
-
-
- Docking Port Status: -
-
- {{if data.docking_status == "docked"}} - DOCKED - {{else data.docking_status == "docking"}} - DOCKING - {{else data.docking_status == "undocking"}} - UNDOCKING - {{else data.docking_status == "undocked"}} - NOT IN USE - {{else}} - ERROR - {{/if}} -
-
-
- -{{for data.airlocks}} -
-
-
- {{:value.name}} -
-
- {{if value.override_enabled}} - OVERRIDE ENABLED - {{else}} - STATUS OK - {{/if}} -
-
-
-{{/for}} \ No newline at end of file diff --git a/nano/templates/ntnet_relay.tmpl b/nano/templates/ntnet_relay.tmpl deleted file mode 100644 index 24bd831782..0000000000 --- a/nano/templates/ntnet_relay.tmpl +++ /dev/null @@ -1,32 +0,0 @@ -{{if data.dos_crashed}} -

NETWORK BUFFERS OVERLOADED

-

Overload Recovery Mode

- This system is suffering temporary outage due to overflow of traffic buffers. Until buffered traffic is processed, all further requests will be dropped. Frequent occurences of this error may indicate insufficient hardware capacity of your network. Please contact your network planning department for instructions on how to resolve this issue. -

ADMINISTRATIVE OVERRIDE

- CAUTION - Data loss may occur - {{:helper.link('Purge buffered traffic', null, { 'restart' : 1 })}} -{{else}} -
- Relay status: -
-
- {{if data.enabled}} - {{:helper.link('ENABLED', null, { 'toggle' : 1 })}} - {{else}} - {{:helper.link('DISABLED', null, { 'toggle' : 1 })}} - {{/if}} - -
-
- Network buffer status: -
-
- {{:data.dos_overload}} / {{:data.dos_capacity}} GQ -
-
- Options: -
-
- {{:helper.link('Purge network blacklist', null, { 'purge' : 1 })}} -
-{{/if}} \ No newline at end of file diff --git a/nano/templates/omni_filter.tmpl b/nano/templates/omni_filter.tmpl deleted file mode 100644 index 672ffcfe05..0000000000 --- a/nano/templates/omni_filter.tmpl +++ /dev/null @@ -1,87 +0,0 @@ -
-
- {{:helper.link(data.power ? 'On' : 'Off', null, {'command' : 'power'}, data.config ? 'disabled' : null)}} -
-
- {{:helper.link('Configure', null, {'command' : 'configure'}, null, data.config ? 'selected' : null)}} -
-
-
- {{if data.config}} - -
-
-
Port
- {{for data.ports}} -
{{:value.dir}} Port
- {{/for}} -
-
-
Input
- {{for data.ports}} -
- {{:helper.link(' ', null, {'command' : 'switch_mode', 'mode' : 'in', 'dir' : value.dir}, null, value.input ? 'selected' : null)}} -
- {{/for}} -
-
-
Output
- {{for data.ports}} -
- {{:helper.link(' ', null, {'command' : 'switch_mode', 'mode' : 'out', 'dir' : value.dir}, null, value.output ? 'selected' : null)}} -
- {{/for}} -
-
-
Filter
- {{for data.ports}} -
- {{:helper.link(value.f_type ? value.f_type : 'None', null, {'command' : 'switch_filter', 'mode' : value.f_type, 'dir' : value.dir}, value.atmo_filter ? null : 'disabled', value.f_type ? 'selected' : null)}} -
- {{/for}} -
-
- -
- Set Flow Rate Limit: {{:(data.set_flow_rate/10)}} L/s -
-
- {{:helper.link('Set Flow Rate Limit', null, {'command' : 'set_flow_rate'})}} -
- - {{else}} - -
-
-
Port
- {{for data.ports}} -
{{:value.dir}} Port
- {{/for}} -
-
-
Mode
- {{for data.ports}} -
- {{if value.input}} - Input - {{else value.output}} - Output - {{else value.f_type}} - {{:value.f_type}} - {{else}} - Disabled - {{/if}} -
- {{/for}} -
-
- -
- Set Flow Rate Limit: {{:(data.set_flow_rate/10)}} L/s -
- -
- Flow Rate: {{:(data.last_flow_rate/10)}} L/s -
- {{/if}} -
diff --git a/nano/templates/omni_mixer.tmpl b/nano/templates/omni_mixer.tmpl deleted file mode 100644 index 77c4573880..0000000000 --- a/nano/templates/omni_mixer.tmpl +++ /dev/null @@ -1,102 +0,0 @@ -
-
- {{:helper.link(data.power ? 'On' : 'Off', null, {'command' : 'power'}, data.config ? 'disabled' : null)}} -
-
- {{:helper.link('Configure', null, {'command' : 'configure'}, null, data.config ? 'selected' : null)}} -
-
-
- {{if data.config}} - -
-
-
Port
- {{for data.ports}} -
{{:value.dir}} Port
- {{/for}} -
-
-
Input
- {{for data.ports}} -
- {{:helper.link(' ', null, value.input ? {'command' : 'switch_mode', 'mode' : 'none', 'dir' : value.dir} : {'command' : 'switch_mode', 'mode' : 'in', 'dir' : value.dir}, value.output ? 'disabled' : null, value.input ? 'selected' : null)}} -
- {{/for}} -
-
-
Output
- {{for data.ports}} -
- {{:helper.link(' ', null, value.output ? null : {'command' : 'switch_mode', 'mode' : 'out', 'dir' : value.dir}, null, value.output ? 'selected' : null)}} -
- {{/for}} -
-
-
Concentration
- {{for data.ports}} -
- {{:helper.link( value.input ? helper.round(value.concentration*100)+' %' : '-', null, {'command' : 'switch_con', 'dir' : value.dir}, value.input ? null : 'disabled')}} -
- {{/for}} -
-
-
Lock
- {{for data.ports}} -
- {{:helper.link(' ', value.con_lock ? 'locked' : 'unlocked', {'command' : 'switch_conlock', 'dir' : value.dir}, value.input ? null : 'disabled', value.con_lock ? 'selected' : null)}} -
- {{/for}} -
-
- -
- Set Flow Rate Limit: {{:(data.set_flow_rate/10)}} L/s -
-
- {{:helper.link('Set Flow Rate Limit', null, {'command' : 'set_flow_rate'})}} -
- - {{else}} - -
-
-
Port
- {{for data.ports}} -
{{:value.dir}} Port
- {{/for}} -
-
-
Mode
- {{for data.ports}} -
- {{if value.input}} - Input - {{else value.output}} - Output - {{else}} - Disabled - {{/if}} -
- {{/for}} -
-
-
Concentration
- {{for data.ports}} -
- {{if value.input}} - {{:helper.round(value.concentration*100)}} % - {{else}} - - - {{/if}} -
- {{/for}} -
-
- -
- Flow Rate: {{:(data.last_flow_rate/10)}} L/s -
- - {{/if}} -
\ No newline at end of file diff --git a/nano/templates/pacman.tmpl b/nano/templates/pacman.tmpl deleted file mode 100644 index 386358c9cc..0000000000 --- a/nano/templates/pacman.tmpl +++ /dev/null @@ -1,113 +0,0 @@ -

Status

-
-
- Generator Status: -
-
- {{if data.active}} - Online - {{else}} - Offline - {{/if}} -
-
- Generator Control: -
-
- {{if data.active}} - {{:helper.link('STOP', 'power', {'action' : "disable"})}} - {{else}} - {{:helper.link('START', 'power', {'action' : "enable"})}} - {{/if}} -
-
-

Fuel

-
-
- Fuel Type: -
-
- {{:data.fuel_type}} -
-
- Fuel Level: -
-
- {{if data.fuel_stored >= 5000}} - {{:helper.displayBar(data.fuel_stored, 0, data.fuel_capacity, 'good')}} -
{{:data.fuel_stored}}/{{:data.fuel_capacity}} cm3 - {{else data.fuel_stored >= 1000}} - {{:helper.displayBar(data.fuel_stored, 0, data.fuel_capacity, 'average')}} -
{{:data.fuel_stored}}/{{:data.fuel_capacity}} cm3 - {{else}} - {{:helper.displayBar(data.fuel_stored, 0, data.fuel_capacity, 'bad')}} -
{{:data.fuel_stored}}/{{:data.fuel_capacity}} cm3 - {{/if}} -
-
- Fuel Usage: -
-
- {{:data.fuel_usage}} cm3/s -
- {{if !data.is_ai}} -
- Control: -
-
- {{:helper.link('EJECT FUEL', 'arrowupthick-1-s', {'action' : "eject"}, data.active ? 'disabled' : null)}} -
- {{/if}} -
-

Output

-
-
- Power setting: -
-
- {{if data.output_set > data.output_safe}} - {{:data.output_set}} / {{:data.output_max}} ({{:data.output_watts}} W) - {{else}} - {{:data.output_set}} / {{:data.output_max}} ({{:data.output_watts}} W) - {{/if}} -
-
- Control: -
-
- {{:helper.link('+', null, {'action' : "higher_power"})}} - {{:helper.link('-', null, {'action' : "lower_power"})}} -
-
-

Temperature

-
-
- Temperature: -
-
- {{if data.temperature_current < (data.temperature_max * 0.8)}} - {{:helper.displayBar(data.temperature_current, 0, (data.temperature_max * 1.5), 'good')}} -
{{:data.temperature_current}} C - {{else data.temperature_current < data.temperature_max}} - {{:helper.displayBar(data.temperature_current, 0, (data.temperature_max * 1.5), 'average')}} -
{{:data.temperature_current}} C - {{else}} - {{:helper.displayBar(data.temperature_current, 0, (data.temperature_max * 1.5), 'bad')}} -
{{:data.temperature_current}} C - {{/if}} -
-
- Generator Status: -
-
- {{if data.temperature_overheat > 50}} - DANGER: CRITICAL OVERHEAT! Deactivate generator immediately! - {{else data.temperature_overheat > 20}} - WARNING: Overheating! - {{else data.temperature_overheat > 1}} - Temperature High - {{else}} - Optimal - {{/if}} -
-
\ No newline at end of file diff --git a/nano/templates/phoron_airlock_console.tmpl b/nano/templates/phoron_airlock_console.tmpl deleted file mode 100644 index 8c0bb69cd7..0000000000 --- a/nano/templates/phoron_airlock_console.tmpl +++ /dev/null @@ -1,47 +0,0 @@ -
-
-
- Chamber Pressure: -
-
- {{:helper.displayBar(data.chamber_pressure, 0, 200, (data.chamber_pressure < 80 || data.chamber_pressure) > 120 ? 'bad' : (data.chamber_pressure < 95 || data.chamber_pressure > 110) ? 'average' : 'good')}} -
- {{:helper.round(data.chamber_pressure)}} kPa -
-
-
-
-
- Chamber Phoron: -
-
- {{:helper.displayBar(data.chamber_phoron, 0, 100, data.chamber_phoron >= 5 ? 'bad' : data.chamber_phoron > 0.5 ? 'average' : 'good')}} -
- {{:data.chamber_phoron < 10 ? helper.fixed(data.chamber_phoron) : helper.round(data.chamber_phoron)}} mol -
-
-
-
-
-
-
- {{:helper.link('Cycle to Exterior', 'arrowthickstop-1-w', {'command' : 'cycle_ext'}, data.processing ? 'disabled' : null)}} - {{:helper.link('Cycle to Interior', 'arrowthickstop-1-e', {'command' : 'cycle_int'}, data.processing ? 'disabled' : null)}} -
-
- {{if data.interior_status.state == "open"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} - {{if data.exterior_status.state == "open"}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} -
-
-
- {{:helper.link('Abort', 'cancel', {'command' : 'abort'}, data.processing ? null : 'disabled', data.processing ? 'redButton' : null)}} -
-
\ No newline at end of file diff --git a/nano/templates/portpump.tmpl b/nano/templates/portpump.tmpl deleted file mode 100644 index 3e14aac8f9..0000000000 --- a/nano/templates/portpump.tmpl +++ /dev/null @@ -1,100 +0,0 @@ -

Pump Status

-
-
- Tank Pressure: -
-
- {{:data.tankPressure}} kPa -
-
- -
-
- Port Status: -
-
- {{:data.portConnected ? 'Connected' : 'Disconnected'}} -
-
- -
-
- Load: -
-
- {{:data.powerDraw}} W -
-
- -
-
- Cell Charge: -
-
- {{:helper.displayBar(data.cellCharge, 0, data.cellMaxCharge)}} -
-
- -

Holding Tank Status

-{{if data.hasHoldingTank}} -
-
- Tank Label: -
-
-
{{:data.holdingTank.name}}
{{:helper.link('Eject', 'eject', {'remove_tank' : 1})}} -
-
- -
-
- Tank Pressure: -
-
- {{:data.holdingTank.tankPressure}} kPa -
-
-{{else}} -
No holding tank inserted.
-
 
-{{/if}} - - -

Power Regulator Status

-
-
- Target Pressure: -
-
- {{:helper.displayBar(data.targetpressure, data.minpressure, data.maxpressure)}} -
- {{:helper.link('-', null, {'pressure_adj' : -1000}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} - {{:helper.link('-', null, {'pressure_adj' : -100}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} - {{:helper.link('-', null, {'pressure_adj' : -10}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} - {{:helper.link('-', null, {'pressure_adj' : -1}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} -
 {{:data.targetpressure}} kPa 
- {{:helper.link('+', null, {'pressure_adj' : 1}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'pressure_adj' : 10}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'pressure_adj' : 100}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'pressure_adj' : 1000}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} -
-
-
- -
-
- Power Switch: -
-
- {{:helper.link('On', 'unlocked', {'power' : 1}, data.on ? 'selected' : null)}} {{:helper.link('Off', 'locked', {'power' : 1}, data.on ? null : 'selected')}} -
-
- -
-
- Pump Direction: -
-
- {{:helper.link('Out', 'arrowreturn-1-e', {'direction' : 1}, data.pump_dir ? 'selected' : null)}} {{:helper.link('In', 'arrowreturn-1-w', {'direction' : 1}, data.pump_dir ? null : 'selected')}} -
-
diff --git a/nano/templates/portscrubber.tmpl b/nano/templates/portscrubber.tmpl deleted file mode 100644 index c99f53344c..0000000000 --- a/nano/templates/portscrubber.tmpl +++ /dev/null @@ -1,91 +0,0 @@ -

Scrubber Status

-
-
- Tank Pressure: -
-
- {{:data.tankPressure}} kPa -
-
- -
-
- Port Status: -
-
- {{:data.portConnected ? 'Connected' : 'Disconnected'}} -
-
- -
-
- Load: -
-
- {{:data.powerDraw}} W -
-
- -
-
- Cell Charge: -
-
- {{:helper.displayBar(data.cellCharge, 0, data.cellMaxCharge)}} -
-
- -

Holding Tank Status

-{{if data.hasHoldingTank}} -
-
- Tank Label: -
-
-
{{:data.holdingTank.name}}
{{:helper.link('Eject', 'eject', {'remove_tank' : 1})}} -
-
q - -
-
- Tank Pressure: -
-
- {{:data.holdingTank.tankPressure}} kPa -
-
-{{else}} -
No holding tank inserted.
-
 
-{{/if}} - - -

Power Regulator Status

-
-
- Volume Rate: -
-
- {{:helper.displayBar(data.rate, data.minrate, data.maxrate)}} -
- {{:helper.link('-', null, {'volume_adj' : -1000}, (data.rate > data.minrate) ? null : 'disabled')}} - {{:helper.link('-', null, {'volume_adj' : -100}, (data.rate > data.minrate) ? null : 'disabled')}} - {{:helper.link('-', null, {'volume_adj' : -10}, (data.rate > data.minrate) ? null : 'disabled')}} - {{:helper.link('-', null, {'volume_adj' : -1}, (data.rate > data.minrate) ? null : 'disabled')}} -
 {{:data.rate}} L/s 
- {{:helper.link('+', null, {'volume_adj' : 1}, (data.rate < data.maxrate) ? null : 'disabled')}} - {{:helper.link('+', null, {'volume_adj' : 10}, (data.rate < data.maxrate) ? null : 'disabled')}} - {{:helper.link('+', null, {'volume_adj' : 100}, (data.rate < data.maxrate) ? null : 'disabled')}} - {{:helper.link('+', null, {'volume_adj' : 1000}, (data.rate < data.maxrate) ? null : 'disabled')}} -
-
-
- -
-
- Power Switch: -
-
- {{:helper.link('On', 'unlocked', {'power' : 1}, data.on ? 'selected' : null)}} {{:helper.link('Off', 'locked', {'power' : 1}, data.on ? null : 'selected')}} -
-
diff --git a/nano/templates/power_monitor.tmpl b/nano/templates/power_monitor.tmpl deleted file mode 100644 index 6c9e5eee34..0000000000 --- a/nano/templates/power_monitor.tmpl +++ /dev/null @@ -1,96 +0,0 @@ -{{if data.focus}} -
- {{:helper.link('Show List', 'cancel', { 'clear' : 1})}} Sensor selected: {{:data.focus.name}} -
- {{if data.map_levels.length}} - {{:helper.link('Show APCs On Map', 'pin-s', {'showMap' : 1})}} - {{/if}} - {{if data.focus.error}} - {{:data.focus.error}} - {{else}} -

Network Information

-
- Network Load Status: -
- {{if data.focus.load_percentage >= 95}} -
DANGER: Overload
- {{else data.focus.load_percentage >= 85}} -
WARNING: High Load
- {{else}} -
Optimal
- {{/if}} -
- Network Security Status: -
- {{if data.focus.alarm}} -
WARNING: Abnormal activity detected!
- {{else}} -
Secure
- {{/if}} - -
- Load Percentage: -
-
- {{:helper.displayBar(data.focus.load_percentage, 0, 100, (data.focus.load_percentage <= 75) ? 'good' : (data.focus.load_percentage <= 90) ? 'average' : 'bad')}}{{:data.focus.load_percentage}}% -
-
- Available Power: -
-
- {{:data.focus.total_avail}} -
-
- APC Power Usage: -
-
- {{:data.focus.total_used_apc}} -
-
- Other Power Usage: -
-
- {{:data.focus.total_used_other}} -
-
- Total Usage: -
-
- {{:data.focus.total_used_all}} -
-

Sensor Readings

- -
APC NameEquipmentLightingEnvironmentCell StatusAPC Load - {{for data.focus.apc_data}} -
{{:value.name}} - {{:value.s_equipment}} - {{:value.s_lighting}} - {{:value.s_environment}} - {{if value.cell_status == "N"}} - {{:helper.link(value.cell_charge + '%', 'batt_disc', null,'disabled', 'width75btn')}} - {{else value.cell_status == "C"}} - {{:helper.link(value.cell_charge + '%', 'batt_chrg', null,'disabled', 'width75btn')}} - {{else}} - {{:helper.link(value.cell_charge + '%', 'batt_full', null,'disabled', 'width75btn')}} - {{/if}} - {{:value.total_load}} - {{empty}} -
No APCs detected in connected powernet. - {{/for}} -
- {{/if}} -{{else}} -
- {{:helper.link('Scan For Sensors', 'refresh', { 'refresh' : 1})}} No active sensor. Printing sensor list. -

- {{for data.all_sensors}} - {{if value.alarm}} -
{{:helper.link(value.name, 'alert', { 'setsensor' : value.name})}} - {{else}} -
{{:helper.link(value.name, '' , { 'setsensor' : value.name})}} - {{/if}} - {{empty}} - WARN: No Sensors Detected! - {{/for}} -
-{{/if}} \ No newline at end of file diff --git a/nano/templates/power_monitor_map_content.tmpl b/nano/templates/power_monitor_map_content.tmpl deleted file mode 100644 index 291903144d..0000000000 --- a/nano/templates/power_monitor_map_content.tmpl +++ /dev/null @@ -1,33 +0,0 @@ - -{{if data.focus}} - {{for data.focus.apc_data}} - {{if value.z == config.mapZLevel}} -
- -
- {{/if}} - {{/for}} -{{/if}} \ No newline at end of file diff --git a/nano/templates/power_monitor_map_header.tmpl b/nano/templates/power_monitor_map_header.tmpl deleted file mode 100644 index 171fd03429..0000000000 --- a/nano/templates/power_monitor_map_header.tmpl +++ /dev/null @@ -1,33 +0,0 @@ - -{{:helper.link('Show Network Information', 'script', {'showMap' : 0})}} -{{if data.focus}}Sensor selected: {{:data.focus.name}}{{/if}} -{{if data.map_levels.length > 1}} -
- Z Level:  - {{for data.map_levels }} - {{:helper.link(value, null, {'mapZLevel' : value}, null, config.mapZLevel == value ? 'selected' : null)}} - {{/for}} -
-{{/if}} -
- Zoom Level:  - - - - -
-
-
Sensors:
-
-{{for data.all_sensors}} - {{if value.alarm}} - {{:helper.link(value.name, 'alert', { 'setsensor' : value.name})}} - {{else}} - {{:helper.link(value.name, '' , { 'setsensor' : value.name})}} - {{/if}} -{{empty}} - WARN: No Sensors Detected! -{{/for}} diff --git a/nano/templates/pressure_regulator.tmpl b/nano/templates/pressure_regulator.tmpl deleted file mode 100644 index bbbfcc22df..0000000000 --- a/nano/templates/pressure_regulator.tmpl +++ /dev/null @@ -1,76 +0,0 @@ -
-
- Input Pressure: -
-
- {{:(data.input_pressure/100)}} kPa -
-
- -
-
- Output Pressure: -
-
- {{:(data.output_pressure/100)}} kPa -
-
- -
-
- Flow Rate: -
-
-
- {{:(data.last_flow_rate/10)}} L/s -
-
-
- -
- -
-
- Valve: -
-
- {{:helper.link(data.on? 'Unlocked' : 'Closed', null, {'toggle_valve' : 1})}} -
-
- -
-
- Pressure Regulation: -
-
- {{:helper.link('Off', null, {'regulate_mode' : 'off'}, data.regulate_mode == 0? 'selected' : null)}} - {{:helper.link('Input', null, {'regulate_mode' : 'input'}, data.regulate_mode == 1? 'selected' : null)}} - {{:helper.link('Output', null, {'regulate_mode' : 'output'}, data.regulate_mode == 2? 'selected' : null)}} -
-
- -
-
- Target Pressure: -
-
-
- {{:helper.link('MAX', null, {'set_press' : 'max'}, null)}} - {{:helper.link('SET', null, {'set_press' : 'set'}, null)}} -
 {{:(data.pressure_set/100)}} kPa 
-
-
-
- -
-
- Flow Rate Limit: -
-
-
- {{:helper.link('MAX', null, {'set_flow_rate' : 'max'}, null)}} - {{:helper.link('SET', null, {'set_flow_rate' : 'set'}, null)}} -
 {{:(data.set_flow_rate/10)}} L/s 
-
-
-
\ No newline at end of file diff --git a/nano/templates/radio_basic.tmpl b/nano/templates/radio_basic.tmpl deleted file mode 100644 index 6cfbb6dc7a..0000000000 --- a/nano/templates/radio_basic.tmpl +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - -{{if data.useSyndMode}} - {{:helper.syndicateMode()}} -{{/if}} - -
-
- Microphone -
-
- {{if data.mic_cut}} - {{:helper.link('On', null, null, 'disabled')}} - {{:helper.link('Off', null, null, 'disabled')}} - {{else}} - {{:helper.link('On', null, {'talk' : 0}, data.mic_status ? 'selected' : null)}} - {{:helper.link('Off', null, {'talk' : 1}, data.mic_status ? null : 'selected')}} - {{/if}} -
-
- -
-
- Speaker -
-
- {{if data.spk_cut}} - {{:helper.link('On', null, null, 'disabled')}} - {{:helper.link('Off', null, null, 'disabled')}} - {{else}} - {{:helper.link('On', null, {'listen' : 0}, data.speaker ? 'selected' : null)}} - {{:helper.link('Off', null, {'listen' : 1}, data.speaker ? null : 'selected')}} - {{/if}} -
-
- -{{if data.has_subspace}} -
-
- Subspace Transmission: -
-
- {{:helper.link('On', null, {'mode' : 1}, data.subspace ? 'selected' : null)}} - {{:helper.link('Off', null, {'mode' : 0}, data.subspace ? null : 'selected')}} -
-
-{{/if}} - -{{if data.has_loudspeaker}} -
-
- Loudspeaker: -
-
- {{:helper.link('On', null, {'shutup' : 0}, data.loudspeaker ? 'selected' : null)}} - {{:helper.link('Off', null, {'shutup' : 1}, data.loudspeaker ? null : 'selected')}} -
-
-{{/if}} - -
-
- Frequency: {{:data.freq}} -
-
- {{:helper.link('--', null, {'freq' : -10})}} - {{:helper.link('-', null, {'freq' : -2})}} - {{:helper.link('+', null, {'freq' : 2})}} - {{:helper.link('++', null, {'freq' : 10})}} -
-
- -{{if data.chan_list_len >= 1}} -

Channels

-
- {{for data.chan_list}} -
- {{:value.display_name}} -
-
- {{if value.secure_channel}} - {{:helper.link('On', null, {'ch_name' : value.chan, 'listen' : value.sec_channel_listen}, value.sec_channel_listen ? null : 'selected')}} - {{:helper.link('Off', null, {'ch_name' : value.chan, 'listen' : value.sec_channel_listen}, value.sec_channel_listen ? 'selected' : null)}} - {{else}} - {{:helper.link('Switch', null, {'spec_freq' : value.chan}, data.rawfreq == value.chan ? 'selected' : null)}} - {{/if}} -
- {{/for}} -{{/if}} diff --git a/nano/templates/rcon.tmpl b/nano/templates/rcon.tmpl deleted file mode 100644 index e16062aec4..0000000000 --- a/nano/templates/rcon.tmpl +++ /dev/null @@ -1,73 +0,0 @@ - -
{{:helper.link('Show/Hide SMES readings', 'folder', { 'hide_smes' : 1})}} -
{{:helper.link('Show/Hide SMES controls', 'folder', { 'hide_smes_details' : 1})}} -
{{:helper.link('Show/Hide Breaker readings', 'folder', { 'hide_breakers' : 1})}} -
-{{if data.hide_smes}} - SMES readings hidden.
-{{else}} - Detected SMES units with RCON support:
- {{for data.smes_info}} -
-
- {{:value.RCON_tag}} -
-
- -
- {{if value.charge > 50}} - {{:helper.displayBar(value.charge, 0, 100, 'good')}} - {{else value.charge > 25}} - {{:helper.displayBar(value.charge, 0, 100, 'average')}} - {{else}} - {{:helper.displayBar(value.charge, 0, 100, 'bad')}} - {{/if}} -
- {{:value.charge}}%
-
- {{if !data.hide_smes_details}} -
- Input: {{:value.input_val}} kW - {{:value.input_set ? "AUTO" : "OFF"}} - - {{:helper.link('', 'power', { 'smes_in_toggle' : value.RCON_tag})}} - {{:helper.link('', 'pencil', { 'smes_in_set' : value.RCON_tag})}} -
- Output: {{:value.output_val}} kW - {{:value.output_set ? "ONLINE" : "OFFLINE"}} - - {{:helper.link('', 'power', { 'smes_out_toggle' : value.RCON_tag})}} - {{:helper.link('', 'pencil', { 'smes_out_set' : value.RCON_tag})}} - -
- Output Load: - - {{:value.output_load}} kW - {{/if}} -
-
-
- {{empty}} - No connected SMES units detected!
- {{/for}} -{{/if}} -{{if data.hide_breakers}} - Breaker readings hidden.
-{{else}} - Detected Breaker Boxes with RCON support:
- {{for data.breaker_info}} -
-
- {{:value.RCON_tag}} -
-
- -
- {{:value.enabled ? "[ENABLED]" : "[DISABLED]"}} - - {{:helper.link('', 'power', {'toggle_breaker' : value.RCON_tag})}} -
-
-
- {{empty}} - No connected Breaker Boxes detected! - {{/for}} -{{/if}} \ No newline at end of file diff --git a/nano/templates/sec_camera.tmpl b/nano/templates/sec_camera.tmpl deleted file mode 100644 index 21ecea71e7..0000000000 --- a/nano/templates/sec_camera.tmpl +++ /dev/null @@ -1,37 +0,0 @@ - -{{if data.map_levels.length}} - {{:helper.link('Show Map', 'pin-s', {'showMap' : 1})}} -{{/if}} -{{:helper.link('Reset', 'refresh', {'reset' : 1})}} -
-
-
Current Camera: 
-
- {{if data.current_camera}} -
{{:data.current_camera.name}}
- {{else}} -
None
- {{/if}} -
-
-
-
Networks:
-
-{{for data.networks}} - {{:helper.link(value, '', {'switch_network' : value}, null, data.current_network == value ? 'selected' : null)}} -{{/for}} -
-
Cameras:
-
-{{for data.cameras}} - {{if data.current_camera && value.name == data.current_camera.name}} - {{:helper.link(value.name, '', {'switch_camera' : value.camera}, 'selected')}} - {{else value.deact}} - {{:helper.link(value.name + " (deactivated)", '', {}, 'inactive')}} - {{else}} - {{:helper.link(value.name, '', {'switch_camera' : value.camera})}} - {{/if}} -{{/for}} diff --git a/nano/templates/sec_camera_map_content.tmpl b/nano/templates/sec_camera_map_content.tmpl deleted file mode 100644 index e9369c4b01..0000000000 --- a/nano/templates/sec_camera_map_content.tmpl +++ /dev/null @@ -1,20 +0,0 @@ - -{{for data.cameras}} - {{if value.z == config.mapZLevel}} -
- {{if data.current && value.name == data.current.name}} - {{:helper.link("#", '', {'switch_camera' : value.camera}, 'selected')}} - {{else value.deact}} - {{:helper.link('#', '', {}, 'inactive')}} - {{else}} - {{:helper.link("#", '', {'switch_camera' : value.camera})}} - {{/if}} - -
- {{/if}} -{{/for}} diff --git a/nano/templates/sec_camera_map_header.tmpl b/nano/templates/sec_camera_map_header.tmpl deleted file mode 100644 index 0281c70cf5..0000000000 --- a/nano/templates/sec_camera_map_header.tmpl +++ /dev/null @@ -1,38 +0,0 @@ - -{{:helper.link('Show Camera List', 'script', {'showMap' : 0})}} -{{:helper.link('Reset', 'refresh', {'reset' : 1})}} -
-
-
Current Camera: 
- {{if data.current_camera}} -
{{:data.current_camera.name}}
- {{else}} -
None
- {{/if}} -
-
-{{if data.map_levels.length > 1}} -
- Z Level:  - {{for data.map_levels }} - {{:helper.link(value, null, {'mapZLevel' : value}, null, config.mapZLevel == value ? 'selected' : null)}} - {{/for}} -
-{{/if}} -
- Zoom Level:  - - - - -
-
-
-
Networks:
-
-{{for data.networks}} - {{:helper.link(value, '', {'switch_network' : value}, null, data.current_network == value ? 'selected' : null)}} -{{/for}} \ No newline at end of file diff --git a/nano/templates/shutoff_monitor.tmpl b/nano/templates/shutoff_monitor.tmpl deleted file mode 100644 index 2597a1b6f5..0000000000 --- a/nano/templates/shutoff_monitor.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -

Automated Shutoff Valve Monitoring Console

-
- -
NamePositionOpenModeActions -{{for data.valves}} -
{{:value.name}} - {{:value.x}}, {{:value.y}}, {{:value.z}} - {{:value.open ? 'Yes' : 'No'}} - {{:value.enabled ? 'Auto' : 'Manual'}} - {{:helper.link(value.open ? 'Close' : 'Open', null, {'toggle_open' : value.ref}, value.enabled ? 'disabled' : null)}} - {{:helper.link(value.enabled ? 'Manual' : 'Auto', null, {'toggle_enable' : value.ref})}} -{{/for}} -
\ No newline at end of file diff --git a/nano/templates/simple_airlock_console.tmpl b/nano/templates/simple_airlock_console.tmpl deleted file mode 100644 index ca49b20f6a..0000000000 --- a/nano/templates/simple_airlock_console.tmpl +++ /dev/null @@ -1,36 +0,0 @@ -
-
-
- Chamber Pressure: -
-
- {{:helper.displayBar(data.chamber_pressure, 0, 200, (data.chamber_pressure < 80) || (data.chamber_pressure > 120) ? 'bad' : (data.chamber_pressure < 95) || (data.chamber_pressure > 110) ? 'average' : 'good')}} -
- {{:data.chamber_pressure}} kPa -
-
-
-
-
-
-
- {{:helper.link('Cycle to Exterior', 'arrowthickstop-1-w', {'command' : 'cycle_ext'}, data.processing ? 'disabled' : null)}} - {{:helper.link('Cycle to Interior', 'arrowthickstop-1-e', {'command' : 'cycle_int'}, data.processing ? 'disabled' : null)}} -
-
- {{if data.interior_status.state == "open"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} - {{if data.exterior_status.state == "open"}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} -
-
-
- {{:helper.link('Abort', 'cancel', {'command' : 'abort'}, data.processing ? null : 'disabled', data.processing ? 'redButton' : null)}} -
-
\ No newline at end of file diff --git a/nano/templates/simple_docking_console.tmpl b/nano/templates/simple_docking_console.tmpl deleted file mode 100644 index 73c8ff8e3e..0000000000 --- a/nano/templates/simple_docking_console.tmpl +++ /dev/null @@ -1,99 +0,0 @@ -
-
-
- Docking Port Status: -
-
- {{if data.docking_status == "docked"}} - {{if !data.override_enabled}} - DOCKED - {{else}} - DOCKED-OVERRIDE ENABLED - {{/if}} - {{else data.docking_status == "docking"}} - {{if !data.override_enabled}} - DOCKING - {{else}} - DOCKING-OVERRIDE ENABLED - {{/if}} - {{else data.docking_status == "undocking"}} - {{if !data.override_enabled}} - UNDOCKING - {{else}} - UNDOCKING-OVERRIDE ENABLED - {{/if}} - {{else data.docking_status == "undocked"}} - {{if !data.override_enabled}} - NOT IN USE - {{else}} - OVERRIDE ENABLED - {{/if}} - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- Docking Hatch: -
-
- {{if data.docking_status == "docked"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed"}} - CLOSED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "docking"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "undocking"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "undocked"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- {{if data.docking_status == "docked"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', data.override_enabled ? 'redButton' : null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : 'yellowButton')}} - {{/if}} -
-
-
\ No newline at end of file diff --git a/nano/templates/simple_docking_console_pod.tmpl b/nano/templates/simple_docking_console_pod.tmpl deleted file mode 100644 index 07f055ea2c..0000000000 --- a/nano/templates/simple_docking_console_pod.tmpl +++ /dev/null @@ -1,101 +0,0 @@ -
-
-
- Docking Port Status: -
-
- {{if data.docking_status == "docked"}} - {{if !data.override_enabled}} - DOCKED - {{else}} - DOCKED-OVERRIDE ENABLED - {{/if}} - {{else data.docking_status == "docking"}} - {{if !data.override_enabled}} - DOCKING - {{else}} - DOCKING-OVERRIDE ENABLED - {{/if}} - {{else data.docking_status == "undocking"}} - {{if !data.override_enabled}} - UNDOCKING - {{else}} - UNDOCKING-OVERRIDE ENABLED - {{/if}} - {{else data.docking_status == "undocked"}} - {{if !data.override_enabled}} - NOT IN USE - {{else}} - OVERRIDE ENABLED - {{/if}} - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- Docking Hatch: -
-
- {{if data.docking_status == "docked"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed"}} - CLOSED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "docking"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "undocking"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else data.docking_status == "undocked"}} - {{if data.door_state == "open"}} - OPEN - {{else data.door_state == "closed" && data.door_lock == "locked"}} - SECURED - {{else data.door_state == "closed" && data.door_lock == "unlocked"}} - UNSECURED - {{else}} - ERROR - {{/if}} - {{else}} - ERROR - {{/if}} -
-
-
-
-
-
- {{if data.docking_status == "docked"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : null)}} - {{:helper.link('MANUAL EJECT', 'alert', {'command' : 'toggle_override'}, 'disabled', null)}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_door'}, data.override_enabled ? null : 'disabled', data.override_enabled ? 'redButton' : null)}} - {{:helper.link('Override', 'alert', {'command' : 'toggle_override'}, null, data.override_enabled ? 'redButton' : 'yellowButton')}} - {{:helper.link('MANUAL EJECT', 'alert', {'command' : 'toggle_override'}, data.can_force ? null : 'disabled', data.can_force ? 'redButton' : null)}} - {{/if}} -
-
-
\ No newline at end of file diff --git a/nano/templates/smes.tmpl b/nano/templates/smes.tmpl deleted file mode 100644 index bdbff2da0e..0000000000 --- a/nano/templates/smes.tmpl +++ /dev/null @@ -1,104 +0,0 @@ -
-
- Stored Charge: -
-
- {{:helper.displayBar(data.storedCapacity, 0, 100, data.charging ? 'good' : 'average')}} -
- {{:helper.round(data.storedCapacity)}}% -

-
- {{:data.storedCapacityAbs}} kWh / {{:data.storedCapacityMax}} kWh -
-
-
- -

Input Management

-
-
- Charge Mode: -
-
- {{:helper.link('Auto', 'refresh', {'cmode' : 1}, data.chargeMode ? 'selected' : null)}}{{:helper.link('Off', 'close', {'cmode' : 1}, data.chargeMode ? null : 'selected')}} -   - {{if data.charging == 2}} - [Charging] - {{else data.charging == 1}} - [Partially Charging] - {{else}} - [Not Charging] - {{/if}} -
-
- -
-
- Input Level: -
-
- {{:helper.displayBar(data.chargeLevel, 0, data.chargeMax)}} -
- {{:helper.link('MIN', null, {'input' : 'min'}, (data.chargeLevel > 0) ? null : 'disabled')}} - {{:helper.link('SET', null, {'input' : 'set'}, null)}} - {{:helper.link('MAX', null, {'input' : 'max'}, (data.chargeLevel < data.chargeMax) ? null : 'disabled')}} -
 {{:data.chargeLevel}} kW 
-
-
-
- -
-
- Input Load: -
-
- {{:helper.displayBar(data.chargeLoad, 0, data.chargeMax, (data.chargeLoad < data.chargeLevel) ? 'good' : 'average')}} -
- {{:data.chargeLoad}} kW -
-
-
- -

Output Management

-
-
- Output Status: -
-
- {{:helper.link('Online', 'power', {'online' : 1}, data.outputOnline ? 'selected' : null)}}{{:helper.link('Offline', 'close', {'online' : 1}, data.outputOnline ? null : 'selected')}} -   - {{if data.outputting == 2}} - [Outputting] - {{else data.outputting == 1}} - [Stored energy too low] - {{else}} - [Not Outputting] - {{/if}} -
-
- -
-
- Output Level: -
-
- {{:helper.displayBar(data.outputLevel, 0, data.outputMax)}} -
- {{:helper.link('MIN', null, {'output' : 'min'}, (data.outputLevel > 0) ? null : 'disabled')}} - {{:helper.link('SET', null, {'output' : 'set'}, null)}} - {{:helper.link('MAX', null, {'output' : 'max'}, (data.outputLevel < data.outputMax) ? null : 'disabled')}} -
 {{:data.outputLevel}} kW 
-
-
-
- -
-
- Output Load: -
-
- {{:helper.displayBar(data.outputLoad, 0, data.outputMax, (data.outputLoad < data.outputLevel) ? 'good' : 'average')}} -
- {{:data.outputLoad}} kW -
-
-
\ No newline at end of file diff --git a/nano/templates/supermatter_crystal.tmpl b/nano/templates/supermatter_crystal.tmpl deleted file mode 100644 index b06aaae746..0000000000 --- a/nano/templates/supermatter_crystal.tmpl +++ /dev/null @@ -1,25 +0,0 @@ -{{if data.detonating}} -
-

CRYSTAL DELAMINATING

-

Evacuate area immediately

-
-
-{{else}} -

Crystal Integrity

- {{:helper.displayBar(data.integrity_percentage, 0, 100, (data.integrity_percentage >= 90) ? 'good' : (data.integrity_percentage >= 25) ? 'average' : 'bad')}} - {{:data.integrity_percentage}} % -

Environment

- - Temperature: - - - {{:helper.displayBar(data.ambient_temp, 0, 10000, (data.ambient_temp >= 5000) ? 'bad' : (data.ambient_temp >= 4000) ? 'average' : 'good')}} - {{:data.ambient_temp}} K - - - Pressure: - - - {{:data.ambient_pressure}} kPa - -{{/if}} \ No newline at end of file diff --git a/nano/templates/supermatter_monitor.tmpl b/nano/templates/supermatter_monitor.tmpl deleted file mode 100644 index 1d7bdb7cff..0000000000 --- a/nano/templates/supermatter_monitor.tmpl +++ /dev/null @@ -1,125 +0,0 @@ -{{if data.active}} - {{:helper.link('Back to Menu', null, {'clear' : 1})}}
-
-
- Core Integrity: -
-
- {{:helper.displayBar(data.SM_integrity, 0, 100, (data.SM_integrity == 100) ? 'good' : (data.SM_integrity >= 50) ? 'average' : 'bad')}} {{:data.SM_integrity}}% -
-
- Relative EER: -
-
- {{if data.SM_power > 300}} - {{:data.SM_power}} MeV/cm3 - {{else data.SM_power > 150}} - {{:data.SM_power}} MeV/cm3 - {{else}} - {{:data.SM_power}} MeV/cm3 - {{/if}} -
-
- Temperature: -
-
- {{if data.SM_ambienttemp > 5000}} - {{:data.SM_ambienttemp}} K - {{else data.SM_ambienttemp > 4000}} - {{:data.SM_ambienttemp}} K - {{else}} - {{:data.SM_ambienttemp}} K - {{/if}} -
-
- Pressure: -
-
- {{if data.SM_ambientpressure > 10000}} - {{:data.SM_ambientpressure}} kPa - {{else data.SM_ambientpressure > 5000}} - {{:data.SM_ambientpressure}} kPa - {{else}} - {{:data.SM_ambientpressure}} kPa - {{/if}} -
-
- Chamber EPR: -
-
- {{if data.SM_EPR > 4}} - {{:data.SM_EPR}} - {{else data.SM_EPR > 2.5}} - {{:data.SM_EPR}} - {{else data.SM_EPR < 1}} - {{:data.SM_EPR}} - {{else}} - {{:data.SM_EPR}} - {{/if}} -
-
-

-
- Gas Composition: -
-
-
-
- O2: -
-
- {{:data.SM_gas_O2}} % -
-
- CO2: -
-
- {{:data.SM_gas_CO2}} % -
-
- N2: -
-
- {{:data.SM_gas_N2}} % -
-
- PH: -
-
- {{:data.SM_gas_PH}} % -
-
- N2O: -
-
- {{:data.SM_gas_N2O}} % -
-
-
- -{{else}} - {{:helper.link('Refresh', null, {'refresh' : 1})}}
- {{for data.supermatters}} -
-
- Area: -
-
- {{:value.area_name}} - (#{{:value.uid}}) -
-
- Integrity: -
-
- {{:value.integrity}} % -
-
- Options: -
-
- {{:helper.link('View Details', null, {'set' : value.uid})}} -
-
- {{/for}} -{{/if}} diff --git a/nano/templates/tanks.tmpl b/nano/templates/tanks.tmpl deleted file mode 100644 index c9d4e6c335..0000000000 --- a/nano/templates/tanks.tmpl +++ /dev/null @@ -1,47 +0,0 @@ -{{if data.maskConnected}} -
This tank is connected to a mask.
-{{else}} -
This tank is NOT connected to a mask.
-{{/if}} - -
-
- Tank Pressure: -
-
- {{:helper.displayBar(data.tankPressure, 0, 1013, (data.tankPressure > 200) ? 'good' : ((data.tankPressure > 100) ? 'average' : 'bad'))}} -
- {{:data.tankPressure}} kPa -
-
-
- -
 
- -
-
- Mask Release Pressure: -
-
- {{:helper.displayBar(data.releasePressure, 0, data.maxReleasePressure, (data.releasePressure >= 23) ? null : ((data.releasePressure >= 17) ? 'average' : 'bad'))}} -
- {{:helper.link('-', null, {'dist_p' : -10}, (data.releasePressure > 0) ? null : 'disabled')}} - {{:helper.link('-', null, {'dist_p' : -1}, (data.releasePressure > 0) ? null : 'disabled')}} -
 {{:data.releasePressure}} kPa 
- {{:helper.link('+', null, {'dist_p' : 1}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} - {{:helper.link('+', null, {'dist_p' : 10}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} - {{:helper.link('Max', null, {'dist_p' : 'max'}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} - {{:helper.link('Reset', null, {'dist_p' : 'reset'}, (data.releasePressure != data.defaultReleasePressure) ? null : 'disabled')}} -
-
-
- -
-
- Mask Release Valve: -
-
- {{:helper.link('Open', 'unlocked', {'stat' : 1}, (!data.maskConnected) ? 'disabled' : (data.valveOpen ? 'selected' : null))}}{{:helper.link('Close', 'locked', {'stat' : 1}, data.valveOpen ? null : 'selected')}} -
-
- diff --git a/nano/templates/vending_machine.tmpl b/nano/templates/vending_machine.tmpl deleted file mode 100644 index 93d5c1007c..0000000000 --- a/nano/templates/vending_machine.tmpl +++ /dev/null @@ -1,56 +0,0 @@ - - -{{if data.mode == 0}} -

Items available

-
- {{for data.products}} -
-
- {{if value.price > 0}} - {{:helper.link('Buy (' + value.price + ')', 'cart', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}} - {{else}} - {{:helper.link('Vend', 'circle-arrow-s', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}} - {{/if}} -
-
- {{if value.color}}{{:value.name}} - {{else}}{{:value.name}} - {{/if}} - ({{:value.amount ? value.amount : "NONE LEFT"}}) -
-
- {{empty}} - No items available! - {{/for}} -
-{{if data.coin}} -

Coin

-
-
Coin deposited:
-
{{:helper.link(data.coin, 'eject', {'remove_coin' : 1})}}
-
-{{/if}} -{{else data.mode == 1}} -

Item selected

-
-
-
Item selected:
{{:data.product}}
-
Charge:
{{:data.price}}
-
-
- {{if data.message_err}} {{/if}} {{:data.message}} -
-
- {{:helper.link('Cancel', 'arrowreturn-1-w', {'cancelpurchase' : 1})}} -
-
-{{/if}} -{{if data.panel}} -

Maintenance panel

-
-
Speaker
{{:helper.link(data.speaker ? 'Enabled' : 'Disabled', 'gear', {'togglevoice' : 1})}}
-
-{{/if}} \ No newline at end of file diff --git a/tgui/packages/tgui/interfaces/AICard.js b/tgui/packages/tgui/interfaces/AICard.js new file mode 100644 index 0000000000..68ecd1af16 --- /dev/null +++ b/tgui/packages/tgui/interfaces/AICard.js @@ -0,0 +1,122 @@ +import { useBackend } from "../backend"; +import { Button, ProgressBar, LabeledList, Box, Section } from "../components"; +import { Window } from "../layouts"; + +export const AICard = (props, context) => { + const { act, data } = useBackend(context); + + const { + has_ai, + integrity, + backup_capacitor, + flushing, + has_laws, + laws, + wireless, + radio, + } = data; + + if (has_ai === 0) { + return ( + + +
+ +

No AI detected.

+
+
+
+
+ ); + } else { + + let integrityColor = null; // Handles changing color of the integrity bar + if (integrity >= 75) { integrityColor = 'green'; } + else if (integrity >= 25) { integrityColor = 'yellow'; } + else { integrityColor = 'red'; } + + let powerColor = null; + if (backup_capacitor >= 75) { powerColor = 'green'; } + if (backup_capacitor >= 25) { powerColor = 'yellow'; } + else { powerColor = 'red'; } + + return ( + + +
+ +

{name}

+
+ + + + + + + + + + + +

{flushing === 1 ? "Wipe of AI in progress..." : ""}

+
+
+ +
+ {!!has_laws && ( + + {laws.map((value, key) => ( + + {value} + + ))} + + ) || ( // Else, no laws. + +

No laws detected.

+
+ )} +
+ +
+ + +
+
+
+ ); + } +}; diff --git a/tgui/packages/tgui/interfaces/APC.js b/tgui/packages/tgui/interfaces/APC.js new file mode 100644 index 0000000000..1ee7419b47 --- /dev/null +++ b/tgui/packages/tgui/interfaces/APC.js @@ -0,0 +1,288 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, Dimmer, Icon, LabeledList, NoticeBox, ProgressBar, Section, Flex } from '../components'; +import { Window } from '../layouts'; +import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; +import { FullscreenNotice } from './common/FullscreenNotice'; + +export const APC = (props, context) => { + const { act, data } = useBackend(context); + + let body = ; + + if (data.gridCheck) { + body = ; + } else if (data.failTime) { + body = ; + } + + return ( + + + {body} + + + ); +}; + +const powerStatusMap = { + 2: { + color: 'good', + externalPowerText: 'External Power', + chargingText: 'Fully Charged', + }, + 1: { + color: 'average', + externalPowerText: 'Low External Power', + chargingText: 'Charging', + }, + 0: { + color: 'bad', + externalPowerText: 'No External Power', + chargingText: 'Not Charging', + }, +}; + +const malfMap = { + 1: { + icon: 'terminal', + content: 'Override Programming', + action: 'hack', + }, + // 2: { + // icon: 'caret-square-down', + // content: 'Shunt Core Process', + // action: 'occupy', + // }, + // 3: { + // icon: 'caret-square-left', + // content: 'Return to Main Core', + // action: 'deoccupy', + // }, + // 4: { + // icon: 'caret-square-down', + // content: 'Shunt Core Process', + // action: 'occupy', + // }, +}; + +const ApcContent = (props, context) => { + const { act, data } = useBackend(context); + const locked = data.locked && !data.siliconUser; + const normallyLocked = data.normallyLocked; + const externalPowerStatus = powerStatusMap[data.externalPower] + || powerStatusMap[0]; + const chargingStatus = powerStatusMap[data.chargingStatus] + || powerStatusMap[0]; + const channelArray = data.powerChannels || []; + // const malfStatus = malfMap[data.malfStatus] || null; + const adjustedCellChange = data.powerCellStatus / 100; + + return ( + + + Fault in ID authenticator. + Please contact maintenance for service. + + )} /> +
+ + act('breaker')} /> + )}> + [ {externalPowerStatus.externalPowerText} ] + + + + + act('charge')} /> + )}> + [ {chargingStatus.chargingText} ] + + +
+
+ + {channelArray.map(channel => { + const { topicParams } = channel; + return ( + + = 2 ? 'good' : 'bad'}> + {channel.status >= 2 ? 'On' : 'Off'} + +
+
act('overload')} /> + )}> + + act('cover')} /> + )} /> + +
+ + ); +}; + +const GridCheck = (props, context) => { + return ( + + + + + + Power surge detected, grid check in effect... + + + ); +}; + +const ApcFailure = (props, context) => { + const { data, act } = useBackend(context); + + let rebootOptions = ( +