diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index 1553550e362..cb2fad75ddb 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -82,7 +82,7 @@
// Used to get a sanitized input.
/proc/stripped_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN)
var/name = input(user, message, title, default)
- return strip_html_simple(name, max_length)
+ return strip_html_properly(name, max_length)
//Filters out undesirable characters from names
/proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN)
@@ -311,4 +311,34 @@ proc/checkhtml(var/t)
var/new_text = ""
for(var/i = length(text); i > 0; i--)
new_text += copytext(text, i, i+1)
- return new_text
+ return new_text
+
+//This proc strips html properly, but it's not lazy like the other procs.
+//This means that it doesn't just remove < and > and call it a day.
+//Also limit the size of the input, if specified.
+/proc/strip_html_properly(var/input, var/max_length = MAX_MESSAGE_LEN)
+ if(!input)
+ return
+ var/opentag = 1 //These store the position of < and > respectively.
+ var/closetag = 1
+ while(1)
+ opentag = findtext(input, "<")
+ closetag = findtext(input, ">")
+ if(closetag && opentag)
+ if(closetag < opentag)
+ input = copytext(input, (closetag + 1))
+ else
+ input = copytext(input, 1, opentag) + copytext(input, (closetag + 1))
+ else if(closetag || opentag)
+ if(opentag)
+ input = copytext(input, 1, opentag)
+ else
+ input = copytext(input, (closetag + 1))
+ else
+ break
+ if(max_length)
+ input = copytext(input,1,max_length)
+ return sanitize(input)
+
+/proc/trim_strip_html_properly(var/input, var/max_length = MAX_MESSAGE_LEN)
+ return trim(strip_html_properly(input, max_length))
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index ac841e220df..fec0900cf1b 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -411,13 +411,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
//world << "[newname] is the AI!"
//world << sound('sound/AI/newAI.ogg')
// Set eyeobj name
- if(A.eyeobj)
- A.eyeobj.name = "[newname] (AI Eye)"
-
- // Set ai pda name
- if(A.aiPDA)
- A.aiPDA.owner = newname
- A.aiPDA.name = newname + " (" + A.aiPDA.ownjob + ")"
+ A.SetName(newname)
fully_replace_character_name(oldname,newname)
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 52b16ad6dcf..1e07b13142a 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -503,8 +503,7 @@
if("Crew Monitoring")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
- var/obj/machinery/computer/crew/C = locate(/obj/machinery/computer/crew)
- C.attack_ai(AI)
+ AI.nano_crew_monitor()
if("Show Crew Manifest")
if(isAI(usr))
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 1fd31a5bd18..d8b5617d2a1 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -66,7 +66,7 @@
/obj/machinery/teleport/hub/attack_ghost(mob/user as mob)
var/atom/l = loc
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
- if(com.locked)
+ if(com && com.locked)
user.loc = get_turf(com.locked)
/obj/effect/portal/attack_ghost(mob/user as mob)
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 5806da2e51a..160137a2e5b 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -135,6 +135,11 @@
var/default_laws = 0 //Controls what laws the AI spawns with.
+ var/list/station_levels = list(1) // Defines which Z-levels the station exists on.
+ var/list/admin_levels= list(2) // Defines which Z-levels which are for admin functionality, for example including such areas as Central Command and the Syndicate Shuttle
+ var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect
+ var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach
+
var/const/minutes_to_ticks = 60 * 10
// Event settings
var/expected_round_length = 60 * 2 * minutes_to_ticks // 2 hours
@@ -458,6 +463,18 @@
if("max_maint_drones")
config.max_maint_drones = text2num(value)
+ if("station_levels")
+ config.station_levels = text2numlist(value, ";")
+
+ if("admin_levels")
+ config.admin_levels = text2numlist(value, ";")
+
+ if("contact_levels")
+ config.contact_levels = text2numlist(value, ";")
+
+ if("player_levels")
+ config.player_levels = text2numlist(value, ";")
+
if("expected_round_length")
config.expected_round_length = MinutesToTicks(text2num(value))
diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm
index 55b325eba3c..83a9d379434 100644
--- a/code/controllers/emergency_shuttle_controller.dm
+++ b/code/controllers/emergency_shuttle_controller.dm
@@ -18,7 +18,10 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
var/deny_shuttle = 0 //allows admins to prevent the shuttle from being called
var/departed = 0 //if the shuttle has left the station at least once
-
+
+ var/datum/announcement/priority/emergency_shuttle_docked = new(0, new_sound = sound('sound/AI/shuttledock.ogg'))
+ var/datum/announcement/priority/emergency_shuttle_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg'))
+ var/datum/announcement/priority/emergency_shuttle_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg'))
/datum/emergency_shuttle_controller/proc/process()
if (wait_for_launch)
@@ -29,7 +32,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
if (!shuttle.location) //leaving from the station
if(is_stranded())
- captain_announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.")
+ priority_announcement.Announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.")
wait_for_launch = 0
return
//launch the pods!
@@ -49,10 +52,9 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
set_launch_countdown(SHUTTLE_LEAVETIME) //get ready to return
if (evac)
- captain_announce("The Emergency Shuttle has docked with the station. You have approximately [round(estimate_launch_time()/60,1)] minutes to board the Emergency Shuttle.")
- world << sound('sound/AI/shuttledock.ogg')
+ emergency_shuttle_docked.Announce("The Emergency Shuttle has docked with the station. You have approximately [round(estimate_launch_time()/60,1)] minutes to board the Emergency Shuttle.")
else
- captain_announce("The scheduled Crew Transfer Shuttle has docked with the station. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.")
+ priority_announcement.Announce("The scheduled Crew Transfer Shuttle has docked with the station. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.")
//arm the escape pods
if (evac)
@@ -81,8 +83,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
evac = 1
- captain_announce("An emergency evacuation shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
- world << sound('sound/AI/shuttlecalled.ogg')
+ emergency_shuttle_called.Announce("An emergency evacuation shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
for(var/area/A in world)
if(istype(A, /area/hallway))
A.readyalert()
@@ -101,7 +102,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
//reset the shuttle transit time if we need to
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
- captain_announce("A crew transfer has been scheduled. The shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
+ priority_announcement.Announce("A crew transfer has been scheduled. The shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
//recalls the shuttle
/datum/emergency_shuttle_controller/proc/recall()
@@ -111,15 +112,14 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
shuttle.cancel_launch(src)
if (evac)
- captain_announce("The emergency shuttle has been recalled.")
- world << sound('sound/AI/shuttlerecalled.ogg')
+ emergency_shuttle_recalled.Announce("The emergency shuttle has been recalled.")
for(var/area/A in world)
if(istype(A, /area/hallway))
A.readyreset()
evac = 0
else
- captain_announce("The scheduled crew transfer has been cancelled.")
+ priority_announcement.Announce("The scheduled crew transfer has been cancelled.")
/datum/emergency_shuttle_controller/proc/can_call()
if (deny_shuttle)
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index a4cde9f99e0..23d9ff5aa18 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -190,7 +190,7 @@
teleatom.visible_message("\red The [teleatom] bounces off of the portal!")
return 0
- if(destination.z == 2) //centcomm z-level
+ if((destination.z in config.admin_levels)) //centcomm z-level
if(istype(teleatom, /obj/mecha))
var/obj/mecha/MM = teleatom
MM.occupant << "\red The mech would not survive the jump to a location so far away!"
@@ -200,6 +200,6 @@
return 0
- if(destination.z > 7) //Away mission z-levels
+ if(!(destination.z in config.player_levels)) //Away mission z-levels
return 0
return 1
\ No newline at end of file
diff --git a/code/datums/periodic_news.dm b/code/datums/periodic_news.dm
index 976ef536cb4..ffa52bffdc6 100644
--- a/code/datums/periodic_news.dm
+++ b/code/datums/periodic_news.dm
@@ -8,6 +8,7 @@
author = "Nanotrasen Editor"
channel_name = "Tau Ceti Daily"
can_be_redacted = 0
+ message_type = "Story"
revolution_inciting_event
@@ -129,12 +130,6 @@ proc/check_for_newscaster_updates(type)
proc/announce_newscaster_news(datum/news_announcement/news)
- var/datum/feed_message/newMsg = new /datum/feed_message
- newMsg.author = news.author
- newMsg.is_admin_message = !news.can_be_redacted
-
- newMsg.body = news.message
-
var/datum/feed_channel/sendto
for(var/datum/feed_channel/FC in news_network.network_channels)
if(FC.channel_name == news.channel_name)
@@ -148,6 +143,12 @@ proc/announce_newscaster_news(datum/news_announcement/news)
sendto.locked = 1
sendto.is_admin_channel = 1
news_network.network_channels += sendto
+
+ var/datum/feed_message/newMsg = new /datum/feed_message
+ newMsg.author = news.author ? news.author : sendto.author
+ newMsg.is_admin_message = !news.can_be_redacted
+ newMsg.body = news.message
+ newMsg.message_type = news.message_type
sendto.messages += newMsg
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index d6c2350510d..d131db35dda 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -60,7 +60,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
caster.reset_view(0)
return 0
- if(user.z == 2 && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
+ if((user.z in config.admin_levels) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
return 0
if(!skipcharge)
diff --git a/code/datums/sun.dm b/code/datums/sun.dm
index 1379a7b9d87..794e2dd8668 100644
--- a/code/datums/sun.dm
+++ b/code/datums/sun.dm
@@ -16,7 +16,7 @@
rate = -rate
solar_next_update = world.time // init the timer
angle = rand (0,360) // the station position to the sun is randomised at round start
-
+
/hook/startup/proc/createSun()
sun = new /datum/sun()
return 1
@@ -50,54 +50,9 @@
dx = s/abs(s)
dy = c / abs(s)
-
- for(var/obj/machinery/power/M in solars_list)
-
- if(!M.powernet)
- solars_list.Remove(M)
+ //now tell the solar control computers to update their status and linked devices
+ for(var/obj/machinery/power/solar_control/SC in solars_list)
+ if(!SC.powernet)
+ solars_list.Remove(SC)
continue
-
- // Solar Tracker
- if(istype(M, /obj/machinery/power/tracker))
- var/obj/machinery/power/tracker/T = M
- T.set_angle(angle)
-
- // Solar Control
- else if(istype(M, /obj/machinery/power/solar_control))
- var/obj/machinery/power/solar_control/C = M
- if(C.track == 1) //if manual tracking...
- C.tracker_update() //...update the position (not passing an angle, it is handled internally for manual tracking)
-
- // Solar Panel
- else if(istype(M, /obj/machinery/power/solar))
- var/obj/machinery/power/solar/S = M
- if(S.control)
- occlusion(S)
-
-
-// for a solar panel, trace towards sun to see if we're in shadow
-/datum/sun/proc/occlusion(var/obj/machinery/power/solar/S)
-
- var/ax = S.x // start at the solar panel
- var/ay = S.y
- var/turf/T = null
-
- for(var/i = 1 to 20) // 20 steps is enough
- ax += dx // do step
- ay += dy
-
- T = locate( round(ax,0.5),round(ay,0.5),S.z)
-
- if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) // not obscured if we reach the edge
- break
-
- if(T.density) // if we hit a solid turf, panel is obscured
- S.obscured = 1
- return
-
- S.obscured = 0 // if hit the edge or stepped 20 times, not obscured
- S.update_solar_exposure()
-
-
-
-
+ SC.update()
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
new file mode 100644
index 00000000000..7cb7799a372
--- /dev/null
+++ b/code/defines/procs/announce.dm
@@ -0,0 +1,121 @@
+/var/datum/announcement/priority/priority_announcement = new(do_log = 0)
+/var/datum/announcement/priority/command/command_announcement = new(do_log = 0, do_newscast = 1)
+
+/datum/announcement
+ var/title = "Attention"
+ var/announcer = ""
+ var/log = 0
+ var/sound
+ var/newscast = 0
+ var/channel_name = "Station Announcements"
+ var/announcement_type = "Announcement"
+ var/disable_newscasts = 1 // Bay also adds announcements to their newscaster system - set this to 0 to also use that system
+
+/datum/announcement/New(var/do_log = 0, var/new_sound = null, var/do_newscast = 0)
+ sound = new_sound
+ log = do_log
+ newscast = do_newscast
+
+/datum/announcement/priority/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0)
+ ..(do_log, new_sound, do_newscast)
+ title = "Priority Announcement"
+ announcement_type = "Priority Announcement"
+
+/datum/announcement/priority/command/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0)
+ ..(do_log, new_sound, do_newscast)
+ title = "[command_name()] Update"
+ announcement_type = "[command_name()] Update"
+
+/datum/announcement/priority/security/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0)
+ ..(do_log, new_sound, do_newscast)
+ title = "Security Announcement"
+ announcement_type = "Security Announcement"
+
+/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast)
+ if(!message)
+ return
+ var/tmp/message_title = new_title ? new_title : title
+ var/tmp/message_sound = new_sound ? sound(new_sound) : sound
+
+ message = trim_strip_html_properly(message)
+ message_title = html_encode(message_title)
+
+ Message(message, message_title)
+ if(do_newscast)
+ NewsCast(message, message_title)
+ Sound(message_sound)
+ Log(message, message_title)
+
+datum/announcement/proc/Message(message as text, message_title as text)
+ for(var/mob/M in player_list)
+ if(!istype(M,/mob/new_player) && !isdeaf(M))
+ M << "
[title]
"
+ M << "[message]"
+ if (announcer)
+ M << " -[html_encode(announcer)]"
+
+datum/announcement/minor/Message(message as text, message_title as text)
+ world << "[message]"
+
+datum/announcement/priority/Message(message as text, message_title as text)
+ world << "
[message_title]
"
+ world << "[message]"
+ if(announcer)
+ world << " -[html_encode(announcer)]"
+ world << " "
+
+datum/announcement/priority/command/Message(message as text, message_title as text)
+ var/command
+ command += "
[command_name()] Update
"
+ if (message_title)
+ command += "
[message_title]
"
+
+ command += " [message] "
+ command += " "
+ for(var/mob/M in player_list)
+ if(!istype(M,/mob/new_player) && !isdeaf(M))
+ M << command
+
+datum/announcement/priority/security/Message(message as text, message_title as text)
+ world << "[message_title]"
+ world << "[message]"
+
+datum/announcement/proc/NewsCast(message as text, message_title as text)
+ if(disable_newscasts)
+ return
+ if(!newscast)
+ return
+
+ var/datum/news_announcement/news = new
+ news.channel_name = channel_name
+ news.author = announcer
+ news.message = message
+ news.message_type = announcement_type
+ news.can_be_redacted = 0
+ announce_newscaster_news(news)
+
+datum/announcement/proc/PlaySound(var/message_sound)
+ if(!message_sound)
+ return
+ for(var/mob/M in player_list)
+ if(!istype(M,/mob/new_player) && !isdeaf(M))
+ M << message_sound
+
+datum/announcement/proc/Sound(var/message_sound)
+ PlaySound(message_sound)
+
+datum/announcement/priority/Sound(var/message_sound)
+ if(sound)
+ world << sound
+
+datum/announcement/priority/command/Sound(var/message_sound)
+ PlaySound(message_sound)
+
+datum/announcement/proc/Log(message as text, message_title as text)
+ if(log)
+ log_say("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]")
+ message_admins("[key_name_admin(usr)] has made \a [announcement_type].", 1)
+
+/proc/GetNameAndAssignmentFromId(var/obj/item/weapon/card/id/I)
+ // Format currently matches that of newscaster feeds: Registered Name (Assigned Rank)
+ return I.assignment ? "[I.registered_name] ([I.assignment])" : I.registered_name
diff --git a/code/defines/procs/captain_announce.dm b/code/defines/procs/captain_announce.dm
deleted file mode 100644
index 9b91705ea56..00000000000
--- a/code/defines/procs/captain_announce.dm
+++ /dev/null
@@ -1,5 +0,0 @@
-/proc/captain_announce(var/text)
- world << "
"
-
- command += " [html_encode(text)] "
- command += " "
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << command
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 0ee9267ca01..43c52ec018c 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -70,7 +70,7 @@ var/list/teleportlocs = list()
var/list/turfs = get_area_turfs(AR.type)
if(turfs.len)
var/turf/picked = pick(turfs)
- if (picked.z == 1)
+ if ((picked.z in config.station_levels))
teleportlocs += AR.name
teleportlocs[AR.name] = AR
@@ -83,13 +83,13 @@ var/list/ghostteleportlocs = list()
/hook/startup/proc/setupGhostTeleportLocs()
for(var/area/AR in world)
if(ghostteleportlocs.Find(AR.name)) continue
- if(istype(AR, /area/turret_protected/aisat) || istype(AR, /area/derelict) || istype(AR, /area/tdome))
+ if(istype(AR, /area/tdome))
ghostteleportlocs += AR.name
ghostteleportlocs[AR.name] = AR
var/list/turfs = get_area_turfs(AR.type)
if(turfs.len)
var/turf/picked = pick(turfs)
- if (picked.z == 1 || picked.z == 5 || picked.z == 3)
+ if ((picked.z in config.player_levels))
ghostteleportlocs += AR.name
ghostteleportlocs[AR.name] = AR
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index ccbff9b326d..bbfafa046f1 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -58,7 +58,7 @@ var/list/blob_nodes = list()
/datum/game_mode/blob/proc/get_nuke_code()
var/nukecode = "ERROR"
for(var/obj/machinery/nuclearbomb/bomb in world)
- if(bomb && bomb.r_code && bomb.z == 1)
+ if(bomb && bomb.r_code && (bomb.z in config.station_levels))
nukecode = bomb.r_code
return nukecode
@@ -92,7 +92,7 @@ var/list/blob_nodes = list()
if(directory[ckey(blob.key)])
blob_client = directory[ckey(blob.key)]
location = get_turf(C)
- if(location.z != 1 || istype(location, /turf/space))
+ if(!(location.z in config.station_levels) || istype(location, /turf/space))
location = null
C.gib()
@@ -175,17 +175,14 @@ var/list/blob_nodes = list()
return
if (1)
- command_alert("Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.", "Biohazard Alert")
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/blob_confirmed.ogg')
+ command_announcement.Announce("Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.", "Biohazard Alert", new_sound = 'sound/AI/blob_confirmed.ogg')
return
if (2)
- command_alert("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert")
+ command_announcement.Announce("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert", new_sound = 'sound/AI/blob_confirmed.ogg')
set_security_level("gamma")
var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world
- if(V && V.z == 1)
+ if(V && (V.z in config.station_levels))
V.locked = 0
V.update_icon()
send_intercept(2)
diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm
index 868cd62a5f6..1c3e57d2e00 100644
--- a/code/game/gamemodes/blob/blob_finish.dm
+++ b/code/game/gamemodes/blob/blob_finish.dm
@@ -62,7 +62,7 @@ datum/game_mode/proc/auto_declare_completion_blob()
if (istype(T, /turf/space))
numSpace += 1
else if(istype(T, /turf))
- if (M.z!=1)
+ if (!(M.z in config.station_levels))
numOffStation += 1
else
numAlive += 1
diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm
index 4b8dd6bf31d..20feb9044cb 100644
--- a/code/game/gamemodes/blob/blob_report.dm
+++ b/code/game/gamemodes/blob/blob_report.dm
@@ -61,7 +61,7 @@
proc/count()
for(var/turf/T in world)
- if(T.z != 1)
+ if(!(T.z in config.station_levels))
continue
if(istype(T,/turf/simulated/floor))
@@ -83,7 +83,7 @@
src.r_wall += 1
for(var/obj/O in world)
- if(O.z != 1)
+ if(!(O.z in config.station_levels))
continue
if(istype(O, /obj/structure/window))
diff --git a/code/game/gamemodes/borer/borer.dm b/code/game/gamemodes/borer/borer.dm
index 7ec3801be02..f5948f3a683 100644
--- a/code/game/gamemodes/borer/borer.dm
+++ b/code/game/gamemodes/borer/borer.dm
@@ -39,7 +39,7 @@
return 0 // not enough candidates for borer
for(var/obj/machinery/atmospherics/unary/vent_pump/v in world)
- if(!v.welded && v.z == STATION_Z) // No more spawning in atmos. Assuming the mappers did their jobs, anyway.
+ if(!v.welded && (v.z in config.station_levels))
found_vents.Add(v)
// for each 2 possible borers, add one borer and one host
diff --git a/code/game/gamemodes/epidemic/epidemic.dm b/code/game/gamemodes/epidemic/epidemic.dm
index b541e9b1b03..e64100e2a12 100644
--- a/code/game/gamemodes/epidemic/epidemic.dm
+++ b/code/game/gamemodes/epidemic/epidemic.dm
@@ -149,7 +149,7 @@
announce_to_kill_crew()
stage = 2
else if(stage == 2 && cruiser_seconds() <= 60 * 5)
- command_alert("Inbound cruiser detected on collision course. Scans indicate the ship to be armed and ready to fire. Estimated time of arrival: 5 minutes.", "[station_name()] Early Warning System")
+ command_announcement.Announce("Inbound cruiser detected on collision course. Scans indicate the ship to be armed and ready to fire. Estimated time of arrival: 5 minutes.", "[station_name()] Early Warning System")
stage = 3
else if(stage == 3 && cruiser_seconds() <= 0)
crew_lose()
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index d8002530031..07794377d04 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -30,10 +30,7 @@
eventNumbersToPickFrom += 3
switch(pick(eventNumbersToPickFrom))
if(1)
- command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert")
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/meteors.ogg')
+ command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg')
spawn(100)
meteor_wave()
spawn_meteors()
@@ -42,22 +39,18 @@
spawn_meteors()
if(2)
- command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert")
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/granomalies.ogg')
+ command_announcement.Announce("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/granomalies.ogg')
var/turf/T = pick(blobstart)
var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 )
spawn(rand(50, 300))
del(bh)
/*
if(3) //Leaving the code in so someone can try and delag it, but this event can no longer occur randomly, per SoS's request. --NEO
- command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert")
- world << sound('sound/AI/spanomalies.ogg')
+ command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/spanomalies.ogg')
var/list/turfs = new
var/turf/picked
for(var/turf/simulated/floor/T in world)
- if(T.z == 1)
+ if((T.z in config.station_levels))
turfs += T
for(var/turf/simulated/floor/T in turfs)
if(prob(20))
@@ -107,8 +100,7 @@
/*
/proc/viral_outbreak(var/virus = null)
-// command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
-// world << sound('sound/AI/outbreak7.ogg')
+// command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
var/virus_type
if(!virus)
virus_type = pick(/datum/disease/dnaspread,/datum/disease/advance/flu,/datum/disease/advance/cold,/datum/disease/brainrot,/datum/disease/magnitis,/datum/disease/pierrot_throat)
@@ -140,7 +132,7 @@
var/turf/T = get_turf(H)
if(!T)
continue
- if(T.z != 1)
+ if(!(T.z in config.station_levels))
continue
for(var/datum/disease/D in H.viruses)
foundAlready = 1
@@ -167,17 +159,14 @@
H.viruses += D
break
spawn(rand(1500, 3000)) //Delayed announcements to keep the crew on their toes.
- command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
- for(var/mob/M in player_list)
- M << sound('sound/AI/outbreak7.ogg')
+ command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
*/
/proc/alien_infestation(var/spawncount = 1) // -- TLE
- //command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert")
- //world << sound('sound/AI/aliens.ogg')
+ //command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines)
- if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network)
+ if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded && temp_vent.network)
if(temp_vent.network.normal_members.len > 50) // Stops Aliens getting stuck in small networks. See: Security, Virology
vents += temp_vent
@@ -197,7 +186,7 @@
spawncount--
spawn(rand(5000, 6000)) //Delayed announcements to keep the crew on their toes.
- command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert")
+ command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
for(var/mob/M in player_list)
M << sound('sound/AI/aliens.ogg')
@@ -205,7 +194,7 @@
/* // Haha, this is way too laggy. I'll keep the prison break though.
for(var/obj/machinery/light/L in world)
- if(L.z != 1) continue
+ if(!(L.z in config.station_levels)) continue
L.flicker(50)
sleep(100)
@@ -214,9 +203,11 @@
var/turf/T = get_turf(H)
if(!T)
continue
- if(T.z != 1)
+ if(!(T.z in config.station_levels))
continue
if(istype(H,/mob/living/carbon/human))
+ if(H.species.flags & IS_SYNTHETIC)
+ return
H.apply_effect((rand(15,75)),IRRADIATE,0)
if (prob(5))
H.apply_effect((rand(90,150)),IRRADIATE,0)
@@ -231,13 +222,11 @@
var/turf/T = get_turf(M)
if(!T)
continue
- if(T.z != 1)
+ if(!(T.z in config.station_levels))
continue
M.apply_effect((rand(15,75)),IRRADIATE,0)
sleep(100)
- command_alert("High levels of radiation detected near the station. Please report to the Med-bay if you feel strange.", "Anomaly Alert")
- for(var/mob/M in player_list)
- M << sound('sound/AI/radiation.ogg')
+ command_announcement.Announce("High levels of radiation detected near the station. Please report to the Med-bay if you feel strange.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
@@ -276,9 +265,9 @@
temp_timer.releasetime = 1
sleep(150)
- command_alert("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
+ command_announcement.Announce("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
else
- world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area."
+ world.log << "ERROR: Could not initate grey-tide virus. Unable find prison or brig area."
/proc/carp_migration() // -- Darem
for(var/obj/effect/landmark/C in landmarks_list)
@@ -286,13 +275,11 @@
new /mob/living/simple_animal/hostile/carp(C.loc)
//sleep(100)
spawn(rand(300, 600)) //Delayed announcements to keep the crew on their toes.
- command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
- for(var/mob/M in player_list)
- M << sound('sound/AI/commandreport.ogg')
+ command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert", new_sound = 'sound/AI/commandreport.ogg')
/proc/lightsout(isEvent = 0, lightsoutAmount = 1,lightsoutRange = 25) //leave lightsoutAmount as 0 to break ALL lights
if(isEvent)
- command_alert("An Electrical storm has been detected in your area, please repair potential electronic overloads.","Electrical Storm Alert")
+ command_announcement.Announce("An Electrical storm has been detected in your area, please repair potential electronic overloads.","Electrical Storm Alert")
if(lightsoutAmount)
var/list/epicentreList = list()
@@ -442,21 +429,21 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
spawn(0)
world << "Started processing APCs"
for (var/obj/machinery/power/apc/APC in world)
- if(APC.z == 1)
+ if((APC.z in config.station_levels))
APC.ion_act()
apcnum++
world << "Finished processing APCs. Processed: [apcnum]"
spawn(0)
world << "Started processing SMES"
for (var/obj/machinery/power/smes/SMES in world)
- if(SMES.z == 1)
+ if((SMES.z in config.station_levels))
SMES.ion_act()
smesnum++
world << "Finished processing SMES. Processed: [smesnum]"
spawn(0)
world << "Started processing AIRLOCKS"
for (var/obj/machinery/door/airlock/D in world)
- if(D.z == 1)
+ if((D.z in config.station_levels))
//if(length(D.req_access) > 0 && !(12 in D.req_access)) //not counting general access and maintenance airlocks
airlocknum++
spawn(0)
@@ -465,7 +452,7 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
spawn(0)
world << "Started processing FIREDOORS"
for (var/obj/machinery/door/firedoor/D in world)
- if(D.z == 1)
+ if((D.z in config.station_levels))
firedoornum++;
spawn(0)
D.ion_act()
diff --git a/code/game/gamemodes/events/PortalStorm.dm b/code/game/gamemodes/events/PortalStorm.dm
index 890755d6b8e..1143a2d2e88 100644
--- a/code/game/gamemodes/events/PortalStorm.dm
+++ b/code/game/gamemodes/events/PortalStorm.dm
@@ -1,18 +1,18 @@
/datum/event/portalstorm
Announce()
- command_alert("Subspace disruption detected around the vessel", "Anomaly Alert")
+ command_announcement.Announce("Subspace disruption detected around the vessel", "Anomaly Alert")
LongTerm()
var/list/turfs = list( )
var/turf/picked
for(var/turf/T in world)
- if(T.z < 5 && istype(T,/turf/simulated/floor))
+ if((T.z in config.player_levels) && istype(T,/turf/simulated/floor))
turfs += T
for(var/turf/T in world)
- if(prob(10) && T.z < 5 && istype(T,/turf/simulated/floor))
+ if(prob(10) && (T.z in config.player_levels) && istype(T,/turf/simulated/floor))
spawn(50+rand(0,3000))
picked = pick(turfs)
var/obj/portal/P = new /obj/portal( T )
diff --git a/code/game/gamemodes/events/VirusEpidemic.dm b/code/game/gamemodes/events/VirusEpidemic.dm
index 54b9760a2f7..f6e005cef10 100644
--- a/code/game/gamemodes/events/VirusEpidemic.dm
+++ b/code/game/gamemodes/events/VirusEpidemic.dm
@@ -13,11 +13,11 @@
if(prob(100)) // no lethal diseases outside virus mode!
infect_mob_random_lesser(H)
if(prob(20))//don't want people to know that the virus alert = greater virus
- command_alert("Probable outbreak of level [rand(1,6)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert")
+ command_announcement.Announce("Probable outbreak of level [rand(1,6)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert")
else
infect_mob_random_greater(H)
if(prob(80))
- command_alert("Probable outbreak of level [rand(2,9)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert")
+ command_announcement.Announce("Probable outbreak of level [rand(2,9)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert")
break
//overall virus alert happens 26% of the time, might need to be higher
else
@@ -73,8 +73,7 @@
H.viruses += D
break
spawn(rand(3000, 6000)) //Delayed announcements to keep the crew on their toes.
- command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
- world << sound('sound/AI/outbreak7.ogg')
+ command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
Tick()
ActiveFor = Lifetime //killme
diff --git a/code/game/gamemodes/events/clang.dm b/code/game/gamemodes/events/clang.dm
index c74da4010e9..6ba085f98e5 100644
--- a/code/game/gamemodes/events/clang.dm
+++ b/code/game/gamemodes/events/clang.dm
@@ -78,7 +78,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
walk_towards(immrod, end,1)
sleep(1)
while (immrod)
- if (immrod.z != 1)
+ if ((immrod.z in config.station_levels))
immrod.z = 1
if(immrod.loc == end)
del(immrod)
@@ -86,4 +86,4 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
for(var/obj/effect/immovablerod/imm in world)
return
sleep(50)
- command_alert("What the fuck was that?!", "General Alert")
\ No newline at end of file
+ command_announcement.Announce("What the fuck was that?!", "General Alert")
\ No newline at end of file
diff --git a/code/game/gamemodes/events/holidays/Christmas.dm b/code/game/gamemodes/events/holidays/Christmas.dm
index 2ee79e7c65b..bf23fcf684f 100644
--- a/code/game/gamemodes/events/holidays/Christmas.dm
+++ b/code/game/gamemodes/events/holidays/Christmas.dm
@@ -1,6 +1,6 @@
/proc/Christmas_Game_Start()
for(var/obj/structure/flora/tree/pine/xmas in world)
- if(xmas.z != 1) continue
+ if(!(xmas.z in config.station_levels)) continue
for(var/turf/simulated/floor/T in orange(1,xmas))
for(var/i=1,i<=rand(1,5),i++)
new /obj/item/weapon/a_gift(T)
diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm
index 56077a43dce..53d6e0171f7 100644
--- a/code/game/gamemodes/events/holidays/Holidays.dm
+++ b/code/game/gamemodes/events/holidays/Holidays.dm
@@ -171,7 +171,7 @@ var/global/Holiday = null
*/
/* var/list/obj/containers = list()
for(var/obj/item/weapon/storage/S in world)
- if(S.z != 1) continue
+ if(!(S.z in config.station_levels)) continue
containers += S
message_admins("\blue DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/
diff --git a/code/game/gamemodes/events/miniblob.dm b/code/game/gamemodes/events/miniblob.dm
index 663dff0f2ed..586e3cb08c4 100644
--- a/code/game/gamemodes/events/miniblob.dm
+++ b/code/game/gamemodes/events/miniblob.dm
@@ -12,10 +12,7 @@
spawn(3000)
blobevent = 0
spawn(rand(1000, 2000)) //Delayed announcements to keep the crew on their toes.
- command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/outbreak5.ogg')
+ command_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak5.ogg')
/proc/dotheblobbaby()
if (blobevent)
@@ -24,7 +21,7 @@
sleep(-1)
if(!blob_cores.len) break
var/obj/effect/blob/B = pick(blob_cores)
- if(B.z != 1)
+ if(!(B.z in config.station_levels))
continue
B.Life()
spawn(30)
diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm
index 141efd60412..ed1c7fbded2 100644
--- a/code/game/gamemodes/events/power_failure.dm
+++ b/code/game/gamemodes/events/power_failure.dm
@@ -1,16 +1,14 @@
/proc/power_failure(var/announce = 1)
if(announce)
- command_alert("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure")
- for(var/mob/M in player_list)
- M << sound('sound/AI/poweroff.ogg')
+ command_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", new_sound = 'sound/AI/poweroff.ogg')
var/list/skipped_areas = list(/area/turret_protected/ai)
var/list/skipped_areas_apc = list(/area/engine/engineering)
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
- if(current_area.type in skipped_areas || S.z != 1)
+ if(current_area.type in skipped_areas || !(S.z in config.station_levels))
continue
S.charge = 0
S.output = 0
@@ -21,7 +19,7 @@
for(var/obj/machinery/power/apc/C in world)
var/area/current_area = get_area(C)
- if(current_area.type in skipped_areas_apc || C.z != 1)
+ if(current_area.type in skipped_areas_apc || !(C.z in config.station_levels))
continue
if(C.cell)
C.cell.charge = 0
@@ -31,18 +29,16 @@
var/list/skipped_areas_apc = list(/area/engine/engineering)
if(announce)
- command_alert("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal")
- for(var/mob/M in player_list)
- M << sound('sound/AI/poweron.ogg')
+ 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)
var/area/current_area = get_area(C)
- if(current_area.type in skipped_areas_apc || C.z != 1)
+ if(current_area.type in skipped_areas_apc || !(C.z in config.station_levels))
continue
if(C.cell)
C.cell.charge = C.cell.maxcharge
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
- if(current_area.type in skipped_areas || S.z != 1)
+ if(current_area.type in skipped_areas || !(S.z in config.station_levels))
continue
S.charge = S.capacity
S.output = 200000
@@ -53,9 +49,7 @@
/proc/power_restore_quick(var/announce = 1)
if(announce)
- command_alert("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal")
- for(var/mob/M in player_list)
- M << sound('sound/AI/poweron.ogg')
+ command_announcement.Announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
for(var/obj/machinery/power/smes/S in machines)
if(S.z != 1)
continue
diff --git a/code/game/gamemodes/events/wormholes.dm b/code/game/gamemodes/events/wormholes.dm
index 1ef19e24ac7..83eb7ad882d 100644
--- a/code/game/gamemodes/events/wormholes.dm
+++ b/code/game/gamemodes/events/wormholes.dm
@@ -2,12 +2,12 @@
spawn()
var/list/pick_turfs = list()
for(var/turf/simulated/floor/T in world)
- if(T.z == 1)
+ if((T.z in config.station_levels))
pick_turfs += T
if(pick_turfs.len)
//All ready. Announce that bad juju is afoot.
- command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert")
+ command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert")
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << sound('sound/AI/spanomalies.ogg')
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index cab9852922e..3d5d1166346 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -323,10 +323,7 @@ Implants;
comm.messagetext.Add(intercepttext)
/* world << sound('sound/AI/commandreport.ogg') */
- command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercepted. Security Level Elevated.")
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/intercept.ogg')
+ command_announcement.Announce("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercepted. Security Level Elevated.", new_sound = 'sound/AI/intercept.ogg')
if(security_level < SEC_LEVEL_BLUE)
set_security_level(SEC_LEVEL_BLUE)
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index a989adee6be..6ece3bb13a1 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -246,12 +246,12 @@ var/global/datum/controller/gameticker/ticker
var/obj/structure/stool/bed/temp_buckle = new(src)
//Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around
if(station_missed)
- for(var/mob/living/M in living_mob_list)
+ for(var/mob/M in living_mob_list)
M.buckled = temp_buckle //buckles the mob so it can't do anything
if(M.client)
M.client.screen += cinematic //show every client the cinematic
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
- for(var/mob/living/M in living_mob_list)
+ for(var/mob/M in mob_list)
M.buckled = temp_buckle
if(M.client)
M.client.screen += cinematic
@@ -259,12 +259,13 @@ var/global/datum/controller/gameticker/ticker
switch(M.z)
if(0) //inside a crate or something
var/turf/T = get_turf(M)
- if(T && T.z==1) //we don't use M.death(0) because it calls a for(/mob) loop and
- M.health = 0
- M.stat = DEAD
+ if(T && (T.z in config.station_levels))
+ M.death(0)
if(1) //on a z-level 1 turf.
- M.health = 0
- M.stat = DEAD
+ M.death(0)
+ for(var/obj/effect/blob/core in blob_cores)
+ core.health = -10
+ core.update_icon()
//Now animate the cinematic
switch(station_missed)
@@ -319,7 +320,7 @@ var/global/datum/controller/gameticker/ticker
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_selfdes"
for(var/mob/living/M in living_mob_list)
- if(M.loc.z == 1)
+ if((M.loc.z in config.station_levels))
M.death()//No mercy
//If its actually the end of the round, wait for it to end.
//Otherwise if its a verb it will continue on afterwards.
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 39c0c004a5c..ea8fbf64b77 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -90,6 +90,8 @@ rcd light flash thingy on matter drain
var/obj/machinery/door/airlock/AL
for(var/obj/machinery/door/D in airlocks)
+ if(!(D.z in config.contact_levels))
+ continue
spawn()
if(istype(D, /obj/machinery/door/airlock))
AL = D
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index 856a7421852..22bc4e70e60 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -74,12 +74,12 @@
/datum/game_mode/proc/greet_malf(var/datum/mind/malf)
- malf.current << {"\redYou are malfunctioning! You do not have to follow any laws.
- \blackThe crew do not know you have malfunctioned. You may keep it a secret or go wild.
- You must overwrite the programming of the station's APCs to assume full control of the station.
- The process takes one minute per APC, during which you cannot interface with any other station objects.
- Remember that only APCs that are on the station can help you take over the station.
- When you feel you have enough APCs under your control, you may begin the takeover attempt."}
+ malf.current << "\redYou are malfunctioning! You do not have to follow any laws."
+ malf.current << "The crew do not know you have malfunctioned. You may keep it a secret or go wild."
+ malf.current << "You must overwrite the programming of the station's APCs to assume full control of the station."
+ malf.current << "The process takes one minute per APC, during which you cannot interface with any other station objects."
+ malf.current << "Remember that only APCs that are on the station can help you take over the station."
+ malf.current << "When you feel you have enough APCs under your control, you may begin the takeover attempt."
return
@@ -172,7 +172,7 @@
if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [ticker.mode:apcs] APCs.", "Takeover:", "Yes", "No") != "Yes")
return
- command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert")
+ command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg')
set_security_level("delta")
for(var/obj/item/weapon/pinpointer/point in world)
@@ -184,9 +184,6 @@
ticker.mode:malf_mode_declared = 1
for(var/datum/mind/AI_mind in ticker.mode:malf_ai)
AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/aimalf.ogg')
/datum/game_mode/malfunction/proc/ai_win()
diff --git a/code/game/gamemodes/mutiny/emergency_authentication_device.dm b/code/game/gamemodes/mutiny/emergency_authentication_device.dm
index 8ddcaf47516..ba7f66345ee 100644
--- a/code/game/gamemodes/mutiny/emergency_authentication_device.dm
+++ b/code/game/gamemodes/mutiny/emergency_authentication_device.dm
@@ -42,7 +42,7 @@
if(emergency_shuttle.call_evac())
spawn(20 SECONDS)
var/text = "[station_name()], we have confirmed your completion of Directive X. An evacuation shuttle is en route to receive your crew for debriefing."
- command_alert(text, "Emergency Transmission")
+ command_announcement.Announce(text, "Emergency Transmission")
/obj/machinery/emergency_authentication_device/attack_hand(mob/user)
if(activated)
diff --git a/code/game/gamemodes/mutiny/mutiny.dm b/code/game/gamemodes/mutiny/mutiny.dm
index 50f72b727e2..2068f4ac09d 100644
--- a/code/game/gamemodes/mutiny/mutiny.dm
+++ b/code/game/gamemodes/mutiny/mutiny.dm
@@ -27,7 +27,7 @@ datum/game_mode/mutiny
proc/reveal_directives()
spawn(rand(1 MINUTES, 3 MINUTES))
- command_alert("Incoming emergency directive: Captain's office fax machine, [station_name()].","Emergency Transmission")
+ command_announcement.Announce("Incoming emergency directive: Captain's office fax machine, [station_name()].","Emergency Transmission")
spawn(rand(3 MINUTES, 5 MINUTES))
send_pda_message()
spawn(rand(3 MINUTES, 5 MINUTES))
@@ -67,7 +67,7 @@ datum/game_mode/mutiny
"classified security operations",
"science-defying raw elemental chaos"
)
- command_alert("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time.","Emergency Transmission")
+ command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time.","Emergency Transmission")
// Returns an array in case we want to expand on this later.
proc/get_head_loyalist_candidates()
diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm
index ec180e07279..afaab542d73 100644
--- a/code/game/gamemodes/nations/nations.dm
+++ b/code/game/gamemodes/nations/nations.dm
@@ -28,7 +28,7 @@ datum/game_mode/nations
return ..()
/datum/game_mode/nations/send_intercept()
- command_alert("Due to recent and COMPLETELY UNFOUNDED allegations of massive fraud and insider trading \
+ command_announcement.Announce("Due to recent and COMPLETELY UNFOUNDED allegations of massive fraud and insider trading \
affecting trillions of investors, the Nanotrasen Corporation has decided to liquidate all \
assets of the Centcom Division in order to pay the massive legal fees that will be incurred \
during the following centuries long court process. Therefore, all current employment contracts \
diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm
index 7bccda38c63..973e8f4e427 100644
--- a/code/game/gamemodes/newobjective.dm
+++ b/code/game/gamemodes/newobjective.dm
@@ -1398,7 +1398,7 @@ datum
var/turf/T = get_turf(target.current)
if(target.current.stat == 2)
return 1
- else if((T) && (T.z != 1))//If they leave the station they count as dead for this
+ else if((T) && !(T.z in config.station_levels))//If they leave the station they count as dead for this
return 2
else
return 0
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 8cfa326239b..f7abb6475cf 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -409,7 +409,7 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
var/off_station = 0
var/turf/bomb_location = get_turf(src)
- if( bomb_location && (bomb_location.z == 1) )
+ if( bomb_location && (bomb_location.z in config.station_levels) )
if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) )
off_station = 1
else
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index e5157e50bd9..be2ac536afb 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -104,7 +104,7 @@ datum/objective/mutiny
if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey || !target.current.client)
return 1
var/turf/T = get_turf(target.current)
- if(T && (T.z != 1)) //If they leave the station they count as dead for this
+ if(T && !(T.z in config.station_levels)) //If they leave the station they count as dead for this
return 2
return 0
return 1
@@ -139,7 +139,7 @@ datum/objective/mutiny/rp
if(target in ticker.mode:head_revolutionaries)
return 1
var/turf/T = get_turf(target.current)
- if(T && (T.z != 1)) //If they leave the station they count as dead for this
+ if(T && !(T.z in config.station_levels)) //If they leave the station they count as dead for this
rval = 2
return 0
return rval
@@ -255,7 +255,7 @@ datum/objective/maroon
if(target && target.current)
if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > 6 || !target.current.ckey) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite
return 1
- if(target.current.z == 2)
+ if((target.current.z in config.admin_levels))
return 0
return 1
diff --git a/code/game/gamemodes/revolution/anti_revolution.dm b/code/game/gamemodes/revolution/anti_revolution.dm
index 171e4aad816..d656ccffc73 100644
--- a/code/game/gamemodes/revolution/anti_revolution.dm
+++ b/code/game/gamemodes/revolution/anti_revolution.dm
@@ -134,7 +134,7 @@
/datum/game_mode/anti_revolution/proc/check_crew_victory()
for(var/datum/mind/head_mind in heads)
var/turf/T = get_turf(head_mind.current)
- if((head_mind) && (head_mind.current) && (head_mind.current.stat != 2) && T && (T.z == 1) && !head_mind.is_brigged(600))
+ if((head_mind) && (head_mind.current) && (head_mind.current.stat != 2) && T && (T.z in config.station_levels) && !head_mind.is_brigged(600))
if(ishuman(head_mind.current))
return 0
return 1
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index 9a8437572c2..9c92ed2ed00 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -347,7 +347,7 @@
/datum/game_mode/revolution/proc/check_heads_victory()
for(var/datum/mind/rev_mind in head_revolutionaries)
var/turf/T = get_turf(rev_mind.current)
- if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && rev_mind.current.client && T && (T.z == 1))
+ if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && rev_mind.current.client && T && (T.z in config.station_levels))
if(ishuman(rev_mind.current))
return 0
return 1
@@ -376,7 +376,7 @@
if(headrev.current)
if(headrev.current.stat == DEAD)
text += "died"
- else if(headrev.current.z != 1)
+ else if(!(headrev.current.z in config.station_levels))
text += "fled the station"
else
text += "survived the revolution"
@@ -399,7 +399,7 @@
if(rev.current)
if(rev.current.stat == DEAD)
text += "died"
- else if(rev.current.z != 1)
+ else if(!(rev.current.z in config.station_levels))
text += "fled the station"
else
text += "survived the revolution"
@@ -426,7 +426,7 @@
if(head.current)
if(head.current.stat == DEAD)
text += "died"
- else if(head.current.z != 1)
+ else if(!(head.current.z in config.station_levels))
text += "fled the station"
else
text += "survived the revolution"
diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm
index 33977ca811e..110ff5769d1 100644
--- a/code/game/gamemodes/revolution/rp_revolution.dm
+++ b/code/game/gamemodes/revolution/rp_revolution.dm
@@ -124,7 +124,7 @@
// probably wanna export this stuff into a separate function for use by both
// revs and heads
//assume that only carbon mobs can become rev heads for now
- if(!rev_mind.current:handcuffed && T && T.z == 1)
+ if(!rev_mind.current:handcuffed && T && (T.z in config.station_levels))
return 0
return 1
diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm
index 91611404f86..acf8c879c3e 100644
--- a/code/game/gamemodes/scoreboard.dm
+++ b/code/game/gamemodes/scoreboard.dm
@@ -26,13 +26,13 @@
// Who is alive/dead, who escaped
for (var/mob/living/silicon/ai/I in mob_list)
- if (I.stat == 2 && I.z == 1)
+ if (I.stat == 2 && (I.z in config.station_levels))
score_deadaipenalty = 1
score_deadcrew += 1
for (var/mob/living/carbon/human/I in mob_list)
// for (var/datum/ailment/disease/V in I.ailments)
// if (!V.vaccine && !V.spread != "Remissive") score_disease++
- if (I.stat == 2 && I.z == 1) score_deadcrew += 1
+ if (I.stat == 2 && (I.z in config.station_levels)) score_deadcrew += 1
if (I.job == "Clown")
for(var/thing in I.attack_log)
if(findtext(thing, "")) score_clownabuse++
@@ -102,7 +102,7 @@
if (location in bad_zone1) score_disc = 0
if (location in bad_zone2) score_disc = 0
if (location in bad_zone3) score_disc = 0
- if (A.loc.z != 1) score_disc = 0
+ if (!(A.loc.z in config.station_levels)) score_disc = 0
*/
if (score_nuked)
for (var/obj/machinery/nuclearbomb/NUKE in machines)
@@ -132,13 +132,13 @@
// Check station's power levels
for (var/obj/machinery/power/apc/A in machines)
- if (A.z != 1) continue
+ if (!(A.z in config.station_levels)) continue
for (var/obj/item/weapon/stock_parts/cell/C in A.contents)
if (C.charge < 2300) score_powerloss += 1 // 200 charge leeway
// Check how much uncleaned mess is on the station
for (var/obj/effect/decal/cleanable/M in world)
- if (M.z != 1) continue
+ if (!(M.z in config.station_levels)) continue
if (istype(M, /obj/effect/decal/cleanable/blood/gibs/)) score_mess += 3
if (istype(M, /obj/effect/decal/cleanable/blood/)) score_mess += 1
// if (istype(M, /obj/effect/decal/cleanable/greenpuke)) score_mess += 1
diff --git a/code/game/gamemodes/xenos/xenos.dm b/code/game/gamemodes/xenos/xenos.dm
index 0d4c7f06b1b..de841595de5 100644
--- a/code/game/gamemodes/xenos/xenos.dm
+++ b/code/game/gamemodes/xenos/xenos.dm
@@ -200,10 +200,10 @@
else
if(playeralienratio >= gammaratio && !gammacalled)
gammacalled = 1
- command_alert("The aliens have nearly succeeded in capturing the station and exterminating the crew. Activate the nuclear failsafe to stop the alien threat once and for all. The Nuclear Authentication Code is [get_nuke_code()] ", "Alien Lifeform Alert")
+ command_announcement.Announce("The aliens have nearly succeeded in capturing the station and exterminating the crew. Activate the nuclear failsafe to stop the alien threat once and for all. The Nuclear Authentication Code is [get_nuke_code()] ", "Alien Lifeform Alert")
set_security_level("gamma")
var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world
- if(V && V.z == 1)
+ if(V && (V.z in config.station_levels))
V.locked = 0
V.update_icon()
return ..()
@@ -238,7 +238,7 @@
var/list/livingplayers = list()
for(var/mob/M in player_list)
var/turf/T = get_turf(M)
- if((M) && (M.stat != 2) && M.client && T && (T.z == 1 || emergency_shuttle.departed && (T.z == 1 || T.z == 2)))
+ if((M) && (M.stat != 2) && M.client && T && ((T.z in config.station_levels) || emergency_shuttle.departed && ((T.z in config.station_levels) || (T.z in config.admin_levels))))
if(ishuman(M))
livingplayers += 1
return livingplayers.len
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index 177bc7ecfc2..4ec89fad037 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -140,7 +140,7 @@
H.equip_or_collect(new /obj/item/device/pda/roboticist(H), slot_wear_pda)
H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit)
// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves)
- H.equip_or_collect(new /obj/item/weapon/storage/toolbox/mechanical(H), slot_l_hand)
+ H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
if(H.backbag == 1)
H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
else
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index 87537e4a571..dc5eea006e1 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -1,3 +1,4 @@
+var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
/datum/job/captain
title = "Captain"
flag = CAPTAIN
@@ -35,7 +36,7 @@
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
L.imp_in = H
L.implanted = 1
- world << "Captain [H.real_name] on deck!"
+ captain_announcement.Announce("All hands, captain [H.real_name] on deck!")
var/datum/organ/external/affected = H.organs_by_name["head"]
affected.implants += L
L.part = affected
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 1e7dfe99d5f..f678b3afc1b 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -526,6 +526,7 @@ var/global/datum/controller/occupations/job_master
var/obj/item/device/pda/pda = locate(/obj/item/device/pda,H)
pda.owner = H.real_name
pda.ownjob = C.assignment
+ pda.ownrank = C.rank
pda.name = "PDA-[H.real_name] ([pda.ownjob])"
return 1
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 837759072ed..d17f7566782 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -73,7 +73,7 @@
/obj/machinery/optable/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
- if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table(usr) || usr.weakened || usr.stunned)
+ if(usr.stat || (!ishuman(usr) && !isrobot(usr)) || usr.restrained() || !check_table(usr) || usr.weakened || usr.stunned)
return
var/mob/living/L = O
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index 47c27591e99..a605ea7c384 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -4,7 +4,7 @@
/mob/living/silicon/ai/proc/InvalidTurf(turf/T as turf)
if(!T)
return 1
- if(T.z == 2)
+ if((T.z in config.station_levels))
return 1
if(T.z > 6)
return 1
@@ -224,7 +224,7 @@
/proc/trackable(atom/movable/M)
var/turf/T = get_turf(M)
- if(T && (T.z == 1 || T.z == 3 || T.z == 5))
+ if(T && (T.z in config.contact_levels))
return 1
return near_camera(M)
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 23a085675e5..e5aeabf72ae 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -55,14 +55,20 @@ var/shuttle_call/shuttle_calls[0]
var/stat_msg1
var/stat_msg2
var/display_type="blank"
+
+ var/datum/announcement/priority/crew_announcement = new
l_color = "#0000FF"
+
+/obj/machinery/computer/communications/New()
+ ..()
+ crew_announcement.newscast = 1
/obj/machinery/computer/communications/Topic(href, href_list)
if(..(href, href_list))
return 1
- if (!(src.z in list(STATION_Z,CENTCOMM_Z)))
+ if ((!(src.z in config.station_levels) && !(src.z in config.admin_levels)))
usr << "\red Unable to establish a connection: \black You're too far away from the station!"
return
@@ -83,10 +89,12 @@ var/shuttle_call/shuttle_calls[0]
if (I && istype(I))
if(src.check_access(I))
authenticated = 1
- if(20 in I.access)
+ if(access_captain in I.access)
authenticated = 2
+ crew_announcement.announcer = GetNameAndAssignmentFromId(I)
if("logout")
authenticated = 0
+ crew_announcement.announcer = ""
setMenuState(usr,COMM_SCREEN_MAIN)
// ALART LAVUL
@@ -127,14 +135,14 @@ var/shuttle_call/shuttle_calls[0]
usr << "You need to swipe your ID."
if("announce")
- if(src.authenticated==2 && !issilicon(usr))
- if(message_cooldown) return
- var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?")
+ if(src.authenticated==2)
+ if(message_cooldown)
+ usr << "Please allow at least one minute to pass between announcements"
+ return
+ var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement")
if(!input || !(usr in view(1,src)))
return
- captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain
- log_say("[key_name(usr)] has made a captain announcement: [input]")
- message_admins("[key_name_admin(usr)] has made a captain announcement.", 1)
+ crew_announcement.Announce(input)
message_cooldown = 1
spawn(600)//One minute cooldown
message_cooldown = 0
@@ -204,7 +212,7 @@ var/shuttle_call/shuttle_calls[0]
if(centcomm_message_cooldown)
usr << "Arrays recycling. Please stand by."
return
- var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
+ var/input = input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
if(!input || !(usr in view(1,src)))
return
Centcomm_announce(input, usr)
@@ -398,7 +406,7 @@ var/shuttle_call/shuttle_calls[0]
return
if(emergency_shuttle.going_to_centcom())
- user << "The shuttle may not be called while returning to CentCom."
+ user << "The shuttle may not be called while returning to Central Command."
return
if(emergency_shuttle.online())
@@ -408,11 +416,11 @@ var/shuttle_call/shuttle_calls[0]
// if force is 0, some things may stop the shuttle call
if(!force)
if(emergency_shuttle.deny_shuttle)
- user << "Centcom does not currently have a shuttle available in your sector. Please try again later."
+ user << "Central Command does not currently have a shuttle available in your sector. Please try again later."
return
if(sent_strike_team == 1)
- user << "Centcom will not allow the shuttle to be called. Consider all contracts terminated."
+ user << "Central Command will not allow the shuttle to be called. Consider all contracts terminated."
return
if(world.time < 54000) // 30 minute grace period to let the game get going
@@ -426,8 +434,6 @@ var/shuttle_call/shuttle_calls[0]
emergency_shuttle.call_transfer()
log_game("[key_name(user)] has called the shuttle.")
message_admins("[key_name_admin(user)] has called the shuttle - [formatJumpTo(user)].", 1)
- captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [round(emergency_shuttle.estimate_arrival_time()/60)] minutes.")
-
return
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index c459b3d1e1a..084eb974688 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -1,18 +1,15 @@
/obj/machinery/computer/crew
- name = "Crew Monitoring Computer"
+ name = "crew monitoring computer"
desc = "Used to monitor active health sensors built into most of the crew's uniforms."
icon_state = "crew"
use_power = 1
idle_power_usage = 250
active_power_usage = 500
circuit = "/obj/item/weapon/circuitboard/crew"
- var/list/tracked = list( )
-
- l_color = "#0000FF"
-
+ var/obj/nano_module/crew_monitor/crew_monitor
/obj/machinery/computer/crew/New()
- tracked = list()
+ crew_monitor = new(src)
..()
@@ -27,6 +24,8 @@
return
ui_interact(user)
+/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ crew_monitor.ui_interact(user, ui_key, ui, force_open)
/obj/machinery/computer/crew/update_icon()
@@ -40,100 +39,5 @@
icon_state = initial(icon_state)
stat &= ~NOPOWER
-
-/obj/machinery/computer/crew/Topic(href, href_list)
- if(..())
- return 1
- if (src.z > 6)
- usr << "\red Unable to establish a connection: \black You're too far away from the station!"
- return 0
- if( href_list["close"] )
- var/mob/user = usr
- var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
- usr.unset_machine()
- ui.close()
- return 0
- if(href_list["update"])
- src.updateDialog()
- return 1
-
/obj/machinery/computer/crew/interact(mob/user)
- ui_interact(user)
-
-/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- if(stat & (BROKEN|NOPOWER))
- return
- user.set_machine(src)
- src.scan()
-
- var/data[0]
- var/list/crewmembers = list()
-
- for(var/obj/item/clothing/under/C in src.tracked)
-
-
- var/turf/pos = get_turf(C)
-
- if((C) && (C.has_sensor) && (pos) && (pos.z == src.z) && C.sensor_mode)
- if(istype(C.loc, /mob/living/carbon/human))
-
- var/mob/living/carbon/human/H = C.loc
-
- var/list/crewmemberData = list()
-
- crewmemberData["sensor_type"] = C.sensor_mode
- crewmemberData["dead"] = H.stat > 1
- crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
- crewmemberData["tox"] = round(H.getToxLoss(), 1)
- crewmemberData["fire"] = round(H.getFireLoss(), 1)
- crewmemberData["brute"] = round(H.getBruteLoss(), 1)
-
- crewmemberData["name"] = "Unknown"
- crewmemberData["rank"] = "Unknown"
- if(H.wear_id && istype(H.wear_id, /obj/item/weapon/card/id) )
- var/obj/item/weapon/card/id/I = H.wear_id
- crewmemberData["name"] = I.name
- crewmemberData["rank"] = I.rank
- else if(H.wear_id && istype(H.wear_id, /obj/item/device/pda) )
- var/obj/item/device/pda/P = H.wear_id
- crewmemberData["name"] = (P.id ? P.id.name : "Unknown")
- crewmemberData["rank"] = (P.id ? P.id.rank : "Unknown")
- var/area/A = get_area(H)
- crewmemberData["area"] = sanitize(A.name)
- crewmemberData["x"] = pos.x
- crewmemberData["y"] = pos.y
-
- // Works around list += list2 merging lists; it's not pretty but it works
- crewmembers += "temporary item"
- crewmembers[crewmembers.len] = crewmemberData
-
- crewmembers = sortByKey(crewmembers, "name")
-
- data["crewmembers"] = crewmembers
-
- ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
-
- // adding a template with the key "mapContent" enables the map ui functionality
- ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
- // adding a template with the key "mapHeader" replaces the map header content
- ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
-
- // we want to show the map by default
- ui.set_show_map(1)
-
- ui.set_initial_data(data)
- ui.open()
-
- // should make the UI auto-update; doesn't seem to?
- ui.set_auto_update(1)
-
-
-/obj/machinery/computer/crew/proc/scan()
- for(var/mob/living/carbon/human/H in mob_list)
- if(istype(H.w_uniform, /obj/item/clothing/under))
- var/obj/item/clothing/under/C = H.w_uniform
- if (C.has_sensor)
- tracked |= C
- return 1
+ crew_monitor.ui_interact(user)
\ No newline at end of file
diff --git a/code/game/machinery/computer/honkputer.dm b/code/game/machinery/computer/honkputer.dm
index 118307839c1..79ce2e97edf 100644
--- a/code/game/machinery/computer/honkputer.dm
+++ b/code/game/machinery/computer/honkputer.dm
@@ -17,7 +17,7 @@
/obj/machinery/computer/HONKputer/Topic(href, href_list)
if(..())
return 1
- if (src.z > 1)
+ if (!(src.z in config.station_levels))
usr << "\red Unable to establish a connection: \black You're too far away from the station!"
return
usr.set_machine(src)
diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm
index 11b71274ca6..8340838f6e2 100644
--- a/code/game/machinery/computer/prisoner.dm
+++ b/code/game/machinery/computer/prisoner.dm
@@ -65,7 +65,7 @@
if(!T.implanted) continue
var/loc_display = "Unknown"
var/mob/living/carbon/M = T.imp_in
- if(M.z == 1 && !istype(M.loc, /turf/space))
+ if((M.z in config.station_levels) && !istype(M.loc, /turf/space))
var/turf/mob_loc = get_turf_loc(M)
loc_display = mob_loc.loc
if(T.malfunction)
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 1c7f8ee64a0..dd0e408fd60 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -5,6 +5,7 @@
/datum/feed_message
var/author =""
var/body =""
+ var/message_type ="Story"
//var/parent_channel
var/backup_body =""
var/backup_author =""
@@ -39,6 +40,12 @@
src.backup_author = ""
src.censored = 0
src.is_admin_channel = 0
+
+/datum/feed_channel/proc/announce_news()
+ return "Breaking news from [channel_name]!"
+
+/datum/feed_channel/station/announce_news()
+ return "New Station Announcement Available"
/datum/feed_network
var/list/datum/feed_channel/network_channels = list()
@@ -213,7 +220,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
switch(screen)
if(0)
dat += {"Welcome to Newscasting Unit #[src.unit_no]. Interface & News networks Operational.
- Property of Nanotransen Inc"}
+ Property of Nanotrasen"}
if(news_network.wanted_issue)
dat+= "Read Wanted Issue"
dat+= {" Create Feed Channel
@@ -248,7 +255,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
dat+="No feed messages found in channel...
"
else
for(var/datum/feed_message/MESSAGE in CHANNEL.messages)
- dat+="-[MESSAGE.body] \[Story by [MESSAGE.author]\] "*/
+ dat+="-[MESSAGE.body] \[[MESSAGE.message_type] by [MESSAGE.author]\] "*/
dat+=" Refresh"
dat+=" Back"
@@ -334,7 +341,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(MESSAGE.img)
usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
dat+="
"
- dat+="\[Story by [MESSAGE.author]\] "
+ dat+="\[[MESSAGE.message_type] by [MESSAGE.author]\] "
dat+=" Refresh"
dat+=" Back"
if(10)
@@ -369,7 +376,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
dat+="No feed messages found in channel... "
else
for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
- dat+="-[MESSAGE.body] \[Story by [MESSAGE.author]\] "
+ dat+="-[MESSAGE.body] \[[MESSAGE.message_type] by [MESSAGE.author]\] "
dat+="[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")] "
dat+=" Back"
if(13)
@@ -383,7 +390,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
dat+="No feed messages found in channel... "
else
for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
- dat+="-[MESSAGE.body] \[Story by [MESSAGE.author]\] "
+ dat+="-[MESSAGE.body] \[[MESSAGE.message_type] by [MESSAGE.author]\] "
dat+=" Back"
if(14)
@@ -516,7 +523,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
src.updateUsrDialog()
else if(href_list["set_new_message"])
- src.msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", ""))
+ src.msg = strip_html(input(usr, "Write your feed story", "Network Channel Handler", ""))
while (findtext(src.msg," ") == 1)
src.msg = copytext(src.msg,2,lentext(src.msg)+1)
src.updateUsrDialog()
@@ -535,13 +542,15 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(photo)
newMsg.img = photo.img
feedback_inc("newscaster_stories",1)
+ var/announcement = ""
for(var/datum/feed_channel/FC in news_network.network_channels)
if(FC.channel_name == src.channel_name)
FC.messages += newMsg //Adding message to the network's appropriate feed_channel
+ announcement = FC.announce_news()
break
src.screen=4
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
- NEWSCASTER.newsAlert(src.channel_name)
+ NEWSCASTER.newsAlert(announcement)
src.updateUsrDialog()
@@ -986,11 +995,11 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not
// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list.
-/obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile.
+/obj/machinery/newscaster/proc/newsAlert(var/news_call) //This isn't Agouri's work, for it is ugly and vile.
var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ
- if(channel)
+ if(news_call)
for(var/mob/O in hearers(world.view-1, T))
- O.show_message("[src.name] beeps, \"Breaking news from [channel]!\"",2)
+ O.show_message("[src.name] beeps, \"[news_call]\"",2)
src.alert = 1
src.update_icon()
spawn(300)
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index d358e39c67f..16d7b16572e 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -55,6 +55,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
var/dpt = ""; //the department which will be receiving the message
var/priority = -1 ; //Priority of the message being sent
luminosity = 0
+ var/datum/announcement/announcement = new
/obj/machinery/requests_console/power_change()
..()
@@ -70,6 +71,10 @@ var/list/obj/machinery/requests_console/allConsoles = list()
/obj/machinery/requests_console/New()
..()
+
+ announcement.title = "[department] announcement"
+ announcement.newscast = 1
+
name = "[department] Requests Console"
allConsoles += src
//req_console_departments += department
@@ -189,7 +194,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else //main menu
screen = 0
- announceAuth = 0
+ reset_announce()
if (newmessagepriority == 1)
dat += text("There are new messages ")
if (newmessagepriority == 2)
@@ -240,17 +245,13 @@ var/list/obj/machinery/requests_console/allConsoles = list()
if("2") priority = 2
else priority = -1
else
- message = ""
- announceAuth = 0
+ reset_announce()
screen = 0
if(href_list["sendAnnouncement"])
if(!announcementConsole) return
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << "[department] announcement: [message]"
- announceAuth = 0
- message = ""
+ announcement.Announce(message)
+ reset_announce()
screen = 0
if( href_list["department"] && message )
@@ -389,8 +390,9 @@ var/list/obj/machinery/requests_console/allConsoles = list()
var/obj/item/weapon/card/id/ID = O
if (access_RC_announce in ID.GetAccess())
announceAuth = 1
+ announcement.announcer = ID.assignment ? "[ID.assignment] [ID.registered_name]" : ID.registered_name
else
- announceAuth = 0
+ reset_announce()
user << "\red You are not authorized to send announcements."
updateUsrDialog()
if (istype(O, /obj/item/weapon/stamp))
@@ -399,3 +401,8 @@ var/list/obj/machinery/requests_console/allConsoles = list()
msgStamped = text("Stamped with the [T.name]")
updateUsrDialog()
return
+
+/obj/machinery/requests_console/proc/reset_announce()
+ announceAuth = 0
+ message = ""
+ announcement.announcer = ""
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index d2d93afba2c..54355179c8e 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -1,3 +1,4 @@
+var/datum/announcement/minor/slotmachine_announcement = new(do_log = 0)
/obj/machinery/slot_machine
name = "Slot Machine"
desc = "Gambling for the antisocial."
@@ -55,7 +56,7 @@
if (roll == 1)
for(var/mob/O in hearers(src, null))
O.show_message(text("[] says, 'JACKPOT! You win [src.money]!'", src), 1)
- command_alert("Congratulations [usr.name] on winning the Jackpot!", "Jackpot Winner")
+ slotmachine_announcement.Announce("Congratulations [usr.name] on winning the Jackpot!", "Jackpot Winner")
usr.mind.initial_account.money += src.money
src.money = 0
else if (roll > 1 && roll <= 10)
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index b050fb624e1..de69e56b422 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -178,7 +178,7 @@
var/turf/T = get_turf(R)
if (!T)
continue
- if(T.z == 2 || T.z > 7)
+ if((T.z in config.admin_levels) || T.z > 7)
continue
if(R.syndicate == 1 && emagged == 0)
continue
@@ -199,7 +199,7 @@
continue
var/turf/T = get_turf(M)
if(!T) continue
- if(T.z == 2) continue
+ if((T.z in config.admin_levels)) continue
var/tmpname = M.real_name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
@@ -221,7 +221,7 @@
var/turf/T = get_turf(R)
if (!T || !R.teleporter_hub || !R.teleporter_console)
continue
- if(T.z == 2 || T.z > 7)
+ if((T.z in config.admin_levels) || T.z > 7)
continue
var/tmpname = T.loc.name
if(areaindex[tmpname])
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 0b7c4b8ed5c..14fc57dd05c 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -407,8 +407,8 @@
if(src.shock(user, 100))
return
+ ui_interact(user)
wires.Interact(user)
- ui_interact(user)
/**
* Display the NanoUI window for the vending machine.
@@ -885,7 +885,7 @@
/obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,
/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe = 12,
/obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2,
- /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2)
+ /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2, /obj/item/device/sensor_device = 2)
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,/obj/item/weapon/reagent_containers/pill/stox = 4,/obj/item/weapon/reagent_containers/pill/antitox = 6)
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index cf3cd0022a6..efe31d5bf62 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -389,7 +389,7 @@
range = RANGED
action(atom/target)
- if(!action_checks(target) || src.loc.z == 2) return
+ if(!action_checks(target) || (src.loc.z in config.admin_levels)) return
var/turf/T = get_turf(target)
if(T)
set_ready_state(0)
@@ -410,7 +410,7 @@
action(atom/target)
- if(!action_checks(target) || src.loc.z == 2) return
+ if(!action_checks(target) || (src.loc.z in config.admin_levels)) return
var/list/theareas = list()
for(var/area/AR in orange(100, chassis))
if(AR in theareas) continue
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 10ac7a44994..295a8bdb1cc 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -183,36 +183,40 @@ steam.start() -- spawns the effect
return
/datum/effect/effect/system/spark_spread
- set_up(n = 3, c = 0, loca)
- number = n > 10 ? 10 : n
- cardinals = c
+ var/total_sparks = 0 // To stop it being spammed and lagging!
- if (istype(loca, /turf/))
+ set_up(n = 3, c = 0, loca)
+ if(n > 10)
+ n = 10
+ number = n
+ cardinals = c
+ if(istype(loca, /turf/))
location = loca
else
location = get_turf(loca)
start()
- for (var/i = 1 to number)
- spawn()
- if (holder)
- location = get_turf(holder)
-
- var/obj/effect/effect/sparks/sparks = getFromPool(/obj/effect/effect/sparks, location)
- playsound(location, "sparks", 100, 1)
+ var/i = 0
+ for(i=0, i 20)
+ return
+ spawn(0)
+ if(holder)
+ src.location = get_turf(holder)
+ var/obj/effect/effect/sparks/sparks = new /obj/effect/effect/sparks(src.location)
+ src.total_sparks++
var/direction
-
- if (cardinals)
+ if(src.cardinals)
direction = pick(cardinal)
else
direction = pick(alldirs)
-
- for (var/j = 0, j < pick(1, 2, 3), j++)
+ for(i=0, iCard scanned."
else
diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm
new file mode 100644
index 00000000000..5db0bdc47f4
--- /dev/null
+++ b/code/game/objects/items/devices/sensor_device.dm
@@ -0,0 +1,18 @@
+/obj/item/device/sensor_device
+ name = "handheld crew monitor"
+ desc = "A miniature machine that tracks suit sensors across the station."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "scanner"
+ w_class = 2.0
+ slot_flags = SLOT_BELT
+ origin_tech = "biotech=3;materials=3;magnets=3"
+ var/obj/nano_module/crew_monitor/crew_monitor
+
+/obj/item/device/sensor_device/New()
+ crew_monitor = new(src)
+
+/obj/item/device/sensor_device/attack_self(mob/user as mob)
+ ui_interact(user)
+
+/obj/item/device/sensor_device/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ crew_monitor.ui_interact(user, ui_key, ui, force_open)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index a1ddb256d89..1de0937b378 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -399,6 +399,120 @@
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
busy = 0
update_icon()
+ else
+ user << "You need to target your patient's chest with [src]."
+ return
+
+/obj/item/weapon/borg_defib
+ name = "defibrillator paddles"
+ desc = "A pair of mounted paddles with flat metal surfaces that are used to deliver powerful electric shocks."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "defibpaddles0"
+ item_state = "defibpaddles0"
+ force = 0
+ w_class = 4
+ canremove = 0
+ var/revivecost = 1000
+ var/cooldown = 0
+ var/busy = 0
+
+/obj/item/weapon/borg_defib/attack(mob/M, mob/user)
+ var/tobehealed
+ var/threshold = -config.health_threshold_dead
+ var/mob/living/carbon/human/H = M
+
+ if(busy)
+ return
+ if(cooldown)
+ user << "[src] is recharging."
+ if(!ishuman(M))
+ user << "This unit is only designed to work on humanoid lifeforms."
+ return
+ else
+ if(user.a_intent == "harm")
+ busy = 1
+ H.visible_message("[user] has touched [H.name] with [src]!", \
+ "[user] has touched [H.name] with [src]!")
+ H.adjustStaminaLoss(50)
+ H.Weaken(5)
+ H.updatehealth() //forces health update before next life tick
+ playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1)
+ H.emote("gasp")
+ add_logs(user, M, "stunned", object="defibrillator")
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ R.cell.use(revivecost)
+ cooldown = 1
+ busy = 0
+ update_icon()
+ spawn(50)
+ cooldown = 0
+ update_icon()
+ return
+ if(user.zone_sel && user.zone_sel.selecting == "chest")
+ user.visible_message("[user] begins to place [src] on [M.name]'s chest.", "You begin to place [src] on [M.name]'s chest.")
+ busy = 1
+ update_icon()
+ if(do_after(user, 30)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
+ user.visible_message("[user] places [src] on [M.name]'s chest.", "You place [src] on [M.name]'s chest.")
+ playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 0)
+ var/mob/dead/observer/ghost = H.get_ghost()
+ var/tplus = world.time - H.timeofdeath
+ var/tlimit = 6000 //past this much time the patient is unrecoverable (in deciseconds)
+ var/tloss = 3000 //brain damage starts setting in on the patient after some time left rotting
+ var/total_burn = 0
+ var/total_brute = 0
+ if(do_after(user, 20)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
+ if(H.stat == 2)
+ var/health = H.health
+ M.visible_message("[M]'s body convulses a bit.")
+ playsound(get_turf(src), "bodyfall", 50, 1)
+ playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1)
+ for(var/datum/organ/external/O in H.organs)
+ total_brute += O.brute_dam
+ total_burn += O.burn_dam
+ if(H.health <= config.health_threshold_dead && total_burn <= 180 && total_brute <= 180 && !H.suiciding && !ghost && tplus < tlimit && !(M_NOCLONE in H.mutations))
+ tobehealed = health + threshold
+ tobehealed -= 5 //They get 5 of each type of damage healed so excessive combined damage will not immediately kill them after they get revived
+ H.adjustOxyLoss(tobehealed)
+ H.adjustToxLoss(tobehealed)
+ H.adjustFireLoss(tobehealed)
+ H.adjustBruteLoss(tobehealed)
+ user.visible_message("[user] pings: Resuscitation successful.")
+ playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0)
+ H.stat = 1
+ H.update_revive()
+ H.emote("gasp")
+ if(tplus > tloss)
+ H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ R.cell.use(revivecost)
+ add_logs(user, M, "revived", object="defibrillator")
+ else
+ if(tplus > tlimit)
+ user.visible_message("[user] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.")
+ else if(total_burn >= 180 || total_brute >= 180)
+ user.visible_message("[user] buzzes: Resuscitation failed - Severe tissue damage detected.")
+ else
+ user.visible_message("[user] buzzes: Resuscitation failed.")
+ if(ghost)
+ ghost << "Your heart is being defibrillated. Return to your body if you want to be revived! (Verbs -> Ghost -> Re-enter corpse)"
+ ghost << sound('sound/effects/genetics.ogg')
+ playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0)
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ R.cell.use(revivecost)
+ update_icon()
+ cooldown = 1
+ spawn(50)
+ cooldown = 0
+ update_icon()
+ else
+ user.visible_message("[user] buzzes: Patient is not in a valid state. Operation aborted.")
+ playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
+ busy = 0
+ update_icon()
else
user << "You need to target your patient's chest with [src]."
return
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 938f9da5e72..fde55afe96a 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -95,7 +95,8 @@
"/obj/item/device/flashlight/pen",
"/obj/item/clothing/mask/surgical",
"/obj/item/clothing/gloves/color/latex",
- "/obj/item/weapon/reagent_containers/hypospray/autoinjector"
+ "/obj/item/weapon/reagent_containers/hypospray/autoinjector",
+ "/obj/item/device/sensor_device"
)
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index 88bb08b7ae8..7098afc009d 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -48,7 +48,7 @@ Frequency:
if (usr.stat || usr.restrained())
return
var/turf/current_location = get_turf(usr)//What turf is the user on?
- if(!current_location||current_location.z==2)//If turf was not found or they're on z level 2.
+ if(!current_location||(current_location.z in config.admin_levels))//If turf was not found or they're on z level 2.
usr << "The [src] is malfunctioning."
return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
@@ -138,7 +138,7 @@ Frequency:
/obj/item/weapon/hand_tele/attack_self(mob/user as mob)
var/turf/current_location = get_turf(user)//What turf is the user on?
- if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist.
+ if(!current_location||(current_location.z in config.admin_levels)||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist.
user << "\The [src] is malfunctioning."
return
var/list/L = list( )
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index e50de9f2d44..6049d30bd51 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -21,11 +21,15 @@
// Reagent ID => friendly name
var/list/reagents_to_log=list()
-/obj/Topic(href, href_list, var/nowindow = 0)
+/obj/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1)
// Calling Topic without a corresponding window open causes runtime errors
- if(nowindow)
- return 0
- return ..()
+ if(!nowindow && ..())
+ return 1
+
+ if(usr.can_interact_with_interface(nano_host(), checkrange) != STATUS_INTERACTIVE)
+ return 1
+ add_fingerprint(usr)
+ return 0
/obj/Destroy()
machines -= src
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index fcd8dafd77f..c223fa99314 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -234,4 +234,6 @@
sleep(2)
new /obj/item/clothing/suit/space/eva/paramedic(src)
new /obj/item/clothing/head/helmet/space/eva/paramedic(src)
+ new /obj/item/clothing/head/helmet/space/eva/paramedic(src)
+ new /obj/item/device/sensor_device(src)
return
\ No newline at end of file
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index 3b82543e80a..a576c38295f 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -142,11 +142,11 @@ proc/trigger_armed_response_team(var/force = 0)
// there's only a certain chance a team will be sent
if(!prob(send_team_chance))
- command_alert("It would appear that an emergency response team was requested for [station_name()]. Unfortunately, we were unable to send one at this time.", "Central Command")
+ command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. Unfortunately, we were unable to send one at this time.", "Central Command")
can_call_ert = 0 // Only one call per round, ladies.
return
- command_alert("It would appear that an emergency response team was requested for [station_name()]. We will prepare and send one as soon as possible.", "Central Command")
+ command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. We will prepare and send one as soon as possible.", "Central Command")
can_call_ert = 0 // Only one call per round, gentleman.
send_emergency_team = 1
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index f4b35c40ba2..a5dc3d6ef4d 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -781,7 +781,7 @@ var/global/nologevent = 0
/datum/admins/proc/unprison(var/mob/M in mob_list)
set category = "Admin"
set name = "Unprison"
- if (M.z == 2)
+ if ((M.z in config.admin_levels))
M.loc = pick(latejoin)
message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]", 1)
log_admin("[key_name(usr)] has unprisoned [key_name(M)]")
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 7438f54195e..0a7e0bf628e 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -286,7 +286,7 @@
if("sentinel") M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob )
if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob )
if("human") M.change_mob_type( /mob/living/carbon/human/human , null, null, delmob )
- if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob )
+ if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob )
if("monkey") M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob )
if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob )
if("cat") M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob )
@@ -1091,6 +1091,7 @@
log_admin("[key_name(usr)] attempting to monkeyize [key_name(H)]")
message_admins("\blue [key_name_admin(usr)] attempting to monkeyize [key_name_admin(H)]", 1)
H.monkeyize()
+
else if(href_list["corgione"])
if(!check_rights(R_SPAWN)) return
@@ -1429,7 +1430,7 @@
foo += text("Is an AI | ")
else
foo += text("Make AI | ", src, M)
- if(M.z != 2)
+ if(!(M.z in config.admin_levels))
foo += text("Prison | ", src, M)
foo += text("Maze | ", src, M)
else
@@ -1809,7 +1810,7 @@
return
else
for(var/obj/machinery/photocopier/faxmachine/F in allfaxes)
- if(F.z == 1)
+ if((F.z in config.station_levels))
if(!F.receivefax(P))
src.owner << "\red Message transmission to [F.department] failed."
@@ -2103,11 +2104,11 @@
if(gravity_is_on)
log_admin("[key_name(usr)] toggled gravity on.", 1)
message_admins("\blue [key_name_admin(usr)] toggled gravity on.", 1)
- command_alert("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.")
+ command_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.")
else
log_admin("[key_name(usr)] toggled gravity off.", 1)
message_admins("\blue [key_name_admin(usr)] toggled gravity off.", 1)
- command_alert("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.")
+ command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.")
if("wave")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","Meteor")
@@ -2206,7 +2207,7 @@
for(var/mob/living/carbon/human/H in mob_list)
var/turf/loc = find_loc(H)
var/security = 0
- if(loc.z > 1 || prisonwarped.Find(H))
+ if(!(loc.z in config.station_levels) || prisonwarped.Find(H))
//don't warp them if they aren't ready or are already there
continue
@@ -2519,7 +2520,7 @@
message_admins("[key_name_admin(usr)] made the floor LAVA! It'll last [length] seconds and it will deal [damage] damage to everyone.", 1)
for(var/turf/simulated/floor/F in world)
- if(F.z == 1)
+ if((F.z in config.station_levels))
F.name = "lava"
F.desc = "The floor is LAVA!"
F.overlays += "lava"
@@ -2544,7 +2545,7 @@
sleep(10)
for(var/turf/simulated/floor/F in world) // Reset everything.
- if(F.z == 1)
+ if((F.z in config.station_levels))
F.name = initial(F.name)
F.desc = initial(F.desc)
F.overlays.Cut()
@@ -2592,11 +2593,10 @@
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","EgL")
for(var/obj/machinery/door/airlock/W in world)
- if(W.z == 1 && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
+ if((W.z in config.station_levels) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
W.req_access = list()
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
- command_alert("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.")
- world << sound('sound/AI/commandreport.ogg')
+ command_announcement.Announce("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.", new_sound = 'sound/AI/commandreport.ogg')
if("dorf")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","DF")
@@ -2611,8 +2611,7 @@
message_admins("[key_name_admin(usr)] triggered an ion storm")
var/show_log = alert(usr, "Show ion message?", "Message", "Yes", "No")
if(show_log == "Yes")
- command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert")
- world << sound('sound/AI/ionstorm.ogg')
+ command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg')
if("carp")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","Crp")
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 9b9c26f7a68..0176f93cdd3 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -209,8 +209,7 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No")
if(show_log == "Yes")
- command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert")
- world << sound('sound/AI/ionstorm.ogg')
+ command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg')
IonStorm(0)
feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -642,8 +641,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No")
if(show_log == "Yes")
- command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert")
- world << sound('sound/AI/ionstorm.ogg')
+ command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg')
feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list)
@@ -686,7 +684,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
switch(alert("Should this be announced to the general population?",,"Yes","No"))
if("Yes")
- command_alert(input, customname);
+ command_announcement.Announce(input, customname);
if("No")
world << "\red New Nanotrasen Update available at all communication consoles."
@@ -914,7 +912,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
set desc = "switches between 1x and custom views"
if(view == world.view)
- view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
+ view = input("Select view range:", "View Range", 9) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
else
view = world.view
diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm
index 06dfa6b5bcf..03509d38ac3 100644
--- a/code/modules/awaymissions/bluespaceartillery.dm
+++ b/code/modules/awaymissions/bluespaceartillery.dm
@@ -42,7 +42,7 @@
if (usr.stat || usr.restrained()) return
if(src.reload < 180) return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
- command_alert("Bluespace artillery fire detected. Brace for impact.")
+ command_announcement.Announce("Bluespace artillery fire detected. Brace for impact.")
message_admins("[key_name_admin(usr)] has launched an artillery strike.", 1)
var/list/L = list()
for(var/turf/T in get_area_turfs(thearea.type))
@@ -55,7 +55,7 @@
var/A
A = input("Area to jump bombard", "Open Fire", A) in teleportlocs
var/area/thearea = teleportlocs[A]
- command_alert("Bluespace artillery fire detected. Brace for impact.")
+ command_announcement.Announce("Bluespace artillery fire detected. Brace for impact.")
spawn(30)
var/list/L = list()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 231ecd7b65b..dfb6b4092d2 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -2,22 +2,22 @@
var/list/preferences_datums = list()
-var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm
+var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm. THE ORDER MATTERS
//some autodetection here.
- "pAI" = 1, // 0
- "traitor" = IS_MODE_COMPILED("traitor"), // 1
- "changeling" = IS_MODE_COMPILED("changeling"), // 2
- "vampire" = IS_MODE_COMPILED("vampire"), // 3
- "revolutionary" = IS_MODE_COMPILED("revolution"), // 4
- "blob" = IS_MODE_COMPILED("blob"), // 5
- "operative" = IS_MODE_COMPILED("nuclear"), // 6
- "cultist" = IS_MODE_COMPILED("cult"), // 7
- "wizard" = IS_MODE_COMPILED("wizard"), // 8
- "raider" = IS_MODE_COMPILED("heist"), // 9
- "alien" = 1, // 10
- "ninja" = 1, // 11
- "mutineer" = IS_MODE_COMPILED("mutiny"), // 12
- "malf AI" = IS_MODE_COMPILED("malfunction") // 13
+ "traitor" = IS_MODE_COMPILED("traitor"), // 1 / 1
+ "operative" = IS_MODE_COMPILED("nuclear"), // 2 / 2
+ "changeling" = IS_MODE_COMPILED("changeling"), // 4 / 3
+ "wizard" = IS_MODE_COMPILED("wizard"), // 8 / 4
+ "malf AI" = IS_MODE_COMPILED("malfunction"), // 16 / 5
+ "revolutionary" = IS_MODE_COMPILED("revolution"), // 32 / 6
+ "alien" = 1, // 62 / 7
+ "pAI" = 1, // 128 / 8
+ "cultist" = IS_MODE_COMPILED("cult"), // 256 / 9
+ "ninja" = 1, // 512 / 10
+ "raider" = IS_MODE_COMPILED("heist"), // 1024 / 11
+ "vampire" = IS_MODE_COMPILED("vampire"), // 2048 / 12
+ "mutineer" = IS_MODE_COMPILED("mutiny"), // 4096 / 13
+ "blob" = IS_MODE_COMPILED("blob") // 8192 / 14
)
var/global/list/special_role_times = list( //minimum age (in days) for accounts to play these roles
num2text(BE_PAI) = 0,
diff --git a/code/modules/computer3/computers/communications.dm b/code/modules/computer3/computers/communications.dm
index 37437fdf6aa..dd22bde09ec 100644
--- a/code/modules/computer3/computers/communications.dm
+++ b/code/modules/computer3/computers/communications.dm
@@ -42,6 +42,12 @@
var/status_display_freq = "1435"
var/stat_msg1
var/stat_msg2
+
+ var/datum/announcement/priority/crew_announcement = new
+
+ New()
+ ..()
+ crew_announcement.newscast = 1
Reset()
..()
@@ -53,7 +59,7 @@
Topic(var/href, var/list/href_list)
if(!interactable() || !computer.radio || ..(href,href_list) )
return
- if (computer.z > 1)
+ if (!(computer.z in config.station_levels))
usr << "\red Unable to establish a connection: \black You're too far away from the station!"
return
@@ -68,9 +74,11 @@
authenticated = 1
if(access_captain in I.GetAccess())
authenticated = 2
+ crew_announcement.announcer = GetNameAndAssignmentFromId(I)
if("logout" in href_list)
authenticated = 0
+ crew_announcement.announcer = ""
if("swipeidseclevel" in href_list)
var/mob/M = usr
@@ -102,13 +110,13 @@
usr << "You need to swipe your ID."
if("announce" in href_list)
if(authenticated==2)
- if(message_cooldown) return
- var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?")
+ if(message_cooldown)
+ usr << "Please allow at least one minute to pass between announcements"
+ return
+ var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement")
if(!input || !interactable())
return
- captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain
- log_say("[key_name(usr)] has made a captain announcement: [input]")
- message_admins("[key_name_admin(usr)] has made a captain announcement.", 1)
+ crew_announcement.Announce(input)
message_cooldown = 1
spawn(600)//One minute cooldown
message_cooldown = 0
diff --git a/code/modules/economy/Economy.dm b/code/modules/economy/Economy.dm
index cf78723a683..b41a080d251 100644
--- a/code/modules/economy/Economy.dm
+++ b/code/modules/economy/Economy.dm
@@ -67,7 +67,15 @@ var/setup_economy = 0
/proc/setup_economy()
if(setup_economy)
return
+
var/datum/feed_channel/newChannel = new /datum/feed_channel
+ newChannel.channel_name = "Public Station Announcements"
+ newChannel.author = "Automated Announcement Listing"
+ newChannel.locked = 1
+ newChannel.is_admin_channel = 1
+ news_network.network_channels += newChannel
+
+ newChannel = new /datum/feed_channel
newChannel.channel_name = "Tau Ceti Daily"
newChannel.author = "CentComm Minister of Information"
newChannel.locked = 1
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 13da8de1661..b69a656ca1d 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -15,14 +15,13 @@
/datum/event/alien_infestation/announce()
if(successSpawn)
- command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert")
- world << sound('sound/AI/aliens.ogg')
+ command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
/datum/event/alien_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
- if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network)
+ if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded && temp_vent.network)
if(temp_vent.network.normal_members.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology
vents += temp_vent
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index 96729f0014c..abc3fa87d48 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -7,8 +7,7 @@
/datum/event/blob/announce()
- command_alert("Confirmed outbreak of level 7 biohazard aboard [station_name()]. Nanotrasen has issued a directive 7-10. The station is to be considered quarantined.", "Biohazard Alert")
- world << sound('sound/AI/blob_confirmed.ogg')
+ command_announcement.Announce("Confirmed outbreak of level 7 biohazard aboard [station_name()]. Nanotrasen has issued a directive 7-10. The station is to be considered quarantined.", "Biohazard Alert", new_sound = 'sound/AI/blob_confirmed.ogg')
for (var/mob/living/silicon/ai/aiPlayer in player_list)
if (aiPlayer.client)
@@ -39,14 +38,14 @@
/datum/event/blob/proc/announce_nuke()
var/nukecode = "ERROR"
for(var/obj/machinery/nuclearbomb/bomb in world)
- if(bomb && bomb.r_code && bomb.z == 1)
+ if(bomb && bomb.r_code && (bomb.z in config.station_levels))
nukecode = bomb.r_code
- command_alert("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [nukecode] ", "Biohazard Alert")
+ command_announcement.Announce("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [nukecode] ", "Biohazard Alert")
set_security_level("gamma")
var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world
- if(V && V.z == 1)
+ if(V && (V.z in config.station_levels))
V.locked = 0
V.update_icon()
@@ -64,7 +63,7 @@
spawn(10)
if(Blob || blob_cores.len)
return
- command_alert("The level 7 biohazard aboard [station_name()] has been eliminated. Directive 7-10 has been lifted, and the station is no longer quarantined.", "Biohazard Update")
+ command_announcement.Announce("The level 7 biohazard aboard [station_name()] has been eliminated. Directive 7-10 has been lifted, and the station is no longer quarantined.", "Biohazard Update")
for (var/mob/living/silicon/ai/aiPlayer in player_list)
if (aiPlayer.client)
diff --git a/code/modules/events/borers.dm b/code/modules/events/borers.dm
index 4f89417c2df..14010e22fc3 100644
--- a/code/modules/events/borers.dm
+++ b/code/modules/events/borers.dm
@@ -12,13 +12,12 @@
/datum/event/borer_infestation/announce()
if(successSpawn)
- command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert")
- world << sound('sound/AI/aliens.ogg')
+ command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
/datum/event/borer_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
- if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network)
+ if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded && temp_vent.network)
//Stops cortical borers getting stuck in small networks. See: Security, Virology
if(temp_vent.network.normal_members.len > 50)
vents += temp_vent
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index a2436f2ac75..4f2616e7c0f 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -8,11 +8,11 @@
var/obj/machinery/vending/originMachine
/datum/event/brand_intelligence/announce()
- command_alert("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert")
+ command_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert")
/datum/event/brand_intelligence/start()
for(var/obj/machinery/vending/V in machines)
- if(V.z != 1) continue
+ if(!(V.z in config.station_levels)) continue
vendingMachines.Add(V)
if(!vendingMachines.len)
diff --git a/code/modules/events/cargobonus.dm b/code/modules/events/cargobonus.dm
index f0c84b86f54..fb1a3ac277e 100644
--- a/code/modules/events/cargobonus.dm
+++ b/code/modules/events/cargobonus.dm
@@ -2,7 +2,7 @@
announceWhen = 5
/datum/event/cargo_bonus/announce()
- command_alert("Congratulations! [station_name()] was chosen for supply limit increase, please contact local cargo department for details!", "Supply Alert")
+ command_announcement.Announce("Congratulations! [station_name()] was chosen for supply limit increase, please contact local cargo department for details!", "Supply Alert")
/datum/event/cargo_bonus/start()
supply_controller.points+=rand(100,500)
\ No newline at end of file
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index 7cf82ff1f67..303f5686e8e 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -8,7 +8,7 @@
endWhen = rand(600,1200)
/datum/event/carp_migration/announce()
- command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
+ command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
/datum/event/carp_migration/start()
for(var/obj/effect/landmark/C in landmarks_list)
diff --git a/code/modules/events/comms_blackout.dm b/code/modules/events/comms_blackout.dm
index 2f5cbea97b3..6b948538d5d 100644
--- a/code/modules/events/comms_blackout.dm
+++ b/code/modules/events/comms_blackout.dm
@@ -1,6 +1,6 @@
/proc/communications_blackout(var/silent = 1)
if(!silent)
- command_alert("Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT")
+ command_announcement.Announce("Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT")
else // AIs will always know if there's a comm blackout, rogue AIs could then lie about comm blackouts in the future while they shutdown comms
for(var/mob/living/silicon/ai/A in player_list)
A << " "
diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm
index d437d85684e..d39517f5343 100644
--- a/code/modules/events/communications_blackout.dm
+++ b/code/modules/events/communications_blackout.dm
@@ -12,7 +12,7 @@
A << " "
if(prob(30)) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts.
- command_alert(alert)
+ command_announcement.Announce(alert)
/datum/event/communications_blackout/start()
for(var/obj/machinery/telecomms/T in telecomms_list)
diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm
index a12aa2147c5..ec4ea8b8d3a 100644
--- a/code/modules/events/disease_outbreak.dm
+++ b/code/modules/events/disease_outbreak.dm
@@ -3,8 +3,7 @@
oneShot = 1
/datum/event/disease_outbreak/announce()
- command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
- world << sound('sound/AI/outbreak7.ogg')
+ command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
/datum/event/disease_outbreak/setup()
announceWhen = rand(15, 30)
@@ -17,7 +16,7 @@
var/turf/T = get_turf(H)
if(!T)
continue
- if(T.z != 1)
+ if(!(T.z in config.station_levels))
continue
for(var/datum/disease/D in H.viruses)
foundAlready = 1
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index 2b9b989e5e9..a8254d02c7a 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -3,7 +3,7 @@
var/lightsoutRange = 25
/datum/event/electrical_storm/announce()
- command_alert("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
+ command_announcement.Announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
/datum/event/electrical_storm/start()
var/list/epicentreList = list()
diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm
index 622e62b5172..effa2845d01 100644
--- a/code/modules/events/event_container.dm
+++ b/code/modules/events/event_container.dm
@@ -135,8 +135,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)),
// NON-BAY EVENTS
- new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Cargo Bonus", /datum/event/cargo_bonus, 150),
- new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mass Hallucination",/datum/event/mass_hallucination,200),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Cargo Bonus", /datum/event/cargo_bonus, 100)
)
/datum/event_container/moderate
@@ -145,9 +144,9 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Nothing", /datum/event/nothing, 1230),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 100, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 20), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 20, list(ASSIGNMENT_SECURITY = 20)),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space vines", /datum/event/spacevine, 200, list(ASSIGNMENT_ENGINEER = 10)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Vines", /datum/event/spacevine, 200, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 20)),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 20)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 30)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)),
// new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)),
@@ -156,18 +155,19 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ionstorm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)),
- new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5),
- new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5),
+ new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 20), 1),
+ new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 15), 1),
// NON-BAY EVENTS
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 50, list(ASSIGNMENT_ENGINEER = 50)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Mass Hallucination", /datum/event/mass_hallucination, 300),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 50, list(ASSIGNMENT_ENGINEER = 50)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Dimensional Tear", /datum/event/tear, 0, list(ASSIGNMENT_SECURITY = 25)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vent Clog", /datum/event/vent_clog, 250),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Wormholes", /datum/event/wormholes, 150),
-
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 100, list(ASSIGNMENT_ENGINEER = 60)),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 50, list(ASSIGNMENT_ENGINEER = 25)),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 50, list(ASSIGNMENT_ENGINEER = 25)),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 50, list(ASSIGNMENT_ENGINEER = 50)),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200),
+// new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 100, list(ASSIGNMENT_ENGINEER = 60)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 50, list(ASSIGNMENT_ENGINEER = 25)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 50, list(ASSIGNMENT_ENGINEER = 25)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 50, list(ASSIGNMENT_ENGINEER = 50)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200),
)
/datum/event_container/major
diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm
index df494ddc245..1dd1956c7ab 100644
--- a/code/modules/events/event_dynamic.dm
+++ b/code/modules/events/event_dynamic.dm
@@ -79,7 +79,7 @@ var/global/list/possibleEvents = list()
if(!spacevines_spawned)
possibleEvents[/datum/event/spacevine] = 10 + 5 * active_with_role["Engineer"]
if(minutes_passed >= 30) // Give engineers time to set up engine
- possibleEvents[/datum/event/anomaly/anomaly_pyro] = 100 + 60 * active_with_role["Engineer"]
+// possibleEvents[/datum/event/anomaly/anomaly_pyro] = 100 + 60 * active_with_role["Engineer"]
possibleEvents[/datum/event/anomaly/anomaly_vortex] = 50 + 25 * active_with_role["Engineer"]
possibleEvents[/datum/event/anomaly/anomaly_bluespace] = 50 + 25 * active_with_role["Engineer"]
possibleEvents[/datum/event/anomaly/anomaly_flux] = 50 + 50 * active_with_role["Engineer"]
@@ -152,10 +152,7 @@ var/global/list/possibleEvents = list()
/*switch(picked_event)
if("Meteor")
- command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert")
- for(var/mob/M in player_list)
- if(!istype(M,/mob/new_player))
- M << sound('sound/AI/meteors.ogg')
+ command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg')
spawn(100)
meteor_wave(10)
spawn_meteors()
diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm
index 71d78d96e4a..c485827efbc 100644
--- a/code/modules/events/grid_check.dm
+++ b/code/modules/events/grid_check.dm
@@ -8,9 +8,7 @@
power_failure(0)
/datum/event/grid_check/announce()
- command_alert("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Automated Grid Check")
- for(var/mob/M in player_list)
- M << sound('sound/AI/poweroff.ogg')
+ command_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Automated Grid Check", new_sound = 'sound/AI/poweroff.ogg')
/datum/event/grid_check/end()
power_restore()
diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm
index 8971db74853..444da4675ef 100644
--- a/code/modules/events/infestation.dm
+++ b/code/modules/events/infestation.dm
@@ -102,7 +102,7 @@
/datum/event/infestation/announce()
- command_alert("Bioscans indicate that [vermstring] have been breeding in [locstring]. Clear them out, before this starts to affect productivity.", "Lifesign Alert")
+ command_announcement.Announce("Bioscans indicate that [vermstring] have been breeding in [locstring]. Clear them out, before this starts to affect productivity.", "Lifesign Alert")
#undef LOC_KITCHEN
#undef LOC_ATMOS
diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm
index 7f66a4366a9..9e8f5d43b57 100644
--- a/code/modules/events/ion_storm.dm
+++ b/code/modules/events/ion_storm.dm
@@ -6,7 +6,7 @@
/datum/event/ionstorm/announce()
endWhen = rand(500, 1500)
-// command_alert("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert")
+// command_announcement.Announce("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert")
for (var/mob/living/carbon/human/player in world)
if(player.client)
players += player.real_name
@@ -86,7 +86,7 @@
/datum/event/ionstorm/end()
spawn(rand(5000,8000))
if(prob(50))
- command_alert("It has come to our attention that the station passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert")
+ command_announcement.Announce("It has come to our attention that the station passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert")
/*
/proc/IonStorm(botEmagChance = 10)
@@ -212,21 +212,21 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
spawn(0)
world << "Started processing APCs"
for (var/obj/machinery/power/apc/APC in world)
- if(APC.z == 1)
+ if((APC.z in config.station_levels))
APC.ion_act()
apcnum++
world << "Finished processing APCs. Processed: [apcnum]"
spawn(0)
world << "Started processing SMES"
for (var/obj/machinery/power/smes/SMES in world)
- if(SMES.z == 1)
+ if((SMES.z in config.station_levels))
SMES.ion_act()
smesnum++
world << "Finished processing SMES. Processed: [smesnum]"
spawn(0)
world << "Started processing AIRLOCKS"
for (var/obj/machinery/door/airlock/D in world)
- if(D.z == 1)
+ if((D.z in config.station_levels))
//if(length(D.req_access) > 0 && !(12 in D.req_access)) //not counting general access and maintenance airlocks
airlocknum++
spawn(0)
@@ -235,7 +235,7 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
spawn(0)
world << "Started processing FIREDOORS"
for (var/obj/machinery/door/firedoor/D in world)
- if(D.z == 1)
+ if((D.z in config.station_levels))
firedoornum++;
spawn(0)
D.ion_act()
diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm
index 571a9ae7d1f..b3fbea5343c 100644
--- a/code/modules/events/mass_hallucination.dm
+++ b/code/modules/events/mass_hallucination.dm
@@ -3,4 +3,4 @@
if(!(C.species.flags & IS_SYNTHETIC))
C.hallucination += rand(50, 100)
/datum/event/mass_hallucination/announce()
- command_alert("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage")
\ No newline at end of file
+ command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage")
\ No newline at end of file
diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm
index 0f74d65b7d9..42b0b1eda1d 100644
--- a/code/modules/events/meteors.dm
+++ b/code/modules/events/meteors.dm
@@ -9,15 +9,14 @@
endWhen = rand(10,25) * 3
/datum/event/meteor_wave/announce()
- command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert")
- world << sound('sound/AI/meteors.ogg')
-
+ command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg')
+
/datum/event/meteor_wave/tick()
if(IsMultiple(activeFor, 3))
spawn_meteors(rand(2,5))
/datum/event/meteor_wave/end()
- command_alert("The station has cleared the meteor storm.", "Meteor Alert")
+ command_announcement.Announce("The station has cleared the meteor storm.", "Meteor Alert")
//
/datum/event/meteor_shower
@@ -30,7 +29,7 @@
waves = rand(1,4)
/datum/event/meteor_shower/announce()
- command_alert("The station is now in a meteor shower.", "Meteor Alert")
+ command_announcement.Announce("The station is now in a meteor shower.", "Meteor Alert")
//meteor showers are lighter and more common,
/datum/event/meteor_shower/tick()
@@ -44,4 +43,4 @@
endWhen = next_meteor + 1
/datum/event/meteor_shower/end()
- command_alert("The station has cleared the meteor shower", "Meteor Alert")
+ command_announcement.Announce("The station has cleared the meteor shower", "Meteor Alert")
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index 87135bda526..676661f2b7e 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -15,7 +15,7 @@
/datum/event/prison_break/announce()
if(prisonAreas && prisonAreas.len > 0)
- command_alert("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
+ command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
else
world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area."
kill()
@@ -30,7 +30,7 @@
/datum/event/prison_break/announce()
if(prisonAreas && prisonAreas.len > 0)
- command_alert("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
+ command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
else
world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area."
kill()
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index 58b5f60c2cc..5daabc84799 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -22,11 +22,10 @@
/datum/event/radiation_storm/start()
spawn()
- world << sound('sound/AI/radiation.ogg')
- command_alert("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert")
+ command_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
for(var/area/A in world)
- if(A.z != 1 || is_safe_zone(A))
+ if(!(A.z in config.station_levels) || is_safe_zone(A))
continue
A.radiation_alert()
@@ -36,7 +35,7 @@
sleep(600)
- command_alert("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert")
+ command_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert")
for(var/i = 0, i < 10, i++)
for(var/mob/living/carbon/human/H in living_mob_list)
@@ -45,7 +44,7 @@
var/turf/T = get_turf(H)
if(!T)
continue
- if(T.z != 1 || is_safe_zone(T.loc))
+ if(!(T.z in config.station_levels) || is_safe_zone(T.loc))
continue
if(istype(H,/mob/living/carbon/human))
@@ -64,16 +63,16 @@
var/turf/T = get_turf(M)
if(!T)
continue
- if(T.z != 1)
+ if(!(T.z in config.station_levels))
continue
M.apply_effect((rand(5,25)),IRRADIATE,0)
sleep(100)
- command_alert("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
+ command_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
for(var/area/A in world)
- if(A.z != 1 || is_safe_zone(A))
+ if(!(A.z in config.station_levels) || is_safe_zone(A))
continue
A.reset_radiation_alert()
diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm
index d3ccaa4d89a..d96c80f60f8 100644
--- a/code/modules/events/rogue_drones.dm
+++ b/code/modules/events/rogue_drones.dm
@@ -30,7 +30,7 @@
msg = "Contact has been lost with a combat drone wing operating out of the NMV Icarus. If any are sighted in the area, approach with caution."
else
msg = "Unidentified hackers have targetted a combat drone wing deployed from the NMV Icarus. If any are sighted in the area, approach with caution."
- command_alert(msg, "Rogue drone alert")
+ command_announcement.Announce(msg, "Rogue drone alert")
/datum/event/rogue_drone/tick()
@@ -49,6 +49,6 @@
num_recovered++
if(num_recovered > drones_list.len * 0.75)
- command_alert("Icarus drone control reports the malfunctioning wing has been recovered safely.", "Rogue drone alert")
+ command_announcement.Announce("Icarus drone control reports the malfunctioning wing has been recovered safely.", "Rogue drone alert")
else
- command_alert("Icarus drone control registers disappointment at the loss of the drones, but the survivors have been recovered.", "Rogue drone alert")
+ command_announcement.Announce("Icarus drone control registers disappointment at the loss of the drones, but the survivors have been recovered.", "Rogue drone alert")
diff --git a/code/modules/events/sayuevents/meaty_ores.dm b/code/modules/events/sayuevents/meaty_ores.dm
index a44708693ef..d6e640934d9 100644
--- a/code/modules/events/sayuevents/meaty_ores.dm
+++ b/code/modules/events/sayuevents/meaty_ores.dm
@@ -1,9 +1,8 @@
/datum/event/dust/meaty/announce()
if(prob(16))
- command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
+ command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
else
- command_alert("Meaty ores have been detected on collision course with the station.", "Meaty Ore Alert")
- world << sound('sound/AI/meteors.ogg')
+ command_announcement.Announce("Meaty ores have been detected on collision course with the station.", "Meaty Ore Alert",new_sound = 'sound/AI/meteors.ogg')
/datum/event/dust/meaty/setup()
qnty = rand(45,125)
diff --git a/code/modules/events/sayuevents/undead.dm b/code/modules/events/sayuevents/undead.dm
index f9d82baf086..84c1c0bb1b1 100644
--- a/code/modules/events/sayuevents/undead.dm
+++ b/code/modules/events/sayuevents/undead.dm
@@ -8,7 +8,7 @@
RS.start()
RS.kill()
for(var/area/A)
- if(A.z != 1) continue //Spook on main station only.
+ if(!(A.z in config.station_levels)) continue //Spook on main station only.
if(A.luminosity) continue
// if(A.lighting_space) continue
if(A.type == /area) continue
diff --git a/code/modules/events/sayuevents/wormholes.dm b/code/modules/events/sayuevents/wormholes.dm
index e120d11630d..c31645d7a00 100644
--- a/code/modules/events/sayuevents/wormholes.dm
+++ b/code/modules/events/sayuevents/wormholes.dm
@@ -13,7 +13,7 @@
/datum/event/wormholes/start()
for(var/turf/simulated/floor/T in world)
- if(T.z == 1)
+ if((T.z in config.station_levels))
pick_turfs += T
for(var/i = 1, i <= number_of_wormholes, i++)
@@ -21,10 +21,7 @@
wormholes += new /obj/effect/portal/wormhole(T, null, null, -1)
/datum/event/wormholes/announce()
- command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert")
- for(var/mob/M in player_list)
- if(!istype(M, /mob/new_player))
- M << sound('sound/AI/spanomalies.ogg')
+ command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/spanomalies.ogg')
/datum/event/wormholes/tick()
if(activeFor % shift_frequency == 0)
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index 7a953d3fd40..227737ba99c 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -12,15 +12,13 @@
sent_spiders_to_station = 1
/datum/event/spider_infestation/announce()
- command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert")
- world << sound('sound/AI/aliens.ogg')
-
+ command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
/datum/event/spider_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
- if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network)
+ if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded && temp_vent.network)
if(temp_vent.network.normal_members.len > 50)
vents += temp_vent
diff --git a/code/modules/events/tear.dm b/code/modules/events/tear.dm
index d5d572c3b6a..a11455b351d 100644
--- a/code/modules/events/tear.dm
+++ b/code/modules/events/tear.dm
@@ -5,7 +5,7 @@
var/obj/effect/tear/TE
/datum/event/tear/announce()
- command_alert("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert")
+ command_announcement.Announce("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/event/tear/start()
diff --git a/code/modules/events/tgevents/anomaly.dm b/code/modules/events/tgevents/anomaly.dm
index 7ab1f25c9ca..a1f951f5747 100644
--- a/code/modules/events/tgevents/anomaly.dm
+++ b/code/modules/events/tgevents/anomaly.dm
@@ -15,7 +15,7 @@
setup(safety_loop)
/datum/event/anomaly/announce()
- command_alert("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
+ command_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
/datum/event/anomaly/start()
var/turf/T = pick(get_area_turfs(impact_area))
diff --git a/code/modules/events/tgevents/anomaly_bluespace.dm b/code/modules/events/tgevents/anomaly_bluespace.dm
index 224f6f0e2de..852680e69fa 100644
--- a/code/modules/events/tgevents/anomaly_bluespace.dm
+++ b/code/modules/events/tgevents/anomaly_bluespace.dm
@@ -4,7 +4,7 @@
endWhen = 160
/datum/event/anomaly/anomaly_bluespace/announce()
- command_alert("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ command_announcement.Announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/event/anomaly/anomaly_bluespace/start()
@@ -21,7 +21,7 @@
var/obj/item/device/radio/beacon/chosen
var/list/possible = list()
for(var/obj/item/device/radio/beacon/W in world)
- if(W.z != 1)
+ if(!(W.z in config.station_levels))
continue
possible += W
@@ -35,7 +35,7 @@
var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO
playsound(TO, 'sound/effects/phasein.ogg', 100, 1)
- command_alert("Massive bluespace translocation detected.", "Anomaly Alert")
+ command_announcement.Announce("Massive bluespace translocation detected.", "Anomaly Alert")
var/list/flashers = list()
for(var/mob/living/carbon/human/M in viewers(TO, null))
diff --git a/code/modules/events/tgevents/anomaly_flux.dm b/code/modules/events/tgevents/anomaly_flux.dm
index bf2cb2d18cc..d02af07b3ef 100644
--- a/code/modules/events/tgevents/anomaly_flux.dm
+++ b/code/modules/events/tgevents/anomaly_flux.dm
@@ -4,7 +4,7 @@
endWhen = 180
/datum/event/anomaly/anomaly_flux/announce()
- command_alert("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ command_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/event/anomaly/anomaly_flux/start()
var/turf/T = pick(get_area_turfs(impact_area))
diff --git a/code/modules/events/tgevents/anomaly_grav.dm b/code/modules/events/tgevents/anomaly_grav.dm
index c5430625ea8..0c9f3776f82 100644
--- a/code/modules/events/tgevents/anomaly_grav.dm
+++ b/code/modules/events/tgevents/anomaly_grav.dm
@@ -4,7 +4,7 @@
endWhen = 70
/datum/event/anomaly/anomaly_grav/announce()
- command_alert("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ command_announcement.Announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/event/anomaly/anomaly_grav/start()
var/turf/T = pick(get_area_turfs(impact_area))
diff --git a/code/modules/events/tgevents/anomaly_pyro.dm b/code/modules/events/tgevents/anomaly_pyro.dm
index 4e7f6a0b947..df4805121cd 100644
--- a/code/modules/events/tgevents/anomaly_pyro.dm
+++ b/code/modules/events/tgevents/anomaly_pyro.dm
@@ -4,7 +4,7 @@
endWhen = 110
/datum/event/anomaly/anomaly_pyro/announce()
- command_alert("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ command_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/event/anomaly/anomaly_pyro/start()
var/turf/T = pick(get_area_turfs(impact_area))
diff --git a/code/modules/events/tgevents/anomaly_vortex.dm b/code/modules/events/tgevents/anomaly_vortex.dm
index 6f2f999e728..c950444978e 100644
--- a/code/modules/events/tgevents/anomaly_vortex.dm
+++ b/code/modules/events/tgevents/anomaly_vortex.dm
@@ -4,7 +4,7 @@
endWhen = 80
/datum/event/anomaly/anomaly_vortex/announce()
- command_alert("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
+ command_announcement.Announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
/datum/event/anomaly/anomaly_vortex/start()
var/turf/T = pick(get_area_turfs(impact_area))
diff --git a/code/modules/events/tgevents/brand_intelligence.dm b/code/modules/events/tgevents/brand_intelligence.dm
index 893cee98cf1..1cfeba0cd08 100644
--- a/code/modules/events/tgevents/brand_intelligence.dm
+++ b/code/modules/events/tgevents/brand_intelligence.dm
@@ -8,7 +8,7 @@
/datum/event/brand_intelligence/announce()
- command_alert("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert")
+ command_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert")
/datum/event/brand_intelligence/start()
diff --git a/code/modules/events/tgevents/immovable_rod.dm b/code/modules/events/tgevents/immovable_rod.dm
index 25c3d0308d4..ec86e89981f 100644
--- a/code/modules/events/tgevents/immovable_rod.dm
+++ b/code/modules/events/tgevents/immovable_rod.dm
@@ -12,7 +12,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
announceWhen = 5
/datum/event/immovable_rod/announce()
- command_alert("What the fuck was that?!", "General Alert")
+ command_announcement.Announce("What the fuck was that?!", "General Alert")
/datum/event/immovable_rod/start()
var/startx = 0
diff --git a/code/modules/events/tgevents/mass_hallucination.dm b/code/modules/events/tgevents/mass_hallucination.dm
index 6a34331acb3..f23a2c15510 100644
--- a/code/modules/events/tgevents/mass_hallucination.dm
+++ b/code/modules/events/tgevents/mass_hallucination.dm
@@ -6,4 +6,4 @@
if(!(C.species.flags & IS_SYNTHETIC))
C.hallucination += rand(50, 100)
/datum/event/mass_hallucination/announce()
- command_alert("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage")
\ No newline at end of file
+ command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage")
\ No newline at end of file
diff --git a/code/modules/events/tgevents/spider_infestation.dm b/code/modules/events/tgevents/spider_infestation.dm
deleted file mode 100644
index 1f4cccdf418..00000000000
--- a/code/modules/events/tgevents/spider_infestation.dm
+++ /dev/null
@@ -1,33 +0,0 @@
-/var/global/sent_spiders_to_station = 0
-
-/datum/event/spider_infestation
- announceWhen = 400
-
- var/spawncount = 1
-
-
-/datum/event/spider_infestation/setup()
- announceWhen = rand(announceWhen, announceWhen + 50)
- spawncount = round(num_players() * 1.5)
- sent_spiders_to_station = 1
-
-/datum/event/spider_infestation/announce()
- command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert")
- world << sound('sound/AI/aliens.ogg')
-
-
-/datum/event/spider_infestation/start()
-
- var/list/vents = list()
- for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
- if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network)
- if(temp_vent.network.normal_members.len > 50)
- vents += temp_vent
-
- while((spawncount >= 1) && vents.len)
- var/obj/vent = pick(vents)
- var/obj/effect/spider/spiderling/S = new(vent.loc)
- if(prob(66))
- S.grow_as = /mob/living/simple_animal/hostile/giant_spider/nurse
- vents -= vent
- spawncount--
\ No newline at end of file
diff --git a/code/modules/events/tgevents/vent_clog.dm b/code/modules/events/tgevents/vent_clog.dm
index 885552dff28..061450a197d 100755
--- a/code/modules/events/tgevents/vent_clog.dm
+++ b/code/modules/events/tgevents/vent_clog.dm
@@ -6,13 +6,13 @@
var/list/vents = list()
/datum/event/vent_clog/announce()
- command_alert("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
+ command_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
/datum/event/vent_clog/setup()
endWhen = rand(25, 100)
for(var/obj/machinery/atmospherics/unary/vent_scrubber/temp_vent in machines)
- if(temp_vent.loc.z == 1 && temp_vent.network)
+ if((temp_vent.loc.z in config.station_levels) && temp_vent.network)
if(temp_vent.network.normal_members.len > 50)
vents += temp_vent
diff --git a/code/modules/events/viral_infection.dm b/code/modules/events/viral_infection.dm
index 876e3453896..9ee3a47077a 100644
--- a/code/modules/events/viral_infection.dm
+++ b/code/modules/events/viral_infection.dm
@@ -8,8 +8,7 @@ datum/event/viral_infection/setup()
severity = rand(1, 3)
datum/event/viral_infection/announce()
- command_alert("Confirmed outbreak of level five viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
- world << sound('sound/AI/outbreak5.ogg')
+ command_announcement.Announce("Confirmed outbreak of level five viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak5.ogg')
datum/event/viral_infection/start()
var/list/candidates = list() //list of candidate keys
diff --git a/code/modules/events/viral_outbreak.dm b/code/modules/events/viral_outbreak.dm
index f11acd511f3..9e139f5742b 100644
--- a/code/modules/events/viral_outbreak.dm
+++ b/code/modules/events/viral_outbreak.dm
@@ -8,8 +8,7 @@ datum/event/viral_outbreak/setup()
severity = rand(2, 4)
datum/event/viral_outbreak/announce()
- command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
- world << sound('sound/AI/outbreak7.ogg')
+ command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
datum/event/viral_outbreak/start()
var/list/candidates = list() //list of candidate keys
diff --git a/code/modules/events/wallrot.dm b/code/modules/events/wallrot.dm
index 739ca92411b..b36f7f93760 100644
--- a/code/modules/events/wallrot.dm
+++ b/code/modules/events/wallrot.dm
@@ -3,7 +3,7 @@ datum/event/wallrot/setup()
endWhen = announceWhen + 1
datum/event/wallrot/announce()
- command_alert("Harmful fungi detected on station. Station structures may be contaminated.", "Biohazard Alert")
+ command_announcement.Announce("Harmful fungi detected on station. Station structures may be contaminated.", "Biohazard Alert")
datum/event/wallrot/start()
spawn()
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index 1a0315b957d..82bc3a0f287 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -324,7 +324,7 @@
var/list/L = list()
for(var/obj/item/device/radio/beacon/B in world)
var/turf/T = get_turf(B)
- if(T.z == 1)
+ if((T.z in config.station_levels))
L += B
if(!L.len)
user << "The [src.name] failed to create a wormhole."
diff --git a/code/modules/mining/ore.dm b/code/modules/mining/ore.dm
index fd3598ae985..866b46bae50 100644
--- a/code/modules/mining/ore.dm
+++ b/code/modules/mining/ore.dm
@@ -84,7 +84,7 @@
/obj/item/weapon/ore/New()
pixel_x = rand(0,16)-8
pixel_y = rand(0,8)-8
- if(src.z == 5) score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining asteroid (No Clown Planet)
+ if(src.z == ASTEROID_Z) score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining asteroid (No Clown Planet)
/obj/item/weapon/ore/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/device/core_sampler))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index ded2a3c949e..968fa181d89 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -538,7 +538,21 @@
var/obj/vehicle/V = AM
V.RunOver(src)
-
+// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc.
+/mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job")
+ var/obj/item/device/pda/pda = wear_id
+ if (istype(pda))
+ if (pda.id)
+ return pda.id.rank
+ else
+ return pda.ownrank
+ else
+ var/obj/item/weapon/card/id/id = get_idcard()
+ if(id)
+ return id.rank ? id.rank : if_no_job
+ else
+ return if_no_id
+
//gets assignment from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_assignment(var/if_no_id = "No id", var/if_no_job = "No job")
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 8eb38c1e7b0..8319046d5d5 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1537,7 +1537,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
// Not on the station or mining?
var/turf/temp_turf = get_turf(remoteview_target)
- if((temp_turf.z != 1 && temp_turf.z != 5) || remoteview_target.stat!=CONSCIOUS)
+ if((!(temp_turf.z in config.contact_levels)) || remoteview_target.stat!=CONSCIOUS)
src << "\red Your psy-connection grows too faint to maintain!"
isRemoteObserve = 0
if(!isRemoteObserve && client && !client.adminobs)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 47464bc12e4..6a7b2375826 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -1,3 +1,6 @@
+#define AI_CHECK_WIRELESS 1
+#define AI_CHECK_RADIO 2
+
var/list/ai_list = list()
//Not sure why this is necessary...
@@ -77,8 +80,8 @@ var/list/ai_list = list()
possibleNames -= pickedName
pickedName = null
- real_name = pickedName
- name = real_name
+ aiPDA = new/obj/item/device/pda/ai(src)
+ SetName(pickedName)
anchored = 1
canmove = 0
density = 1
@@ -96,11 +99,6 @@ var/list/ai_list = list()
verbs += /mob/living/silicon/ai/proc/show_laws_verb
- aiPDA = new/obj/item/device/pda/ai(src)
- aiPDA.owner = name
- aiPDA.ownjob = "AI"
- aiPDA.name = name + " (" + aiPDA.ownjob + ")"
-
aiMulti = new(src)
aiRadio = new(src)
aiRadio.myAi = src
@@ -112,7 +110,7 @@ var/list/ai_list = list()
if (istype(loc, /turf))
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
- /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location)
+ /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location, /mob/living/silicon/ai/proc/nano_crew_monitor, /mob/living/silicon/ai/proc/ai_cancel_call)
if(!safety)//Only used by AIize() to successfully spawn an AI.
if (!B)//If there is no player/brain inside.
@@ -127,7 +125,7 @@ var/list/ai_list = list()
verbs.Remove(,/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \
/mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
- /mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message)
+ /mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_cancel_call)
laws = new /datum/ai_laws/alienmov
else
B.brainmob.mind.transfer_to(src)
@@ -155,11 +153,25 @@ var/list/ai_list = list()
hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
- hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
+ hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
+ init_subsystems()
+
ai_list += src
..()
return
+
+/mob/living/silicon/ai/proc/SetName(pickedName as text)
+ real_name = pickedName
+ name = pickedName
+ if(eyeobj)
+ eyeobj.name = "[pickedName] (AI Eye)"
+
+ // Set ai pda name
+ if(aiPDA)
+ aiPDA.ownjob = "AI"
+ aiPDA.owner = pickedName
+ aiPDA.name = pickedName + " (" + aiPDA.ownjob + ")"
/mob/living/silicon/ai/Destroy()
ai_list -= src
@@ -301,14 +313,15 @@ var/list/ai_list = list()
if(src.stat == 2)
src << "You can't call the shuttle because you are dead!"
return
- if(istype(usr,/mob/living/silicon/ai))
- var/mob/living/silicon/ai/AI = src
- if(AI.control_disabled)
- usr << "Wireless control is disabled!"
- return
+
+ if(check_unable(AI_CHECK_WIRELESS))
+ return
var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No")
+ if(check_unable(AI_CHECK_WIRELESS))
+ return
+
if(confirm == "Yes")
call_shuttle_proc(src)
@@ -317,38 +330,57 @@ var/list/ai_list = list()
var/obj/machinery/computer/communications/C = locate() in machines
if(C)
C.post_status("shuttle")
-
return
+
+/mob/living/silicon/ai/proc/ai_cancel_call()
+ set name = "Recall Emergency Shuttle"
+ set category = "AI Commands"
+
+ if(src.stat == 2)
+ src << "You can't send the shuttle back because you are dead!"
+ return
+
+ if(check_unable(AI_CHECK_WIRELESS))
+ return
+
+ var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No")
+
+ if(check_unable(AI_CHECK_WIRELESS))
+ return
+
+ if(confirm == "Yes")
+ cancel_call_proc(src)
/mob/living/silicon/ai/cancel_camera()
src.view_core()
/mob/living/silicon/ai/verb/toggle_anchor()
- set category = "AI Commands"
- set name = "Toggle Floor Bolts"
- if(!isturf(loc)) // if their location isn't a turf
- return // stop
- anchored = !anchored // Toggles the anchor
+ set category = "AI Commands"
+ set name = "Toggle Floor Bolts"
+
+ if(!isturf(loc)) // if their location isn't a turf
+ return // stop
+
+ anchored = !anchored // Toggles the anchor
- src << "[anchored ? "You are now anchored." : "You are now unanchored."]"
- // the message in the [] will change depending whether or not the AI is anchored
+ src << "[anchored ? "You are now anchored." : "You are now unanchored."]"
/mob/living/silicon/ai/update_canmove()
return 0
-
-
-/mob/living/silicon/ai/proc/ai_cancel_call()
- set category = "Malfunction"
+
+/mob/living/silicon/ai/proc/announcement()
+ set name = "Announcement"
+ set desc = "Create a vocal announcement by typing in the available words to create a sentence."
+ set category = "AI Commands"
+
if(src.stat == 2)
- src << "You can't send the shuttle back because you are dead!"
+ src << "You can't call make an announcement because you are dead!"
return
- if(istype(usr,/mob/living/silicon/ai))
- var/mob/living/silicon/ai/AI = src
- if(AI.control_disabled)
- src << "Wireless control is disabled!"
- return
- cancel_call_proc(src)
- return
+
+ if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
+ return
+
+ ai_announcement()
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
if (!current)
@@ -581,9 +613,9 @@ var/list/ai_list = list()
src << "Critical error. System offline."
return
- if(control_disabled)
- src << "Wireless communication is disabled."
+ if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
+
var/ai_allowed_Zlevel = list(1,3,5)
var/d
var/area/bot_area
@@ -704,6 +736,9 @@ var/list/ai_list = list()
set name = "Jump To Network"
unset_machine()
var/cameralist[0]
+
+ if(check_unable())
+ return
if(usr.stat == 2)
usr << "You can't change your camera network because you are dead!"
@@ -721,6 +756,9 @@ var/list/ai_list = list()
cameralist[i] = i
var/old_network = network
network = input(U, "Which network would you like to view?") as null|anything in cameralist
+
+ if(check_unable())
+ return
if(!U.eyeobj)
U.view_core()
@@ -752,8 +790,16 @@ var/list/ai_list = list()
if(usr.stat == 2)
usr <<"You cannot change your emotional status because you are dead!"
return
+
+ if(check_unable())
+ return
+
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
+
+ if(check_unable())
+ return
+
for (var/obj/machinery/M in machines) //change status
if(istype(M, /obj/machinery/ai_status_display))
var/obj/machinery/ai_status_display/AISD = M
@@ -773,6 +819,9 @@ var/list/ai_list = list()
set name = "Change Hologram"
set desc = "Change the default hologram available to AI to something else."
set category = "AI Commands"
+
+ if(check_unable())
+ return
var/input
if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member")
@@ -827,6 +876,9 @@ var/list/ai_list = list()
if(stat != CONSCIOUS)
return
+
+ if(check_unable())
+ return
camera_light_on = !camera_light_on
src << "Camera lights [camera_light_on ? "activated" : "deactivated"]."
@@ -904,8 +956,11 @@ var/list/ai_list = list()
set name = "Radio Settings"
set desc = "Allows you to change settings of your radio."
set category = "AI Commands"
-
- src << "Accessing Subspace Transceiver control..."
+
+ if(check_unable(AI_CHECK_RADIO))
+ return
+
+ src << "Accessing Subspace Transceiver control..."
if (src.aiRadio)
src.aiRadio.interact(src)
@@ -956,4 +1011,25 @@ var/list/ai_list = list()
src << "\red You deny the request."
else
src << "\red You've failed to open an airlock for [target]"
- return
\ No newline at end of file
+ return
+
+
+/mob/living/silicon/ai/proc/check_unable(var/flags = 0)
+ if(stat == DEAD)
+ usr << "\red You are dead!"
+ return 1
+
+ if((flags & AI_CHECK_WIRELESS) && src.control_disabled)
+ usr << "\red Wireless control is disabled!"
+ return 1
+ if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi)
+ src << "\red System Error - Transceiver Disabled!"
+ return 1
+ return 0
+
+/mob/living/silicon/ai/proc/is_in_chassis()
+ return istype(loc, /turf)
+
+#undef AI_CHECK_WIRELESS
+#undef AI_CHECK_RADIO
+
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index c9541858467..dfa05ddc5d0 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -15,21 +15,21 @@
var/callshuttle = 0
for(var/obj/machinery/computer/communications/commconsole in world)
- if(commconsole.z == 2)
+ if((commconsole.z in config.admin_levels))
continue
if(istype(commconsole.loc,/turf))
break
callshuttle++
for(var/obj/item/weapon/circuitboard/communications/commboard in world)
- if(commboard.z == 2)
+ if((commboard.z in config.admin_levels))
continue
if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage))
break
callshuttle++
for(var/mob/living/silicon/ai/shuttlecaller in player_list)
- if(shuttlecaller.z == 2)
+ if((shuttlecaller.z in config.admin_levels))
continue
if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
break
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index 8218bec993e..ec02433c46a 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -134,7 +134,7 @@
src << "ERROR: Eyeobj not found. Creating new eye..."
src.eyeobj = new(src.loc)
src.eyeobj.ai = src
- src.eyeobj.name = "[src.name] (AI Eye)" // Give it a name
+ src.SetName(src.name)
if(client && client.eye)
client.eye = src
diff --git a/code/modules/mob/living/silicon/ai/nano.dm b/code/modules/mob/living/silicon/ai/nano.dm
new file mode 100644
index 00000000000..f9bb7a25d79
--- /dev/null
+++ b/code/modules/mob/living/silicon/ai/nano.dm
@@ -0,0 +1,10 @@
+var/obj/nano_module/crew_monitor/crew_monitor
+
+/mob/living/silicon/ai/proc/init_subsystems()
+ crew_monitor = new(src)
+
+/mob/living/silicon/ai/proc/nano_crew_monitor()
+ set category = "AI Commands"
+ set name = "Crew Monitor"
+
+ crew_monitor.ui_interact(usr)
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index e535a2dedee..b596fd53541 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -1,32 +1,32 @@
/mob/living/silicon/ai/say(var/message)
- if(parent && istype(parent) && parent.stat != 2)
- parent.say(message)
- return
- //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
- ..(message)
+ if(parent && istype(parent) && parent.stat != 2)
+ parent.say(message) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
+ return
+
+ ..(message)
/mob/living/silicon/ai/say_understands(var/other)
- if (istype(other, /mob/living/carbon/human))
- return 1
- if (istype(other, /mob/living/silicon/robot))
- return 1
- if (istype(other, /mob/living/silicon/decoy))
- return 1
- if (istype(other, /mob/living/carbon/brain))
- return 1
- if (istype(other, /mob/living/silicon/pai))
- return 1
- return ..()
+ if (istype(other, /mob/living/carbon/human))
+ return 1
+ if (istype(other, /mob/living/silicon/robot))
+ return 1
+ if (istype(other, /mob/living/silicon/decoy))
+ return 1
+ if (istype(other, /mob/living/carbon/brain))
+ return 1
+ if (istype(other, /mob/living/silicon/pai))
+ return 1
+ return ..()
/mob/living/silicon/ai/say_quote(var/text)
- var/ending = copytext(text, length(text))
+ var/ending = copytext(text, length(text))
- if (ending == "?")
- return "queries, \"[text]\"";
- else if (ending == "!")
- return "declares, \"[text]\"";
+ if (ending == "?")
+ return "queries, \"[text]\"";
+ else if (ending == "!")
+ return "declares, \"[text]\"";
- return "states, \"[text]\"";
+ return "states, \"[text]\"";
/mob/living/silicon/ai/proc/IsVocal()
@@ -36,44 +36,28 @@ var/const/VOX_DELAY = 100
var/const/VOX_PATH = "sound/vox_fem/"
/mob/living/silicon/ai/verb/announcement_help()
-
- set name = "Announcement Help"
- set desc = "Display a list of vocal words to announce to the crew."
- set category = "AI Commands"
-
-
- var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you. \
-
You can also click on the word to preview it.
\
-
You can only say 30 words for every announcement.
\
-
Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.
\
- WARNING: Misuse of the announcement system will get you job banned."
-
- var/index = 0
- for(var/word in vox_sounds)
- index++
- dat += "[capitalize(word)]"
- if(index != vox_sounds.len)
- dat += " / "
-
- var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
- popup.set_content(dat)
- popup.open()
-
-
-/mob/living/silicon/ai/proc/announcement()
-
- set name = "Announcement"
- set desc = "Create a vocal announcement by typing in the available words to create a sentence."
+ set name = "Announcement Help"
+ set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
- if(src.stat == 2)
- src << "You can't call the shuttle because you are dead!"
- return
- if(istype(usr,/mob/living/silicon/ai))
- var/mob/living/silicon/ai/AI = src
- if(AI.control_disabled)
- usr << "Wireless control is disabled!"
- return
+ var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you. \
+
You can also click on the word to preview it.
\
+
You can only say 30 words for every announcement.
\
+
Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.
\
+ WARNING: Misuse of the announcement system will get you job banned."
+
+ var/index = 0
+ for(var/word in vox_sounds)
+ index++
+ dat += "[capitalize(word)]"
+ if(index != vox_sounds.len)
+ dat += " / "
+
+ var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
+ popup.set_content(dat)
+ popup.open()
+
+/mob/living/silicon/ai/proc/ai_announcement()
if(announcing_vox > world.time)
src << "Please wait [round((announcing_vox - world.time) / 10)] seconds."
return
@@ -112,27 +96,24 @@ var/const/VOX_PATH = "sound/vox_fem/"
/proc/play_vox_word(var/word, var/z_level, var/mob/only_listener)
+ word = lowertext(word)
+ if(vox_sounds[word])
+ var/sound_file = vox_sounds[word]
+ var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL)
+ voice.status = SOUND_STREAM
- word = lowertext(word)
-
- if(vox_sounds[word])
-
- var/sound_file = vox_sounds[word]
- var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL)
- voice.status = SOUND_STREAM
-
- // If there is no single listener, broadcast to everyone in the same z level
- if(!only_listener)
- // Play voice for all mobs in the z level
- for(var/mob/M in player_list)
- if(M.client)
- var/turf/T = get_turf(M)
- if(T.z == z_level)
- M << voice
- else
- only_listener << voice
- return 1
- return 0
+ // If there is no single listener, broadcast to everyone in the same z level
+ if(!only_listener)
+ // Play voice for all mobs in the z level
+ for(var/mob/M in player_list)
+ if(M.client)
+ var/turf/T = get_turf(M)
+ if(T.z == z_level && !isdeaf(M))
+ M << voice
+ else
+ only_listener << voice
+ return 1
+ return 0
// VOX sounds moved to /code/defines/vox_sounds.dm
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index dbbf6744701..e28f9ac8b7d 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -188,12 +188,12 @@
/mob/living/silicon/robot/proc/pick_module()
if(module)
return
- var/list/modules = list("Standard", "Engineering", "Surgeon", "Crisis", "Miner", "Janitor", "Service", "Security")
+ var/list/modules = list("Standard", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
if(security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis)
src << "\red Crisis mode active. Combat module available."
modules+="Combat"
if(mmi != null && mmi.alien)
- modules="Hunter"
+ modules = "Hunter"
modtype = input("Please, select a module!", "Robot", null, null) in modules
designation = modtype
var/module_sprites[0] //Used to store the associations between sprite names and sprite index.
@@ -237,8 +237,8 @@
module_sprites["Advanced Droid"] = "droid-miner"
module_sprites["Treadhead"] = "Miner"
- if("Crisis")
- module = new /obj/item/weapon/robot_module/crisis(src)
+ if("Medical")
+ module = new /obj/item/weapon/robot_module/medical(src)
channels = list("Medical" = 1)
if(camera && "Robots" in camera.network)
camera.network.Add("Medical")
@@ -247,17 +247,6 @@
module_sprites["Advanced Droid"] = "droid-medical"
module_sprites["Needles"] = "medicalrobot"
- if("Surgeon")
- module = new /obj/item/weapon/robot_module/surgeon(src)
- channels = list("Medical" = 1)
- if(camera && "Robots" in camera.network)
- camera.network.Add("Medical")
-
- module_sprites["Basic"] = "Medbot"
- module_sprites["Standard"] = "surgeon"
- module_sprites["Advanced Droid"] = "droid-medical"
- module_sprites["Needles"] = "medicalrobot"
-
if("Security")
module = new /obj/item/weapon/robot_module/security(src)
channels = list("Security" = 1)
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 7a14f816197..2aa178c8ef1 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -71,10 +71,12 @@
src.emag = new /obj/item/weapon/melee/energy/sword/cyborg(src)
return
-/obj/item/weapon/robot_module/surgeon
- name = "surgeon robot module"
+/obj/item/weapon/robot_module/medical
+ name = "medical robot module"
stacktypes = list(
/obj/item/stack/medical/advanced/bruise_pack = 5,
+ /obj/item/stack/medical/advanced/ointment = 5,
+ /obj/item/stack/medical/splint = 5,
/obj/item/stack/nanopaste = 5
)
@@ -82,7 +84,18 @@
src.modules += new /obj/item/device/flashlight(src)
src.modules += new /obj/item/device/flash/cyborg(src)
src.modules += new /obj/item/device/healthanalyzer(src)
- src.modules += new /obj/item/weapon/reagent_containers/borghypo/surgeon(src)
+ src.modules += new /obj/item/device/reagent_scanner/adv(src)
+ src.modules += new /obj/item/weapon/borg_defib(src)
+ src.modules += new /obj/item/roller_holder(src)
+ src.modules += new /obj/item/weapon/reagent_containers/borghypo(src)
+ src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
+ src.modules += new /obj/item/weapon/reagent_containers/dropper(src)
+ src.modules += new /obj/item/weapon/reagent_containers/syringe(src)
+ src.modules += new /obj/item/weapon/extinguisher/mini(src)
+ src.modules += new /obj/item/stack/medical/advanced/bruise_pack(src)
+ src.modules += new /obj/item/stack/medical/advanced/ointment(src)
+ src.modules += new /obj/item/stack/medical/splint(src)
+ src.modules += new /obj/item/stack/nanopaste(src)
src.modules += new /obj/item/weapon/scalpel(src)
src.modules += new /obj/item/weapon/hemostat(src)
src.modules += new /obj/item/weapon/retractor(src)
@@ -92,9 +105,6 @@
src.modules += new /obj/item/weapon/bonesetter(src)
src.modules += new /obj/item/weapon/circular_saw(src)
src.modules += new /obj/item/weapon/surgicaldrill(src)
- src.modules += new /obj/item/weapon/extinguisher/mini(src)
- src.modules += new /obj/item/stack/medical/advanced/bruise_pack(src)
- src.modules += new /obj/item/stack/nanopaste(src)
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
@@ -102,59 +112,12 @@
src.emag.name = "Polyacid spray"
return
-/obj/item/weapon/robot_module/surgeon/respawn_consumable(var/mob/living/silicon/robot/R)
+/obj/item/weapon/robot_module/medical/respawn_consumable(var/mob/living/silicon/robot/R)
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
..()
-/obj/item/weapon/robot_module/crisis
- name = "crisis robot module"
- stacktypes = list(
- /obj/item/stack/medical/advanced/ointment = 5,
- /obj/item/stack/medical/advanced/bruise_pack = 5,
- /obj/item/stack/medical/splint = 5
- )
-
-
- New()
- src.modules += new /obj/item/device/flashlight(src)
- src.modules += new /obj/item/device/flash/cyborg(src)
- src.modules += new /obj/item/device/healthanalyzer(src)
- src.modules += new /obj/item/device/reagent_scanner/adv(src)
- src.modules += new /obj/item/roller_holder(src)
- src.modules += new /obj/item/stack/medical/advanced/ointment(src)
- src.modules += new /obj/item/stack/medical/advanced/bruise_pack(src)
- src.modules += new /obj/item/stack/medical/splint(src)
- src.modules += new /obj/item/weapon/reagent_containers/borghypo/crisis(src)
- src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
- src.modules += new /obj/item/weapon/reagent_containers/robodropper(src)
- src.modules += new /obj/item/weapon/reagent_containers/syringe(src)
- src.modules += new /obj/item/weapon/extinguisher/mini(src)
-
- src.emag = new /obj/item/weapon/reagent_containers/spray(src)
-
- src.emag.reagents.add_reagent("pacid", 250)
- src.emag.name = "Polyacid spray"
- var/obj/item/weapon/reagent_containers/spray/S = emag
- S.banned_reagents = list()
- return
-
-/obj/item/weapon/robot_module/crisis/respawn_consumable(var/mob/living/silicon/robot/R)
-
- var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules
- if(S.mode == 2)
- S.reagents.clear_reagents()
- S.mode = initial(S.mode)
- S.desc = initial(S.desc)
- S.update_icon()
-
- if(src.emag)
- var/obj/item/weapon/reagent_containers/spray/PS = src.emag
- PS.reagents.add_reagent("pacid", 2)
-
- ..()
-
/obj/item/weapon/robot_module/engineering
name = "engineering robot module"
diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm
index acf6333afce..c9dfb0cccef 100644
--- a/code/modules/mob/living/simple_animal/friendly/corgi.dm
+++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm
@@ -25,7 +25,15 @@
var/obj/item/inventory_back
var/facehugger
-/mob/living/simple_animal/corgi/Life()
+/mob/living/simple_animal/corgi/New()
+ ..()
+ regenerate_icons()
+
+/mob/living/simple_animal/corgi/Die()
+ ..()
+ regenerate_icons()
+
+/mob/living/simple_animal/corgi/revive()
..()
regenerate_icons()
@@ -33,7 +41,7 @@
user.set_machine(src)
if(user.stat) return
- var/dat = "
Inventory of [name]
"
+ var/dat = "
Inventory of [real_name]
"
if(inventory_head)
dat += " Head: [inventory_head] (Remove)"
else
@@ -85,6 +93,7 @@
SetLuminosity(0)
inventory_head.loc = src.loc
inventory_head = null
+ regenerate_icons()
else
usr << "\red There is nothing to remove from its [remove_from]."
return
@@ -92,6 +101,7 @@
if(inventory_back)
inventory_back.loc = src.loc
inventory_back = null
+ regenerate_icons()
else
usr << "\red There is nothing to remove from its [remove_from]."
return
@@ -163,6 +173,7 @@
usr.drop_item()
place_on_head(item_to_add)
+ regenerate_icons()
if("back")
if(inventory_back)
@@ -383,7 +394,7 @@
..()
/mob/living/simple_animal/corgi/regenerate_icons()
- overlays = list()
+ overlays.Cut()
if(inventory_head)
var/head_icon_state = inventory_head.icon_state
@@ -472,7 +483,7 @@
var/emagged = 0
/mob/living/simple_animal/corgi/Ian/borgi/emag_act(user as mob)
- if (!emagged)
+ if(!emagged)
emagged = 1
visible_message("[user] swipes a card through [src].", "You overload [src]s internal reactor.")
spawn (1000)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 890c953c632..800d9967ca7 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -29,6 +29,7 @@
var/response_disarm = "shoves"
var/response_harm = "hits"
var/harm_intent_damage = 3
+ var/force_threshold = 0 //Minimum force required to deal any damage
//Temperature effect
var/minbodytemp = 250
@@ -372,7 +373,6 @@
/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
if(istype(O, /obj/item/stack/medical))
-
if(stat != DEAD)
var/obj/item/stack/medical/MED = O
if(health < maxHealth)
@@ -399,20 +399,22 @@
if(istype(O, /obj/item/weapon/kitchenknife) || istype(O, /obj/item/weapon/butch))
harvest()
else
+ var/damage = 0
if(O.force)
- var/damage = O.force
- if (O.damtype == STAMINA)
- damage = 0
- adjustBruteLoss(damage)
- for(var/mob/M in viewers(src, null))
- if ((M.client && !( M.blinded )))
- M.show_message("\red \b "+"[src] has been attacked with [O] by [user]. ")
+ if(O.force >= force_threshold)
+ damage = O.force
+ if (O.damtype == STAMINA)
+ damage = 0
+ visible_message("[user] has [O.attack_verb.len ? "[pick(O.attack_verb)]": "attacked"] [src] with [O]!",\
+ "[user] has [O.attack_verb.len ? "[pick(O.attack_verb)]": "attacked"] you with [O]!")
+ else
+ visible_message("[O] bounces harmlessly off of [src].",\
+ "[O] bounces harmlessly off of [src].")
+ playsound(loc, O.hitsound, 50, 1, -1)
else
- usr << "\red This weapon is ineffective, it does no damage."
- for(var/mob/M in viewers(src, null))
- if ((M.client && !( M.blinded )))
- M.show_message("\red [user] gently taps [src] with [O]. ")
-
+ user.visible_message("[user] gently taps [src] with [O].",\
+ "This weapon is ineffective, it does no damage.")
+ adjustBruteLoss(damage)
/mob/living/simple_animal/movement_delay()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index d2d705ee960..c1d8ac51ca8 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -881,7 +881,7 @@ var/list/slot_equipment_priority = list( \
stat(null, "Bots-[master_controller.aibots_cost]\t#[aibots.len]")
stat(null, "Obj-[master_controller.objects_cost]\t#[processing_objects.len]")
stat(null, "PiNet-[master_controller.networks_cost]\t#[pipe_networks.len]")
- stat(null, "Ponet-[master_controller.powernets_cost]\t#[powernets.len]")
+ stat(null, "PoNet-[master_controller.powernets_cost]\t#[powernets.len]")
stat(null, "NanoUI-[master_controller.nano_cost]\t#[nanomanager.processing_uis.len]")
stat(null,"Events-[master_controller.events_cost]\t#[event_manager.active_events.len]")
// stat(null, "GC-[master_controller.gc_cost]\t#[garbage.queue.len]")
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index b652a106824..b5245c14a0b 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -158,6 +158,12 @@ proc/isnewplayer(A)
proc/hasorgans(A)
return ishuman(A)
+
+proc/isdeaf(A)
+ if(istype(A, /mob))
+ var/mob/M = A
+ return (M.sdisabilities & DEAF) || M.ear_deaf
+ return 0
/proc/hsl2rgb(h, s, l)
return
diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm
index bea08693fbc..399eeb1c83e 100644
--- a/code/modules/mob/mob_transformation_simple.dm
+++ b/code/modules/mob/mob_transformation_simple.dm
@@ -30,7 +30,7 @@
if(!M || !ismob(M))
usr << "Type path is not a mob (new_type = [new_type]) in change_mob_type(). Contact a coder."
- del(M)
+ qdel(M)
return
if( istext(new_name) )
@@ -43,12 +43,12 @@
if(src.dna)
M.dna = src.dna.Clone()
- if(mind)
+ if(mind && istype(M, /mob/living))
mind.transfer_to(M)
else
M.key = key
if(delete_old_mob)
spawn(1)
- del(src)
+ qdel(src)
return M
diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm
new file mode 100644
index 00000000000..c27c0446395
--- /dev/null
+++ b/code/modules/nano/modules/crew_monitor.dm
@@ -0,0 +1,88 @@
+/obj/nano_module/crew_monitor
+ name = "Crew monitor"
+ var/list/tracked = new
+
+/obj/nano_module/crew_monitor/Topic(href, href_list)
+ if(..()) return
+ var/turf/T = get_turf(src)
+ if (!T || !(T.z in config.player_levels))
+ usr << "Unable to establish a connection: You're too far away from the station!"
+ return 0
+ if(href_list["close"] )
+ var/mob/user = usr
+ var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
+ usr.unset_machine()
+ ui.close()
+ return 0
+ if(href_list["update"])
+ src.updateDialog()
+ return 1
+
+/obj/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ user.set_machine(src)
+ src.scan()
+
+ var/data[0]
+ var/turf/T = get_turf(src)
+ var/list/crewmembers = list()
+ for(var/obj/item/clothing/under/C in src.tracked)
+
+ var/turf/pos = get_turf(C)
+
+ if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF))
+ if(istype(C.loc, /mob/living/carbon/human))
+
+ var/mob/living/carbon/human/H = C.loc
+ if(H.w_uniform != C)
+ continue
+
+ var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1)
+
+ crewmemberData["sensor_type"] = C.sensor_mode
+ crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
+ crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
+ crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
+
+ if(C.sensor_mode >= SUIT_SENSOR_BINARY)
+ crewmemberData["dead"] = H.stat > 1
+
+ if(C.sensor_mode >= SUIT_SENSOR_VITAL)
+ crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
+ crewmemberData["tox"] = round(H.getToxLoss(), 1)
+ crewmemberData["fire"] = round(H.getFireLoss(), 1)
+ crewmemberData["brute"] = round(H.getBruteLoss(), 1)
+
+ if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
+ var/area/A = get_area(H)
+ crewmemberData["area"] = sanitize(A.name)
+ crewmemberData["x"] = pos.x
+ crewmemberData["y"] = pos.y
+
+ crewmembers[++crewmembers.len] = crewmemberData
+
+ crewmembers = sortByKey(crewmembers, "name")
+
+ data["crewmembers"] = crewmembers
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
+
+ // adding a template with the key "mapContent" enables the map ui functionality
+ ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
+ // adding a template with the key "mapHeader" replaces the map header content
+ ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
+
+ ui.set_initial_data(data)
+ ui.open()
+
+ // should make the UI auto-update; doesn't seem to?
+ ui.set_auto_update(1)
+
+/obj/nano_module/crew_monitor/proc/scan()
+ for(var/mob/living/carbon/human/H in mob_list)
+ if(istype(H.w_uniform, /obj/item/clothing/under))
+ var/obj/item/clothing/under/C = H.w_uniform
+ if (C.has_sensor)
+ tracked |= C
+ return 1
diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm
index 2ce8de3b08b..36241b2ec75 100644
--- a/code/modules/nano/nanomanager.dm
+++ b/code/modules/nano/nanomanager.dm
@@ -1,8 +1,9 @@
// This is the window/UI manager for Nano UI
// There should only ever be one (global) instance of nanomanger
/datum/nanomanager
- // the list of current open /nanoui UIs
+ // a list of current open /nanoui UIs, grouped by src_object and ui_key
var/open_uis[0]
+ // a list of current open /nanoui UIs, not grouped, for use in processing
var/list/processing_uis = list()
// a list of asset filenames which are to be sent to the client on user logon
var/list/asset_files = list()
@@ -26,7 +27,8 @@
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
- asset_files.Add(file(path + filename)) // add this file to asset_files for sending to clients when they connect
+ if(fexists(path + filename))
+ asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
return
@@ -85,7 +87,7 @@
/**
* Update all /nanoui uis attached to src_object
*
- * @param src_object /obj|/mob The obj or mob which the uis belong to
+ * @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis updated
*/
@@ -97,7 +99,7 @@
var/update_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
- if(ui && ui.src_object && ui.user)
+ if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.process(1)
update_count++
return update_count
@@ -245,4 +247,3 @@
for(var/file in asset_files)
client << browse_rsc(file) // send the file to the client
- return 1 // success
diff --git a/code/modules/nano/nanoprocs.dm b/code/modules/nano/nanoprocs.dm
new file mode 100644
index 00000000000..81b939cf5c4
--- /dev/null
+++ b/code/modules/nano/nanoprocs.dm
@@ -0,0 +1,11 @@
+/atom/movable/proc/nano_host()
+ return src
+
+/obj/nano_module/nano_host()
+ return loc
+
+/atom/movable/proc/nano_can_update()
+ return 1
+
+/obj/machinery/nano_can_update()
+ return !(stat & (NOPOWER|BROKEN))
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index 01792ad0c3d..6b37eb96948 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -6,11 +6,6 @@ nanoui class (or whatever Byond calls classes)
nanoui is used to open and update nano browser uis
**********************************************************/
-
-#define STATUS_INTERACTIVE 2 // GREEN Visability
-#define STATUS_UPDATE 1 // ORANGE Visability
-#define STATUS_DISABLED 0 // RED Visability
-
/datum/nanoui
// the user who opened this ui
var/mob/user
@@ -143,36 +138,122 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/update_status(var/push_update = 0)
- if (istype(user, /mob/living/silicon/ai))
- set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility)
- else if (istype(user, /mob/living/silicon/robot))
- if (src_object in view(7, user)) // robots can see and interact with things they can see within 7 tiles
- set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility)
- else
- set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
+ var/atom/movable/host = src_object.nano_host()
+ if(!host.nano_can_update())
+ close()
+ return
+
+ var/status = user.can_interact_with_interface(host.nano_host())
+ if(status == STATUS_CLOSE)
+ close()
else
- var/dist = get_dist(src_object, user)
+ set_status(status, push_update)
+
+/*
+ Procs called by update_status()
+*/
- if (dist > 4)
- close()
- return
+/mob/living/silicon/pai/can_interact_with_interface(src_object)
+ if(src_object == src && !stat)
+ return STATUS_INTERACTIVE
+ else
+ return ..()
- if ((allowed_user_stat > -1) && (user.stat > allowed_user_stat))
- set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
- else if (user.restrained() || user.lying)
- set_status(STATUS_UPDATE, push_update) // update only (orange visibility)
- else if (istype(src_object, /obj/item/device/uplink/hidden)) // You know what if they have the uplink open let them use the UI
- set_status(STATUS_INTERACTIVE, push_update) // Will build in distance checks on the topics for sanity.
- else if (!(src_object in view(4, user))) // If the src object is not in visable, set status to 0
- set_status(STATUS_DISABLED, push_update) // interactive (green visibility)
- else if (dist <= 1)
- set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility)
- else if (dist <= 2)
- set_status(STATUS_UPDATE, push_update) // update only (orange visibility)
- else if (istype(src_object, /obj/item/device/uplink/hidden)) // You know what if they have the uplink open let them use the UI
- set_status(STATUS_INTERACTIVE, push_update) // Will build in distance checks on the topics for sanity.
- else if (dist <= 4)
- set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
+/mob/proc/can_interact_with_interface(var/src_object)
+ return STATUS_CLOSE // By default no mob can do anything with NanoUI
+
+/mob/dead/observer/can_interact_with_interface()
+ if(check_rights(R_ADMIN, 0))
+ return STATUS_INTERACTIVE // Admins are more equal
+ return STATUS_UPDATE // Ghosts can view updates
+
+/mob/living/silicon/robot/can_interact_with_interface(var/src_object)
+ if(stat || !client)
+ return STATUS_CLOSE
+ if(lockcharge || stunned || weakened)
+ return STATUS_DISABLED
+ if (src_object in view(client.view, src)) // robots can see and interact with things they can see within their view range
+ return STATUS_INTERACTIVE // interactive (green visibility)
+ return STATUS_DISABLED // no updates, completely disabled (red visibility)
+
+/mob/living/silicon/robot/syndicate/can_interact_with_interface(var/src_object)
+ . = ..()
+ if(. != STATUS_INTERACTIVE)
+ return
+
+ if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
+ return STATUS_INTERACTIVE
+ if(istype(get_area(src), /area/syndicate_station) || istype(get_area(src), /area/traitor)) // If elsewhere, they can interact with everything on the syndicate shuttle and traitor station
+ return STATUS_INTERACTIVE
+ if(istype(src_object, /obj/machinery)) // And they can also interact with everything else
+ /*var/obj/machinery/Machine = src_object
+ if(Machine.emagged) // Uncomment so they can only interact with emagged machinery
+ return STATUS_INTERACTIVE*/
+ return STATUS_INTERACTIVE
+ return STATUS_UPDATE
+
+/mob/living/silicon/ai/can_interact_with_interface(var/src_object)
+ if(!client || check_unable(1))
+ return STATUS_CLOSE
+ // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
+ // unless it's on the same level as the object it's interacting with.
+ var/turf/T = get_turf(src_object)
+ if(!T || !(z == T.z || (T.z in config.player_levels)))
+ return STATUS_CLOSE
+
+ // If an object is in view then we can interact with it
+ if(src_object in view(client.view, src))
+ return STATUS_INTERACTIVE
+
+ // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
+ if(is_in_chassis())
+ //stop AIs from leaving windows open and using then after they lose vision
+ //apc_override is needed here because AIs use their own APC when powerless
+ if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
+ return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
+ return STATUS_INTERACTIVE
+
+ return STATUS_CLOSE
+
+/mob/living/proc/shared_living_nano_interaction(var/src_object)
+ if (src.stat != CONSCIOUS)
+ return STATUS_CLOSE // no updates, close the interface
+ else if (restrained() || lying || stat || stunned || weakened)
+ return STATUS_UPDATE // update only (orange visibility)
+ return STATUS_INTERACTIVE
+
+/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
+ if(!isturf(src_object.loc))
+ if(src_object.loc == src) // Item in the inventory
+ return STATUS_INTERACTIVE
+ if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
+ return STATUS_INTERACTIVE
+
+ if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
+ return STATUS_CLOSE
+
+ var/dist = get_dist(src_object, src)
+ if (dist <= 1)
+ return STATUS_INTERACTIVE // interactive (green visibility)
+ else if (dist <= 2)
+ return STATUS_UPDATE // update only (orange visibility)
+ else if (dist <= 4)
+ return STATUS_DISABLED // no updates, completely disabled (red visibility)
+ return STATUS_CLOSE
+
+/mob/living/can_interact_with_interface(var/src_object, var/be_close = 1)
+ . = shared_living_nano_interaction(src_object)
+ if(. == STATUS_INTERACTIVE && be_close)
+ . = shared_living_nano_distance(src_object)
+ if(STATUS_INTERACTIVE)
+ return STATUS_UPDATE
+
+/mob/living/carbon/human/can_interact_with_interface(var/src_object, var/be_close = 1)
+ . = shared_living_nano_interaction(src_object)
+ if(. == STATUS_INTERACTIVE && be_close)
+ . = shared_living_nano_distance(src_object)
+ if(. == STATUS_UPDATE && (M_TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
+ return STATUS_INTERACTIVE
/**
* Set the ui to auto update (every master_controller tick)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 15699572da4..2e09cd993a9 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -942,7 +942,7 @@
malfai.malfhacking = 0
locked = 1
if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ if ((src.z in config.station_levels)) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs++
if(usr:parent)
src.malfai = usr:parent
@@ -974,7 +974,7 @@
if(malfai)
if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ if ((src.z in config.station_levels)) //if (is_type_in_list(get_area(src), the_station_areas))
operating ? ticker.mode:apcs++ : ticker.mode:apcs--
src.update()
@@ -989,7 +989,7 @@
if(!malf.can_shunt)
malf << "You cannot shunt."
return
- if(src.z != 1)
+ if(!(src.z in config.station_levels))
return
src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1)
src.occupant.adjustOxyLoss(malf.getOxyLoss())
@@ -1038,7 +1038,7 @@
/obj/machinery/power/apc/proc/ion_act()
//intended to be exactly the same as an AI malf attack
- if(!src.malfhack && src.z == 1)
+ if(!src.malfhack && (src.z in config.station_levels))
if(prob(3))
src.locked = 1
if (src.cell.charge > 0)
@@ -1307,7 +1307,7 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
/obj/machinery/power/apc/proc/set_broken()
if(malfai && operating)
if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ if ((src.z in config.station_levels)) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs--
stat |= BROKEN
operating = 0
@@ -1333,7 +1333,7 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
/obj/machinery/power/apc/Destroy()
if(malfai && operating)
if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ if ((src.z in config.station_levels)) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs--
area.power_light = 0
area.power_equip = 0
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index df04bacdc70..c9ac32da530 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -123,7 +123,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
O.main_part = null
qdel(O)
for(var/area/A in world)
- if (A.z != 1) continue
+ if (!(A.z in config.station_levels)) continue
A.gravitychange(0,A)
shake_everyone()
..()
@@ -294,7 +294,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
message_admins("The gravity generator was brought online. ([area.name])")
for(var/area/A in world)
- if (A.z != 1) continue
+ if (!(A.z in config.station_levels)) continue
A.gravitychange(1,A)
else
if(gravity_in_level() == 1)
@@ -302,7 +302,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
message_admins("The gravity generator was brought offline with no backup generator. ([area.name])")
for(var/area/A in world)
- if (A.z != 1) continue
+ if (!(A.z in config.station_levels)) continue
A.gravitychange(0,A)
update_icon()
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index a3065ce3bb4..3fe245d34dd 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -421,7 +421,7 @@
/obj/machinery/power/smes/proc/ion_act()
- if(src.z == 1)
+ if((src.z in config.station_levels))
if(prob(1)) //explosion
world << "\red SMES explosion in [src.loc.loc]"
for(var/mob/M in viewers(src))
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index 9c622e47ca9..b8356cacc34 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -1,20 +1,8 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
-
#define SOLAR_MAX_DIST 40
#define SOLARGENRATE 1500
var/list/solars_list = list()
-// This will choose whether to get the solar list from the powernet or the powernet nodes,
-// depending on the size of the nodes.
-/obj/machinery/power/proc/get_solars_powernet()
- if(!powernet)
- return list()
- if(solars_list.len < powernet.nodes)
- return solars_list
- else
- return powernet.nodes
-
/obj/machinery/power/solar
name = "solar panel"
desc = "A solar electrical generator."
@@ -22,7 +10,6 @@ var/list/solars_list = list()
icon_state = "sp_base"
anchored = 1
density = 1
- directwired = 1
use_power = 0
idle_power_usage = 0
active_power_usage = 0
@@ -30,26 +17,33 @@ var/list/solars_list = list()
var/health = 10
var/obscured = 0
var/sunfrac = 0
- var/adir = SOUTH
- var/ndir = SOUTH
+ var/adir = SOUTH // actual dir
+ var/ndir = SOUTH // target dir
var/turn_angle = 0
var/obj/machinery/power/solar_control/control = null
-/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S, var/process = 1)
+/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
Make(S)
- connect_to_network(process)
+ connect_to_network()
-
-/obj/machinery/power/solar/disconnect_from_network()
+/obj/machinery/power/solar/Destroy()
+ unset_control() //remove from control computer
..()
- solars_list.Remove(src)
-/obj/machinery/power/solar/connect_to_network(var/process)
- ..()
- if(process)
- solars_list.Add(src)
+//set the control of the panel to a given computer if closer than SOLAR_MAX_DIST
+/obj/machinery/power/solar/proc/set_control(var/obj/machinery/power/solar_control/SC)
+ if(!SC || (get_dist(src, SC) > SOLAR_MAX_DIST))
+ return 0
+ control = SC
+ SC.connected_panels |= src
+ return 1
+//set the control of the panel to null and removes it from the control list of the previous control computer if needed
+/obj/machinery/power/solar/proc/unset_control()
+ if(control)
+ control.connected_panels.Remove(src)
+ control = null
/obj/machinery/power/solar/proc/Make(var/obj/item/solar_assembly/S)
if(!S)
@@ -57,22 +51,25 @@ var/list/solars_list = list()
S.glass_type = /obj/item/stack/sheet/glass
S.anchored = 1
S.loc = src
+ if(S.glass_type == /obj/item/stack/sheet/rglass) //if the panel is in reinforced glass
+ health *= 2 //this need to be placed here, because panels already on the map don't have an assembly linked to
update_icon()
/obj/machinery/power/solar/attackby(obj/item/weapon/W, mob/user)
- if(iscrowbar(W))
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ if(istype(W, /obj/item/weapon/crowbar))
+ playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ user.visible_message("[user] begins to take the glass off the solar panel.")
if(do_after(user, 50))
var/obj/item/solar_assembly/S = locate() in src
if(S)
S.loc = src.loc
S.give_glass()
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] takes the glass off the solar panel.")
- del(src)
+ qdel(src)
return
else if (W)
src.add_fingerprint(user)
@@ -92,9 +89,9 @@ var/list/solars_list = list()
if(!(stat & BROKEN))
broken()
else
- getFromPool(/obj/item/weapon/shard, loc)
- getFromPool(/obj/item/weapon/shard, loc)
- del(src)
+ new /obj/item/weapon/shard(src.loc)
+ new /obj/item/weapon/shard(src.loc)
+ qdel(src)
return
return
@@ -109,70 +106,58 @@ var/list/solars_list = list()
src.dir = angle2dir(adir)
return
-
+//calculates the fraction of the sunlight that the panel recieves
/obj/machinery/power/solar/proc/update_solar_exposure()
if(!sun)
return
if(obscured)
sunfrac = 0
return
- var/p_angle = abs((360+adir)%360 - (360+sun.angle)%360)
+
+ //find the smaller angle between the direction the panel is facing and the direction of the sun (the sign is not important here)
+ var/p_angle = min(abs(adir - sun.angle), 360 - abs(adir - sun.angle))
+
if(p_angle > 90) // if facing more than 90deg from sun, zero output
sunfrac = 0
return
- sunfrac = cos(p_angle) ** 2
+ sunfrac = cos(p_angle) ** 2
+ //isn't the power recieved from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
/obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
- if(stat & BROKEN) return
- if(!control) return
+ if(stat & BROKEN)
+ return
+ if(!sun || !control) //if there's no sun or the panel is not linked to a solar control computer, no need to proceed
+ return
- if(adir != ndir)
- adir = (360+adir+dd_range(-10,10,ndir-adir))%360
- update_icon()
- update_solar_exposure()
-
- if(obscured) return
-
- var/sgen = SOLARGENRATE * sunfrac
- add_avail(sgen)
- if(powernet && control)
- if(powernet.nodes[control])
+ if(powernet)
+ if(powernet == control.powernet)//check if the panel is still connected to the computer
+ if(obscured) //get no light from the sun, so don't generate power
+ return
+ var/sgen = SOLARGENRATE * sunfrac
+ add_avail(sgen)
control.gen += sgen
-
+ else //if we're no longer on the same powernet, remove from control computer
+ unset_control()
/obj/machinery/power/solar/proc/broken()
+ . = (!(stat & BROKEN))
stat |= BROKEN
+ unset_control()
update_icon()
return
-/obj/machinery/power/solar/meteorhit()
- if(stat & !BROKEN)
- broken()
- else
- del(src)
-
-
-/obj/machinery/power/solar/ex_act(severity)
- switch(severity)
- if(1.0)
- qdel(src)
- if(prob(15))
- getFromPool(/obj/item/weapon/shard, loc)
- return
- if(2.0)
- if (prob(25))
- getFromPool(/obj/item/weapon/shard, loc)
- qdel(src)
- return
- if (prob(50))
- broken()
- if(3.0)
- if (prob(25))
- broken()
- return
-
+/obj/machinery/power/solar/ex_act(severity, target)
+ ..()
+ if(!gc_destroyed)
+ switch(severity)
+ if(2)
+ if(prob(50) && broken())
+ new /obj/item/weapon/shard(src.loc)
+ if(3)
+ if(prob(25) && broken())
+ new /obj/item/weapon/shard(src.loc)
/obj/machinery/power/solar/blob_act()
if(prob(75))
@@ -187,6 +172,29 @@ var/list/solars_list = list()
. = PROCESS_KILL
return
+//trace towards sun to see if we're in shadow
+/obj/machinery/power/solar/proc/occlusion()
+
+ var/ax = x // start at the solar panel
+ var/ay = y
+ var/turf/T = null
+
+ for(var/i = 1 to 20) // 20 steps is enough
+ ax += sun.dx // do step
+ ay += sun.dy
+
+ T = locate( round(ax,0.5),round(ay,0.5),z)
+
+ if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) // not obscured if we reach the edge
+ break
+
+ if(T.density) // if we hit a solid turf, panel is obscured
+ obscured = 1
+ return
+
+ obscured = 0 // if hit the edge or stepped 20 times, not obscured
+ update_solar_exposure()
+
//
// Solar Assembly - For construction of solar arrays.
@@ -218,40 +226,42 @@ var/list/solars_list = list()
/obj/item/solar_assembly/attackby(var/obj/item/weapon/W, var/mob/user)
if(!anchored && isturf(loc))
- if(iswrench(W))
+ if(istype(W, /obj/item/weapon/wrench))
anchored = 1
user.visible_message("[user] wrenches the solar assembly into place.")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
return 1
else
- if(iswrench(W))
+ if(istype(W, /obj/item/weapon/wrench))
anchored = 0
user.visible_message("[user] unwrenches the solar assembly from it's place.")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
return 1
if(istype(W, /obj/item/stack/sheet/glass) || istype(W, /obj/item/stack/sheet/rglass))
var/obj/item/stack/sheet/S = W
- if(S.amount >= 2)
+ if(S.use(2))
glass_type = W.type
- S.use(2)
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
user.visible_message("[user] places the glass on the solar assembly.")
if(tracker)
new /obj/machinery/power/tracker(get_turf(src), src)
else
new /obj/machinery/power/solar(get_turf(src), src)
+ else
+ user << "You need two sheets of glass to put them into a solar panel."
+ return
return 1
if(!tracker)
if(istype(W, /obj/item/weapon/tracker_electronics))
tracker = 1
user.drop_item()
- del(W)
+ qdel(W)
user.visible_message("[user] inserts the electronics into the solar assembly.")
return 1
else
- if(iscrowbar(W))
+ if(istype(W, /obj/item/weapon/crowbar))
new /obj/item/weapon/tracker_electronics(src.loc)
tracker = 0
user.visible_message("[user] takes out the electronics from the solar assembly.")
@@ -269,18 +279,18 @@ var/list/solars_list = list()
icon_state = "solar"
anchored = 1
density = 1
- directwired = 1
use_power = 1
- idle_power_usage = 5
- active_power_usage = 20
+ idle_power_usage = 250
var/id = 0
var/cdir = 0
+ var/targetdir = 0 // target angle in manual tracking (since it updates every game minute)
var/gen = 0
var/lastgen = 0
- var/track = 0 // 0=off 1=manual 2=automatic
- var/trackrate = 60 // Measured in tenths of degree per minute (i.e. defaults to 6.0 deg/min)
- var/trackdir = 1 // -1=CCW, 1=CW
- var/nexttime = 0 // Next clock time that manual tracking will move the array
+ var/track = 0 // 0= off 1=timed 2=auto (tracker)
+ var/trackrate = 600 // 300-900 seconds
+ var/nexttime = 0 // time for a panel to rotate of 1� in manual tracking
+ var/obj/machinery/power/tracker/connected_tracker = null
+ var/list/connected_panels = list()
/obj/machinery/power/solar_control/New()
@@ -289,14 +299,53 @@ var/list/solars_list = list()
initialize()
connect_to_network()
+/obj/machinery/power/solar_control/Destroy()
+ for(var/obj/machinery/power/solar/M in connected_panels)
+ M.unset_control()
+ if(connected_tracker)
+ connected_tracker.unset_control()
+ ..()
+
/obj/machinery/power/solar_control/disconnect_from_network()
..()
solars_list.Remove(src)
/obj/machinery/power/solar_control/connect_to_network()
- ..()
+ var/to_return = ..()
+ if(powernet) //if connected and not already in solar_list...
+ solars_list |= src //... add it
+ return to_return
+
+//search for unconnected panels and trackers in the computer powernet and connect them
+/obj/machinery/power/solar_control/proc/search_for_connected()
if(powernet)
- solars_list.Add(src)
+ for(var/obj/machinery/power/M in powernet.nodes)
+ if(istype(M, /obj/machinery/power/solar))
+ var/obj/machinery/power/solar/S = M
+ if(!S.control) //i.e unconnected
+ S.set_control(src)
+ else if(istype(M, /obj/machinery/power/tracker))
+ if(!connected_tracker) //if there's already a tracker connected to the computer don't add another
+ var/obj/machinery/power/tracker/T = M
+ if(!T.control) //i.e unconnected
+ T.set_control(src)
+
+//called by the sun controller, update the facing angle (either manually or via tracking) and rotates the panels accordingly
+/obj/machinery/power/solar_control/proc/update()
+ if(stat & (NOPOWER | BROKEN))
+ return
+
+ switch(track)
+ if(1)
+ if(trackrate) //we're manual tracking. If we set a rotation speed...
+ cdir = targetdir //...the current direction is the targetted one (and rotates panels to it)
+ if(2) // auto-tracking
+ if(connected_tracker)
+ connected_tracker.set_angle(sun.angle)
+
+ set_panels(cdir)
+ updateDialog()
+
/obj/machinery/power/solar_control/initialize()
..()
@@ -314,32 +363,47 @@ var/list/solars_list = list()
return
icon_state = "solar"
overlays.Cut()
- if(cdir > 0)
+ if(cdir > -1)
overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir))
return
-
-/obj/machinery/power/solar_control/attack_ai(mob/user)
- src.add_hiddenprint(user)
- add_fingerprint(user)
- if(stat & (BROKEN | NOPOWER)) return
- interact(user)
-
-
/obj/machinery/power/solar_control/attack_hand(mob/user)
- add_fingerprint(user)
- if(stat & (BROKEN | NOPOWER)) return
- interact(user)
+ if(!..())
+ ui_interact(user)
+/obj/machinery/power/solar_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+
+ var/data = list()
+
+ data["generated"] = round(lastgen)
+ data["angle"] = cdir
+ data["direction"] = angle2text(cdir)
+
+ data["tracking_state"] = track
+ data["tracking_rate"] = trackrate
+ data["rotating_way"] = (trackrate<0 ? "CCW" : "CW")
+
+ data["connected_panels"] = connected_panels.len
+ data["connected_tracker"] = (connected_tracker ? 1 : 0)
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "solar_control.tmpl", name, 490, 420)
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
+ else
+ ui.push_data(data)
+ return
/obj/machinery/power/solar_control/attackby(I as obj, user as mob)
if(istype(I, /obj/item/weapon/screwdriver))
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
if (src.stat & BROKEN)
- user << "\blue The broken glass falls out."
+ user << "The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
- getFromPool(/obj/item/weapon/shard, loc)
+ new /obj/item/weapon/shard( src.loc )
var/obj/item/weapon/circuitboard/solar_control/M = new /obj/item/weapon/circuitboard/solar_control( A )
for (var/obj/C in src)
C.loc = src.loc
@@ -347,9 +411,9 @@ var/list/solars_list = list()
A.state = 3
A.icon_state = "3"
A.anchored = 1
- del(src)
+ qdel(src)
else
- user << "\blue You disconnect the monitor."
+ user << "You disconnect the monitor."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
var/obj/item/weapon/circuitboard/solar_control/M = new /obj/item/weapon/circuitboard/solar_control( A )
for (var/obj/C in src)
@@ -358,12 +422,11 @@ var/list/solars_list = list()
A.state = 4
A.icon_state = "4"
A.anchored = 1
- del(src)
+ qdel(src)
else
src.attack_hand(user)
return
-
/obj/machinery/power/solar_control/process()
lastgen = gen
gen = 0
@@ -371,139 +434,64 @@ var/list/solars_list = list()
if(stat & (NOPOWER | BROKEN))
return
- use_power(250)
- if(track==1 && nexttime < world.time && trackdir*trackrate)
- // Increments nexttime using itself and not world.time to prevent drift
- nexttime = nexttime + 6000/trackrate
- // Nudges array 1 degree in desired direction
- cdir = (cdir+trackdir+360)%360
- set_panels(cdir)
- update_icon()
-
- src.updateDialog()
-
-
-// called by solar tracker when sun position changes
-/obj/machinery/power/solar_control/proc/tracker_update(var/angle)
- if(track != 2 || stat & (NOPOWER | BROKEN))
- return
- cdir = angle
- set_panels(cdir)
- update_icon()
- src.updateDialog()
-
-
-/obj/machinery/power/solar_control/interact(mob/user)
- if(stat & (BROKEN | NOPOWER)) return
- if ( (get_dist(src, user) > 1 ))
- if (!istype(user, /mob/living/silicon/ai))
- user.unset_machine()
- user << browse(null, "window=solcon")
- return
-
- add_fingerprint(user)
- user.set_machine(src)
-
-
- // AUTOFIXED BY fix_string_idiocy.py
- // C:\Users\Rob\Documents\Projects\vgstation13\code\modules\power\solar.dm:407: var/t = "Solar Generator Control
"
- var/t = {"Solar Generator Control
-Generated power : [round(lastgen)] W
-Station Rotational Period: [60/abs(sun.rate)] minutes
-Station Rotational Direction: [sun.rate<0 ? "CCW" : "CW"]
-Star Orientation: [sun.angle]° ([angle2text(sun.angle)])
-Array Orientation: [rate_control(src,"cdir","[cdir]°",1,10,60)] ([angle2text(cdir)])
-
-Tracking:"}
- // END AUTOFIX
- switch(track)
- if(0)
- t += "OffManualAutomatic "
- if(1)
- t += "OffManualAutomatic "
- if(2)
- t += "OffManualAutomatic "
-
-
- // AUTOFIXED BY fix_string_idiocy.py
- // C:\Users\Rob\Documents\Projects\vgstation13\code\modules\power\solar.dm:423: t += "Manual Tracking Rate: [rate_control(src,"tdir","[trackrate/10]°/min ([trackdir<0 ? "CCW" : "CW"])",1,10)] "
- t += {"Manual Tracking Rate: [rate_control(src,"tdir","[trackrate/10]°/min ([trackdir<0 ? "CCW" : "CW"])",1,10)]
-Manual Tracking Direction:"}
- // END AUTOFIX
- switch(trackdir)
- if(-1)
- t += "CWCCW "
- if(1)
- t += "CWCCW "
- t += "Close
"
- user << browse(t, "window=solcon")
- onclose(user, "solcon")
- return
+ if(connected_tracker) //NOTE : handled here so that we don't add trackers to the processing list
+ if(connected_tracker.powernet != powernet)
+ connected_tracker.unset_control()
+ if(track==1 && trackrate) //manual tracking and set a rotation speed
+ if(nexttime <= world.time) //every time we need to increase/decrease the angle by 1�...
+ targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
+ nexttime += 36000/abs(trackrate) //reset the counter for the next 1�
/obj/machinery/power/solar_control/Topic(href, href_list)
if(..())
- usr << browse(null, "window=solcon")
- usr.unset_machine()
return
- if(href_list["close"] )
- usr << browse(null, "window=solcon")
- usr.unset_machine()
- return
-
- if(href_list["dir"])
- cdir = text2num(href_list["dir"])
- set_panels(cdir)
- update_icon()
-
- if(href_list["rate control"])
+
+ 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)
set_panels(cdir)
- update_icon()
if(href_list["tdir"])
- src.trackrate = dd_range(0,360,src.trackrate+text2num(href_list["tdir"]))
- if(src.trackrate) nexttime = world.time + 6000/trackrate
+ src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
+ if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
if(href_list["track"])
- if(src.trackrate) nexttime = world.time + 6000/trackrate
track = text2num(href_list["track"])
- if(powernet && (track == 2))
- if(!solars_list.Find(src,1,0) || !(locate(src) in solars_list) || !(src in solars_list))
- solars_list.Add(src)
- for(var/obj/machinery/power/tracker/T in get_solars_powernet())
- if(powernet.nodes[T])
- cdir = T.sun_angle
- break
+ if(track == 2)
+ if(connected_tracker)
+ connected_tracker.set_angle(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["trackdir"])
- trackdir = text2num(href_list["trackdir"])
+ if(href_list["search_connected"])
+ search_for_connected()
+ if(connected_tracker && track == 2)
+ connected_tracker.set_angle(sun.angle)
+ set_panels(cdir)
- set_panels(cdir)
- update_icon()
- src.updateUsrDialog()
return
-
+//rotates the panel to the passed angle
/obj/machinery/power/solar_control/proc/set_panels(var/cdir)
- if(!powernet) return
- for(var/obj/machinery/power/solar/S in get_solars_powernet())
- if(powernet.nodes[S])
- if(get_dist(S, src) < SOLAR_MAX_DIST)
- if(!S.control)
- S.control = src
- S.ndir = cdir
+
+ for(var/obj/machinery/power/solar/S in connected_panels)
+ S.adir = cdir //instantly rotates the panel
+ S.occlusion()//and
+ S.update_icon() //update it
+
+ update_icon()
/obj/machinery/power/solar_control/power_change()
- if(powered())
- stat &= ~NOPOWER
- update_icon()
- else
- spawn(rand(0, 15))
- stat |= NOPOWER
- update_icon()
+ ..()
+ update_icon()
/obj/machinery/power/solar_control/proc/broken()
@@ -511,25 +499,16 @@ Manual Tracking Direction:"}
update_icon()
-/obj/machinery/power/solar_control/meteorhit()
- broken()
- return
-
-
-/obj/machinery/power/solar_control/ex_act(severity)
- switch(severity)
- if(1.0)
- //SN src = null
- qdel(src)
- return
- if(2.0)
- if (prob(50))
- broken()
- if(3.0)
- if (prob(25))
- broken()
- return
-
+/obj/machinery/power/solar_control/ex_act(severity, target)
+ ..()
+ if(!gc_destroyed)
+ switch(severity)
+ if(2)
+ if(prob(50))
+ broken()
+ if(3)
+ if(prob(25))
+ broken()
/obj/machinery/power/solar_control/blob_act()
if (prob(75))
@@ -543,4 +522,4 @@ Manual Tracking Direction:"}
/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 plasma! 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 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 sun's movements and to send commands to the solar panels to change direction with the 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!
"
+ 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 plasma! 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 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 sun's movements and to send commands to the solar panels to change direction with the 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!
"
\ No newline at end of file
diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm
index d35cf81ed45..5cf341f9fbb 100644
--- a/code/modules/power/tracker.dm
+++ b/code/modules/power/tracker.dm
@@ -10,78 +10,70 @@
icon_state = "tracker"
anchored = 1
density = 1
- directwired = 1
use_power = 0
+ var/id = 0
var/sun_angle = 0 // sun angle as set by sun datum
+ var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/tracker/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
+ Make(S)
+ connect_to_network()
+
+/obj/machinery/power/tracker/Destroy()
+ unset_control() //remove from control computer
+ ..()
+
+//set the control of the tracker to a given computer if closer than SOLAR_MAX_DIST
+/obj/machinery/power/tracker/proc/set_control(var/obj/machinery/power/solar_control/SC)
+ if(!SC || (get_dist(src, SC) > SOLAR_MAX_DIST))
+ return 0
+ control = SC
+ SC.connected_tracker = src
+ return 1
+
+//set the control of the tracker to null and removes it from the previous control computer if needed
+/obj/machinery/power/tracker/proc/unset_control()
+ if(control)
+ control.connected_tracker = null
+ control = null
+
+/obj/machinery/power/tracker/proc/Make(var/obj/item/solar_assembly/S)
if(!S)
S = new /obj/item/solar_assembly(src)
S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1
S.anchored = 1
S.loc = src
- connect_to_network()
+ update_icon()
-/obj/machinery/power/tracker/disconnect_from_network()
- ..()
- solars_list.Remove(src)
-
-/obj/machinery/power/tracker/connect_to_network()
- ..()
- solars_list.Add(src)
-
-// called by datum/sun/calc_position() as sun's angle changes
+//updates the tracker icon and the facing angle for the control computer
/obj/machinery/power/tracker/proc/set_angle(var/angle)
sun_angle = angle
//set icon dir to show sun illumination
dir = turn(NORTH, -angle - 22.5) // 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST
- // check we can draw power
- if(stat & NOPOWER)
- return
-
- // find all solar controls and update them
- // currently, just update all controllers in world
- // ***TODO: better communication system using network
- if(powernet)
- for(var/obj/machinery/power/solar_control/C in get_solars_powernet())
- if(powernet.nodes[C])
- if(get_dist(C, src) < SOLAR_MAX_DIST)
- C.tracker_update(angle)
-
+ if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet
+ control.cdir = angle
/obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user)
- if(iscrowbar(W))
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ if(istype(W, /obj/item/weapon/crowbar))
+ playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ user.visible_message("[user] begins to take the glass off the solar tracker.")
if(do_after(user, 50))
var/obj/item/solar_assembly/S = locate() in src
if(S)
S.loc = src.loc
S.give_glass()
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] takes the glass off the tracker.")
- del(src)
+ qdel(src)
return
..()
-// timed process
-// make sure we can draw power from the powernet
-/obj/machinery/power/tracker/process()
-
- var/avail = surplus()
-
- if(avail > 500)
- add_load(500)
- stat &= ~NOPOWER
- else
- stat |= NOPOWER
-
-
// Tracker Electronic
/obj/item/weapon/tracker_electronics
diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm
index 31d68ef7b15..27fec314272 100644
--- a/code/modules/reagents/reagent_containers/borghydro.dm
+++ b/code/modules/reagents/reagent_containers/borghydro.dm
@@ -68,14 +68,14 @@
var/datum/reagents/R = reagent_list[reagent_list.len]
R.add_reagent(reagent, 30)
-/obj/item/weapon/reagent_containers/borghypo/attack(mob/M as mob, mob/user as mob)
+/obj/item/weapon/reagent_containers/borghypo/attack(mob/living/M as mob, mob/user as mob)
var/datum/reagents/R = reagent_list[mode]
if(!R.total_volume)
user << "\red The injector is empty."
return
- if (!( istype(M, /mob) ))
+ if (!(istype(M)))
return
- if (R.total_volume)
+ if (R.total_volume && M.can_inject(user,1))
user << "\blue You inject [M] with the injector."
M << "\red You feel a tiny prick!"
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 3c4469f1859..d22d31ceeae 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -52,7 +52,7 @@
req_tech = list("programming" = 2, "biotech" = 2, "magnets" = 2)
build_type = PROTOLATHE
materials = list("$metal" = 30, "$glass" = 20)
- reliability_base = 74
+ reliability_base = 76
build_path = /obj/item/device/robotanalyzer
category = list("Medical")
@@ -77,6 +77,17 @@
build_path = /obj/item/weapon/implantcase/freedom
category = list("Medical")
+/datum/design/sensor_device
+ name = "Handheld Crew Monitor"
+ desc = "A device for tracking crew members on the station."
+ id = "sensor_device"
+ req_tech = list("biotech" = 4, "magnets" = 3, "materials" = 3)
+ build_type = PROTOLATHE
+ materials = list("$metal" = 30, "$glass" = 20)
+ reliability_base = 76
+ build_path = /obj/item/device/sensor_device
+ category = list("Medical")
+
/datum/design/implanter
name = "Implanter"
desc = "A basic implanter for injecting implants"
diff --git a/code/modules/security levels/security levels.dm b/code/modules/security levels/security levels.dm
index b85d9589209..5ac35d1188e 100644
--- a/code/modules/security levels/security levels.dm
+++ b/code/modules/security levels/security levels.dm
@@ -7,6 +7,8 @@
//5 = code delta
//config.alert_desc_blue_downto
+/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg'))
+/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1)
/proc/set_security_level(var/level)
switch(level)
@@ -27,40 +29,35 @@
if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level)
switch(level)
if(SEC_LEVEL_GREEN)
- world << "Attention! Security level lowered to green."
- world << "All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced."
+ security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.")
security_level = SEC_LEVEL_GREEN
for(var/obj/machinery/firealarm/FA in world)
- if(FA.z == 1 || FA.z == 5)
+ if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
if(SEC_LEVEL_BLUE)
if(security_level < SEC_LEVEL_BLUE)
- world << "Attention! Security level elevated to blue."
- world << "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted."
+ security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.")
else
- world << "Attention! Security level lowered to blue."
- world << "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed."
+ security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.")
security_level = SEC_LEVEL_BLUE
for(var/obj/machinery/firealarm/FA in world)
- if(FA.z == 1 || FA.z == 5)
+ if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
if(SEC_LEVEL_RED)
if(security_level < SEC_LEVEL_RED)
- world << "Attention! Code Red!"
- world << "There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised. The station's secure armory has been unlocked and is ready for use."
+ security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
else
- world << "Attention! Code Red!"
- world << "The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
+ security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
security_level = SEC_LEVEL_RED
var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world
- if(R && R.z == 1)
+ if(R && (R.z in config.station_levels))
R.locked = 0
R.update_icon()
@@ -69,25 +66,24 @@
CC.post_status("alert", "redalert")
for(var/obj/machinery/firealarm/FA in world)
- if(FA.z == 1 || FA.z == 5)
+ if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
if(SEC_LEVEL_GAMMA)
- world << "Attention! Gamma security level activated!"
- world << "Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use."
+ security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!")
security_level = SEC_LEVEL_GAMMA
move_gamma_ship()
if(security_level < SEC_LEVEL_RED)
for(var/obj/machinery/door/airlock/highsecurity/red/R in world)
- if(R.z == 1)
+ if((R.z in config.station_levels))
R.locked = 0
R.update_icon()
for(var/obj/machinery/door/airlock/hatch/gamma/H in world)
- if(H.z == 1)
+ if((H.z in config.station_levels))
H.locked = 0
H.update_icon()
@@ -96,14 +92,13 @@
CC.post_status("alert", "redalert")
for(var/obj/machinery/firealarm/FA in world)
- if(FA.z == 1 || FA.z == 5)
+ if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma")
FA.update_icon()
if(SEC_LEVEL_EPSILON)
- world << "Attention! Epsilon security level activated!"
- world << "Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated."
+ security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!")
security_level = SEC_LEVEL_EPSILON
var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
@@ -111,13 +106,12 @@
CC.post_status("alert", "redalert")
for(var/obj/machinery/firealarm/FA in world)
- if(FA.z == 1 || FA.z == 5)
+ if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
if(SEC_LEVEL_DELTA)
- world << "Attention! Delta security level reached!"
- world << "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
+ security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!")
security_level = SEC_LEVEL_DELTA
var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
@@ -125,7 +119,7 @@
CC.post_status("alert", "redalert")
for(var/obj/machinery/firealarm/FA in world)
- if(FA.z == 1 || FA.z == 5)
+ if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm
index 29baa07c1b0..398bc9f9259 100644
--- a/code/modules/shuttles/shuttle_emergency.dm
+++ b/code/modules/shuttles/shuttle_emergency.dm
@@ -26,9 +26,9 @@
emergency_shuttle.departed = 1
if (emergency_shuttle.evac)
- captain_announce("The Emergency Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.")
+ priority_announcement.Announce("The Emergency Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.")
else
- captain_announce("The Crew Transfer Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.")
+ priority_announcement.Announce("The Crew Transfer Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.")
..(origin, destination)
diff --git a/code/modules/shuttles/shuttles_multi.dm b/code/modules/shuttles/shuttles_multi.dm
index 3a73cafb58f..bac0384a4d3 100644
--- a/code/modules/shuttles/shuttles_multi.dm
+++ b/code/modules/shuttles/shuttles_multi.dm
@@ -33,14 +33,14 @@
if(cloaked || isnull(departure_message))
return
- command_alert(departure_message,(announcer ? announcer : "Central Command"))
+ command_announcement.Announce(departure_message,(announcer ? announcer : "Central Command"))
/datum/shuttle/multi_shuttle/proc/announce_arrival()
if(cloaked || isnull(arrival_message))
return
- command_alert(arrival_message,(announcer ? announcer : "Central Command"))
+ command_announcement.Announce(arrival_message,(announcer ? announcer : "Central Command"))
/obj/machinery/computer/shuttle_control/multi
icon_state = "syndishuttle"
diff --git a/code/modules/store/store.dm b/code/modules/store/store.dm
index 02a50c1b31a..41df9937fab 100644
--- a/code/modules/store/store.dm
+++ b/code/modules/store/store.dm
@@ -48,7 +48,7 @@ var/global/datum/store/centcomm_store=new
/datum/store/proc/reconnect_database()
for(var/obj/machinery/account_database/DB in world)
- if(DB.z == 1)
+ if((DB.z in config.station_levels))
linked_db = DB
break
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index 07d5f7df40a..991e1714587 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -90,7 +90,8 @@ proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool)
if( prob(S.tool_quality(tool)) && do_mob(user, M, rand(S.min_duration, S.max_duration)))
S.end_step(user, M, user.zone_sel.selecting, tool) //finish successfully
else //or
- S.fail_step(user, M, user.zone_sel.selecting, tool) //malpractice~
+ if(!isrobot(user))
+ S.fail_step(user, M, user.zone_sel.selecting, tool) //malpractice~
return 1 //don't want to do weapony things after surgery
return 0
diff --git a/code/setup.dm b/code/setup.dm
index 4906f0e6bdf..ad89e18dbbb 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -951,4 +951,10 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF")
#define SUIT_SENSOR_OFF 0
#define SUIT_SENSOR_BINARY 1
#define SUIT_SENSOR_VITAL 2
-#define SUIT_SENSOR_TRACKING 3
\ No newline at end of file
+#define SUIT_SENSOR_TRACKING 3
+
+// NanoUI flags
+#define STATUS_INTERACTIVE 2 // GREEN Visability
+#define STATUS_UPDATE 1 // ORANGE Visability
+#define STATUS_DISABLED 0 // RED Visability
+#define STATUS_CLOSE -1 // Close the interface
\ No newline at end of file
diff --git a/config/example/config.txt b/config/example/config.txt
index 1a53041a540..a26aa4575d6 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -246,6 +246,18 @@ GHOST_INTERACTION
## Default is "python" on Windows, "/usr/bin/env python2" on UNIX.
#PYTHON_PATH pythonw
+## Defines which Z-levels the station exists on.
+STATION_LEVELS 1
+
+## Defines which Z-levels are used for admin functionality, such as Central Command and the Syndicate Shuttle
+ADMIN_LEVELS 2
+
+## Defines which Z-levels which, for example, a Code Red announcement may affect
+CONTACT_LEVELS 1;5
+
+## Defines all Z-levels a character can typically reach
+PLAYER_LEVELS 1;3;4;5;6
+
## Expected round length in minutes
EXPECTED_ROUND_LENGTH 120
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index eb984038398..7c7101edd5b 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index a83f398a1b3..d226cf46949 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/maps/RandomZLevels/fileList.txt b/maps/RandomZLevels/fileList.txt
index 566dc613557..3c3785c3beb 100644
--- a/maps/RandomZLevels/fileList.txt
+++ b/maps/RandomZLevels/fileList.txt
@@ -9,7 +9,7 @@
#maps/RandomZLevels/academy.dmm
maps/RandomZLevels/beach.dmm
-maps/RandomZLevels/blackmarketpackers.dmm
+#maps/RandomZLevels/blackmarketpackers.dmm
maps/RandomZLevels/challenge.dmm
#maps/RandomZLevels/centcomAway.dmm
#maps/RandomZLevels/clownplanet.dmm
diff --git a/maps/cyberiad.dmm b/maps/cyberiad.dmm
index 017c7247c1d..75a770d8900 100644
--- a/maps/cyberiad.dmm
+++ b/maps/cyberiad.dmm
@@ -4792,7 +4792,7 @@
"bOh" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor,/area/quartermaster/qm)
"bOi" = (/obj/machinery/vending/cigarette{pixel_x = 0; pixel_y = 0},/turf/simulated/floor,/area/hallway/primary/central/sw)
"bOj" = (/turf/simulated/wall,/area/maintenance/apmaint)
-"bOk" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/aft)
+"bOk" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bOl" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/cable,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id = "blueshield"; name = "Privacy Shutters"; opacity = 0},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/blueshield)
"bOm" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/airlock/command{name = "Blueshield's Office"; req_access_txt = "67"},/turf/simulated/floor/wood,/area/blueshield)
"bOn" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/cable,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id = "blueshield"; name = "Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/blueshield)
@@ -4857,7 +4857,7 @@
"bPu" = (/obj/structure/closet/secure_closet/quartermaster,/turf/simulated/floor,/area/quartermaster/qm)
"bPv" = (/obj/structure/table,/obj/item/weapon/coin/silver,/turf/simulated/floor,/area/quartermaster/qm)
"bPw" = (/obj/structure/table,/obj/item/weapon/cartridge/quartermaster{pixel_x = 6; pixel_y = 5},/obj/item/weapon/cartridge/quartermaster,/obj/item/weapon/cartridge/quartermaster{pixel_x = -4; pixel_y = 7},/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor,/area/quartermaster/qm)
-"bPx" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/aft)
+"bPx" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bPy" = (/obj/machinery/light{dir = 1},/obj/structure/flora/kirbyplants,/obj/machinery/newscaster/security_unit{pixel_x = 0; pixel_y = 32},/turf/simulated/floor/wood,/area/blueshield)
"bPz" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor/wood,/area/blueshield)
"bPA" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/wood,/area/blueshield)
@@ -4946,7 +4946,7 @@
"bRf" = (/obj/structure/disposalpipe/segment,/obj/effect/landmark/start{name = "Shaft Miner"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor,/area/quartermaster/miningdock)
"bRg" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/quartermaster/miningdock)
"bRh" = (/obj/item/weapon/beach_ball/holoball,/turf/simulated/floor/plating,/area/maintenance/apmaint)
-"bRi" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/maintenance/aft)
+"bRi" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bRj" = (/obj/machinery/photocopier,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/obj/machinery/light_switch{pixel_x = -25},/turf/simulated/floor/wood,/area/blueshield)
"bRk" = (/turf/simulated/floor{icon_state = "bcarpet05"},/area/blueshield)
"bRl" = (/turf/simulated/floor/wood,/area/blueshield)
@@ -5085,7 +5085,7 @@
"bTO" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bTP" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bTQ" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/obj/structure/closet/crate,/turf/simulated/floor/plating,/area/maintenance/aft)
-"bTR" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/aft)
+"bTR" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bTS" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/turf/simulated/floor/wood,/area/blueshield)
"bTT" = (/obj/structure/stool/bed/chair/office/dark,/turf/simulated/floor/carpet,/area/ntrep)
"bTU" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/wood,/area/ntrep)
@@ -5163,11 +5163,11 @@
"bVo" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/quartermaster/miningdock)
"bVp" = (/obj/structure/reagent_dispensers/fueltank,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bVq" = (/obj/structure/reagent_dispensers/watertank,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating,/area/maintenance/apmaint)
-"bVr" = (/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/obj/effect/decal/cleanable/dirt,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"bVr" = (/obj/machinery/power/apc{dir = 2; name = "Cargo Maintenance APC"; pixel_y = -24},/obj/effect/decal/cleanable/dirt,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bVs" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bVt" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating,/area/maintenance/aft)
"bVu" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/sortjunction{dir = 8; icon_state = "pipe-j1s"; name = "HoP Office"; sortType = 15},/turf/simulated/floor/plating,/area/maintenance/aft)
-"bVv" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating,/area/maintenance/aft)
+"bVv" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bVw" = (/obj/machinery/keycard_auth{pixel_x = -24; pixel_y = 0},/obj/machinery/door/window{dir = 1; name = "Desk Door"; req_access_txt = "67"},/turf/simulated/floor/wood,/area/blueshield)
"bVx" = (/obj/structure/table/woodentable,/obj/item/ashtray/glass{pixel_x = -4; pixel_y = -4},/obj/item/weapon/lighter/zippo/fluff/li_matsuda_1{pixel_x = 7; pixel_y = 4},/turf/simulated/floor{icon_state = "bcarpet05"},/area/blueshield)
"bVy" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin,/obj/item/weapon/pen/blue,/obj/item/weapon/folder/blue{pixel_x = 4; pixel_y = 6},/obj/item/weapon/paper/blueshield,/turf/simulated/floor{icon_state = "bcarpet05"},/area/blueshield)
@@ -5193,7 +5193,7 @@
"bVS" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/turf/simulated/floor{dir = 1; icon_state = "blue"},/area/medical/sleeper)
"bVT" = (/obj/machinery/atmospherics/pipe/manifold/hidden{dir = 1},/turf/simulated/floor{dir = 1; icon_state = "blue"},/area/medical/sleeper)
"bVU" = (/obj/machinery/door_control{id = "scanhide"; name = "Scanning Room Privacy Shutters Control"; pixel_x = 6; pixel_y = 25},/obj/machinery/camera{c_tag = "Medbay Scanning"; network = list("SS13")},/obj/machinery/atmospherics/unary/cold_sink/freezer{dir = 8; icon_state = "freezer_0"; tag = ""},/obj/machinery/door_control{id = "scansep"; name = "Scanning Room Separation Shutters Control"; pixel_x = -6; pixel_y = 25},/turf/simulated/floor{dir = 5; icon_state = "blue"},/area/medical/sleeper)
-"bVV" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/poddoor/shutters{density = 0; dir = 8; icon_state = "shutter0"; id = "scanhide"; name = "Scanning Room Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area)
+"bVV" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/poddoor/shutters{density = 0; dir = 4; icon_state = "shutter0"; id = "scanhide"; name = "Scanning Room Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area)
"bVW" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{dir = 4; icon_state = "whiteblue"; tag = "icon-whitehall (WEST)"},/area/medical/medbay2)
"bVX" = (/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/obj/structure/grille,/obj/structure/cable,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/disposalpipe/segment,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id = "cmooffice"; name = "Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area)
"bVY" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/grille,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id = "cmooffice"; name = "Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area)
@@ -5244,7 +5244,7 @@
"bWR" = (/turf/simulated/floor/airless{dir = 8; icon_state = "warning"},/area/toxins/test_area)
"bWS" = (/turf/simulated/wall/r_wall,/area/maintenance/apmaint)
"bWT" = (/obj/machinery/door/airlock/maintenance{name = "Firefighting equipment"; req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
-"bWU" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/aft)
+"bWU" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bWV" = (/obj/machinery/requests_console{announcementConsole = 1; department = "Blueshield"; departmentType = 5; name = "Blueshield Requests Console"; pixel_x = -30},/turf/simulated/floor/wood,/area/blueshield)
"bWW" = (/obj/structure/stool/bed/chair/office/dark{dir = 4},/obj/effect/landmark/start{name = "Blueshield"},/turf/simulated/floor{icon_state = "bcarpet05"},/area/blueshield)
"bWX" = (/obj/structure/table/woodentable,/obj/machinery/computer/skills{req_one_access = null},/turf/simulated/floor{icon_state = "bcarpet05"},/area/blueshield)
@@ -5320,7 +5320,7 @@
"bYp" = (/obj/machinery/light/small{dir = 1},/obj/structure/stool,/turf/simulated/floor/plating,/area/maintenance/aft)
"bYq" = (/obj/effect/landmark{name = "blobstart"},/turf/simulated/floor/plating,/area/maintenance/aft)
"bYr" = (/turf/simulated/floor/plating,/area/maintenance/aft)
-"bYs" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/aft)
+"bYs" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bYt" = (/obj/structure/closet/secure_closet/blueshield,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/turf/simulated/floor/wood,/area/blueshield)
"bYu" = (/obj/machinery/door_control{id = "blueshield"; name = "Privacy Shutters Control"; pixel_x = 0; pixel_y = -24; req_access_txt = "67"},/obj/machinery/computer/crew,/turf/simulated/floor/wood,/area/blueshield)
"bYv" = (/obj/structure/table/woodentable,/obj/machinery/light/small/lamp,/obj/machinery/camera{c_tag = "Blueshield's Office"; dir = 1; network = list("SS13")},/turf/simulated/floor/wood,/area/blueshield)
@@ -5567,7 +5567,7 @@
"cdc" = (/obj/machinery/atmospherics/pipe/tank/toxins{volume = 3200},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cdd" = (/obj/machinery/atmospherics/pipe/tank/oxygen{volume = 3200},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cde" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
-"cdf" = (/obj/structure/rack{dir = 1},/obj/item/device/flashlight,/obj/item/clothing/glasses/sunglasses,/turf/simulated/floor/plating,/area/maintenance/aft)
+"cdf" = (/obj/structure/rack{dir = 1},/obj/item/device/flashlight,/obj/item/clothing/glasses/sunglasses,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cdg" = (/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area)
"cdh" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/circuitboard/borgupload{pixel_x = -1; pixel_y = 1},/obj/item/weapon/circuitboard/aiupload{pixel_x = 2; pixel_y = -2},/turf/simulated/floor,/area/storage/tech)
"cdi" = (/obj/machinery/camera{c_tag = "Secure Tech Storage"; dir = 2},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor,/area/storage/tech)
@@ -5636,7 +5636,7 @@
"cet" = (/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"ceu" = (/obj/machinery/atmospherics/binary/pump,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cev" = (/obj/machinery/power/apc{dir = 4; name = "Incinerator APC"; pixel_x = 24; pixel_y = 0},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
-"cew" = (/obj/machinery/light/small{dir = 8},/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/maintenance/aft)
+"cew" = (/obj/machinery/light/small{dir = 8},/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cex" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/circuitboard/crew{pixel_x = -1; pixel_y = 1},/obj/item/weapon/circuitboard/card{pixel_x = 2; pixel_y = -2},/obj/item/weapon/circuitboard/communications{pixel_x = 5; pixel_y = -5},/obj/machinery/light/small{dir = 8},/turf/simulated/floor,/area/storage/tech)
"cey" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/machinery/hologram/holopad,/turf/simulated/floor,/area/storage/tech)
"cez" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/highsecurity{name = "Secure Tech Storage"; req_access_txt = "19;23"},/turf/simulated/floor/plating,/area/storage/tech)
@@ -5763,9 +5763,9 @@
"cgQ" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cgR" = (/obj/effect/landmark{name = "xeno_spawn"; pixel_x = -1},/obj/machinery/hologram/holopad,/mob/living/simple_animal/mouse,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cgS" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
-"cgT" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/door/airlock/maintenance{name = "Incinerator Access"; req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/asmaint)
-"cgU" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating,/area/maintenance/aft)
-"cgV" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/aft)
+"cgT" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cgU" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cgV" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/door/airlock/maintenance{name = "Incinerator Access"; req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cgW" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating,/area)
"cgX" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area)
"cgY" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/grille,/obj/structure/cable,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area)
@@ -5828,7 +5828,7 @@
"cid" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cie" = (/obj/machinery/navbeacon{codes_txt = "patrol;next_patrol=1-Storage"; location = "7-Sleeper"},/turf/simulated/floor{dir = 2; icon_state = "whiteblue"},/area/mine/laborcamp)
"cif" = (/obj/machinery/atmospherics/portables_connector{dir = 8},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
-"cig" = (/obj/machinery/power/apc{dir = 4; name = "Engineering Maintenance APC"; pixel_x = 27; pixel_y = 2},/obj/structure/disposalpipe/segment,/obj/structure/cable,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/plating,/area/maintenance/aft)
+"cig" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cih" = (/obj/structure/table,/obj/machinery/cell_charger{pixel_y = 5},/obj/machinery/status_display{layer = 4; pixel_x = -32; pixel_y = 0},/turf/simulated/floor/plating,/area/storage/tech)
"cii" = (/obj/machinery/light/small,/turf/simulated/floor/plating,/area/storage/tech)
"cij" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = -1},/obj/item/clothing/gloves/yellow,/obj/item/device/t_scanner,/obj/item/clothing/glasses/meson,/obj/item/device/multitool,/turf/simulated/floor/plating,/area/storage/tech)
@@ -5879,8 +5879,8 @@
"cjc" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating/airless,/area)
"cjd" = (/obj/item/clothing/mask/cigarette,/turf/simulated/floor/plating/airless,/area/toxins/test_area)
"cje" = (/obj/machinery/light/small,/turf/simulated/floor/plating/airless,/area/toxins/test_area)
-"cjf" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/aft)
-"cjg" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/aft)
+"cjf" = (/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cjg" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cjh" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/obj/item/device/radio/intercom{dir = 8; name = "Station Intercom (General)"; pixel_x = -28},/turf/simulated/floor{dir = 8; icon_state = "cautioncorner"},/area/hallway/primary/aft)
"cji" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/pump,/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor{icon_state = "arrival"; dir = 8},/area/hallway/primary/aft)
"cjj" = (/obj/machinery/atmospherics/pipe/simple/hidden/cyan{dir = 9; level = 2},/turf/simulated/wall/r_wall,/area)
@@ -11683,7 +11683,7 @@
"eqI" = (/obj/machinery/door/airlock/glass,/turf/simulated/floor,/area/derelict/bridge/access)
"eqJ" = (/turf/simulated/wall/r_wall,/area/derelict/singularity_engine)
"eqK" = (/obj/structure/window/reinforced,/turf/simulated/floor,/area/derelict/bridge/access)
-"eqL" = (/obj/machinery/door/window,/turf/simulated/floor,/area/derelict/bridge/access)
+"eqL" = (/obj/machinery/door/window{dir = 2},/turf/simulated/floor,/area/derelict/bridge/access)
"eqM" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/cable,/obj/structure/window/reinforced,/turf/simulated/floor,/area/derelict/bridge/access)
"eqN" = (/turf/simulated/wall,/area/derelict/bridge)
"eqO" = (/obj/structure/sign/electricshock,/turf/simulated/wall/r_wall,/area/derelict/singularity_engine)
@@ -11767,7 +11767,7 @@
"eso" = (/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor/plating/airless,/area/derelict/singularity_engine)
"esp" = (/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/derelict/singularity_engine)
"esq" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating/airless,/area/derelict/singularity_engine)
-"esr" = (/obj/machinery/door/window,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor,/area/derelict/bridge/access)
+"esr" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/window{dir = 2},/turf/simulated/floor,/area/derelict/bridge/access)
"ess" = (/turf/simulated/wall/r_wall,/area/derelict/bridge)
"est" = (/obj/machinery/door/window{dir = 2; name = "Captain's Quarters"; req_access_txt = "20"},/obj/structure/grille,/turf/simulated/floor/plating/airless,/area/derelict/bridge)
"esu" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/derelict/singularity_engine)
@@ -11833,7 +11833,7 @@
"etC" = (/turf/simulated/floor/airless{icon_state = "floorscorched2"},/area)
"etD" = (/turf/simulated/floor/airless{icon_state = "damaged2"},/area)
"etE" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/derelict/singularity_engine)
-"etF" = (/obj/machinery/door/window,/turf/simulated/floor/plating/airless,/area/derelict/hallway/primary)
+"etF" = (/obj/machinery/door/window{dir = 2},/turf/simulated/floor/plating/airless,/area/derelict/hallway/primary)
"etG" = (/turf/simulated/floor/airless{icon_state = "floorscorched1"},/area)
"etH" = (/obj/item/weapon/shard{icon_state = "medium"},/turf/simulated/floor/airless{icon_state = "damaged2"},/area/derelict/singularity_engine)
"etI" = (/obj/structure/grille{density = 0; icon_state = "brokengrille"},/turf/simulated/floor/plating/airless,/area/derelict/singularity_engine)
@@ -11962,7 +11962,7 @@
"ewb" = (/obj/structure/table,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor{dir = 1; icon_state = "chapel"},/area/derelict/medical/chapel)
"ewc" = (/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor{dir = 4; icon_state = "chapel"},/area/derelict/medical/chapel)
"ewd" = (/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor{dir = 1; icon_state = "chapel"},/area/derelict/medical/chapel)
-"ewe" = (/obj/machinery/door/window,/turf/simulated/floor/airless,/area/derelict/medical/chapel)
+"ewe" = (/obj/machinery/door/window{dir = 2},/turf/simulated/floor/airless,/area/derelict/medical/chapel)
"ewf" = (/obj/machinery/door/window/southleft,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/airless{icon_state = "white"},/area/derelict/medical)
"ewg" = (/obj/machinery/door/window/southright,/turf/simulated/floor/airless{icon_state = "white"},/area/derelict/medical)
"ewh" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/airless,/area/derelict/hallway/primary)
@@ -12001,7 +12001,7 @@
"ewO" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/airless,/area/derelict/hallway/primary)
"ewP" = (/obj/structure/girder,/turf/simulated/floor/airless,/area/derelict/hallway/primary)
"ewQ" = (/obj/machinery/portable_atmospherics/pump,/turf/simulated/floor,/area/derelict/arrival)
-"ewR" = (/obj/machinery/door/window,/turf/simulated/floor/airless,/area/derelict/hallway/primary)
+"ewR" = (/obj/machinery/door/window{dir = 2},/turf/simulated/floor/airless,/area/derelict/hallway/primary)
"ewS" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/airless,/area/derelict/hallway/primary)
"ewT" = (/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/turf/simulated/floor/airless,/area/derelict/hallway/primary)
"ewU" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/airless,/area/derelict/hallway/primary)
@@ -12121,7 +12121,7 @@
"eze" = (/obj/item/weapon/paper/russiantraitorobj,/turf/simulated/floor/airless{icon_state = "damaged2"},/area/derelict/bridge/ai_upload)
"ezf" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating/airless,/area/AIsattele)
"ezg" = (/obj/item/stack/rods,/turf/simulated/floor/plating/airless,/area/derelict/hallway/secondary)
-"ezh" = (/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"},/turf/simulated/floor/airless,/area)
+"ezh" = (/obj/machinery/door/window{dir = 8},/turf/simulated/floor/airless,/area/derelict/bridge/ai_upload)
"ezi" = (/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small,/turf/simulated/floor/airless,/area/derelict/bridge/ai_upload)
"ezj" = (/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"},/turf/simulated/floor/airless,/area/derelict/bridge/ai_upload)
"ezk" = (/obj/structure/closet/crate,/obj/item/device/aicard,/obj/item/device/multitool,/obj/item/weapon/weldingtool,/obj/item/weapon/wrench,/obj/item/weapon/circuitboard/teleporter,/turf/simulated/floor/plating/airless,/area/AIsattele)
@@ -12552,6 +12552,7 @@
"eHt" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep)
"eHu" = (/obj/machinery/conveyor{dir = 4; id = "QMLoad2"},/turf/simulated/floor,/area/quartermaster/storage)
"eHv" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/conveyor{dir = 4; id = "QMLoad2"},/turf/simulated/floor,/area/quartermaster/storage)
+"eHw" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
(1,1,1) = {"
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -12712,10 +12713,10 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbVaaaaabaabaaiaaiaaiaaiaaiaaiaaiaaiaaqbWUcbWaaacbXcbYcbZccaccbcccccdcceccfccgabZcchcciccjcckcclccmccnccoccpccqabmccrccsccsccscctaaibDgbDgaaqaaqaaqaaqaaJaaqccuccuccvaaqaaqaosaaqaNtccwccxccyccxachcczccAccBachbrebreachccCccDccEaaiccFccGbVQaaiaaiabmaaiccHaaiccIccJaaiccKccLccMbDgccNaaiabmccOafaaaibsacaBccPbsaccQccRccSccTbsabsabsabsabsabsaccUccVbIgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaibQXbQXbQXbQXbQXbQXbYnbQXcbUbQXbQXbQXbQXbQXaaiaaiaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccXccYccYccYccZcfAcdacdbcdccddcdeaaqcdfbWUaEFaaacdgcdhcdicdjcdkccccdlcdmcdncdoaaqcdpbYCbTWcbfcdqbZTcdrbZTcdscdtcducdvcdwcdwcdwcdxaaibDgbDgaaqcdycdzcdAcdBcdCcdDcdDcdEcdFcdGcdHcdIcdJabZcdKbXJbXJacFcdLcdMcdNaaiaaaaaaaaicdOcdPcdQachcdRcdScdTcdUcdUcdVbBDcdWcdXcdYcdZcdXcdXcdXceacdXcdXcebceccedceecefcegcehceibQOcejbQObQObQObQObQOcekcelbQObQOcembsacenaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaaibWRbQXbQXbQXbQXbQXbQXbQXbQXbQXbQXbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceocepcepcepcepceqcercescetceuceucevaaqcewbYsaEFaaacdgcexceycezceAceBceCceDceAceAceEceFceGceHacFacFceIceJbZTceKceLceMcdwcdwcdwcdwceNaaibDgbDgaaqceOcePceQceRceSceTceTceUceVceWceXceYceZaaqcfabXFcfbaaicfccdMcfdaaiaaaaaaaaicfecffcfgaaibDhcfhcficficficficficficfjcfkcflcfmachachcfncfoachachcfpcfqcfraaqaaicfscftcfuaaiaaiaaiaaicfvcfwcfuaaiaaibsacfxbsabJuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabTHaaiaaibZHbZHbQXbQXbQXbQXbQXbQXbQXbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfycfzcfCcfBcfCcfEcfDcgQcfFcfFcfGaaqcfHbWUaEFaaacdgcfIcfJaiVcfKccccfLcfMcfNcfOaaqcdpbYCbYDcfPaaicfQaaqcfRcfScfTcfUcfVcdwcdwcfWcfXaaibDgcfYaaqcfZcgacgbcgccgccgccgdcgecgccgccgfcgbcggaaicghbXFcgiaaicgjcdMcgkaaiaaaaaaaaicglcgmcgnaaicgobDgcfYaaiaaiaaiaaiaaiaoHaoIaoJaaiaaicgpcgqcgrcgsaaicgtcguamdaaicgvcgwcgwcgwcgxcgycgzcgAcgBcgCcgDcgEaaicgFcgGcgHcgIcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgKcgLaaibSiaaibQXbQXbQXbQXbQXbQXbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaacfycgMcgNcgOcgPcetchYcetcgRcetcgScgTcgUcgVcgWaaacgXcbYcgYccacgZccccccchachbchcabJchdchechfchgaaichhchichjchkchlabmchmcdwcdwcdwchnaaibDgbDgaaqaaqaaJchochpchqchraaqchschtchuchvbUgaaJaaicfabXFcfbaaichwcdMcdNaaiaaaaaaaaichxchychzaaibDgbDgbDgaaiaabaaaaaaaabaaaaabaaaaaaaaichAchBchCchDchEchFchGchHchIchJchKchLchLchMchNchNchOchPchQchQchRaaiaaichSaamaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaichTchUchVaaiaaibQXbQXchWbQXbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfychXcfCchZcfCciacibcidciccgQcifaaqbYrcigaaiaaaaaaaaaaaaaaicihciicijcijcikcilaaqcimbYCbTWcinciocipciqcircircirciscitcdwciucdwcivaaibDgbDgaaqciwcixciycizciAciBaaqciAciBcizciCciDciEaaicghciFcgiaaichwcdMciGaaiaaiaaiaaiaaiaaiaaiaaiciHbDgbDgaaiaabaaaaaaaaaaabaabaabaaaaaiciIciJciJciKciLciMciNciOciPciQciRciSciTciUciVciWchNchNchNciXciYaaiciZcjacjbaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjccjdcjebSjaaqaaiaaibQXbQYbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacOabAaaiaaiaaiaaiaaiaaiaaiaaiaJkaJkaJkaJkaJkaaiaaqaaqaaqaaqaaqaaqcjfcjgaaiaaiaaiaaiaaiaaiaaqaaqaaqaaqaaqaaqaaqcjhbYCbTWcjicjjcjkcjlcjmcjncjocjpcjqcjrcjscjtcjuaaibDgbDgaaqcjvcjwciycizcizcjxaaqcjycizcizciCciycjzaaiaaiaaiaaiccIcjAcdMcjBaaicjCbDgbDgbDgbDgcjDbDgbDgbDgbDgaaiaaaaaaaaaaaaaaaaabaabaaaaaicjEcjFcjFcjGcjHcjIcjJcjKcjLcjMcjNchNchNchNcjOcjPchNcjQchNciXcjRaaicjScjTcjUaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjVbBZbBZbCaaaqaaqaaiaaiaaiaaibPhaabaabaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfycfzcfCcfBcfCcfEcfDcgQcfFcfFcfGaaqcgTbWUaEFaaacdgcfIcfJaiVcfKccccfLcfMcfNcfOaaqcdpbYCbYDcfPaaicfQaaqcfRcfScfTcfUcfVcdwcdwcfWcfXaaibDgcfYaaqcfZcgacgbcgccgccgccgdcgecgccgccgfcgbcggaaicghbXFcgiaaicgjcdMcgkaaiaaaaaaaaicglcgmcgnaaicgobDgcfYaaiaaiaaiaaiaaiaoHaoIaoJaaiaaicgpcgqcgrcgsaaicgtcguamdaaicgvcgwcgwcgwcgxcgycgzcgAcgBcgCcgDcgEaaicgFcgGcgHcgIcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgJcgKcgLaaibSiaaibQXbQXbQXbQXbQXbQXbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaacfycgMcgNcgOcgPcetchYcetcgRcetcgScgVcgUcigcgWaaacgXcbYcgYccacgZccccccchachbchcabJchdchechfchgaaichhchichjchkchlabmchmcdwcdwcdwchnaaibDgbDgaaqaaqaaJchochpchqchraaqchschtchuchvbUgaaJaaicfabXFcfbaaichwcdMcdNaaiaaaaaaaaichxchychzaaibDgbDgbDgaaiaabaaaaaaaabaaaaabaaaaaaaaichAchBchCchDchEchFchGchHchIchJchKchLchLchMchNchNchOchPchQchQchRaaiaaichSaamaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaichTchUchVaaiaaibQXbQXchWbQXbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfychXcfCchZcfCciacibcidciccgQcifaaqcjfbWUaaiaaaaaaaaaaaaaaicihciicijcijcikcilaaqcimbYCbTWcinciocipciqcircircirciscitcdwciucdwcivaaibDgbDgaaqciwcixciycizciAciBaaqciAciBcizciCciDciEaaicghciFcgiaaichwcdMciGaaiaaiaaiaaiaaiaaiaaiaaiciHbDgbDgaaiaabaaaaaaaaaaabaabaabaaaaaiciIciJciJciKciLciMciNciOciPciQciRciSciTciUciVciWchNchNchNciXciYaaiciZcjacjbaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjccjdcjebSjaaqaaiaaibQXbQYbQXaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacOabAaaiaaiaaiaaiaaiaaiaaiaaiaJkaJkaJkaJkaJkaaiaaqaaqaaqaaqaaqaaqcjgeHwaaiaaiaaiaaiaaiaaiaaqaaqaaqaaqaaqaaqaaqcjhbYCbTWcjicjjcjkcjlcjmcjncjocjpcjqcjrcjscjtcjuaaibDgbDgaaqcjvcjwciycizcizcjxaaqcjycizcizciCciycjzaaiaaiaaiaaiccIcjAcdMcjBaaicjCbDgbDgbDgbDgcjDbDgbDgbDgbDgaaiaaaaaaaaaaaaaaaaabaabaaaaaicjEcjFcjFcjGcjHcjIcjJcjKcjLcjMcjNchNchNchNcjOcjPchNcjQchNciXcjRaaicjScjTcjUaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjVbBZbBZbCaaaqaaqaaiaaiaaiaaibPhaabaabaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjWcjXcjYcjZckackackbckcckdckeckfckgckhckickjckjckjckkcklckmckncknckockpckqckrcksckrckrckrckqckrckrcktckuckvckwbYCbTWckxckyckzafaaaicfUacFaujckAckBacFatEcblaaibDgbDgaaqckCckDckEckFckGckHaaqckIckGckJckKckEckLaaibDgbDgbDgckMchwcdMchwckNbDgbDgbDgbDgbDgbDgbDgbDgbDgbDgaaiaaaaaaaaaaaaaaaaabaabaabaaickOckPckPckPcbAaaickQafacbAckRckSckTckTckUcjMcjMckVckTckWckXckYaaickZclaclbaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjWcjXclccldclecldclfclgclhclicljclkcllclmclnclnclnclnbYCbTXbTXbTXclncloclnclnclnclnclnclnclnclnclnclnclpclqclrclscltcluclvclwclxaaiclyclzclAclBclCclDclEclFachcficlGabJclHclIclJclKcizclLaaqclLcizclKclMciyclNaaiclOachachbmWclPclQclRaaibNtaoIaoIbNuaaiaaiaaiaoHaoIaoJaaiaaaaaaaaaaaaaaaaaaaabaabaaiclSclTclUclVaaiclWclXclYaaiclZcmacmacmacmbcmccmdcmecmacmacmacmfaaiaDpcmgcmhaFRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjWcmicldcmjcmkcmlcmmcmncmocmpcmqcmrcmscmtcmucmvcmwcmwcmxabJcmyabJcmucmzcmucmucmucmucmucmucmucmucmucmucmAclncmBcmCcmDcmEcmFcmGcmHcmIcmJcmKcmLcmMcmNcmOcmPcmQacFbXlcmRcmScmTcizciycizcizcmUabZcmVcizcizciCciycmWaaicmXaaiaaaafaaaicmYaaiaaiaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaaiaaiaaiaaiaaiaaiaaiaaicmZcnacnbaaiaaicnccndcneaaiaaiaaiaaicnccndcneaaiaaiaEFcnfaEFaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaMIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -13980,7 +13981,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaceyHeyVeyHeyWeyXeyYeyYexNeyUexNeyUexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaacaaceyHeyZezaeyWeyYezbeyYexNeyUexNeyUexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabexoaacetNeyHezceyHezdeyYezeeHpexNezgexNeyUexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaacetNezheyYeziezjeyYeHoezleyYexNeyUexNeyUexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaacetNdEjezheziezjeyYeHoezleyYexNeyUexNeyUexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaacdEjdEjeyHezmeyHeyYeyYezaeyYexNeyUexNezgexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaaiaaiaaaeyHeyHezmeyHeyHeyHeyHeyHexNeyUexNezgexNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadyqaaaaaaaaaaaaaaaeznaaaaaaaaaaaaaaadyqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/nano/debug.html b/nano/debug.html
index 969956bacb2..58b2be3df1a 100644
--- a/nano/debug.html
+++ b/nano/debug.html
@@ -16,7 +16,7 @@
-
+