Ports Nightshift from Paradise (#3817)

* Ports Nightshift and converts tick time to ds time

* Moves Nightshift config to the new system and ports the forgotten APC TGUI updates

* Attempting to fix your god damn tome's init.

* Lets do station time the paradise way. Also think I fixed some apc misfires?

* Rerecompiles tgui.bundle.js
This commit is contained in:
Zandario
2022-03-21 23:25:46 -05:00
committed by GitHub
parent 411290e995
commit dfaee1de90
37 changed files with 534 additions and 168 deletions

View File

@@ -118,7 +118,8 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_PLANETS -2
#define INIT_ORDER_ASSETS -4
#define INIT_ORDER_HOLOMAPS -5
#define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_NIGHTSHIFT -6
#define INIT_ORDER_OVERLAY -7
#define INIT_ORDER_EVENTS -8
#define INIT_ORDER_OVERMAPS -9
#define INIT_ORDER_TICKER -10
@@ -133,6 +134,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_NIGHTSHIFT 6
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
@@ -140,7 +142,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_VIS 10
#define FIRE_PRIORITY_SERVER_MAINT 10
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_CHARSETUP 25
#define FIRE_PRIORITY_CHARSETUP 25
#define FIRE_PRIORITY_SPACEDRIFT 25
#define FIRE_PRIORITY_AIRFLOW 30
#define FIRE_PRIORITY_AIR 35

View File

@@ -61,6 +61,7 @@
#define LIGHT_COLOR_INCANDESCENT_TUBE "#E0EFF0"
#define LIGHT_COLOR_INCANDESCENT_BULB "#FFFEB8"
#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66"
#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86"
#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.

View File

@@ -18,25 +18,25 @@
return wtime + (time_offset + wusage) * world.tick_lag
var/roundstart_hour
GLOBAL_VAR_INIT(roundstart_hour, pick(2,7,12,17))
var/station_date = ""
var/next_station_date_change = 1 DAY
#define duration2stationtime(time) time2text(station_time_in_ticks + time, "hh:mm")
#define worldtime2stationtime(time) time2text(roundstart_hour HOURS + time, "hh:mm")
#define round_duration_in_ticks (SSticker.round_start_time ? world.time - SSticker.round_start_time : 0)
#define station_time_in_ticks (roundstart_hour HOURS + round_duration_in_ticks)
#define duration2stationtime(time) time2text(station_time_in_ds + time, "hh:mm")
#define worldtime2stationtime(time) time2text(GLOB.roundstart_hour HOURS + time, "hh:mm")
#define round_duration_in_ds (SSticker.round_start_time ? world.time - SSticker.round_start_time : 0)
#define station_time_in_ds (GLOB.roundstart_hour HOURS + round_duration_in_ds)
/proc/stationtime2text()
return time2text(station_time_in_ticks, "hh:mm")
return time2text(station_time_in_ds + GLOB.timezoneOffset, "hh:mm")
/proc/stationdate2text()
var/update_time = FALSE
if(station_time_in_ticks > next_station_date_change)
if(station_time_in_ds > next_station_date_change)
next_station_date_change += 1 DAY
update_time = TRUE
if(!station_date || update_time)
var/extra_days = round(station_time_in_ticks / (1 DAY)) DAYS
var/extra_days = round(station_time_in_ds / (1 DAY)) DAYS
var/timeofday = world.timeofday + extra_days
station_date = num2text((text2num(time2text(timeofday, "YYYY"))+544)) + "-" + time2text(timeofday, "MM-DD")
return station_date
@@ -47,11 +47,28 @@ var/next_station_date_change = 1 DAY
var/time_portion = time2text(world.timeofday, "hh:mm:ss")
return "[date_portion]T[time_portion]"
/proc/get_timezone_offset()
var/midnight_gmt_here = text2num(time2text(0,"hh")) * 36000
if(midnight_gmt_here > 12 HOURS)
return 24 HOURS - midnight_gmt_here
else
return midnight_gmt_here
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
wtime = world.time
return time2text(wtime - GLOB.timezoneOffset, format)
/* This is used for displaying the "station time" equivelent of a world.time value
Calling it with no args will give you the current time, but you can specify a world.time-based value as an argument
- You can use this, for example, to do "This will expire at [station_time_at(world.time + 500)]" to display a "station time" expiration date
which is much more useful for a player)*/
/proc/station_time(time=world.time, display_only=FALSE)
return ((((time - SSticker.round_start_time)) + GLOB.gametime_offset) % 864000) - (display_only ? GLOB.timezoneOffset : 0)
/proc/station_time_timestamp(format = "hh:mm:ss", time=world.time)
return time2text(station_time(time, TRUE), format)
/* Returns 1 if it is the selected month and day */
proc/isDay(var/month, var/day)
if(isnum(month) && isnum(day))
@@ -73,7 +90,7 @@ var/last_round_duration = 0
if(last_round_duration && world.time < next_duration_update)
return last_round_duration
var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
var/mills = round_duration_in_ds // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
@@ -85,10 +102,6 @@ var/last_round_duration = 0
next_duration_update = world.time + 1 MINUTES
return last_round_duration
/hook/startup/proc/set_roundstart_hour()
roundstart_hour = pick(2,7,12,17)
return 1
/var/midnight_rollovers = 0
/var/rollovercheck_last_timeofday = 0
/proc/update_midnight_rollover()

View File

@@ -1,5 +1,7 @@
GLOBAL_VAR_INIT(timezoneOffset, 0) // The difference betwen midnight (of the host computer) and 0 world.ticks.
GLOBAL_VAR_INIT(gametime_offset, 432000) // 12:00 in seconds
GLOBAL_VAR_INIT(TAB, "&nbsp;&nbsp;&nbsp;&nbsp;")
GLOBAL_VAR_INIT(Debug2, FALSE)

View File

@@ -8,3 +8,6 @@
/datum/config_entry/flag/allow_holidays
config_entry_value = TRUE
/datum/config_entry/flag/nightshifts_enabled
config_entry_value = TRUE

View File

@@ -268,6 +268,7 @@
var/list/gamemode_cache = list()
/datum/configuration_legacy/New()
var/list/L = subtypesof(/datum/game_mode)
for (var/T in L)

View File

@@ -58,7 +58,7 @@ SUBSYSTEM_DEF(gamemaster)
if(ignore_time_restrictions)
return TRUE
// Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round.
var/mills = round_duration_in_ticks
var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
@@ -153,5 +153,3 @@ SUBSYSTEM_DEF(gamemaster)
return best_actions
else
log_debug("Game Master failed to find a suitable event, something very wrong is going on.")

View File

@@ -0,0 +1,63 @@
SUBSYSTEM_DEF(nightshift)
name = "Night Shift"
init_order = INIT_ORDER_NIGHTSHIFT
priority = FIRE_PRIORITY_NIGHTSHIFT
wait = 60 SECONDS
flags = SS_NO_TICK_CHECK
var/nightshift_active = FALSE
var/nightshift_start_time = 702000 //7:30 PM, station time
var/nightshift_end_time = 270000 //7:30 AM, station time
var/nightshift_first_check = 30 SECONDS
var/high_security_mode = FALSE
/datum/controller/subsystem/nightshift/Initialize()
if (!CONFIG_GET(flag/nightshifts_enabled))
can_fire = FALSE
//if(CONFIG_GET(flag/randomized_start_time_enabled))
//GLOB.gametime_offset = rand(0, 23) HOURS
return ..()
/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
if(world.time - SSticker.round_start_time < nightshift_first_check)
return
check_nightshift()
/datum/controller/subsystem/nightshift/proc/announce(message)
var/announce_z
if(GLOB.using_map.station_levels.len)
announce_z = pick(GLOB.using_map.station_levels)
priority_announcement.Announce(message, new_title = "Automated Lighting System Announcement", new_sound = 'sound/misc/notice2.ogg', zlevel = announce_z)
/datum/controller/subsystem/nightshift/proc/check_nightshift(check_canfire=FALSE) //This is called from elsewhere, like setting the alert levels
if(check_canfire && !can_fire)
return
var/emergency = security_level > SEC_LEVEL_GREEN
var/announcing = TRUE
var/time = station_time()
var/night_time = (time < nightshift_end_time) || (time > nightshift_start_time)
if(high_security_mode != emergency)
high_security_mode = emergency
if(night_time)
announcing = FALSE
if(!emergency)
announce("Restoring night lighting configuration to normal operation.")
else
announce("Disabling night lighting: Station is in a state of emergency.")
if(emergency)
night_time = FALSE
if(nightshift_active != night_time)
update_nightshift(night_time, announcing)
/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE)
nightshift_active = active
if(announce)
if(active)
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
else
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
for(var/obj/machinery/power/apc/apc in GLOB.apcs)
if(apc.z in GLOB.using_map.station_levels)
apc.set_nightshift(active, TRUE)
CHECK_TICK

