diff --git a/baystation12.dme b/baystation12.dme index 1885dd11dec..65f15e23785 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1605,6 +1605,7 @@ #include "code\modules\nano\modules\exosuit_control.dm" #include "code\modules\nano\modules\human_appearance.dm" #include "code\modules\nano\modules\law_manager.dm" +#include "code\modules\nano\modules\lighting_ctrl.dm" #include "code\modules\nano\modules\nano_module.dm" #include "code\modules\nano\modules\power_monitor.dm" #include "code\modules\nano\modules\rcon.dm" diff --git a/code/controllers/Processes/night_lighting.dm b/code/controllers/Processes/night_lighting.dm index d7d360d739a..7c80a7c2cf7 100644 --- a/code/controllers/Processes/night_lighting.dm +++ b/code/controllers/Processes/night_lighting.dm @@ -1,39 +1,23 @@ -/datum/controller/process/night_lighting/ +var/datum/controller/process/night_lighting/nl_ctrl +/datum/controller/process/night_lighting/ var/isactive = 0 var/firstrun = 1 - var/list/area/lighting_areas = list( - /area/hallway/primary/fore, - /area/hallway/primary/starboard, - /area/hallway/primary/aft, - /area/hallway/primary/port, - /area/hallway/primary/central_one, - /area/hallway/primary/central_two, - /area/hallway/primary/central_three, - /area/hallway/secondary/exit, - /area/hallway/secondary/entry/fore, - /area/hallway/secondary/entry/port, - /area/hallway/secondary/entry/starboard, - /area/hallway/secondary/entry/aft, - /area/crew_quarters/sleep, - /area/crew_quarters/locker, - /area/crew_quarters/fitness, - /area/crew_quarters/bar, - /area/engineering/foyer, - /area/security/lobby, - /area/storage/tools, - /area/storage/primary - ) +/datum/controller/process/night_lighting/proc/is_active() + return isactive /datum/controller/process/night_lighting/setup() name = "night lighting controller" schedule_interval = 3600 // Every 5 minutes. + nl_ctrl = src + if (!config.night_lighting) // Stop trying to delete processes. Not how it goes. disabled = 1 + /datum/controller/process/night_lighting/preStart() switch (worldtime2ticks()) @@ -60,28 +44,30 @@ if (isactive) deactivate() -/datum/controller/process/night_lighting/proc/activate() - for (var/obj/machinery/power/apc/APC in get_apc_list()) +// 'whitelisted' areas are areas that have nightmode explicitly enabled + +/datum/controller/process/night_lighting/proc/activate(var/whitelisted_only = 1) + isactive = 1 + for (var/obj/machinery/power/apc/APC in get_apc_list(whitelisted_only)) APC.toggle_nightlight("on") - isactive = 1 SCHECK -/datum/controller/process/night_lighting/proc/deactivate() - for (var/obj/machinery/power/apc/APC in get_apc_list()) +/datum/controller/process/night_lighting/proc/deactivate(var/whitelisted_only = 1) + isactive = 0 + for (var/obj/machinery/power/apc/APC in get_apc_list(whitelisted_only)) APC.toggle_nightlight("off") - isactive = 0 SCHECK -/datum/controller/process/night_lighting/proc/get_apc_list() +/datum/controller/process/night_lighting/proc/get_apc_list(var/whitelisted_only = 1) var/list/obj/machinery/power/apc/lighting_apcs = list() for (var/A in all_areas) var/area/B = A - if (!(B.type in lighting_areas)) + if (B.no_light_control || (!(B.allow_nightmode) && whitelisted_only)) continue - if (B.apc) + if (B.apc && !B.apc.aidisabled) lighting_apcs += B.apc SCHECK diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 7a31a353b6d..7bd9e6c4356 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -52,6 +52,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/list/forced_ambience = null var/sound_env = STANDARD_STATION var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf + var/no_light_control = 0 // if 1, lights in area cannot be toggled with light controller + var/allow_nightmode = 0 // if 1, lights in area will be darkened by the night mode controller /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ @@ -103,6 +105,7 @@ var/list/ghostteleportlocs = list() power_equip = 0 power_environ = 0 ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg') + no_light_control = 1 area/space/atmosalert() return @@ -123,6 +126,7 @@ area/space/atmosalert() /area/arrival requires_power = 0 + no_light_control = 1 /area/arrival/start name = "\improper Arrival Area" @@ -145,6 +149,7 @@ area/space/atmosalert() requires_power = 0 sound_env = SMALL_ENCLOSED base_turf = /turf/space + no_light_control = 1 /area/shuttle/arrival name = "\improper Arrival Shuttle" @@ -338,6 +343,7 @@ area/space/atmosalert() name = "\improper Alien base" icon_state = "yellow" requires_power = 0 + no_light_control = 1 // CENTCOM @@ -346,6 +352,7 @@ area/space/atmosalert() icon_state = "centcom" requires_power = 0 lighting_use_dynamic = 0 + no_light_control = 1 /area/centcom/control name = "\improper Centcom Control" @@ -384,6 +391,7 @@ area/space/atmosalert() icon_state = "syndie-ship" requires_power = 0 lighting_use_dynamic = 0 + no_light_control = 1 /area/syndicate_mothership/control name = "\improper Mercenary Control Room" @@ -400,6 +408,7 @@ area/space/atmosalert() icon_state = "asteroid" requires_power = 0 sound_env = ASTEROID + no_light_control = 1 /area/asteroid/cave // -- TLE name = "\improper Moon - Underground" @@ -430,6 +439,7 @@ area/space/atmosalert() name = "\improper Clown Planet" icon_state = "honk" requires_power = 0 + no_light_control = 1 /area/tdome name = "\improper Thunderdome" @@ -437,6 +447,7 @@ area/space/atmosalert() requires_power = 0 lighting_use_dynamic = 0 sound_env = ARENA + no_light_control = 1 /area/tdome/tdome1 name = "\improper Thunderdome (Team 1)" @@ -460,6 +471,7 @@ area/space/atmosalert() icon_state = "red" lighting_use_dynamic = 0 requires_power = 0 + no_light_control = 1 /area/acting/backstage name = "\improper Backstage" @@ -478,6 +490,7 @@ area/space/atmosalert() icon_state = "yellow" requires_power = 0 flags = RAD_SHIELDED + no_light_control = 1 /area/syndicate_station/start name = "\improper Mercenary Forward Operating Base" @@ -532,11 +545,13 @@ area/space/atmosalert() icon_state = "yellow" requires_power = 0 lighting_use_dynamic = 0 + no_light_control = 1 /area/skipjack_station name = "\improper Skipjack" icon_state = "yellow" requires_power = 0 + no_light_control = 1 /area/skipjack_station/start name = "\improper Skipjack" @@ -570,6 +585,7 @@ area/space/atmosalert() /area/prison name = "\improper Prison Station" icon_state = "brig" + no_light_control = 1 /area/prison/arrival_airlock name = "\improper Prison Station Airlock" @@ -827,6 +843,7 @@ area/space/atmosalert() /area/hallway/primary/ sound_env = LARGE_ENCLOSED + allow_nightmode = 1 /area/hallway/primary/fore name = "\improper Fore Primary Hallway" @@ -859,10 +876,12 @@ area/space/atmosalert() /area/hallway/secondary/exit name = "\improper Escape Shuttle Hallway" icon_state = "escape" + no_light_control = 1 /area/hallway/secondary/construction name = "\improper Construction Area" icon_state = "construction" + allow_nightmode = 0 /area/hallway/secondary/entry/fore name = "\improper Arrival Shuttle Hallway - Fore" @@ -885,6 +904,7 @@ area/space/atmosalert() /area/bridge name = "\improper Bridge" icon_state = "bridge" + no_light_control = 1 /area/bridge/meeting_room name = "\improper Heads of Staff Meeting Room" @@ -928,6 +948,7 @@ area/space/atmosalert() /area/comms name = "\improper Communications Relay" icon_state = "tcomsatcham" + no_light_control = 1 /area/server name = "\improper Research Server Room" @@ -948,6 +969,7 @@ area/space/atmosalert() /area/crew_quarters/sleep name = "\improper Dormitories" icon_state = "Sleep" + allow_nightmode = 1 /area/crew_quarters/sleep/engi_wash name = "\improper Engineering Washroom" @@ -984,6 +1006,7 @@ area/space/atmosalert() /area/crew_quarters/locker name = "\improper Locker Room" icon_state = "locker" + allow_nightmode = 1 /area/crew_quarters/locker/locker_toilet name = "\improper Locker Toilets" @@ -993,6 +1016,7 @@ area/space/atmosalert() /area/crew_quarters/fitness name = "\improper Fitness Room" icon_state = "fitness" + allow_nightmode = 1 /area/crew_quarters/cafeteria name = "\improper Cafeteria" @@ -1006,6 +1030,7 @@ area/space/atmosalert() name = "\improper Bar" icon_state = "bar" sound_env = LARGE_SOFTFLOOR + allow_nightmode = 1 /area/crew_quarters/theatre name = "\improper Theatre" @@ -1039,6 +1064,7 @@ area/space/atmosalert() icon_state = "Holodeck" lighting_use_dynamic = 0 sound_env = LARGE_ENCLOSED + no_light_control = 1 /area/holodeck/alphadeck name = "\improper Holodeck Alpha" @@ -1112,6 +1138,7 @@ area/space/atmosalert() name = "\improper Atmospherics" icon_state = "atmos" sound_env = LARGE_ENCLOSED + no_light_control = 1 /area/engineering/atmos/monitoring name = "\improper Atmospherics Monitoring Room" @@ -1137,6 +1164,7 @@ area/space/atmosalert() name = "\improper Engine Room" icon_state = "engine" sound_env = LARGE_ENCLOSED + no_light_control = 1 /area/engineering/engine_airlock name = "\improper Engine Room Airlock" @@ -1149,6 +1177,7 @@ area/space/atmosalert() /area/engineering/engine_waste name = "\improper Engine Waste Handling" icon_state = "engine_waste" + no_light_control = 1 /area/engineering/engineering_monitoring name = "\improper Engineering Monitoring Room" @@ -1157,6 +1186,7 @@ area/space/atmosalert() /area/engineering/foyer name = "\improper Engineering Foyer" icon_state = "engineering_foyer" + allow_nightmode = 1 /area/engineering/storage name = "\improper Engineering Storage" @@ -1367,10 +1397,12 @@ area/space/atmosalert() /area/medical/surgery name = "\improper Operating Theatre 1" icon_state = "surgery" + no_light_control = 1 /area/medical/surgery2 name = "\improper Operating Theatre 2" icon_state = "surgery" + no_light_control = 1 /area/medical/surgeryobs name = "\improper Operation Observation Room" @@ -1399,16 +1431,20 @@ area/space/atmosalert() /area/medical/sleeper name = "\improper Emergency Treatment Centre" icon_state = "exam_room" + no_light_control = 1 //Security /area/security/main name = "\improper Security Office" icon_state = "security" + no_light_control = 1 /area/security/lobby name = "\improper Security Lobby" icon_state = "security" + allow_nightmode = 1 + no_light_control = 0 /area/security/brig name = "\improper Security - Brig" @@ -1604,10 +1640,12 @@ area/space/atmosalert() /area/storage/tools name = "Auxiliary Tool Storage" icon_state = "storage" + allow_nightmode = 1 /area/storage/primary name = "Primary Tool Storage" icon_state = "primarystorage" + allow_nightmode = 1 /area/storage/autolathe name = "Autolathe Storage" @@ -1655,6 +1693,7 @@ area/space/atmosalert() /area/djstation name = "\improper Listening Post" icon_state = "LP" + no_light_control = 1 /area/djstation/solars name = "\improper Listening Post Solars" @@ -1665,6 +1704,7 @@ area/space/atmosalert() /area/derelict name = "\improper Derelict Station" icon_state = "storage" + no_light_control = 1 /area/derelict/hallway/primary name = "\improper Derelict Primary Hallway" @@ -1763,6 +1803,7 @@ area/space/atmosalert() /area/constructionsite name = "\improper Construction Site" icon_state = "storage" + no_light_control = 1 /area/constructionsite/storage name = "\improper Construction Site Storage Area" @@ -1823,6 +1864,7 @@ area/space/atmosalert() /area/construction name = "\improper Engineering Construction Area" icon_state = "yellow" + no_light_control = 1 /area/construction/supplyshuttle name = "\improper Supply Shuttle" @@ -1959,6 +2001,7 @@ area/space/atmosalert() // Telecommunications Satellite /area/tcommsat/ ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') + no_light_control = 1 /area/tcommsat/entrance name = "\improper Telecoms Teleporter" @@ -2005,6 +2048,7 @@ area/space/atmosalert() /area/awaymission name = "\improper Strange Location" icon_state = "away" + no_light_control = 1 /area/awaymission/example name = "\improper Strange Station" @@ -2221,6 +2265,7 @@ var/list/the_station_areas = list ( lighting_use_dynamic = 0 requires_power = 0 var/sound/mysound = null + no_light_control = 1 New() ..() diff --git a/code/modules/modular_computers/file_system/programs/_engineering.dm b/code/modules/modular_computers/file_system/programs/_engineering.dm index 71bc0d475b3..82aca650199 100644 --- a/code/modules/modular_computers/file_system/programs/_engineering.dm +++ b/code/modules/modular_computers/file_system/programs/_engineering.dm @@ -83,3 +83,17 @@ requires_ntnet_feature = NTNET_SYSTEMCONTROL usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE size = 19 + +// Night-Mode Toggle for CE +/datum/computer_file/program/lighting_control + filename = "lightctrl" + filedesc = "Lighting Controller" + nanomodule_path = /datum/nano_module/lighting_ctrl + program_icon_state = "comm_monitor" + extended_desc = "This program allows mass-control of the station's lighting systems. This program cannot be run on tablet computers." + required_access = access_ce + requires_ntnet = 1 + network_destination = "APC Coordinator" + requires_ntnet_feature = NTNET_SYSTEMCONTROL + usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE + size = 9 \ No newline at end of file diff --git a/code/modules/nano/modules/lighting_ctrl.dm b/code/modules/nano/modules/lighting_ctrl.dm new file mode 100644 index 00000000000..a7c4a3f2855 --- /dev/null +++ b/code/modules/nano/modules/lighting_ctrl.dm @@ -0,0 +1,49 @@ +/datum/nano_module/lighting_ctrl + name = "Lighting Control" + var/context = "pub" + var/lstate = "full" + var/mob/lusr = null // for admin logs + +/datum/nano_module/lighting_ctrl/New() + ..() + lstate = nl_ctrl.is_active() ? "dark" : "full" + +/datum/nano_module/lighting_ctrl/proc/update_lighting() + if (!config.night_lighting) + return + + // whether to only select areas explicitly marked for nightlighting + var/wl_only = context == "all" ? 0 : 1 + + if (lstate == "dark") + log_and_message_admins("enabled night-mode [wl_only ? "in public areas" : "globally"].", lusr) + nl_ctrl.activate(wl_only) + else if (lstate == "full") + log_and_message_admins("disabled night-mode [wl_only ? "in public areas" : "globally"].", lusr) + nl_ctrl.deactivate(wl_only) + +/datum/nano_module/lighting_ctrl/Topic(href, href_list) + if(..()) + return 1 + if (href_list["context"]) + context = href_list["context"] + if (href_list["mode"]) + lstate = href_list["mode"] + if (href_list["set"]) + update_lighting() + +/datum/nano_module/lighting_ctrl/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) + lusr = user + var/list/data = host.initial_data() + + data["context"] = context + data["status"] = lstate + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "lighting_ctrl.tmpl", "Lighting Control", 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 + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) \ No newline at end of file diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index e91fca33e05..9c1b2a0b1cb 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1262,9 +1262,9 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on) for (var/obj/machinery/light/L in area.contents) if (!listgetindex(night_light_args, L.type)) // if L's type isn't defined in our args list continue - if (force == "on" || !night_mode) + if (force == "on") L.set_light_source(arglist(night_light_args[L.type])) - else if (force == "off" || night_mode) + else if (force == "off") L.set_light_source() L.update() switch (force) diff --git a/code/modules/security levels/security levels.dm b/code/modules/security levels/security levels.dm index 4b73c0dd28d..cbb4a9b4312 100644 --- a/code/modules/security levels/security levels.dm +++ b/code/modules/security levels/security levels.dm @@ -23,17 +23,18 @@ if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) switch(level) if(SEC_LEVEL_GREEN) - security_announcement_down.Announce("[config.alert_desc_green]", "Attention! Security level lowered to green") + security_announcement_down.Announce("[config.alert_desc_green]", "Attention! Security level lowered to green.") security_level = SEC_LEVEL_GREEN if(SEC_LEVEL_BLUE) if(security_level < SEC_LEVEL_BLUE) - security_announcement_up.Announce("[config.alert_desc_blue_upto]", "Attention! Security level elevated to blue") + security_announcement_up.Announce("[config.alert_desc_blue_upto]", "Attention! Security level elevated to blue.") else - security_announcement_down.Announce("[config.alert_desc_blue_downto]", "Attention! Security level lowered to blue") + security_announcement_down.Announce("[config.alert_desc_blue_downto]", "Attention! Security level lowered to blue.") security_level = SEC_LEVEL_BLUE if(SEC_LEVEL_RED) if(security_level < SEC_LEVEL_RED) - security_announcement_up.Announce("[config.alert_desc_red_upto]", "Attention! Code red!") + security_announcement_up.Announce("[config.alert_desc_red_upto]", "Attention! Security level elevated to red!") + nl_ctrl.deactivate(0) // Disable nightmode globally else security_announcement_down.Announce("[config.alert_desc_red_downto]", "Attention! Code red!") security_level = SEC_LEVEL_RED diff --git a/html/changelogs/Lohikar-NightmodeTweaks.yml b/html/changelogs/Lohikar-NightmodeTweaks.yml new file mode 100644 index 00000000000..405cb4df444 --- /dev/null +++ b/html/changelogs/Lohikar-NightmodeTweaks.yml @@ -0,0 +1,40 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Lohikar + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a night-mode control program for the Chief Engineer." + - tweak: "Changed how night-mode works internally." + - tweak: "Red alert now disables night-mode." + - spellcheck: "Slightly changed alert messages." + - bugfix: "Speculative fix for perpetual night-mode." diff --git a/nano/templates/lighting_ctrl.tmpl b/nano/templates/lighting_ctrl.tmpl new file mode 100644 index 00000000000..3290277cce3 --- /dev/null +++ b/nano/templates/lighting_ctrl.tmpl @@ -0,0 +1,16 @@ +