View File

@@ -6,16 +6,16 @@ SUBSYSTEM_DEF(planets)
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/new_outdoor_turfs = list()
var/list/new_outdoor_walls = list()
var/static/list/new_outdoor_turfs = list()
var/static/list/new_outdoor_walls = list()
var/list/planets = list()
var/list/z_to_planet = list()
var/static/list/planets = list()
var/static/list/z_to_planet = list()
var/list/currentrun = list()
var/static/list/currentrun = list()
var/list/needs_sun_update = list()
var/list/needs_temp_update = list()
var/static/list/needs_sun_update = list()
var/static/list/needs_temp_update = list()
/datum/controller/subsystem/planets/Initialize(timeofday)
admin_notice("<span class='danger'>Initializing planetary weather.</span>", R_DEBUG)

View File

@@ -18,15 +18,15 @@ SUBSYSTEM_DEF(transfer)
/datum/controller/subsystem/transfer/fire(resumed)
currenttick = currenttick + 1
//VOREStation Edit START
/* if (round_duration_in_ticks >= shift_last_vote - 2 MINUTES)
/* if (round_duration_in_ds >= shift_last_vote - 2 MINUTES)
shift_last_vote = 999999999999 //Setting to a stupidly high number since it'll be not used again.
to_world("<b>Warning: This upcoming round-extend vote will be your ONLY extend vote. Wrap up your scenes in the next 60 minutes if the round is extended.</b>") //VOREStation Edit
*/
if (round_duration_in_ticks >= shift_hard_end - 1 MINUTE)
if (round_duration_in_ds >= shift_hard_end - 1 MINUTE)
init_shift_change(null, 1)
shift_hard_end = timerbuffer + config_legacy.vote_autotransfer_interval //If shuttle somehow gets recalled, let's force it to call again next time a vote would occur.
timerbuffer = timerbuffer + config_legacy.vote_autotransfer_interval //Just to make sure a vote doesn't occur immediately afterwords.
else if (round_duration_in_ticks >= timerbuffer - 1 MINUTE)
else if (round_duration_in_ds >= timerbuffer - 1 MINUTE)
SSvote.autotransfer()
//VOREStation Edit END
timerbuffer = timerbuffer + config_legacy.vote_autotransfer_interval

View File

@@ -78,7 +78,7 @@ In short:
alm.ex_act(2)
/datum/universal_state/hell/proc/APCSet()
for (var/obj/machinery/power/apc/APC in machines)
for (var/obj/machinery/power/apc/APC in GLOB.apcs)
if (!(APC.stat & BROKEN) && !APC.is_critical)
APC.emagged = 1
APC.queue_icon_update()

View File

@@ -283,8 +283,8 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
</body>
</html>
"}
/obj/item/book/tome/Initialize()
..()
/obj/item/book/tome/Initialize(mapload)
. = ..()
if(!cultwords["travel"])
runerandom()
for(var/V in cultwords)

View File

@@ -107,7 +107,7 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked
alm.ex_act(2)
/datum/universal_state/supermatter_cascade/proc/APCSet()
for (var/obj/machinery/power/apc/APC in machines)
for (var/obj/machinery/power/apc/APC in GLOB.apcs)
if (!(APC.stat & BROKEN) && !APC.is_critical)
APC.chargemode = 0
if(APC.cell)

View File

@@ -135,7 +135,7 @@ var/hadevent = 0
apc.overload_lighting()
else
for(var/obj/machinery/power/apc/apc in machines)
for(var/obj/machinery/power/apc/apc in GLOB.apcs)
apc.overload_lighting()
return
@@ -261,14 +261,14 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
spawn(0)
to_chat(world, "Started processing APCs")
for (var/obj/machinery/power/apc/APC in machines)
for (var/obj/machinery/power/apc/apc in GLOB.apcs)
if(APC.z in station_levels)
APC.ion_act()
apcnum++
to_chat(world, "Finished processing APCs. Processed: [apcnum]")
spawn(0)
to_chat(world, "Started processing SMES")
for (var/obj/machinery/power/smes/SMES in machines)
for (var/obj/machinery/power/smes/SMES in GLOB.smeses)
if(SMES.z in station_levels)
SMES.ion_act()
smesnum++

View File

@@ -20,7 +20,7 @@
S.power_change()
for(var/obj/machinery/power/apc/C in machines)
for(var/obj/machinery/power/apc/C in GLOB.apcs)
if(!C.is_critical && C.cell && (C.z in GLOB.using_map.station_levels))
C.cell.charge = 0
@@ -29,7 +29,7 @@
if(announce)
command_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
for(var/obj/machinery/power/apc/C in machines)
for(var/obj/machinery/power/apc/C in GLOB.apcs)
if(C.cell && (C.z in GLOB.using_map.station_levels))
C.cell.charge = C.cell.maxcharge
for(var/obj/machinery/power/smes/S in machines)

View File

@@ -34,7 +34,7 @@
if(SSemergencyshuttle.shuttle && (SSemergencyshuttle.shuttle.moving_status == SHUTTLE_WARMUP || SSemergencyshuttle.shuttle.moving_status == SHUTTLE_INTRANSIT))
return // Don't do anything if the shuttle's coming.
var/mills = round_duration_in_ticks
var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)

View File

@@ -168,7 +168,7 @@
// Description: Returns a list of all unhacked APCs
/proc/get_unhacked_apcs(var/mob/living/silicon/ai/user)
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
for(var/obj/machinery/power/apc/A in GLOB.apcs)
if(A.hacker && A.hacker == user)
continue
H.Add(A)

View File

@@ -147,7 +147,7 @@
to_chat(user, "You already started the system override sequence.")
return
var/list/remaining_apcs = list()
for(var/obj/machinery/power/apc/A in machines)
for(var/obj/machinery/power/apc/A in GLOB.apcs)
if(!(A.z in GLOB.using_map.station_levels)) // Only station APCs
continue
if(A.hacker == user || A.aidisabled) // This one is already hacked, or AI control is disabled on it.
@@ -193,7 +193,7 @@
to_chat(user, "## REACHABLE APC SYSTEMS OVERTAKEN. BYPASSING PRIMARY FIREWALL.")
sleep(300)
// Hack all APCs, including those built during hack sequence.
for(var/obj/machinery/power/apc/A in machines)
for(var/obj/machinery/power/apc/A in GLOB.apcs)
if((!A.hacker || (A.hacker != src)) && !A.aidisabled && (A.z in GLOB.using_map.station_levels))
A.ai_hack(src)

View File

@@ -184,7 +184,7 @@
// Description: This writes to the logs list, so that people can see what people are doing on the Exonet ingame. Note that this is not an admin logging function.
// Communicators are already logged seperately.
/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content)
//var/timestamp = time2text(station_time_in_ticks, "hh:mm:ss")
//var/timestamp = time2text(station_time_in_ds, "hh:mm:ss")
var/timestamp = "[stationdate2text()] [stationtime2text()]"
var/msg = "[timestamp] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]"
logs.Add(msg)

View File

@@ -79,7 +79,7 @@
newMsg.body = msg
newMsg.time_stamp = "[stationtime2text()]"
newMsg.is_admin_message = adminMessage
newMsg.post_time = round_duration_in_ticks // Should be almost universally unique
newMsg.post_time = round_duration_in_ds // Should be almost universally unique
if(message_type)
newMsg.message_type = message_type
if(photo)

View File

@@ -55,7 +55,7 @@ GLOBAL_LIST(topic_status_cache)
// if(config && config_legacy.log_runtime)
// log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log")
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
GLOB.timezoneOffset = get_timezone_offset()
callHook("startup")
//Emergency Fix

View File

@@ -376,8 +376,8 @@
if(!(A.type in areas_all))
areas_all.Add(A.type)
for(var/obj/machinery/power/apc/APC in machines)
var/area/A = get_area(APC)
for(var/obj/machinery/power/apc/apc in GLOB.apcs)
var/area/A = get_area(apc)
if(A && !(A.type in areas_with_APC))
areas_with_APC.Add(A.type)

View File

@@ -197,14 +197,14 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
spawn(0)
to_chat(world, "Started processing APCs")
for (var/obj/machinery/power/apc/APC in machines)
for (var/obj/machinery/power/apc/apc in GLOB.apcs)
if(APC.z in station_levels)
APC.ion_act()
apcnum++
to_chat(world, "Finished processing APCs. Processed: [apcnum]")
spawn(0)
to_chat(world, "Started processing SMES")
for (var/obj/machinery/power/smes/SMES in machines)
for (var/obj/machinery/power/smes/SMES in GLOB.smeses)
if(SMES.z in station_levels)
SMES.ion_act()
smesnum++

View File

@@ -86,10 +86,10 @@
power_draw_per_use = 4
/obj/item/integrated_circuit/time/clock/do_work()
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) )
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ds, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ds, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ds, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ds, "ss") ) )
push_data()
activate_pin(2)

View File

@@ -122,7 +122,7 @@
// Description: Refreshes local list of known devices.
/datum/nano_module/rcon/proc/FindDevices()
known_SMESs = new /list()
for(var/obj/machinery/power/smes/buildable/SMES in machines)
for(var/obj/machinery/power/smes/buildable/SMES in GLOB.smeses)
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
known_SMESs.Add(SMES)

View File

@@ -1,3 +1,5 @@
GLOBAL_LIST_EMPTY(apcs)
#define CRITICAL_APC_EMP_PROTECTION 10 // EMP effect duration is divided by this number if the APC has "critical" flag
//update_state
#define UPDATE_CELL_IN 1
@@ -34,10 +36,14 @@
// controls power to devices in that area
// may be opened to change power cell
// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto
#define POWERCHAN_OFF 0
#define POWERCHAN_OFF_AUTO 1
#define POWERCHAN_ON 2
#define POWERCHAN_ON_AUTO 3
#define POWERCHAN_OFF 0 // Power channel is off and will stay that way dammit
#define POWERCHAN_OFF_AUTO 1 // Power channel is off until power rises above a threshold
#define POWERCHAN_ON 2 // Power channel is on until there is no power
#define POWERCHAN_ON_AUTO 3 // Power channel is on until power drops below a threshold
#define NIGHTSHIFT_AUTO 1
#define NIGHTSHIFT_NEVER 2
#define NIGHTSHIFT_ALWAYS 3
//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx
@@ -104,6 +110,7 @@
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
var/emergency_lights = FALSE
var/update_state = -1
var/update_overlay = -1
var/is_critical = 0
@@ -118,6 +125,10 @@
var/global/list/status_overlays_environ
var/alarms_hidden = FALSE //If power alarms from this APC are visible on consoles
var/nightshift_lights = FALSE
var/nightshift_setting = NIGHTSHIFT_AUTO
var/last_nightshift_switch = 0
/obj/machinery/power/apc/updateDialog()
if (stat & (BROKEN|MAINT))
return
@@ -159,6 +170,7 @@
/obj/machinery/power/apc/Initialize(mapload, ndir, building = FALSE)
. = ..()
wires = new(src)
GLOB.apcs += src
// offset 24 pixels in direction of dir
// this allows the APC to be embedded in a wall, yet still inside an area
@@ -179,6 +191,7 @@
src.update_icon()
/obj/machinery/power/apc/Destroy()
GLOB.apcs -= src
src.update()
area.apc = null
area.power_light = 0
@@ -805,6 +818,9 @@
"gridCheck" = grid_check,
"coverLocked" = coverlocked,
"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,
"powerChannels" = list(
list(
@@ -873,6 +889,13 @@
coverlocked = !coverlocked
if("breaker")
toggle_breaker()
if("nightshift")
if(last_nightshift_switch > world.time - 10 SECONDS) // don't spam...
to_chat(usr, "<span class='warning'>[src]'s night lighting circuit breaker is still cycling!</span>")
return 0
last_nightshift_switch = world.time
nightshift_setting = params["nightshift"]
update_nightshift()
if("charge")
chargemode = !chargemode
if(!chargemode)
@@ -895,6 +918,13 @@
failure_timer = 0
update_icon()
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()
@@ -923,7 +953,7 @@
return 0
if(IsAdminGhost(user)) //This is to allow nanoUI interaction by ghost admins.
return TRUE
if (user.stat)
if(user.stat)
return 0
if(inoperable())
return 0
@@ -936,7 +966,7 @@
to_chat(user,"<span class='warning'>You must stand to use [src]!</span>")
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
@@ -948,83 +978,17 @@
if(aidisabled && !permit)
if(!loud)
to_chat(user,"<span class='danger'>\The AI control for [src] has been disabled!</span>")
to_chat(user, "<span class='danger'>\The AI control for [src] has been disabled!</span>")
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()))
to_chat(user,"<span class='danger'>You momentarily forget how to use [src].</span>")
if(istype(H) && prob(H.getBrainLoss()))
to_chat(user, "<span class='danger'>You momentarily forget how to use [src].</span>")
return 0
return 1
/obj/machinery/power/apc/Topic(href, href_list)
if(..())
return 1
if(!can_use(usr, 1))
return 1
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["breaker"])
toggle_breaker()
else if (href_list["cmode"])
chargemode = !chargemode
if(!chargemode)
charging = 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
/obj/machinery/power/apc/proc/toggle_breaker()
operating = !operating
src.update()
@@ -1421,4 +1385,24 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on)
name = "[area.name] APC"
update()
/obj/machinery/power/apc/proc/set_nightshift(on, var/automated)
set waitfor = FALSE
if(automated && istype(area, /area/shuttle))
return
nightshift_lights = on
update_nightshift()
/obj/machinery/power/apc/proc/update_nightshift()
var/new_state = nightshift_lights
switch(nightshift_setting)
if(NIGHTSHIFT_NEVER)
new_state = FALSE
if(NIGHTSHIFT_ALWAYS)
new_state = TRUE
for(var/obj/machinery/light/L in area)
L.nightshift_mode(new_state)
CHECK_TICK
#undef APC_UPDATE_ICON_COOLDOWN

View File

@@ -125,3 +125,16 @@
overlays.Cut()
target.nutrition += amount
user.custom_emote(message = "connects \the [src] to [user == target ? "their" : "[target]'s"] charging port, expending it.")
/obj/item/cell/emergency_light
name = "miniature power cell"
desc = "A tiny power cell with a very low power capacity. Used in light fixtures to power them in the event of an outage."
maxcharge = 120 //Emergency lights use 0.2 W per tick, meaning ~10 minutes of emergency power from a cell
matter = list("glass" = 20)
w_class = ITEMSIZE_TINY
/obj/item/cell/emergency_light/Initialize()
. = ..()
var/area/A = get_area(src)
if(!A.lightswitch || !A.light_power)
charge = 0 //For naturally depowered areas, we start with no power

View File

@@ -10,6 +10,7 @@
#define LIGHT_BURNED 3
#define LIGHT_BULB_TEMPERATURE 400 //K - used value for a 60W bulb
#define LIGHTING_POWER_FACTOR 2 //5W per luminosity * range //VOREStation Edit: why the fuck are lights eating so much power, 2W per thing
#define LIGHT_EMERGENCY_POWER_USE 0.2 //How much power emergency lights will consume per tick
var/global/list/light_type_cache = list()
/proc/get_light_type_instance(var/light_type)
@@ -29,6 +30,10 @@ var/global/list/light_type_cache = list()
var/stage = 1
var/fixture_type = /obj/machinery/light
var/sheets_refunded = 2
var/obj/machinery/light/newlight = null
var/obj/item/cell/cell = null
var/cell_connectors = TRUE
/obj/machinery/light_construct/Initialize(mapload, newdir, building = FALSE, datum/frame/frame_types/frame_type, obj/machinery/light/fixture)
. = ..(mapload, newdir)
@@ -61,8 +66,45 @@ var/global/list/light_type_cache = list()
if(3)
. += "The casing is closed."
if(cell_connectors)
if(cell)
to_chat(user, "You see [cell] inside the casing.")
else
to_chat(user, "The casing has no power cell for backup power.")
else
to_chat(user, "<span class='danger'>This casing doesn't support power cells for backup power.</span>")
/obj/machinery/light_construct/attack_hand(mob/user)
. = ..()
if(.)
return . // obj/machinery/attack_hand returns 1 if user can't use the machine
if(cell)
user.visible_message("[user] removes [cell] from [src]!","<span class='notice'>You remove [cell].</span>")
user.put_in_hands(cell)
cell.update_icon()
cell = null
/obj/machinery/light_construct/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
if(istype(W, /obj/item/cell/emergency_light))
if(!cell_connectors)
to_chat(user, "<span class='warning'>This [name] can't support a power cell!</span>")
return
if(!user.unEquip(W))
to_chat(user, "<span class='warning'>[W] is stuck to your hand!</span>")
return
if(cell)
to_chat(user, "<span class='warning'>There is a power cell already installed!</span>")
else if(user.drop_from_inventory(W))
user.visible_message("<span class='notice'>[user] hooks up [W] to [src].</span>", \
"<span class='notice'>You add [W] to [src].</span>")
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
W.forceMove(src)
cell = W
add_fingerprint(user)
return
if (W.is_wrench())
if (src.stage == 1)
playsound(src, W.usesound, 75, 1)
@@ -113,6 +155,10 @@ var/global/list/light_type_cache = list()
var/obj/machinery/light/newlight = new fixture_type(src.loc, src)
newlight.setDir(src.dir)
src.transfer_fingerprints_to(newlight)
if(cell)
newlight.cell = cell
cell.forceMove(newlight)
cell = null
qdel(src)
return
..()
@@ -183,17 +229,34 @@ var/global/list/light_type_cache = list()
// this is used to calc the probability the light burns out
var/rigged = 0 // true if rigged to explode
//VOREStation Edit Start
var/needsound = FALSE // Flag to prevent playing turn-on sound multiple times, and from playing at roundstart
var/shows_alerts = TRUE // Flag for if this fixture should show alerts. Make sure icon states exist!
var/current_alert = null // Which alert are we showing right now?
//VOREStation Edit End
var/auto_flicker = FALSE // If true, will constantly flicker, so long as someone is around to see it (otherwise its a waste of CPU).
var/obj/item/cell/emergency_light/cell
var/start_with_cell = TRUE // if true, this fixture generates a very weak cell at roundstart
var/emergency_mode = FALSE // if true, the light is in emergency mode
var/no_emergency = FALSE // if true, this light cannot ever have an emergency mode
var/bulb_emergency_brightness_mul = 0.25 // multiplier for this light's base brightness in emergency power mode
var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode
var/bulb_emergency_pow_mul = 0.75 // the multiplier for determining the light's power in emergency mode
var/bulb_emergency_pow_min = 0.5 // the minimum value for the light's power in emergency mode
var/nightshift_enabled = FALSE
var/nightshift_allowed = TRUE
var/brightness_range_ns
var/brightness_power_ns
var/brightness_color_ns
/obj/machinery/light/flicker
auto_flicker = TRUE
/obj/machinery/light/no_nightshift
nightshift_allowed = FALSE
// the smaller bulb light fixture
/obj/machinery/light/small
@@ -207,6 +270,12 @@ var/global/list/light_type_cache = list()
/obj/machinery/light/small/flicker
auto_flicker = TRUE
/obj/machinery/light/poi
start_with_cell = FALSE
/obj/machinery/light/small/poi
start_with_cell = FALSE
/obj/machinery/light/flamp
icon = 'icons/obj/lighting.dmi' //VOREStation Edit
icon_state = "flamp1"
@@ -222,8 +291,12 @@ var/global/list/light_type_cache = list()
/obj/machinery/light/flamp/Initialize(mapload, obj/machinery/light_construct/construct)
. = ..()
if(construct)
start_with_cell = FALSE
lamp_shade = 0
update_icon()
else
if(start_with_cell && !no_emergency)
cell = new/obj/item/cell/emergency_light(src)
/obj/machinery/light/flamp/flicker
auto_flicker = TRUE
@@ -254,11 +327,14 @@ var/global/list/light_type_cache = list()
. = ..(mapload)
if(construct)
start_with_cell = FALSE
status = LIGHT_EMPTY
construct_type = construct.type
construct.transfer_fingerprints_to(src)
setDir(construct.dir)
else
if(start_with_cell && !no_emergency)
cell = new/obj/item/cell/emergency_light(src)
var/obj/item/light/L = get_light_type_instance(light_type)
update_from_bulb(L)
if(prob(L.broken_chance))
@@ -272,6 +348,7 @@ var/global/list/light_type_cache = list()
if(A)
on = 0
// A.update_lights()
QDEL_NULL(cell)
return ..()
/obj/machinery/light/update_icon()
@@ -348,7 +425,10 @@ var/global/list/light_type_cache = list()
//VOREStation Edit End
if(on)
if(light_range != brightness_range || light_power != brightness_power || light_color != brightness_color)
var/correct_range = nightshift_enabled ? brightness_range_ns : brightness_range
var/correct_power = nightshift_enabled ? brightness_power_ns : brightness_power
var/correct_color = nightshift_enabled ? brightness_color_ns : brightness_color
if(light_range != correct_range || light_power != correct_power || light_color != correct_color)
if(!auto_flicker)
switchcount++
if(rigged)
@@ -366,13 +446,24 @@ var/global/list/light_type_cache = list()
set_light(0)
else
update_use_power(USE_POWER_ACTIVE)
set_light(brightness_range, brightness_power, brightness_color)
set_light(correct_range, correct_power, correct_color)
else if(has_emergency_power(LIGHT_EMERGENCY_POWER_USE) && !turned_off())
update_use_power(USE_POWER_IDLE)
emergency_mode = TRUE
START_PROCESSING(SSobj, src)
else
update_use_power(USE_POWER_IDLE)
set_light(0)
active_power_usage = ((light_range * light_power) * LIGHTING_POWER_FACTOR)
/obj/machinery/light/proc/nightshift_mode(var/state)
if(!nightshift_allowed)
return
if(state != nightshift_enabled)
nightshift_enabled = state
update(FALSE)
/obj/machinery/light/attack_generic(var/mob/user, var/damage)
if(!damage)
@@ -406,6 +497,9 @@ var/global/list/light_type_cache = list()
on = (s && status == LIGHT_OK)
update()
/obj/machinery/light/get_cell()
return cell
// examine verb
/obj/machinery/light/examine(mob/user)
. = ..()
@@ -419,6 +513,8 @@ var/global/list/light_type_cache = list()
. += "[desc] The [fitting] is burnt out."
if(LIGHT_BROKEN)
. += "[desc] The [fitting] has been smashed."
if(cell)
to_chat(user, "Its backup power charge meter reads [round((cell.charge / cell.maxcharge) * 100, 0.1)]%.")
/obj/machinery/light/proc/get_fitting_name()
var/obj/item/light/L = light_type
@@ -428,10 +524,15 @@ var/global/list/light_type_cache = list()
status = L.status
switchcount = L.switchcount
rigged = L.rigged
brightness_range = L.brightness_range
brightness_power = L.brightness_power
brightness_color = L.brightness_color
brightness_range_ns = L.nightshift_range
brightness_power_ns = L.nightshift_power
brightness_color_ns = L.nightshift_color
// attack with item - insert light (if right type), otherwise try to break the light
/obj/machinery/light/proc/insert_bulb(obj/item/light/L)
@@ -544,6 +645,12 @@ var/global/list/light_type_cache = list()
..()
// returns if the light has power /but/ is manually turned off
// if a light is turned off, it won't activate emergency power
/obj/machinery/light/proc/turned_off()
var/area/A = get_area(src)
return !A.lightswitch && A.power_light || flickering
// returns whether this light has power
// true if area has power and lightswitch is on
/obj/machinery/light/proc/has_power()
@@ -557,6 +664,29 @@ var/global/list/light_type_cache = list()
else
return A && A.lightswitch && (!A.requires_power || A.power_light)
// returns whether this light has emergency power
// can also return if it has access to a certain amount of that power
/obj/machinery/light/proc/has_emergency_power(pwr)
if(no_emergency || !cell)
return FALSE
if(pwr ? cell.charge >= pwr : cell.charge)
return status == LIGHT_OK
// attempts to use power from the installed emergency cell, returns true if it does and false if it doesn't
/obj/machinery/light/proc/use_emergency_power(pwr = LIGHT_EMERGENCY_POWER_USE)
if(turned_off())
return FALSE
if(!has_emergency_power(pwr))
return FALSE
if(cell.charge > 300) //it's meant to handle 120 W, ya doofus
visible_message("<span class='warning'>[src] short-circuits from too powerful of a power cell!</span>")
status = LIGHT_BURNED
return FALSE
cell.use(pwr)
set_light(brightness_range * bulb_emergency_brightness_mul, max(bulb_emergency_pow_min, bulb_emergency_pow_mul * (cell.charge / cell.maxcharge)), bulb_emergency_colour)
return TRUE
/obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
if(flickering) return
flickering = 1
@@ -571,11 +701,20 @@ var/global/list/light_type_cache = list()
update(0)
flickering = 0
// ai attack - make lights flicker, because why not
// ai attack - turn on/off emergency lighting for a specific fixture
/obj/machinery/light/attack_ai(mob/user)
no_emergency = !no_emergency
to_chat(user, "<span class='notice'>Emergency lights for this fixture have been [no_emergency ? "disabled" : "enabled"].</span>")
update(FALSE)
// ai alt click - Make light flicker. Very important for atmosphere.
/obj/machinery/light/AIAltClick(mob/user)
flicker(1)
/obj/machinery/light/flamp/attack_ai(mob/user)
attack_hand()
return
// attack with hand - remove tube/bulb
// if hands aren't protected and the light is on, burn the player
/obj/machinery/light/attack_hand(mob/user)
@@ -694,6 +833,17 @@ var/global/list/light_type_cache = list()
// use power
/obj/machinery/light/process(delta_time)
if(!cell)
return PROCESS_KILL
if(has_power())
emergency_mode = FALSE
update(FALSE)
if(cell.charge == cell.maxcharge)
return PROCESS_KILL
cell.charge = min(cell.maxcharge, cell.charge + LIGHT_EMERGENCY_POWER_USE*2) //Recharge emergency power automatically while not using it
if(emergency_mode && !use_emergency_power(LIGHT_EMERGENCY_POWER_USE))
update(FALSE) //Disables emergency mode and sets the color to normal
if(auto_flicker && !flickering)
if(check_for_player_proximity(src, radius = 12, ignore_ghosts = FALSE, ignore_afk = TRUE))
seton(TRUE) // Lights must be on to flicker.
@@ -745,6 +895,10 @@ var/global/list/light_type_cache = list()
drop_sound = 'sound/items/drop/glass.ogg'
pickup_sound = 'sound/items/pickup/glass.ogg'
var/nightshift_range = 8
var/nightshift_power = 0.7
var/nightshift_color = LIGHT_COLOR_NIGHTSHIFT
/obj/item/light/tube
name = "light tube"
desc = "A replacement light tube."
@@ -755,6 +909,9 @@ var/global/list/light_type_cache = list()
brightness_range = 12 // luminosity when on, also used in power calculation //VOREStation Edit
brightness_power = 1
nightshift_range = 7
nightshift_power = 0.5
/obj/item/light/tube/large
w_class = ITEMSIZE_SMALL
name = "large light tube"
@@ -820,6 +977,9 @@ var/global/list/light_type_cache = list()
brightness_power = 1
brightness_color = LIGHT_COLOR_INCANDESCENT_BULB
nightshift_range = 3
nightshift_power = 0.45
/obj/item/light/throw_impact(atom/hit_atom)
..()
shatter()

View File

@@ -64,10 +64,6 @@
else
security_announcement_down.Announce("[config_legacy.alert_desc_red_downto]", "Attention! Code red!", new_sound = 'sound/misc/voyalert.ogg')
security_level = SEC_LEVEL_RED
/* - At the time of commit, setting status displays didn't work properly
var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
if(CC)
CC.post_status("alert", "redalert")*/
if(SEC_LEVEL_DELTA)
security_announcement_up.Announce("[config_legacy.alert_desc_delta]", "Attention! Delta alert level reached!", new_sound = 'sound/effects/alert_levels/deltaklaxon.ogg')
security_level = SEC_LEVEL_DELTA
@@ -85,6 +81,10 @@
GLOB.lore_atc.reroute_traffic(TRUE) // Tell them fuck off we're busy.
else
GLOB.lore_atc.reroute_traffic(FALSE)
spawn()
SSnightshift.check_nightshift()
admin_chat_message(message = "Security level is now: [uppertext(get_security_level())]", color = "#CC2222") //VOREStation Add
/proc/get_security_level()

View File

@@ -6,7 +6,7 @@
/datum/artifact_effect/cellcharge/DoEffectTouch(var/mob/user)
if(user)
if(istype(user, /mob/living/silicon/robot))
if(isrobot(user))
var/mob/living/silicon/robot/R = user
for (var/obj/item/cell/D in R.contents)
D.charge += rand() * 100 + 50
@@ -16,12 +16,24 @@
/datum/artifact_effect/cellcharge/DoEffectAura()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in range(200, T))
for (var/obj/machinery/power/apc/C in GLOB.apcs)
if(T.z != C.z)
continue
if(get_dist(T, C) > 200)
continue
for (var/obj/item/cell/B in C.contents)
B.charge += 25
for (var/obj/machinery/power/smes/S in range (src.effectrange,src))
for (var/obj/machinery/power/smes/S in GLOB.smeses)
if(T.z != S.z)
continue
if(get_dist(T, S) > src.effectrange)
continue
S.charge += 25
for (var/mob/living/silicon/robot/M in range(50, T))
for (var/mob/living/silicon/robot/M in silicon_mob_list)
if(T.z != M.z)
continue
if(get_dist(T, M) > 50)
continue
for (var/obj/item/cell/D in M.contents)
D.charge += 25
if(world.time - last_message > 200)
@@ -32,12 +44,24 @@
/datum/artifact_effect/cellcharge/DoEffectPulse()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in range(200, T))
for (var/obj/machinery/power/apc/C in GLOB.apcs)
if(T.z != C.z)
continue
if(get_dist(T, C) > 200)
continue
for (var/obj/item/cell/B in C.contents)
B.charge += rand() * 100
for (var/obj/machinery/power/smes/S in range (src.effectrange,src))
for (var/obj/machinery/power/smes/S in GLOB.smeses)
if(T.z != S.z)
continue
if(get_dist(T, S) > src.effectrange)
continue
S.charge += 250
for (var/mob/living/silicon/robot/M in range(100, T))
for (var/mob/living/silicon/robot/M in silicon_mob_list)
if(T.z != M.z)
continue
if(get_dist(T, M) > 100)
continue
for (var/obj/item/cell/D in M.contents)
D.charge += rand() * 100
if(world.time - last_message > 200)

View File

@@ -18,12 +18,24 @@
/datum/artifact_effect/celldrain/DoEffectAura()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in range(200, T))
for (var/obj/machinery/power/apc/C in GLOB.apcs)
if(T.z != C.z)
continue
if(get_dist(T, C) > 200)
continue
for (var/obj/item/cell/B in C.contents)
B.charge = max(B.charge - 50,0)
for (var/obj/machinery/power/smes/S in range (src.effectrange,src))
for (var/obj/machinery/power/smes/S in GLOB.smeses)
if(T.z != S.z)
continue
if(get_dist(T, S) > src.effectrange)
continue
S.charge = max(S.charge - 100,0)
for (var/mob/living/silicon/robot/M in range(50, T))
for (var/mob/living/silicon/robot/M in silicon_mob_list)
if(T.z != M.z)
continue
if(get_dist(T, M) > 50)
continue
for (var/obj/item/cell/D in M.contents)
D.charge = max(D.charge - 50,0)
if(world.time - last_message > 200)
@@ -34,12 +46,24 @@
/datum/artifact_effect/celldrain/DoEffectPulse()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in range(200, T))
for (var/obj/machinery/power/apc/C in GLOB.apcs)
if(T.z != C.z)
continue
if(get_dist(T, C) > 200)
continue
for (var/obj/item/cell/B in C.contents)
B.charge = max(B.charge - rand() * 150,0)
for (var/obj/machinery/power/smes/S in range (src.effectrange,src))
for (var/obj/machinery/power/smes/S in GLOB.smeses)
if(T.z != S.z)
continue
if(get_dist(T, S) > src.effectrange)
continue
S.charge = max(S.charge - 250,0)
for (var/mob/living/silicon/robot/M in range(100, T))
for (var/mob/living/silicon/robot/M in silicon_mob_list)
if(T.z != M.z)
continue
if(get_dist(T, M) > 100)
continue
for (var/obj/item/cell/D in M.contents)
D.charge = max(D.charge - rand() * 150,0)
if(world.time - last_message > 200)

View File

@@ -14,3 +14,6 @@ ENGINE_SUBMAP EngineSubmap_RUST 40
ENGINE_SUBMAP EngineSubmap_Tesla 20
## Singulo
ENGINE_SUBMAP EngineSubmap_Singulo 20
## Comment this out if you don't want to use the 'nightshift lighting' subsystem to adjust lights based on ingame time.
NIGHTSHIFTS_ENABLED

View File

@@ -23,21 +23,26 @@ var/list/all_maps = list()
var/full_name = "Unnamed Map"
var/path
var/list/zlevels = list()
var/zlevel_datum_type // If populated, all subtypes of this type will be instantiated and used to populate the *_levels lists.
var/list/station_levels = list() // Z-levels the station exists on
var/list/admin_levels = list() // Z-levels for admin functionality (Centcom, shuttle transit, etc)
var/list/contact_levels = list() // Z-levels that can be contacted from the station, for eg announcements
var/list/player_levels = list() // Z-levels a character can typically reach
var/list/sealed_levels = list() // Z-levels that don't allow random transit at edge
var/list/xenoarch_exempt_levels = list() // Z-levels exempt from xenoarch finds and digsites spawning.
var/list/empty_levels = null // Empty Z-levels that may be used for various things (currently used by bluespace jump)
var/list/map_levels // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset.
var/list/base_turf_by_z = list() // Custom base turf by Z-level. Defaults to world.turf for unlisted Z-levels
// Automatically populated lists made static for faster lookups
var/list/zlevels = list()
var/list/station_levels = list() // Z-levels the station exists on
var/list/admin_levels = list() // Z-levels for admin functionality (Centcom, shuttle transit, etc)
var/list/contact_levels = list() // Z-levels that can be contacted from the station, for eg announcements
var/list/player_levels = list() // Z-levels a character can typically reach
var/list/sealed_levels = list() // Z-levels that don't allow random transit at edge
var/list/xenoarch_exempt_levels = list() //Z-levels exempt from xenoarch finds and digsites spawning.
var/list/empty_levels = null // Empty Z-levels that may be used for various things (currently used by bluespace jump)
// End Static Lists
// Z-levels available to various consoles, such as the crew monitor. Defaults to station_levels if unset.
var/list/map_levels
// E-mail TLDs to use for NTnet modular computer e-mail addresses
var/list/usable_email_tlds = list("freemail.nt")
// This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
var/list/accessible_z_levels = list()
@@ -138,6 +143,39 @@ var/list/all_maps = list()
if(!allowed_jobs || !allowed_jobs.len)
allowed_jobs = subtypesof(/datum/job)
// Gets the current time on a current zlevel, and returns a time datum
/datum/map/proc/get_zlevel_time(var/z)
if(!z)
z = 1
var/datum/planet/P = z <= SSplanets.z_to_planet.len ? SSplanets.z_to_planet[z] : null
// We found a planet tied to that zlevel, give them the time
if(P?.current_time)
return P.current_time
// We have to invent a time
else
var/datum/time/T = new (station_time_in_ds)
return T
// Returns a boolean for if it's night or not on a particular zlevel
/datum/map/proc/get_night(var/z)
if(!z)
z = 1
var/datum/time/now = get_zlevel_time(z)
var/percent = now.seconds_stored / now.seconds_in_day //practically all of these are in DS
testing("get_night is [percent] through the day on [z]")
// First quarter, last quarter
if(percent < 0.25 || percent > 0.75)
return TRUE
// Second quarter, third quarter
else
return FALSE
// Boolean for if we should use SSnightshift night hours
/datum/map/proc/get_nightshift()
return get_night(1) //Defaults to z1, customize however you want on your own maps
/datum/map/proc/setup_map()
return

View File

@@ -193,6 +193,42 @@ const ApcContent = (props, context) => {
disabled={locked}
onClick={() => act('cover')} />
)} />
<LabeledList.Item
label="Night Shift Lighting"
buttons={(
<Fragment>
<Button
icon="lightbulb-o"
content="Disabled"
selected={data.nightshiftSetting === 2}
onClick={() => act('nightshift', {
nightshift: 2,
})} />
<Button
icon="lightbulb-o"
content="Automatic"
selected={data.nightshiftSetting === 1}
onClick={() => act('nightshift', {
nightshift: 1,
})} />
<Button
icon="lightbulb-o"
content="Enabled"
selected={data.nightshiftSetting === 3}
onClick={() => act('nightshift', {
nightshift: 3,
})} />
</Fragment>
)} />
<LabeledList.Item
label="Emergency Lighting"
buttons={(
<Button
icon="lightbulb-o"
content={data.emergencyLights ? 'Enabled' : 'Disabled'}
selected={data.emergencyLights}
onClick={() => act('emergency_lighting')} />
)} />
</LabeledList>
</Section>
</Fragment>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -265,6 +265,7 @@
#include "code\controllers\subsystems\minimaps.dm"
#include "code\controllers\subsystems\mobs.dm"
#include "code\controllers\subsystems\nanoui.dm"
#include "code\controllers\subsystems\nightshift.dm"
#include "code\controllers\subsystems\openspace.dm"
#include "code\controllers\subsystems\overlays.dm"
#include "code\controllers\subsystems\overmap.dm"