Ohkay
This commit is contained in:
@@ -113,6 +113,11 @@ Class Procs:
|
||||
var/atom/movable/occupant = null
|
||||
var/speed_process = FALSE // Process as fast as possible?
|
||||
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
|
||||
// For storing and overriding ui id and dimensions
|
||||
var/tgui_id // ID of TGUI interface
|
||||
var/ui_style // ID of custom TGUI style (optional)
|
||||
var/ui_x
|
||||
var/ui_y
|
||||
|
||||
var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
|
||||
|
||||
|
||||
@@ -46,34 +46,37 @@
|
||||
new /obj/item/stack/spacecash/c200(drop_location()) // will autostack
|
||||
playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
|
||||
SSshuttle.points -= 200
|
||||
if(next_warning < world.time && prob(15))
|
||||
var/area/A = get_area(loc)
|
||||
var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!"
|
||||
radio.talk_into(src, message, radio_channel)
|
||||
next_warning = world.time + minimum_time_between_warnings
|
||||
if(next_warning < world.time && prob(15))
|
||||
var/area/A = get_area(loc)
|
||||
var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!"
|
||||
radio.talk_into(src, message, radio_channel)
|
||||
next_warning = world.time + minimum_time_between_warnings
|
||||
|
||||
/obj/machinery/computer/bank_machine/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "[station_name()] secure vault. Authorized personnel only.<br>"
|
||||
dat += "Current Balance: [SSshuttle.points] credits.<br>"
|
||||
if(!siphoning)
|
||||
dat += "<A href='?src=[REF(src)];siphon=1'>Siphon Credits</A><br>"
|
||||
else
|
||||
dat += "<A href='?src=[REF(src)];halt=1'>Halt Credit Siphon</A><br>"
|
||||
/obj/machinery/computer/bank_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "bank_machine", name, 320, 165, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
dat += "<a href='?src=[REF(user)];mach_close=computer'>Close</a>"
|
||||
/obj/machinery/computer/bank_machine/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["current_balance"] = SSshuttle.points
|
||||
data["siphoning"] = siphoning
|
||||
data["station_name"] = station_name()
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Bank Vault", 300, 200)
|
||||
popup.set_content("<center>[dat]</center>")
|
||||
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/bank_machine/Topic(href, href_list)
|
||||
/obj/machinery/computer/bank_machine/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["siphon"])
|
||||
say("Siphon of station credits has begun!")
|
||||
siphoning = TRUE
|
||||
if(href_list["halt"])
|
||||
say("Station credit withdrawal halted.")
|
||||
siphoning = FALSE
|
||||
|
||||
switch(action)
|
||||
if("siphon")
|
||||
say("Siphon of station credits has begun!")
|
||||
siphoning = TRUE
|
||||
. = TRUE
|
||||
if("halt")
|
||||
say("Station credit withdrawal halted.")
|
||||
siphoning = FALSE
|
||||
. = TRUE
|
||||
|
||||
@@ -1,128 +1,123 @@
|
||||
#define MENU_OPERATION 1
|
||||
#define MENU_SURGERIES 2
|
||||
|
||||
/obj/machinery/computer/operating
|
||||
name = "operating computer"
|
||||
desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures."
|
||||
icon_screen = "crew"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/operating
|
||||
var/mob/living/carbon/human/patient
|
||||
var/obj/structure/table/optable/table
|
||||
var/list/advanced_surgeries = list()
|
||||
var/datum/techweb/linked_techweb
|
||||
var/menu = MENU_OPERATION
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/operating/Initialize()
|
||||
. = ..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
find_table()
|
||||
|
||||
/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/disk/surgery))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a surgery protocol from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
var/obj/item/disk/surgery/D = O
|
||||
if(do_after(user, 10, target = src))
|
||||
advanced_surgeries |= D.surgeries
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/operating/proc/sync_surgeries()
|
||||
for(var/i in linked_techweb.researched_designs)
|
||||
var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i)
|
||||
if(!istype(D))
|
||||
continue
|
||||
advanced_surgeries |= D.surgery
|
||||
|
||||
/obj/machinery/computer/operating/proc/find_table()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
table = locate(/obj/structure/table/optable, get_step(src, direction))
|
||||
if(table)
|
||||
table.computer = src
|
||||
break
|
||||
|
||||
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["table"] = table
|
||||
if(table)
|
||||
data["menu"] = menu
|
||||
|
||||
var/list/surgeries = list()
|
||||
for(var/X in advanced_surgeries)
|
||||
var/datum/surgery/S = X
|
||||
var/list/surgery = list()
|
||||
surgery["name"] = initial(S.name)
|
||||
surgery["desc"] = initial(S.desc)
|
||||
surgeries += list(surgery)
|
||||
data["surgeries"] = surgeries
|
||||
|
||||
data["patient"] = list()
|
||||
if(table.check_patient())
|
||||
patient = table.patient
|
||||
switch(patient.stat)
|
||||
if(CONSCIOUS)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["patient"]["stat"] = "Unconscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["patient"]["stat"] = "Dead"
|
||||
data["patient"]["statstate"] = "bad"
|
||||
data["patient"]["health"] = patient.health
|
||||
data["patient"]["blood_type"] = patient.dna.blood_type
|
||||
data["patient"]["maxHealth"] = patient.maxHealth
|
||||
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["patient"]["bruteLoss"] = patient.getBruteLoss()
|
||||
data["patient"]["fireLoss"] = patient.getFireLoss()
|
||||
data["patient"]["toxLoss"] = patient.getToxLoss()
|
||||
data["patient"]["oxyLoss"] = patient.getOxyLoss()
|
||||
if(patient.surgeries.len)
|
||||
data["procedures"] = list()
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
|
||||
var/chems_needed = surgery_step.get_chem_list()
|
||||
var/alternative_step
|
||||
var/alt_chems_needed = ""
|
||||
if(surgery_step.repeatable)
|
||||
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
|
||||
if(next_step)
|
||||
alternative_step = capitalize(next_step.name)
|
||||
alt_chems_needed = next_step.get_chem_list()
|
||||
else
|
||||
alternative_step = "Finish operation"
|
||||
data["procedures"] += list(list(
|
||||
"name" = capitalize(procedure.name),
|
||||
"next_step" = capitalize(surgery_step.name),
|
||||
"chems_needed" = chems_needed,
|
||||
"alternative_step" = alternative_step,
|
||||
"alt_chems_needed" = alt_chems_needed
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("change_menu")
|
||||
menu = text2num(params["menu"])
|
||||
. = TRUE
|
||||
if("sync")
|
||||
sync_surgeries()
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
#undef MENU_OPERATION
|
||||
#undef MENU_SURGERIES
|
||||
#define MENU_OPERATION 1
|
||||
#define MENU_SURGERIES 2
|
||||
|
||||
/obj/machinery/computer/operating
|
||||
name = "operating computer"
|
||||
desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures."
|
||||
icon_screen = "crew"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/operating
|
||||
var/mob/living/carbon/human/patient
|
||||
var/obj/structure/table/optable/table
|
||||
var/list/advanced_surgeries = list()
|
||||
var/datum/techweb/linked_techweb
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/operating/Initialize()
|
||||
. = ..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
find_table()
|
||||
|
||||
/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/disk/surgery))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a surgery protocol from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
var/obj/item/disk/surgery/D = O
|
||||
if(do_after(user, 10, target = src))
|
||||
advanced_surgeries |= D.surgeries
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/operating/proc/sync_surgeries()
|
||||
for(var/i in linked_techweb.researched_designs)
|
||||
var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i)
|
||||
if(!istype(D))
|
||||
continue
|
||||
advanced_surgeries |= D.surgery
|
||||
|
||||
/obj/machinery/computer/operating/proc/find_table()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
table = locate(/obj/structure/table/optable, get_step(src, direction))
|
||||
if(table)
|
||||
table.computer = src
|
||||
break
|
||||
|
||||
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["table"] = table
|
||||
if(table)
|
||||
var/list/surgeries = list()
|
||||
for(var/X in advanced_surgeries)
|
||||
var/datum/surgery/S = X
|
||||
var/list/surgery = list()
|
||||
surgery["name"] = initial(S.name)
|
||||
surgery["desc"] = initial(S.desc)
|
||||
surgeries += list(surgery)
|
||||
data["surgeries"] = surgeries
|
||||
if(table.check_patient())
|
||||
data["patient"] = list()
|
||||
patient = table.patient
|
||||
switch(patient.stat)
|
||||
if(CONSCIOUS)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["patient"]["stat"] = "Unconscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["patient"]["stat"] = "Dead"
|
||||
data["patient"]["statstate"] = "bad"
|
||||
data["patient"]["health"] = patient.health
|
||||
data["patient"]["blood_type"] = patient.dna.blood_type
|
||||
data["patient"]["maxHealth"] = patient.maxHealth
|
||||
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["patient"]["bruteLoss"] = patient.getBruteLoss()
|
||||
data["patient"]["fireLoss"] = patient.getFireLoss()
|
||||
data["patient"]["toxLoss"] = patient.getToxLoss()
|
||||
data["patient"]["oxyLoss"] = patient.getOxyLoss()
|
||||
if(patient.surgeries.len)
|
||||
data["procedures"] = list()
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
|
||||
var/chems_needed = surgery_step.get_chem_list()
|
||||
var/alternative_step
|
||||
var/alt_chems_needed = ""
|
||||
if(surgery_step.repeatable)
|
||||
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
|
||||
if(next_step)
|
||||
alternative_step = capitalize(next_step.name)
|
||||
alt_chems_needed = next_step.get_chem_list()
|
||||
else
|
||||
alternative_step = "Finish operation"
|
||||
data["procedures"] += list(list(
|
||||
"name" = capitalize(procedure.name),
|
||||
"next_step" = capitalize(surgery_step.name),
|
||||
"chems_needed" = chems_needed,
|
||||
"alternative_step" = alternative_step,
|
||||
"alt_chems_needed" = alt_chems_needed
|
||||
))
|
||||
else
|
||||
data["patient"] = null
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("sync")
|
||||
sync_surgeries()
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
#undef MENU_OPERATION
|
||||
#undef MENU_SURGERIES
|
||||
|
||||
@@ -1,98 +1,99 @@
|
||||
/obj/machinery/computer/station_alert
|
||||
name = "station alert console"
|
||||
desc = "Used to access the station's automated alert system."
|
||||
icon_screen = "alert:0"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/stationalert
|
||||
var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list())
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/station_alert/Initialize()
|
||||
. = ..()
|
||||
GLOB.alert_consoles += src
|
||||
|
||||
/obj/machinery/computer/station_alert/Destroy()
|
||||
GLOB.alert_consoles -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "station_alert", name, 300, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_data(mob/user)
|
||||
. = list()
|
||||
|
||||
.["alarms"] = list()
|
||||
for(var/class in alarms)
|
||||
.["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
.["alarms"][class] += area
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
if(source.z != z)
|
||||
return
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
|
||||
var/list/L = alarms[class]
|
||||
for(var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/sources = alarm[3]
|
||||
if (!(source in sources))
|
||||
sources += source
|
||||
return 1
|
||||
var/obj/machinery/camera/C = null
|
||||
var/list/CL = null
|
||||
if(O && islist(O))
|
||||
CL = O
|
||||
if (CL.len == 1)
|
||||
C = CL[1]
|
||||
else if(O && istype(O, /obj/machinery/camera))
|
||||
C = O
|
||||
L[A.name] = list(A, (C ? C : O), list(source))
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin)
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
var/list/L = alarms[class]
|
||||
var/cleared = 0
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
return !cleared
|
||||
|
||||
/obj/machinery/computer/station_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
var/active_alarms = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
active_alarms = TRUE
|
||||
if(active_alarms)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
/obj/machinery/computer/station_alert
|
||||
name = "station alert console"
|
||||
desc = "Used to access the station's automated alert system."
|
||||
icon_screen = "alert:0"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/stationalert
|
||||
var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list())
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/station_alert/Initialize()
|
||||
. = ..()
|
||||
GLOB.alert_consoles += src
|
||||
|
||||
/obj/machinery/computer/station_alert/Destroy()
|
||||
GLOB.alert_consoles -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "station_alert", name, 325, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["alarms"] = list()
|
||||
for(var/class in alarms)
|
||||
data["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
data["alarms"][class] += area
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
if(source.z != z)
|
||||
return
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
|
||||
var/list/L = alarms[class]
|
||||
for(var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/sources = alarm[3]
|
||||
if (!(source in sources))
|
||||
sources += source
|
||||
return 1
|
||||
var/obj/machinery/camera/C = null
|
||||
var/list/CL = null
|
||||
if(O && islist(O))
|
||||
CL = O
|
||||
if (CL.len == 1)
|
||||
C = CL[1]
|
||||
else if(O && istype(O, /obj/machinery/camera))
|
||||
C = O
|
||||
L[A.name] = list(A, (C ? C : O), list(source))
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin)
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
var/list/L = alarms[class]
|
||||
var/cleared = 0
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
return !cleared
|
||||
|
||||
/obj/machinery/computer/station_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
var/active_alarms = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
active_alarms = TRUE
|
||||
if(active_alarms)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
|
||||
@@ -1434,7 +1434,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ai_airlock", name, 550, 456, master_ui, state)
|
||||
ui = new(user, src, ui_key, "ai_airlock", name, 500, 390, master_ui, state)
|
||||
ui.open()
|
||||
return TRUE
|
||||
|
||||
@@ -1503,83 +1503,24 @@
|
||||
if("shock-perm")
|
||||
shock_perm(usr)
|
||||
. = TRUE
|
||||
if("idscan-on")
|
||||
if(wires.is_cut(WIRE_IDSCAN))
|
||||
to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.")
|
||||
else if(src.aiDisabledIdScanner)
|
||||
aiDisabledIdScanner = FALSE
|
||||
else
|
||||
to_chat(usr, "The IdScan feature is not disabled.")
|
||||
if("idscan-toggle")
|
||||
aiDisabledIdScanner = !aiDisabledIdScanner
|
||||
. = TRUE
|
||||
if("idscan-off")
|
||||
if(wires.is_cut(WIRE_IDSCAN))
|
||||
to_chat(usr, "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways.")
|
||||
else if(aiDisabledIdScanner)
|
||||
to_chat(usr, "You've already disabled the IdScan feature.")
|
||||
else
|
||||
aiDisabledIdScanner = TRUE
|
||||
if("emergency-toggle")
|
||||
toggle_emergency(usr)
|
||||
. = TRUE
|
||||
if("emergency-on")
|
||||
emergency_on(usr)
|
||||
if("bolt-toggle")
|
||||
toggle_bolt(usr)
|
||||
. = TRUE
|
||||
if("emergency-off")
|
||||
emergency_off(usr)
|
||||
if("light-toggle")
|
||||
lights = !lights
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("bolt-raise")
|
||||
bolt_raise(usr)
|
||||
if("safe-toggle")
|
||||
safe = !safe
|
||||
. = TRUE
|
||||
if("bolt-drop")
|
||||
bolt_drop(usr)
|
||||
. = TRUE
|
||||
if("light-on")
|
||||
if(wires.is_cut(WIRE_LIGHT))
|
||||
to_chat(usr, "Control to door bolt lights has been severed.")
|
||||
else if (!src.lights)
|
||||
lights = TRUE
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, text("Door bolt lights are already enabled!"))
|
||||
. = TRUE
|
||||
if("light-off")
|
||||
if(wires.is_cut(WIRE_LIGHT))
|
||||
to_chat(usr, "Control to door bolt lights has been severed.")
|
||||
else if (lights)
|
||||
lights = FALSE
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "Door bolt lights are already disabled!")
|
||||
. = TRUE
|
||||
if("safe-on")
|
||||
if(wires.is_cut(WIRE_SAFETY))
|
||||
to_chat(usr, "Control to door sensors is disabled.")
|
||||
else if (!src.safe)
|
||||
safe = TRUE
|
||||
else
|
||||
to_chat(usr, "Firmware reports safeties already in place.")
|
||||
. = TRUE
|
||||
if("safe-off")
|
||||
if(wires.is_cut(WIRE_SAFETY))
|
||||
to_chat(usr, "Control to door sensors is disabled.")
|
||||
else if (safe)
|
||||
safe = FALSE
|
||||
else
|
||||
to_chat(usr, "Firmware reports safeties already overridden.")
|
||||
. = TRUE
|
||||
if("speed-on")
|
||||
if(wires.is_cut(WIRE_TIMING))
|
||||
to_chat(usr, "Control to door timing circuitry has been severed.")
|
||||
else if (!src.normalspeed)
|
||||
normalspeed = 1
|
||||
else
|
||||
to_chat(usr,"Door timing circuitry currently operating normally.")
|
||||
. = TRUE
|
||||
if("speed-off")
|
||||
if(wires.is_cut(WIRE_TIMING))
|
||||
to_chat(usr, "Control to door timing circuitry has been severed.")
|
||||
else if (normalspeed)
|
||||
normalspeed = 0
|
||||
else
|
||||
to_chat(usr, "Door timing circuitry already accelerated.")
|
||||
if("speed-toggle")
|
||||
normalspeed = !normalspeed
|
||||
|
||||
. = TRUE
|
||||
if("open-close")
|
||||
@@ -1617,45 +1558,26 @@
|
||||
log_combat(user, src, "electrified")
|
||||
set_electrified(ELECTRIFIED_PERMANENT)
|
||||
|
||||
/obj/machinery/door/airlock/proc/emergency_on(mob/user)
|
||||
if(!user_allowed(user))
|
||||
return
|
||||
if (!emergency)
|
||||
emergency = TRUE
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "Emergency access is already enabled!")
|
||||
|
||||
/obj/machinery/door/airlock/proc/emergency_off(mob/user)
|
||||
if(!user_allowed(user))
|
||||
return
|
||||
if (emergency)
|
||||
emergency = FALSE
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "Emergency access is already disabled!")
|
||||
|
||||
/obj/machinery/door/airlock/proc/bolt_raise(mob/user)
|
||||
/obj/machinery/door/airlock/proc/toggle_bolt(mob/user)
|
||||
if(!user_allowed(user))
|
||||
return
|
||||
if(wires.is_cut(WIRE_BOLTS))
|
||||
to_chat(user, "The door bolt drop wire is cut - you can't raise the door bolts")
|
||||
else if(!src.locked)
|
||||
to_chat(user, "The door bolts are already up")
|
||||
else
|
||||
if(src.hasPower())
|
||||
unbolt()
|
||||
to_chat(user, "<span class='warning'>The door bolt drop wire is cut - you can't toggle the door bolts.</span>")
|
||||
return
|
||||
if(locked)
|
||||
if(!hasPower())
|
||||
to_chat(user, "<span class='warning'>The door has no power - you can't raise the door bolts.</span>")
|
||||
else
|
||||
to_chat(user, "Cannot raise door bolts due to power failure")
|
||||
|
||||
/obj/machinery/door/airlock/proc/bolt_drop(mob/user)
|
||||
if(!user_allowed(user))
|
||||
return
|
||||
if(wires.is_cut(WIRE_BOLTS))
|
||||
to_chat(user, "You can't drop the door bolts - The door bolt dropping wire has been cut.")
|
||||
unbolt()
|
||||
else
|
||||
bolt()
|
||||
|
||||
/obj/machinery/door/airlock/proc/toggle_emergency(mob/user)
|
||||
if(!user_allowed(user))
|
||||
return
|
||||
emergency = !emergency
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/airlock/proc/user_toggle_open(mob/user)
|
||||
if(!user_allowed(user))
|
||||
return
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "airlock_electronics", name, 975, 420, master_ui, state)
|
||||
ui = new(user, src, ui_key, "airlock_electronics", name, 420, 485, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/electronics/airlock/ui_data()
|
||||
@@ -43,13 +43,16 @@
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("clear")
|
||||
if("clear_all")
|
||||
accesses = list()
|
||||
one_access = 0
|
||||
. = TRUE
|
||||
if("one_access")
|
||||
one_access = !one_access
|
||||
. = TRUE
|
||||
if("grant_all")
|
||||
accesses = get_all_accesses()
|
||||
. = TRUE
|
||||
if("set")
|
||||
var/access = text2num(params["access"])
|
||||
if (!(access in accesses))
|
||||
|
||||
@@ -1,256 +1,256 @@
|
||||
#define CHARS_PER_LINE 5
|
||||
#define FONT_SIZE "5pt"
|
||||
#define FONT_COLOR "#09f"
|
||||
#define FONT_STYLE "Arial Black"
|
||||
#define MAX_TIMER 9000
|
||||
|
||||
#define PRESET_SHORT 1200
|
||||
#define PRESET_MEDIUM 1800
|
||||
#define PRESET_LONG 3000
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Brig Door control displays.
|
||||
// Description: This is a controls the timer for the brig doors, displays the timer on itself and
|
||||
// has a popup window when used, allowing to set the timer.
|
||||
// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code
|
||||
// Date: 01/September/2010
|
||||
// Programmer: Veryinky
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/machinery/door_timer
|
||||
name = "door timer"
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
desc = "A remote control for a door."
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
density = FALSE
|
||||
var/id = null // id of linked machinery/lockers
|
||||
|
||||
var/activation_time = 0
|
||||
var/timer_duration = 0
|
||||
|
||||
var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing
|
||||
var/list/obj/machinery/targets = list()
|
||||
var/obj/item/radio/Radio //needed to send messages to sec radio
|
||||
|
||||
maptext_height = 26
|
||||
maptext_width = 32
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
|
||||
Radio = new/obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
if(id != null)
|
||||
for(var/obj/machinery/door/window/brigdoor/M in urange(20, src))
|
||||
if (M.id == id)
|
||||
targets += M
|
||||
|
||||
for(var/obj/machinery/flasher/F in urange(20, src))
|
||||
if(F.id == id)
|
||||
targets += F
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src))
|
||||
if(C.id == id)
|
||||
targets += C
|
||||
|
||||
if(!targets.len)
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
|
||||
//Main door timer loop, if it's timing and time is >0 reduce time by 1.
|
||||
// if it's less than 0, open door, reset timer
|
||||
// update the door_timer window and the icon
|
||||
/obj/machinery/door_timer/process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(timing)
|
||||
if(world.realtime - activation_time >= timer_duration)
|
||||
timer_end() // open doors, reset timer, clear status screen
|
||||
update_icon()
|
||||
|
||||
// has the door power sitatuation changed, if so update icon.
|
||||
/obj/machinery/door_timer/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
// open/closedoor checks if door_timer has power, if so it checks if the
|
||||
// linked door is open/closed (by density) then opens it/closes it.
|
||||
/obj/machinery/door_timer/proc/timer_start()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
activation_time = world.realtime
|
||||
timing = TRUE
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened && !C.close())
|
||||
continue
|
||||
C.locked = TRUE
|
||||
C.update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/timer_end(forced = FALSE)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
if(!forced)
|
||||
Radio.set_frequency(FREQ_SECURITY)
|
||||
Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY)
|
||||
|
||||
timing = FALSE
|
||||
activation_time = null
|
||||
set_timer(0)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(!door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened)
|
||||
continue
|
||||
C.locked = FALSE
|
||||
C.update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/time_left(seconds = FALSE)
|
||||
. = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0))
|
||||
if(seconds)
|
||||
. /= 10
|
||||
|
||||
/obj/machinery/door_timer/proc/set_timer(value)
|
||||
var/new_time = CLAMP(value,0,MAX_TIMER)
|
||||
. = new_time == timer_duration //return 1 on no change
|
||||
timer_duration = new_time
|
||||
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "brig_timer", name, 300, 200, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
//icon update function
|
||||
// if NOPOWER, display blank
|
||||
// if BROKEN, display blue screen of death icon AI uses
|
||||
// if timing=true, run update display function
|
||||
/obj/machinery/door_timer/update_icon()
|
||||
if(stat & (NOPOWER))
|
||||
icon_state = "frame"
|
||||
return
|
||||
|
||||
if(stat & (BROKEN))
|
||||
set_picture("ai_bsod")
|
||||
return
|
||||
|
||||
if(timing)
|
||||
var/disp1 = id
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]"
|
||||
if(length(disp2) > CHARS_PER_LINE)
|
||||
disp2 = "Error"
|
||||
update_display(disp1, disp2)
|
||||
else
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
return
|
||||
|
||||
|
||||
// Adds an icon in case the screen is broken/off, stolen from status_display.dm
|
||||
/obj/machinery/door_timer/proc/set_picture(state)
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
cut_overlays()
|
||||
add_overlay(mutable_appearance('icons/obj/status_display.dmi', state))
|
||||
|
||||
|
||||
//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display
|
||||
// Stolen from status_display
|
||||
/obj/machinery/door_timer/proc/update_display(line1, line2)
|
||||
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
|
||||
if(maptext != new_text)
|
||||
maptext = new_text
|
||||
|
||||
/obj/machinery/door_timer/ui_data()
|
||||
var/list/data = list()
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
data["seconds"] = round(time_left % 60)
|
||||
data["minutes"] = round((time_left - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["flash_charging"] = FALSE
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
data["flash_charging"] = TRUE
|
||||
break
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/door_timer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("time")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(value)
|
||||
. = set_timer(time_left()+value)
|
||||
if("start")
|
||||
timer_start()
|
||||
if("stop")
|
||||
timer_end(forced = TRUE)
|
||||
if("flash")
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
F.flash()
|
||||
if("preset")
|
||||
var/preset = params["preset"]
|
||||
var/preset_time = time_left()
|
||||
switch(preset)
|
||||
if("short")
|
||||
preset_time = PRESET_SHORT
|
||||
if("medium")
|
||||
preset_time = PRESET_MEDIUM
|
||||
if("long")
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = world.realtime
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
#undef PRESET_SHORT
|
||||
#undef PRESET_MEDIUM
|
||||
#undef PRESET_LONG
|
||||
|
||||
#undef MAX_TIMER
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef CHARS_PER_LINE
|
||||
#define CHARS_PER_LINE 5
|
||||
#define FONT_SIZE "5pt"
|
||||
#define FONT_COLOR "#09f"
|
||||
#define FONT_STYLE "Arial Black"
|
||||
#define MAX_TIMER 9000
|
||||
|
||||
#define PRESET_SHORT 1200
|
||||
#define PRESET_MEDIUM 1800
|
||||
#define PRESET_LONG 3000
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Brig Door control displays.
|
||||
// Description: This is a controls the timer for the brig doors, displays the timer on itself and
|
||||
// has a popup window when used, allowing to set the timer.
|
||||
// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code
|
||||
// Date: 01/September/2010
|
||||
// Programmer: Veryinky
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/machinery/door_timer
|
||||
name = "door timer"
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
desc = "A remote control for a door."
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
density = FALSE
|
||||
var/id = null // id of linked machinery/lockers
|
||||
|
||||
var/activation_time = 0
|
||||
var/timer_duration = 0
|
||||
|
||||
var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing
|
||||
var/list/obj/machinery/targets = list()
|
||||
var/obj/item/radio/Radio //needed to send messages to sec radio
|
||||
|
||||
maptext_height = 26
|
||||
maptext_width = 32
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
|
||||
Radio = new/obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
if(id != null)
|
||||
for(var/obj/machinery/door/window/brigdoor/M in urange(20, src))
|
||||
if (M.id == id)
|
||||
targets += M
|
||||
|
||||
for(var/obj/machinery/flasher/F in urange(20, src))
|
||||
if(F.id == id)
|
||||
targets += F
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src))
|
||||
if(C.id == id)
|
||||
targets += C
|
||||
|
||||
if(!targets.len)
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
|
||||
//Main door timer loop, if it's timing and time is >0 reduce time by 1.
|
||||
// if it's less than 0, open door, reset timer
|
||||
// update the door_timer window and the icon
|
||||
/obj/machinery/door_timer/process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(timing)
|
||||
if(world.realtime - activation_time >= timer_duration)
|
||||
timer_end() // open doors, reset timer, clear status screen
|
||||
update_icon()
|
||||
|
||||
// has the door power sitatuation changed, if so update icon.
|
||||
/obj/machinery/door_timer/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
// open/closedoor checks if door_timer has power, if so it checks if the
|
||||
// linked door is open/closed (by density) then opens it/closes it.
|
||||
/obj/machinery/door_timer/proc/timer_start()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
activation_time = world.realtime
|
||||
timing = TRUE
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened && !C.close())
|
||||
continue
|
||||
C.locked = TRUE
|
||||
C.update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/timer_end(forced = FALSE)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
if(!forced)
|
||||
Radio.set_frequency(FREQ_SECURITY)
|
||||
Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY)
|
||||
|
||||
timing = FALSE
|
||||
activation_time = null
|
||||
set_timer(0)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(!door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened)
|
||||
continue
|
||||
C.locked = FALSE
|
||||
C.update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/time_left(seconds = FALSE)
|
||||
. = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0))
|
||||
if(seconds)
|
||||
. /= 10
|
||||
|
||||
/obj/machinery/door_timer/proc/set_timer(value)
|
||||
var/new_time = CLAMP(value,0,MAX_TIMER)
|
||||
. = new_time == timer_duration //return 1 on no change
|
||||
timer_duration = new_time
|
||||
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "brig_timer", name, 300, 138, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
//icon update function
|
||||
// if NOPOWER, display blank
|
||||
// if BROKEN, display blue screen of death icon AI uses
|
||||
// if timing=true, run update display function
|
||||
/obj/machinery/door_timer/update_icon()
|
||||
if(stat & (NOPOWER))
|
||||
icon_state = "frame"
|
||||
return
|
||||
|
||||
if(stat & (BROKEN))
|
||||
set_picture("ai_bsod")
|
||||
return
|
||||
|
||||
if(timing)
|
||||
var/disp1 = id
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]"
|
||||
if(length(disp2) > CHARS_PER_LINE)
|
||||
disp2 = "Error"
|
||||
update_display(disp1, disp2)
|
||||
else
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
return
|
||||
|
||||
|
||||
// Adds an icon in case the screen is broken/off, stolen from status_display.dm
|
||||
/obj/machinery/door_timer/proc/set_picture(state)
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
cut_overlays()
|
||||
add_overlay(mutable_appearance('icons/obj/status_display.dmi', state))
|
||||
|
||||
|
||||
//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display
|
||||
// Stolen from status_display
|
||||
/obj/machinery/door_timer/proc/update_display(line1, line2)
|
||||
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
|
||||
if(maptext != new_text)
|
||||
maptext = new_text
|
||||
|
||||
/obj/machinery/door_timer/ui_data()
|
||||
var/list/data = list()
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
data["seconds"] = round(time_left % 60)
|
||||
data["minutes"] = round((time_left - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["flash_charging"] = FALSE
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
data["flash_charging"] = TRUE
|
||||
break
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/door_timer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("time")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(value)
|
||||
. = set_timer(time_left()+value)
|
||||
if("start")
|
||||
timer_start()
|
||||
if("stop")
|
||||
timer_end(forced = TRUE)
|
||||
if("flash")
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
F.flash()
|
||||
if("preset")
|
||||
var/preset = params["preset"]
|
||||
var/preset_time = time_left()
|
||||
switch(preset)
|
||||
if("short")
|
||||
preset_time = PRESET_SHORT
|
||||
if("medium")
|
||||
preset_time = PRESET_MEDIUM
|
||||
if("long")
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = world.realtime
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
#undef PRESET_SHORT
|
||||
#undef PRESET_MEDIUM
|
||||
#undef PRESET_LONG
|
||||
|
||||
#undef MAX_TIMER
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef CHARS_PER_LINE
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "gulag_item_reclaimer", name, 455, 440, master_ui, state)
|
||||
ui = new(user, src, ui_key, "gulag_item_reclaimer", name, 300, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
|
||||
|
||||
@@ -1,443 +1,453 @@
|
||||
// SUIT STORAGE UNIT /////////////////
|
||||
/obj/machinery/suit_storage_unit
|
||||
name = "suit storage unit"
|
||||
desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
|
||||
icon = 'icons/obj/machines/suit_storage.dmi'
|
||||
icon_state = "close"
|
||||
density = TRUE
|
||||
max_integrity = 250
|
||||
|
||||
var/obj/item/clothing/suit/space/suit = null
|
||||
var/obj/item/clothing/head/helmet/space/helmet = null
|
||||
var/obj/item/clothing/mask/mask = null
|
||||
var/obj/item/storage = null
|
||||
|
||||
var/suit_type = null
|
||||
var/helmet_type = null
|
||||
var/mask_type = null
|
||||
var/storage_type = null
|
||||
|
||||
state_open = FALSE
|
||||
var/locked = FALSE
|
||||
panel_open = FALSE
|
||||
var/safeties = TRUE
|
||||
|
||||
var/uv = FALSE
|
||||
var/uv_super = FALSE
|
||||
var/uv_cycles = 6
|
||||
var/message_cooldown
|
||||
var/breakout_time = 300
|
||||
|
||||
/obj/machinery/suit_storage_unit/standard_unit
|
||||
suit_type = /obj/item/clothing/suit/space/eva
|
||||
helmet_type = /obj/item/clothing/head/helmet/space/eva
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/captain
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/captain
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/captain
|
||||
|
||||
/obj/machinery/suit_storage_unit/engine
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots
|
||||
|
||||
/obj/machinery/suit_storage_unit/ce
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots/advance
|
||||
|
||||
/obj/machinery/suit_storage_unit/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/security
|
||||
|
||||
/obj/machinery/suit_storage_unit/hos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/internals/oxygen
|
||||
|
||||
/obj/machinery/suit_storage_unit/atmos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
|
||||
mask_type = /obj/item/clothing/mask/gas
|
||||
storage_type = /obj/item/watertank/atmos
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining
|
||||
suit_type = /obj/item/clothing/suit/hooded/explorer/standard
|
||||
mask_type = /obj/item/clothing/mask/gas/explorer
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining/eva
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/cmo
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/rd
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/syndicate
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
mask_type = /obj/item/clothing/mask/gas/syndicate
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/harness
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/command
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/engineer
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/medical
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/radsuit
|
||||
name = "radiation suit storage unit"
|
||||
suit_type = /obj/item/clothing/suit/radiation
|
||||
helmet_type = /obj/item/clothing/head/radiation
|
||||
storage_type = /obj/item/geiger_counter
|
||||
|
||||
/obj/machinery/suit_storage_unit/open
|
||||
state_open = TRUE
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/suit_storage_unit/Initialize()
|
||||
. = ..()
|
||||
wires = new /datum/wires/suit_storage_unit(src)
|
||||
if(suit_type)
|
||||
suit = new suit_type(src)
|
||||
if(helmet_type)
|
||||
helmet = new helmet_type(src)
|
||||
if(mask_type)
|
||||
mask = new mask_type(src)
|
||||
if(storage_type)
|
||||
storage = new storage_type(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/Destroy()
|
||||
QDEL_NULL(suit)
|
||||
QDEL_NULL(helmet)
|
||||
QDEL_NULL(mask)
|
||||
QDEL_NULL(storage)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
if(uv)
|
||||
if(uv_super)
|
||||
add_overlay("super")
|
||||
else if(occupant)
|
||||
add_overlay("uvhuman")
|
||||
else
|
||||
add_overlay("uv")
|
||||
else if(state_open)
|
||||
if(stat & BROKEN)
|
||||
add_overlay("broken")
|
||||
else
|
||||
add_overlay("open")
|
||||
if(suit)
|
||||
add_overlay("suit")
|
||||
if(helmet)
|
||||
add_overlay("helm")
|
||||
if(storage)
|
||||
add_overlay("storage")
|
||||
else if(occupant)
|
||||
add_overlay("human")
|
||||
|
||||
/obj/machinery/suit_storage_unit/power_change()
|
||||
..()
|
||||
if(!is_operational() && state_open)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/dump_contents()
|
||||
dropContents()
|
||||
helmet = null
|
||||
suit = null
|
||||
mask = null
|
||||
storage = null
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
open_machine()
|
||||
dump_contents()
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
|
||||
return
|
||||
var/mob/living/target = A
|
||||
if(!state_open)
|
||||
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
|
||||
return
|
||||
if(!is_operational())
|
||||
to_chat(user, "<span class='warning'>The unit is not operational!</span>")
|
||||
return
|
||||
if(occupant || helmet || suit || storage)
|
||||
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
|
||||
return
|
||||
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
|
||||
|
||||
if(do_mob(user, target, 30))
|
||||
if(occupant || helmet || suit || storage)
|
||||
return
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind [user.p_them()]!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
|
||||
close_machine(target)
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/cook()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_cycles)
|
||||
uv_cycles--
|
||||
uv = TRUE
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
if(occupant)
|
||||
if(uv_super)
|
||||
mob_occupant.adjustFireLoss(rand(20, 36))
|
||||
else
|
||||
mob_occupant.adjustFireLoss(rand(10, 16))
|
||||
mob_occupant.emote("scream")
|
||||
addtimer(CALLBACK(src, .proc/cook), 50)
|
||||
else
|
||||
uv_cycles = initial(uv_cycles)
|
||||
uv = FALSE
|
||||
locked = FALSE
|
||||
if(uv_super)
|
||||
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
|
||||
helmet = null
|
||||
qdel(helmet)
|
||||
suit = null
|
||||
qdel(suit) // Delete everything but the occupant.
|
||||
mask = null
|
||||
qdel(mask)
|
||||
storage = null
|
||||
qdel(storage)
|
||||
// The wires get damaged too.
|
||||
wires.cut_all()
|
||||
else
|
||||
if(!occupant)
|
||||
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
|
||||
mob_occupant.radiation = 0
|
||||
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
|
||||
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
|
||||
if(suit)
|
||||
things_to_clear += suit
|
||||
things_to_clear += suit.GetAllContents()
|
||||
if(helmet)
|
||||
things_to_clear += helmet
|
||||
things_to_clear += helmet.GetAllContents()
|
||||
if(mask)
|
||||
things_to_clear += mask
|
||||
things_to_clear += mask.GetAllContents()
|
||||
if(storage)
|
||||
things_to_clear += storage
|
||||
things_to_clear += storage.GetAllContents()
|
||||
if(occupant)
|
||||
things_to_clear += occupant
|
||||
things_to_clear += occupant.GetAllContents()
|
||||
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
|
||||
AM.clean_blood()
|
||||
AM.fingerprints = list()
|
||||
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
|
||||
if(contamination)
|
||||
qdel(contamination)
|
||||
open_machine(FALSE)
|
||||
if(occupant)
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
|
||||
if(!prob(prb))
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if(electrocute_mob(user, src, src, 1, TRUE))
|
||||
return 1
|
||||
|
||||
/obj/machinery/suit_storage_unit/relaymove(mob/user)
|
||||
if(locked)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
return
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/container_resist(mob/living/user)
|
||||
if(!locked)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a thump from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src )
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
add_fingerprint(user)
|
||||
if(locked)
|
||||
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors...</span>")
|
||||
addtimer(CALLBACK(src, .proc/resist_open, user), 300)
|
||||
else
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
|
||||
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
|
||||
visible_message("<span class='notice'>You see [user] burst out of [src]!</span>", \
|
||||
"<span class='notice'>You escape the cramped confines of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
|
||||
if(state_open && is_operational())
|
||||
if(istype(I, /obj/item/clothing/head/mob_holder))
|
||||
to_chat(user, "<span class='warning'>You can't quite fit that in while you hold it!</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/clothing/suit))
|
||||
if(suit)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
suit = I
|
||||
else if(istype(I, /obj/item/clothing/head))
|
||||
if(helmet)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
helmet = I
|
||||
else if(istype(I, /obj/item/clothing/mask))
|
||||
if(mask)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
mask = I
|
||||
else
|
||||
if(storage)
|
||||
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
storage = I
|
||||
|
||||
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(panel_open && is_wire_tool(I))
|
||||
wires.interact(user)
|
||||
return
|
||||
if(!state_open)
|
||||
if(default_deconstruction_screwdriver(user, "panel", "close", I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
dump_contents()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
var/list/data = list()
|
||||
data["locked"] = locked
|
||||
data["open"] = state_open
|
||||
data["safeties"] = safeties
|
||||
data["uv_active"] = uv
|
||||
data["uv_super"] = uv_super
|
||||
if(helmet)
|
||||
data["helmet"] = helmet.name
|
||||
if(suit)
|
||||
data["suit"] = suit.name
|
||||
if(mask)
|
||||
data["mask"] = mask.name
|
||||
if(storage)
|
||||
data["storage"] = storage.name
|
||||
if(occupant)
|
||||
data["occupied"] = 1
|
||||
return data
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_act(action, params)
|
||||
if(..() || uv)
|
||||
return
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine(0)
|
||||
if(occupant)
|
||||
dump_contents() // Dump out contents if someone is in there.
|
||||
. = TRUE
|
||||
if("lock")
|
||||
if(state_open)
|
||||
return
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("uv")
|
||||
if(occupant && safeties)
|
||||
return
|
||||
else if(!helmet && !mask && !suit && !storage && !occupant)
|
||||
return
|
||||
else
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
|
||||
cook()
|
||||
. = TRUE
|
||||
if("dispense")
|
||||
if(!state_open)
|
||||
return
|
||||
|
||||
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
|
||||
var/item_name = params["item"]
|
||||
if(item_name in valid_items)
|
||||
var/obj/item/I = vars[item_name]
|
||||
vars[item_name] = null
|
||||
if(I)
|
||||
I.forceMove(loc)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
// SUIT STORAGE UNIT /////////////////
|
||||
/obj/machinery/suit_storage_unit
|
||||
name = "suit storage unit"
|
||||
desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
|
||||
icon = 'icons/obj/machines/suit_storage.dmi'
|
||||
icon_state = "close"
|
||||
density = TRUE
|
||||
max_integrity = 250
|
||||
|
||||
var/obj/item/clothing/suit/space/suit = null
|
||||
var/obj/item/clothing/head/helmet/space/helmet = null
|
||||
var/obj/item/clothing/mask/mask = null
|
||||
var/obj/item/storage = null
|
||||
|
||||
var/suit_type = null
|
||||
var/helmet_type = null
|
||||
var/mask_type = null
|
||||
var/storage_type = null
|
||||
|
||||
state_open = FALSE
|
||||
var/locked = FALSE
|
||||
panel_open = FALSE
|
||||
var/safeties = TRUE
|
||||
|
||||
var/uv = FALSE
|
||||
var/uv_super = FALSE
|
||||
var/uv_cycles = 6
|
||||
var/message_cooldown
|
||||
var/breakout_time = 300
|
||||
|
||||
/obj/machinery/suit_storage_unit/standard_unit
|
||||
suit_type = /obj/item/clothing/suit/space/eva
|
||||
helmet_type = /obj/item/clothing/head/helmet/space/eva
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/captain
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/captain
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/captain
|
||||
|
||||
/obj/machinery/suit_storage_unit/engine
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots
|
||||
|
||||
/obj/machinery/suit_storage_unit/ce
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots/advance
|
||||
|
||||
/obj/machinery/suit_storage_unit/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/security
|
||||
|
||||
/obj/machinery/suit_storage_unit/hos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/internals/oxygen
|
||||
|
||||
/obj/machinery/suit_storage_unit/atmos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
|
||||
mask_type = /obj/item/clothing/mask/gas
|
||||
storage_type = /obj/item/watertank/atmos
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining
|
||||
suit_type = /obj/item/clothing/suit/hooded/explorer/standard
|
||||
mask_type = /obj/item/clothing/mask/gas/explorer
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining/eva
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/cmo
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/rd
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/syndicate
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
mask_type = /obj/item/clothing/mask/gas/syndicate
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/harness
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/command
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/engineer
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/medical
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/radsuit
|
||||
name = "radiation suit storage unit"
|
||||
suit_type = /obj/item/clothing/suit/radiation
|
||||
helmet_type = /obj/item/clothing/head/radiation
|
||||
storage_type = /obj/item/geiger_counter
|
||||
|
||||
/obj/machinery/suit_storage_unit/open
|
||||
state_open = TRUE
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/suit_storage_unit/Initialize()
|
||||
. = ..()
|
||||
wires = new /datum/wires/suit_storage_unit(src)
|
||||
if(suit_type)
|
||||
suit = new suit_type(src)
|
||||
if(helmet_type)
|
||||
helmet = new helmet_type(src)
|
||||
if(mask_type)
|
||||
mask = new mask_type(src)
|
||||
if(storage_type)
|
||||
storage = new storage_type(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/Destroy()
|
||||
QDEL_NULL(suit)
|
||||
QDEL_NULL(helmet)
|
||||
QDEL_NULL(mask)
|
||||
QDEL_NULL(storage)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
if(uv)
|
||||
if(uv_super)
|
||||
add_overlay("super")
|
||||
else if(occupant)
|
||||
add_overlay("uvhuman")
|
||||
else
|
||||
add_overlay("uv")
|
||||
else if(state_open)
|
||||
if(stat & BROKEN)
|
||||
add_overlay("broken")
|
||||
else
|
||||
add_overlay("open")
|
||||
if(suit)
|
||||
add_overlay("suit")
|
||||
if(helmet)
|
||||
add_overlay("helm")
|
||||
if(storage)
|
||||
add_overlay("storage")
|
||||
else if(occupant)
|
||||
add_overlay("human")
|
||||
|
||||
/obj/machinery/suit_storage_unit/power_change()
|
||||
..()
|
||||
if(!is_operational() && state_open)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/dump_contents()
|
||||
dropContents()
|
||||
helmet = null
|
||||
suit = null
|
||||
mask = null
|
||||
storage = null
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
open_machine()
|
||||
dump_contents()
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
|
||||
return
|
||||
var/mob/living/target = A
|
||||
if(!state_open)
|
||||
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
|
||||
return
|
||||
if(!is_operational())
|
||||
to_chat(user, "<span class='warning'>The unit is not operational!</span>")
|
||||
return
|
||||
if(occupant || helmet || suit || storage)
|
||||
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
|
||||
return
|
||||
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
|
||||
|
||||
if(do_mob(user, target, 30))
|
||||
if(occupant || helmet || suit || storage)
|
||||
return
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind [user.p_them()]!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
|
||||
close_machine(target)
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/cook()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_cycles)
|
||||
uv_cycles--
|
||||
uv = TRUE
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
if(occupant)
|
||||
if(uv_super)
|
||||
mob_occupant.adjustFireLoss(rand(20, 36))
|
||||
else
|
||||
mob_occupant.adjustFireLoss(rand(10, 16))
|
||||
mob_occupant.emote("scream")
|
||||
addtimer(CALLBACK(src, .proc/cook), 50)
|
||||
else
|
||||
uv_cycles = initial(uv_cycles)
|
||||
uv = FALSE
|
||||
locked = FALSE
|
||||
if(uv_super)
|
||||
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
|
||||
helmet = null
|
||||
qdel(helmet)
|
||||
suit = null
|
||||
qdel(suit) // Delete everything but the occupant.
|
||||
mask = null
|
||||
qdel(mask)
|
||||
storage = null
|
||||
qdel(storage)
|
||||
// The wires get damaged too.
|
||||
wires.cut_all()
|
||||
else
|
||||
if(!occupant)
|
||||
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
|
||||
mob_occupant.radiation = 0
|
||||
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
|
||||
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
|
||||
if(suit)
|
||||
things_to_clear += suit
|
||||
things_to_clear += suit.GetAllContents()
|
||||
if(helmet)
|
||||
things_to_clear += helmet
|
||||
things_to_clear += helmet.GetAllContents()
|
||||
if(mask)
|
||||
things_to_clear += mask
|
||||
things_to_clear += mask.GetAllContents()
|
||||
if(storage)
|
||||
things_to_clear += storage
|
||||
things_to_clear += storage.GetAllContents()
|
||||
if(occupant)
|
||||
things_to_clear += occupant
|
||||
things_to_clear += occupant.GetAllContents()
|
||||
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
|
||||
AM.clean_blood()
|
||||
AM.fingerprints = list()
|
||||
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
|
||||
if(contamination)
|
||||
qdel(contamination)
|
||||
open_machine(FALSE)
|
||||
if(occupant)
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
|
||||
if(!prob(prb))
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if(electrocute_mob(user, src, src, 1, TRUE))
|
||||
return 1
|
||||
|
||||
/obj/machinery/suit_storage_unit/relaymove(mob/user)
|
||||
if(locked)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
return
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/container_resist(mob/living/user)
|
||||
if(!locked)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a thump from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src )
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
add_fingerprint(user)
|
||||
if(locked)
|
||||
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors...</span>")
|
||||
addtimer(CALLBACK(src, .proc/resist_open, user), 300)
|
||||
else
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
|
||||
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
|
||||
visible_message("<span class='notice'>You see [user] burst out of [src]!</span>", \
|
||||
"<span class='notice'>You escape the cramped confines of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
|
||||
if(state_open && is_operational())
|
||||
if(istype(I, /obj/item/clothing/head/mob_holder))
|
||||
to_chat(user, "<span class='warning'>You can't quite fit that in while you hold it!</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/clothing/suit))
|
||||
if(suit)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
suit = I
|
||||
else if(istype(I, /obj/item/clothing/head))
|
||||
if(helmet)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
helmet = I
|
||||
else if(istype(I, /obj/item/clothing/mask))
|
||||
if(mask)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
mask = I
|
||||
else
|
||||
if(storage)
|
||||
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
storage = I
|
||||
|
||||
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(panel_open && is_wire_tool(I))
|
||||
wires.interact(user)
|
||||
return
|
||||
if(!state_open)
|
||||
if(default_deconstruction_screwdriver(user, "panel", "close", I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
dump_contents()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
var/list/data = list()
|
||||
data["locked"] = locked
|
||||
data["open"] = state_open
|
||||
data["safeties"] = safeties
|
||||
data["uv_active"] = uv
|
||||
data["uv_super"] = uv_super
|
||||
if(helmet)
|
||||
data["helmet"] = helmet.name
|
||||
else
|
||||
data["helmet"] = null
|
||||
if(suit)
|
||||
data["suit"] = suit.name
|
||||
else
|
||||
data["suit"] = null
|
||||
if(mask)
|
||||
data["mask"] = mask.name
|
||||
else
|
||||
data["mask"] = null
|
||||
if(storage)
|
||||
data["storage"] = storage.name
|
||||
else
|
||||
data["storage"] = null
|
||||
if(occupant)
|
||||
data["occupied"] = TRUE
|
||||
else
|
||||
data["occupied"] = FALSE
|
||||
return data
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_act(action, params)
|
||||
if(..() || uv)
|
||||
return
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine(0)
|
||||
if(occupant)
|
||||
dump_contents() // Dump out contents if someone is in there.
|
||||
. = TRUE
|
||||
if("lock")
|
||||
if(state_open)
|
||||
return
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("uv")
|
||||
if(occupant && safeties)
|
||||
return
|
||||
else if(!helmet && !mask && !suit && !storage && !occupant)
|
||||
return
|
||||
else
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
|
||||
cook()
|
||||
. = TRUE
|
||||
if("dispense")
|
||||
if(!state_open)
|
||||
return
|
||||
|
||||
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
|
||||
var/item_name = params["item"]
|
||||
if(item_name in valid_items)
|
||||
var/obj/item/I = vars[item_name]
|
||||
vars[item_name] = null
|
||||
if(I)
|
||||
I.forceMove(loc)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "mech_bay_power_console", "Mech Bay Power Control Console", 400, 170, master_ui, state)
|
||||
ui = new(user, src, ui_key, "mech_bay_power_console", "Mech Bay Power Control Console", 400, 200, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_act(action, params)
|
||||
@@ -96,7 +96,7 @@
|
||||
if(recharge_port && !QDELETED(recharge_port))
|
||||
data["recharge_port"] = list("mech" = null)
|
||||
if(recharge_port.recharging_mech && !QDELETED(recharge_port.recharging_mech))
|
||||
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null)
|
||||
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null, "name" = recharge_port.recharging_mech.name,)
|
||||
if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell))
|
||||
data["recharge_port"]["mech"]["cell"] = list(
|
||||
"critfail" = recharge_port.recharging_mech.cell.crit_fail,
|
||||
|
||||
@@ -246,7 +246,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
|
||||
assets.send(user)
|
||||
|
||||
ui = new(user, src, ui_key, "rpd", name, 300, 550, master_ui, state)
|
||||
ui = new(user, src, ui_key, "rpd", name, 425, 472, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/pipe_dispenser/ui_data(mob/user)
|
||||
@@ -313,9 +313,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
playeffect = FALSE
|
||||
if("mode")
|
||||
var/n = text2num(params["mode"])
|
||||
if(n == 2 && !(mode&1) && !(mode&2))
|
||||
mode |= 3
|
||||
else if(mode&n)
|
||||
if(mode & n)
|
||||
mode &= ~n
|
||||
else
|
||||
mode |= n
|
||||
@@ -324,6 +322,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
spark_system.start()
|
||||
effectcooldown = world.time + 100
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
|
||||
return TRUE
|
||||
|
||||
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
|
||||
if(!user.IsAdvancedToolUser() || istype(A, /turf/open/space/transit))
|
||||
|
||||
@@ -1,228 +1,226 @@
|
||||
GLOBAL_LIST_EMPTY(GPS_list)
|
||||
/obj/item/gps
|
||||
name = "global positioning system"
|
||||
desc = "Helping lost spacemen find their way through the planets since 2016."
|
||||
icon = 'icons/obj/telescience.dmi'
|
||||
icon_state = "gps-c"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
obj_flags = UNIQUE_RENAME
|
||||
var/gpstag = "COM0"
|
||||
var/emped = FALSE
|
||||
var/tracking = TRUE
|
||||
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
|
||||
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
|
||||
|
||||
/obj/item/gps/examine(mob/user)
|
||||
. = ..()
|
||||
var/turf/curr = get_turf(src)
|
||||
. += "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
|
||||
. += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
|
||||
|
||||
/obj/item/gps/Initialize()
|
||||
. = ..()
|
||||
GLOB.GPS_list += src
|
||||
name = "global positioning system ([gpstag])"
|
||||
add_overlay("working")
|
||||
|
||||
/obj/item/gps/Destroy()
|
||||
GLOB.GPS_list -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
emped = TRUE
|
||||
cut_overlay("working")
|
||||
add_overlay("emp")
|
||||
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
|
||||
SStgui.close_uis(src) //Close the UI control if it is open.
|
||||
|
||||
/obj/item/gps/proc/reboot()
|
||||
emped = FALSE
|
||||
cut_overlay("emp")
|
||||
add_overlay("working")
|
||||
|
||||
/obj/item/gps/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
toggletracking(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/gps/proc/toggletracking(mob/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
return //user not valid to use gps
|
||||
if(emped)
|
||||
to_chat(user, "It's busted!")
|
||||
return
|
||||
if(tracking)
|
||||
cut_overlay("working")
|
||||
to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.")
|
||||
tracking = FALSE
|
||||
else
|
||||
add_overlay("working")
|
||||
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
|
||||
tracking = TRUE
|
||||
|
||||
|
||||
/obj/item/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
|
||||
if(emped)
|
||||
to_chat(user, "[src] fizzles weakly.")
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
var/gps_window_height = 300 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
|
||||
ui = new(user, src, ui_key, "gps", "Global Positioning System", 600, gps_window_height, master_ui, state) //width, height
|
||||
ui.open()
|
||||
|
||||
ui.set_autoupdate(state = updating)
|
||||
|
||||
|
||||
/obj/item/gps/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["power"] = tracking
|
||||
data["tag"] = gpstag
|
||||
data["updating"] = updating
|
||||
data["globalmode"] = global_mode
|
||||
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
|
||||
return data
|
||||
|
||||
var/turf/curr = get_turf(src)
|
||||
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
|
||||
|
||||
var/list/signals = list()
|
||||
data["signals"] = list()
|
||||
|
||||
for(var/gps in GLOB.GPS_list)
|
||||
var/obj/item/gps/G = gps
|
||||
if(G.emped || !G.tracking || G == src)
|
||||
continue
|
||||
var/turf/pos = get_turf(G)
|
||||
if(!global_mode && pos.z != curr.z)
|
||||
continue
|
||||
var/list/signal = list()
|
||||
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
|
||||
signal["area"] = get_area_name(G, TRUE)
|
||||
signal["coord"] = "[pos.x], [pos.y], [pos.z]"
|
||||
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
|
||||
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
|
||||
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
|
||||
var/direction = uppertext(dir2text(get_dir(curr, pos))) //Direction text (East, etc). Not as precise, but still helpful.
|
||||
if(!direction)
|
||||
direction = "CENTER"
|
||||
signal["degrees"] = "N/A"
|
||||
signal["direction"] = direction
|
||||
|
||||
signals += list(signal) //Add this signal to the list of signals
|
||||
data["signals"] = signals
|
||||
return data
|
||||
|
||||
|
||||
|
||||
/obj/item/gps/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("rename")
|
||||
var/a = input("Please enter desired tag.", name, gpstag) as text
|
||||
a = copytext(sanitize(a), 1, 20)
|
||||
gpstag = a
|
||||
. = TRUE
|
||||
name = "global positioning system ([gpstag])"
|
||||
|
||||
if("power")
|
||||
toggletracking(usr)
|
||||
. = TRUE
|
||||
if("updating")
|
||||
updating = !updating
|
||||
. = TRUE
|
||||
if("globalmode")
|
||||
global_mode = !global_mode
|
||||
. = TRUE
|
||||
|
||||
|
||||
/obj/item/gps/science
|
||||
icon_state = "gps-s"
|
||||
gpstag = "SCI0"
|
||||
|
||||
/obj/item/gps/engineering
|
||||
icon_state = "gps-e"
|
||||
gpstag = "ENG0"
|
||||
|
||||
/obj/item/gps/mining
|
||||
icon_state = "gps-m"
|
||||
gpstag = "MINE0"
|
||||
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
|
||||
|
||||
/obj/item/gps/cyborg
|
||||
icon_state = "gps-b"
|
||||
gpstag = "BORG0"
|
||||
desc = "A mining cyborg internal positioning system. Used as a recovery beacon for damaged cyborg assets, or a collaboration tool for mining teams."
|
||||
|
||||
/obj/item/gps/cyborg/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
|
||||
|
||||
/obj/item/gps/internal
|
||||
icon_state = null
|
||||
item_flags = ABSTRACT
|
||||
gpstag = "Eerie Signal"
|
||||
desc = "Report to a coder immediately."
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
var/obj/item/implant/gps/implant
|
||||
|
||||
/obj/item/gps/internal/Initialize(mapload, obj/item/implant/gps/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/gps/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/internal/mining
|
||||
icon_state = "gps-m"
|
||||
gpstag = "MINER"
|
||||
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
|
||||
|
||||
/obj/item/gps/internal/base
|
||||
gpstag = "NT_AUX"
|
||||
desc = "A homing signal from Nanotrasen's mining base."
|
||||
|
||||
/obj/item/gps/visible_debug
|
||||
name = "visible GPS"
|
||||
gpstag = "ADMIN"
|
||||
desc = "This admin-spawn GPS unit leaves the coordinates visible \
|
||||
on any turf that it passes over, for debugging. Especially useful \
|
||||
for marking the area around the transition edges."
|
||||
var/list/turf/tagged
|
||||
|
||||
/obj/item/gps/visible_debug/Initialize()
|
||||
. = ..()
|
||||
tagged = list()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/item/gps/visible_debug/process()
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
// I assume it's faster to color,tag and OR the turf in, rather
|
||||
// then checking if its there
|
||||
T.color = RANDOM_COLOUR
|
||||
T.maptext = "[T.x],[T.y],[T.z]"
|
||||
tagged |= T
|
||||
|
||||
/obj/item/gps/visible_debug/proc/clear()
|
||||
while(tagged.len)
|
||||
var/turf/T = pop(tagged)
|
||||
T.color = initial(T.color)
|
||||
T.maptext = initial(T.maptext)
|
||||
|
||||
/obj/item/gps/visible_debug/Destroy()
|
||||
if(tagged)
|
||||
clear()
|
||||
tagged = null
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
. = ..()
|
||||
GLOBAL_LIST_EMPTY(GPS_list)
|
||||
/obj/item/gps
|
||||
name = "global positioning system"
|
||||
desc = "Helping lost spacemen find their way through the planets since 2016."
|
||||
icon = 'icons/obj/telescience.dmi'
|
||||
icon_state = "gps-c"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
obj_flags = UNIQUE_RENAME
|
||||
var/gpstag = "COM0"
|
||||
var/emped = FALSE
|
||||
var/tracking = TRUE
|
||||
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
|
||||
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
|
||||
|
||||
/obj/item/gps/examine(mob/user)
|
||||
. = ..()
|
||||
var/turf/curr = get_turf(src)
|
||||
. += "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
|
||||
. += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
|
||||
|
||||
/obj/item/gps/Initialize()
|
||||
. = ..()
|
||||
GLOB.GPS_list += src
|
||||
name = "global positioning system ([gpstag])"
|
||||
add_overlay("working")
|
||||
|
||||
/obj/item/gps/Destroy()
|
||||
GLOB.GPS_list -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
emped = TRUE
|
||||
cut_overlay("working")
|
||||
add_overlay("emp")
|
||||
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
|
||||
SStgui.close_uis(src) //Close the UI control if it is open.
|
||||
|
||||
/obj/item/gps/proc/reboot()
|
||||
emped = FALSE
|
||||
cut_overlay("emp")
|
||||
add_overlay("working")
|
||||
|
||||
/obj/item/gps/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
toggletracking(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/gps/proc/toggletracking(mob/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
return //user not valid to use gps
|
||||
if(emped)
|
||||
to_chat(user, "It's busted!")
|
||||
return
|
||||
if(tracking)
|
||||
cut_overlay("working")
|
||||
to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.")
|
||||
tracking = FALSE
|
||||
else
|
||||
add_overlay("working")
|
||||
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
|
||||
tracking = TRUE
|
||||
|
||||
|
||||
/obj/item/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
|
||||
if(emped)
|
||||
to_chat(user, "[src] fizzles weakly.")
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// Variable window height, depending on how many GPS units there are
|
||||
// to show, clamped to relatively safe range.
|
||||
var/gps_window_height = CLAMP(325 + GLOB.GPS_list.len * 14, 325, 700)
|
||||
ui = new(user, src, ui_key, "gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
|
||||
ui.open()
|
||||
|
||||
ui.set_autoupdate(state = updating)
|
||||
|
||||
|
||||
/obj/item/gps/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["power"] = tracking
|
||||
data["tag"] = gpstag
|
||||
data["updating"] = updating
|
||||
data["globalmode"] = global_mode
|
||||
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
|
||||
return data
|
||||
|
||||
var/turf/curr = get_turf(src)
|
||||
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
|
||||
data["currentArea"] = "[get_area_name(curr, TRUE)]"
|
||||
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
|
||||
|
||||
var/list/signals = list()
|
||||
data["signals"] = list()
|
||||
|
||||
for(var/gps in GLOB.GPS_list)
|
||||
var/obj/item/gps/G = gps
|
||||
if(G.emped || !G.tracking || G == src)
|
||||
continue
|
||||
var/turf/pos = get_turf(G)
|
||||
if(!global_mode && pos.z != curr.z)
|
||||
continue
|
||||
var/list/signal = list()
|
||||
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
|
||||
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
|
||||
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
|
||||
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
|
||||
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
|
||||
|
||||
signals += list(signal) //Add this signal to the list of signals
|
||||
data["signals"] = signals
|
||||
return data
|
||||
|
||||
|
||||
|
||||
/obj/item/gps/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("rename")
|
||||
var/a = input("Please enter desired tag.", name, gpstag) as text
|
||||
a = copytext(sanitize(a), 1, 20)
|
||||
gpstag = a
|
||||
. = TRUE
|
||||
name = "global positioning system ([gpstag])"
|
||||
|
||||
if("power")
|
||||
toggletracking(usr)
|
||||
. = TRUE
|
||||
if("updating")
|
||||
updating = !updating
|
||||
. = TRUE
|
||||
if("globalmode")
|
||||
global_mode = !global_mode
|
||||
. = TRUE
|
||||
|
||||
|
||||
/obj/item/gps/science
|
||||
icon_state = "gps-s"
|
||||
gpstag = "SCI0"
|
||||
|
||||
/obj/item/gps/engineering
|
||||
icon_state = "gps-e"
|
||||
gpstag = "ENG0"
|
||||
|
||||
/obj/item/gps/mining
|
||||
icon_state = "gps-m"
|
||||
gpstag = "MINE0"
|
||||
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
|
||||
|
||||
/obj/item/gps/cyborg
|
||||
icon_state = "gps-b"
|
||||
gpstag = "BORG0"
|
||||
desc = "A mining cyborg internal positioning system. Used as a recovery beacon for damaged cyborg assets, or a collaboration tool for mining teams."
|
||||
|
||||
/obj/item/gps/cyborg/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
|
||||
|
||||
/obj/item/gps/internal
|
||||
icon_state = null
|
||||
item_flags = ABSTRACT
|
||||
gpstag = "Eerie Signal"
|
||||
desc = "Report to a coder immediately."
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
var/obj/item/implant/gps/implant
|
||||
|
||||
/obj/item/gps/internal/Initialize(mapload, obj/item/implant/gps/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/gps/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/internal/mining
|
||||
icon_state = "gps-m"
|
||||
gpstag = "MINER"
|
||||
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
|
||||
|
||||
/obj/item/gps/internal/base
|
||||
gpstag = "NT_AUX"
|
||||
desc = "A homing signal from Nanotrasen's mining base."
|
||||
|
||||
/obj/item/gps/visible_debug
|
||||
name = "visible GPS"
|
||||
gpstag = "ADMIN"
|
||||
desc = "This admin-spawn GPS unit leaves the coordinates visible \
|
||||
on any turf that it passes over, for debugging. Especially useful \
|
||||
for marking the area around the transition edges."
|
||||
var/list/turf/tagged
|
||||
|
||||
/obj/item/gps/visible_debug/Initialize()
|
||||
. = ..()
|
||||
tagged = list()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/item/gps/visible_debug/process()
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
// I assume it's faster to color,tag and OR the turf in, rather
|
||||
// then checking if its there
|
||||
T.color = RANDOM_COLOUR
|
||||
T.maptext = "[T.x],[T.y],[T.z]"
|
||||
tagged |= T
|
||||
|
||||
/obj/item/gps/visible_debug/proc/clear()
|
||||
while(tagged.len)
|
||||
var/turf/T = pop(tagged)
|
||||
T.color = initial(T.color)
|
||||
T.maptext = initial(T.maptext)
|
||||
|
||||
/obj/item/gps/visible_debug/Destroy()
|
||||
if(tagged)
|
||||
clear()
|
||||
tagged = null
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
. = ..()
|
||||
|
||||
@@ -1,429 +1,436 @@
|
||||
/obj/item/radio
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
name = "station bounced radio"
|
||||
icon_state = "walkietalkie"
|
||||
item_state = "walkietalkie"
|
||||
desc = "A basic handheld radio that communicates with local telecommunication networks."
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
flags_1 = CONDUCT_1 | HEAR_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL=75, MAT_GLASS=25)
|
||||
obj_flags = USES_TGUI
|
||||
|
||||
var/on = TRUE
|
||||
var/frequency = FREQ_COMMON
|
||||
var/canhear_range = 3 // The range around the radio in which mobs can hear what it receives.
|
||||
var/emped = 0 // Tracks the number of EMPs currently stacked.
|
||||
|
||||
var/broadcasting = FALSE // Whether the radio will transmit dialogue it hears nearby.
|
||||
var/listening = TRUE // Whether the radio is currently receiving.
|
||||
var/prison_radio = FALSE // If true, the transmit wire starts cut.
|
||||
var/unscrewed = FALSE // Whether wires are accessible. Toggleable by screwdrivering.
|
||||
var/freerange = FALSE // If true, the radio has access to the full spectrum.
|
||||
var/subspace_transmission = FALSE // If true, the radio transmits and receives on subspace exclusively.
|
||||
var/subspace_switchable = FALSE // If true, subspace_transmission can be toggled at will.
|
||||
var/freqlock = FALSE // Frequency lock to stop the user from untuning specialist radios.
|
||||
var/use_command = FALSE // If true, broadcasts will be large and BOLD.
|
||||
var/command = FALSE // If true, use_command can be toggled at will.
|
||||
var/commandspan = SPAN_COMMAND //allow us to set what the fuck we want for headsets
|
||||
|
||||
// Encryption key handling
|
||||
var/obj/item/encryptionkey/keyslot
|
||||
var/translate_binary = FALSE // If true, can hear the special binary channel.
|
||||
var/independent = FALSE // If true, can say/hear on the special CentCom channel.
|
||||
var/syndie = FALSE // If true, hears all well-known channels automatically, and can say/hear on the Syndicate channel.
|
||||
var/list/channels = list() // Map from name (see communications.dm) to on/off. First entry is current department (:h).
|
||||
var/list/secure_radio_connections
|
||||
|
||||
var/const/FREQ_LISTENING = 1
|
||||
//FREQ_BROADCASTING = 2
|
||||
|
||||
/obj/item/radio/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] starts bouncing [src] off [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/radio/proc/set_frequency(new_frequency)
|
||||
SEND_SIGNAL(src, COMSIG_RADIO_NEW_FREQUENCY, args)
|
||||
remove_radio(src, frequency)
|
||||
frequency = add_radio(src, new_frequency)
|
||||
|
||||
/obj/item/radio/proc/recalculateChannels()
|
||||
channels = list()
|
||||
translate_binary = FALSE
|
||||
syndie = FALSE
|
||||
independent = FALSE
|
||||
|
||||
if(keyslot)
|
||||
for(var/ch_name in keyslot.channels)
|
||||
if(!(ch_name in channels))
|
||||
channels[ch_name] = keyslot.channels[ch_name]
|
||||
|
||||
if(keyslot.translate_binary)
|
||||
translate_binary = TRUE
|
||||
if(keyslot.syndie)
|
||||
syndie = TRUE
|
||||
if(keyslot.independent)
|
||||
independent = TRUE
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/proc/make_syndie() // Turns normal radios into Syndicate radios!
|
||||
qdel(keyslot)
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
syndie = 1
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/Destroy()
|
||||
remove_radio_all(src) //Just to be sure
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(keyslot)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/Initialize()
|
||||
wires = new /datum/wires/radio(src)
|
||||
if(prison_radio)
|
||||
wires.cut(WIRE_TX) // OH GOD WHY
|
||||
secure_radio_connections = new
|
||||
. = ..()
|
||||
frequency = sanitize_frequency(frequency, freerange)
|
||||
set_frequency(frequency)
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
|
||||
|
||||
/obj/item/radio/interact(mob/user)
|
||||
if(unscrewed && !isAI(user))
|
||||
wires.interact(user)
|
||||
add_fingerprint(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/radio/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["broadcasting"] = broadcasting
|
||||
data["listening"] = listening
|
||||
data["frequency"] = frequency
|
||||
data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ
|
||||
data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ
|
||||
data["freqlock"] = freqlock
|
||||
data["channels"] = list()
|
||||
for(var/channel in channels)
|
||||
data["channels"][channel] = channels[channel] & FREQ_LISTENING
|
||||
data["command"] = command
|
||||
data["useCommand"] = use_command
|
||||
data["subspace"] = subspace_transmission
|
||||
data["subspaceSwitchable"] = subspace_switchable
|
||||
data["headset"] = istype(src, /obj/item/radio/headset)
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/radio/ui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if(freqlock)
|
||||
return
|
||||
var/tune = params["tune"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(tune == "input")
|
||||
var/min = format_frequency(freerange ? MIN_FREE_FREQ : MIN_FREQ)
|
||||
var/max = format_frequency(freerange ? MAX_FREE_FREQ : MAX_FREQ)
|
||||
tune = input("Tune frequency ([min]-[max]):", name, format_frequency(frequency)) as null|num
|
||||
if(!isnull(tune) && !..())
|
||||
if (tune < MIN_FREE_FREQ && tune <= MAX_FREE_FREQ / 10)
|
||||
// allow typing 144.7 to get 1447
|
||||
tune *= 10
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
tune = frequency + adjust * 10
|
||||
. = TRUE
|
||||
else if(text2num(tune) != null)
|
||||
tune = tune * 10
|
||||
. = TRUE
|
||||
if(.)
|
||||
set_frequency(sanitize_frequency(tune, freerange))
|
||||
if("listen")
|
||||
listening = !listening
|
||||
. = TRUE
|
||||
if("broadcast")
|
||||
broadcasting = !broadcasting
|
||||
. = TRUE
|
||||
if("channel")
|
||||
var/channel = params["channel"]
|
||||
if(!(channel in channels))
|
||||
return
|
||||
if(channels[channel] & FREQ_LISTENING)
|
||||
channels[channel] &= ~FREQ_LISTENING
|
||||
else
|
||||
channels[channel] |= FREQ_LISTENING
|
||||
. = TRUE
|
||||
if("command")
|
||||
use_command = !use_command
|
||||
. = TRUE
|
||||
if("subspace")
|
||||
if(subspace_switchable)
|
||||
subspace_transmission = !subspace_transmission
|
||||
if(!subspace_transmission)
|
||||
channels = list()
|
||||
else
|
||||
recalculateChannels()
|
||||
. = TRUE
|
||||
|
||||
/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!spans)
|
||||
spans = list(M.speech_span)
|
||||
if(!language)
|
||||
language = M.get_default_language()
|
||||
INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
/obj/item/radio/proc/talk_into_impl(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!on)
|
||||
return // the device has to be on
|
||||
if(!M || !message)
|
||||
return
|
||||
if(wires.is_cut(WIRE_TX)) // Permacell and otherwise tampered-with radios
|
||||
return
|
||||
if(!M.IsVocal())
|
||||
return
|
||||
|
||||
if(use_command)
|
||||
spans |= commandspan
|
||||
|
||||
/*
|
||||
Roughly speaking, radios attempt to make a subspace transmission (which
|
||||
is received, processed, and rebroadcast by the telecomms satellite) and
|
||||
if that fails, they send a mundane radio transmission.
|
||||
|
||||
Headsets cannot send/receive mundane transmissions, only subspace.
|
||||
Syndicate radios can hear transmissions on all well-known frequencies.
|
||||
CentCom radios can hear the CentCom frequency no matter what.
|
||||
*/
|
||||
|
||||
// From the channel, determine the frequency and get a reference to it.
|
||||
var/freq
|
||||
if(channel && channels && channels.len > 0)
|
||||
if(channel == MODE_DEPARTMENT)
|
||||
channel = channels[1]
|
||||
freq = secure_radio_connections[channel]
|
||||
if (!channels[channel]) // if the channel is turned off, don't broadcast
|
||||
return
|
||||
else
|
||||
freq = frequency
|
||||
channel = null
|
||||
|
||||
// Nearby active jammers severely gibberish the message
|
||||
var/turf/position = get_turf(src)
|
||||
for(var/obj/item/jammer/jammer in GLOB.active_jammers)
|
||||
var/turf/jammer_turf = get_turf(jammer)
|
||||
if(position.z == jammer_turf.z && (get_dist(position, jammer_turf) < jammer.range))
|
||||
message = Gibberish(message,100)
|
||||
break
|
||||
|
||||
// Determine the identity information which will be attached to the signal.
|
||||
var/atom/movable/virtualspeaker/speaker = new(null, M, src)
|
||||
|
||||
// Construct the signal
|
||||
var/datum/signal/subspace/vocal/signal = new(src, freq, speaker, language, message, spans)
|
||||
|
||||
// Independent radios, on the CentCom frequency, reach all independent radios
|
||||
if (independent && (freq == FREQ_CENTCOM || freq == FREQ_CTF_RED || freq == FREQ_CTF_BLUE))
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_SUPERSPACE
|
||||
signal.levels = list(0) // reaches all Z-levels
|
||||
signal.broadcast()
|
||||
return
|
||||
|
||||
// All radios make an attempt to use the subspace system first
|
||||
signal.send_to_receivers()
|
||||
|
||||
// If the radio is subspace-only, that's all it can do
|
||||
if (subspace_transmission)
|
||||
return
|
||||
|
||||
// Non-subspace radios will check in a couple of seconds, and if the signal
|
||||
// was never received, send a mundane broadcast (no headsets).
|
||||
addtimer(CALLBACK(src, .proc/backup_transmission, signal), 20)
|
||||
|
||||
/obj/item/radio/proc/backup_transmission(datum/signal/subspace/vocal/signal)
|
||||
var/turf/T = get_turf(src)
|
||||
if (signal.data["done"] && (T.z in signal.levels))
|
||||
return
|
||||
|
||||
// Okay, the signal was never processed, send a mundane broadcast.
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
signal.levels = list(T.z)
|
||||
signal.broadcast()
|
||||
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range)
|
||||
return
|
||||
|
||||
if(message_mode == MODE_WHISPER || message_mode == MODE_WHISPER_CRIT)
|
||||
// radios don't pick up whispers very well
|
||||
raw_message = stars(raw_message)
|
||||
else if(message_mode == MODE_L_HAND || message_mode == MODE_R_HAND)
|
||||
// try to avoid being heard double
|
||||
if (loc == speaker && ismob(speaker))
|
||||
var/mob/M = speaker
|
||||
var/idx = M.get_held_index_of_item(src)
|
||||
// left hands are odd slots
|
||||
if (idx && (idx % 2) == (message_mode == MODE_L_HAND))
|
||||
return
|
||||
|
||||
talk_into(speaker, raw_message, , spans, language=message_language)
|
||||
|
||||
// Checks if this radio can receive on the given frequency.
|
||||
/obj/item/radio/proc/can_receive(freq, level)
|
||||
// deny checks
|
||||
if (!on || !listening || wires.is_cut(WIRE_RX))
|
||||
return FALSE
|
||||
if (freq == FREQ_SYNDICATE && !syndie)
|
||||
return FALSE
|
||||
if (freq == FREQ_CENTCOM)
|
||||
return independent // hard-ignores the z-level check
|
||||
if (!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(!position || !(position.z in level))
|
||||
return FALSE
|
||||
|
||||
// allow checks: are we listening on that frequency?
|
||||
if (freq == frequency)
|
||||
return TRUE
|
||||
for(var/ch_name in channels)
|
||||
if(channels[ch_name] & FREQ_LISTENING)
|
||||
//the GLOB.radiochannels list is located in communications.dm
|
||||
if(GLOB.radiochannels[ch_name] == text2num(freq) || syndie)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/item/radio/examine(mob/user)
|
||||
. = ..()
|
||||
if (unscrewed)
|
||||
. += "<span class='notice'>It can be attached and modified.</span>"
|
||||
else
|
||||
. += "<span class='notice'>It cannot be modified or attached.</span>"
|
||||
|
||||
/obj/item/radio/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
unscrewed = !unscrewed
|
||||
if(unscrewed)
|
||||
to_chat(user, "<span class='notice'>The radio can now be attached and modified!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The radio can no longer be modified or attached!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
emped++ //There's been an EMP; better count it
|
||||
var/curremp = emped //Remember which EMP this was
|
||||
if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice
|
||||
to_chat(loc, "<span class='warning'>\The [src] overloads.</span>")
|
||||
broadcasting = FALSE
|
||||
listening = FALSE
|
||||
for (var/ch_name in channels)
|
||||
channels[ch_name] = 0
|
||||
on = FALSE
|
||||
spawn(200)
|
||||
if(emped == curremp) //Don't fix it if it's been EMP'd again
|
||||
emped = 0
|
||||
if (!istype(src, /obj/item/radio/intercom)) // intercoms will turn back on on their own
|
||||
on = TRUE
|
||||
|
||||
///////////////////////////////
|
||||
//////////Borg Radios//////////
|
||||
///////////////////////////////
|
||||
//Giving borgs their own radio to have some more room to work with -Sieve
|
||||
|
||||
/obj/item/radio/borg
|
||||
name = "cyborg radio"
|
||||
subspace_switchable = TRUE
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/borg/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/borg/syndicate
|
||||
syndie = 1
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
|
||||
/obj/item/radio/borg/syndicate/Initialize()
|
||||
. = ..()
|
||||
set_frequency(FREQ_SYNDICATE)
|
||||
|
||||
/obj/item/radio/borg/attackby(obj/item/W, mob/user, params)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(keyslot)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
|
||||
if(keyslot)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "<span class='notice'>You pop out the encryption key in the radio.</span>")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This radio doesn't have any encryption keys!</span>")
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey/))
|
||||
if(keyslot)
|
||||
to_chat(user, "<span class='warning'>The radio can't hold another key!</span>")
|
||||
return
|
||||
|
||||
if(!keyslot)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
keyslot = W
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
|
||||
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
|
||||
listening = 0 // And it's nice to have a subtype too for future features.
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/radio/internal
|
||||
var/obj/item/implant/radio/implant
|
||||
|
||||
/obj/item/radio/internal/Initialize(mapload, obj/item/implant/radio/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/radio/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
/obj/item/radio
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
name = "station bounced radio"
|
||||
icon_state = "walkietalkie"
|
||||
item_state = "walkietalkie"
|
||||
desc = "A basic handheld radio that communicates with local telecommunication networks."
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
flags_1 = CONDUCT_1 | HEAR_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL=75, MAT_GLASS=25)
|
||||
obj_flags = USES_TGUI
|
||||
|
||||
var/on = TRUE
|
||||
var/frequency = FREQ_COMMON
|
||||
var/canhear_range = 3 // The range around the radio in which mobs can hear what it receives.
|
||||
var/emped = 0 // Tracks the number of EMPs currently stacked.
|
||||
|
||||
var/broadcasting = FALSE // Whether the radio will transmit dialogue it hears nearby.
|
||||
var/listening = TRUE // Whether the radio is currently receiving.
|
||||
var/prison_radio = FALSE // If true, the transmit wire starts cut.
|
||||
var/unscrewed = FALSE // Whether wires are accessible. Toggleable by screwdrivering.
|
||||
var/freerange = FALSE // If true, the radio has access to the full spectrum.
|
||||
var/subspace_transmission = FALSE // If true, the radio transmits and receives on subspace exclusively.
|
||||
var/subspace_switchable = FALSE // If true, subspace_transmission can be toggled at will.
|
||||
var/freqlock = FALSE // Frequency lock to stop the user from untuning specialist radios.
|
||||
var/use_command = FALSE // If true, broadcasts will be large and BOLD.
|
||||
var/command = FALSE // If true, use_command can be toggled at will.
|
||||
var/commandspan = SPAN_COMMAND //allow us to set what the fuck we want for headsets
|
||||
|
||||
// Encryption key handling
|
||||
var/obj/item/encryptionkey/keyslot
|
||||
var/translate_binary = FALSE // If true, can hear the special binary channel.
|
||||
var/independent = FALSE // If true, can say/hear on the special CentCom channel.
|
||||
var/syndie = FALSE // If true, hears all well-known channels automatically, and can say/hear on the Syndicate channel.
|
||||
var/list/channels = list() // Map from name (see communications.dm) to on/off. First entry is current department (:h).
|
||||
var/list/secure_radio_connections
|
||||
|
||||
var/const/FREQ_LISTENING = 1
|
||||
//FREQ_BROADCASTING = 2
|
||||
|
||||
/obj/item/radio/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] starts bouncing [src] off [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/radio/proc/set_frequency(new_frequency)
|
||||
SEND_SIGNAL(src, COMSIG_RADIO_NEW_FREQUENCY, args)
|
||||
remove_radio(src, frequency)
|
||||
frequency = add_radio(src, new_frequency)
|
||||
|
||||
/obj/item/radio/proc/recalculateChannels()
|
||||
channels = list()
|
||||
translate_binary = FALSE
|
||||
syndie = FALSE
|
||||
independent = FALSE
|
||||
|
||||
if(keyslot)
|
||||
for(var/ch_name in keyslot.channels)
|
||||
if(!(ch_name in channels))
|
||||
channels[ch_name] = keyslot.channels[ch_name]
|
||||
|
||||
if(keyslot.translate_binary)
|
||||
translate_binary = TRUE
|
||||
if(keyslot.syndie)
|
||||
syndie = TRUE
|
||||
if(keyslot.independent)
|
||||
independent = TRUE
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/proc/make_syndie() // Turns normal radios into Syndicate radios!
|
||||
qdel(keyslot)
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
syndie = 1
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/Destroy()
|
||||
remove_radio_all(src) //Just to be sure
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(keyslot)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/Initialize()
|
||||
wires = new /datum/wires/radio(src)
|
||||
if(prison_radio)
|
||||
wires.cut(WIRE_TX) // OH GOD WHY
|
||||
secure_radio_connections = new
|
||||
. = ..()
|
||||
frequency = sanitize_frequency(frequency, freerange)
|
||||
set_frequency(frequency)
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
|
||||
|
||||
/obj/item/radio/interact(mob/user)
|
||||
if(unscrewed && !isAI(user))
|
||||
wires.interact(user)
|
||||
add_fingerprint(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
var/ui_width = 360
|
||||
var/ui_height = 106
|
||||
if(subspace_transmission)
|
||||
if(channels.len > 0)
|
||||
ui_height += 6 + channels.len * 21
|
||||
else
|
||||
ui_height += 24
|
||||
ui = new(user, src, ui_key, "radio", name, ui_width, ui_height, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/radio/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["broadcasting"] = broadcasting
|
||||
data["listening"] = listening
|
||||
data["frequency"] = frequency
|
||||
data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ
|
||||
data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ
|
||||
data["freqlock"] = freqlock
|
||||
data["channels"] = list()
|
||||
for(var/channel in channels)
|
||||
data["channels"][channel] = channels[channel] & FREQ_LISTENING
|
||||
data["command"] = command
|
||||
data["useCommand"] = use_command
|
||||
data["subspace"] = subspace_transmission
|
||||
data["subspaceSwitchable"] = subspace_switchable
|
||||
data["headset"] = istype(src, /obj/item/radio/headset)
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/radio/ui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if(freqlock)
|
||||
return
|
||||
var/tune = params["tune"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(tune == "input")
|
||||
var/min = format_frequency(freerange ? MIN_FREE_FREQ : MIN_FREQ)
|
||||
var/max = format_frequency(freerange ? MAX_FREE_FREQ : MAX_FREQ)
|
||||
tune = input("Tune frequency ([min]-[max]):", name, format_frequency(frequency)) as null|num
|
||||
if(!isnull(tune) && !..())
|
||||
if (tune < MIN_FREE_FREQ && tune <= MAX_FREE_FREQ / 10)
|
||||
// allow typing 144.7 to get 1447
|
||||
tune *= 10
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
tune = frequency + adjust * 10
|
||||
. = TRUE
|
||||
else if(text2num(tune) != null)
|
||||
tune = tune * 10
|
||||
. = TRUE
|
||||
if(.)
|
||||
set_frequency(sanitize_frequency(tune, freerange))
|
||||
if("listen")
|
||||
listening = !listening
|
||||
. = TRUE
|
||||
if("broadcast")
|
||||
broadcasting = !broadcasting
|
||||
. = TRUE
|
||||
if("channel")
|
||||
var/channel = params["channel"]
|
||||
if(!(channel in channels))
|
||||
return
|
||||
if(channels[channel] & FREQ_LISTENING)
|
||||
channels[channel] &= ~FREQ_LISTENING
|
||||
else
|
||||
channels[channel] |= FREQ_LISTENING
|
||||
. = TRUE
|
||||
if("command")
|
||||
use_command = !use_command
|
||||
. = TRUE
|
||||
if("subspace")
|
||||
if(subspace_switchable)
|
||||
subspace_transmission = !subspace_transmission
|
||||
if(!subspace_transmission)
|
||||
channels = list()
|
||||
else
|
||||
recalculateChannels()
|
||||
. = TRUE
|
||||
|
||||
/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!spans)
|
||||
spans = list(M.speech_span)
|
||||
if(!language)
|
||||
language = M.get_default_language()
|
||||
INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
/obj/item/radio/proc/talk_into_impl(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!on)
|
||||
return // the device has to be on
|
||||
if(!M || !message)
|
||||
return
|
||||
if(wires.is_cut(WIRE_TX)) // Permacell and otherwise tampered-with radios
|
||||
return
|
||||
if(!M.IsVocal())
|
||||
return
|
||||
|
||||
if(use_command)
|
||||
spans |= commandspan
|
||||
|
||||
/*
|
||||
Roughly speaking, radios attempt to make a subspace transmission (which
|
||||
is received, processed, and rebroadcast by the telecomms satellite) and
|
||||
if that fails, they send a mundane radio transmission.
|
||||
|
||||
Headsets cannot send/receive mundane transmissions, only subspace.
|
||||
Syndicate radios can hear transmissions on all well-known frequencies.
|
||||
CentCom radios can hear the CentCom frequency no matter what.
|
||||
*/
|
||||
|
||||
// From the channel, determine the frequency and get a reference to it.
|
||||
var/freq
|
||||
if(channel && channels && channels.len > 0)
|
||||
if(channel == MODE_DEPARTMENT)
|
||||
channel = channels[1]
|
||||
freq = secure_radio_connections[channel]
|
||||
if (!channels[channel]) // if the channel is turned off, don't broadcast
|
||||
return
|
||||
else
|
||||
freq = frequency
|
||||
channel = null
|
||||
|
||||
// Nearby active jammers severely gibberish the message
|
||||
var/turf/position = get_turf(src)
|
||||
for(var/obj/item/jammer/jammer in GLOB.active_jammers)
|
||||
var/turf/jammer_turf = get_turf(jammer)
|
||||
if(position.z == jammer_turf.z && (get_dist(position, jammer_turf) < jammer.range))
|
||||
message = Gibberish(message,100)
|
||||
break
|
||||
|
||||
// Determine the identity information which will be attached to the signal.
|
||||
var/atom/movable/virtualspeaker/speaker = new(null, M, src)
|
||||
|
||||
// Construct the signal
|
||||
var/datum/signal/subspace/vocal/signal = new(src, freq, speaker, language, message, spans)
|
||||
|
||||
// Independent radios, on the CentCom frequency, reach all independent radios
|
||||
if (independent && (freq == FREQ_CENTCOM || freq == FREQ_CTF_RED || freq == FREQ_CTF_BLUE))
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_SUPERSPACE
|
||||
signal.levels = list(0) // reaches all Z-levels
|
||||
signal.broadcast()
|
||||
return
|
||||
|
||||
// All radios make an attempt to use the subspace system first
|
||||
signal.send_to_receivers()
|
||||
|
||||
// If the radio is subspace-only, that's all it can do
|
||||
if (subspace_transmission)
|
||||
return
|
||||
|
||||
// Non-subspace radios will check in a couple of seconds, and if the signal
|
||||
// was never received, send a mundane broadcast (no headsets).
|
||||
addtimer(CALLBACK(src, .proc/backup_transmission, signal), 20)
|
||||
|
||||
/obj/item/radio/proc/backup_transmission(datum/signal/subspace/vocal/signal)
|
||||
var/turf/T = get_turf(src)
|
||||
if (signal.data["done"] && (T.z in signal.levels))
|
||||
return
|
||||
|
||||
// Okay, the signal was never processed, send a mundane broadcast.
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
signal.levels = list(T.z)
|
||||
signal.broadcast()
|
||||
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range)
|
||||
return
|
||||
|
||||
if(message_mode == MODE_WHISPER || message_mode == MODE_WHISPER_CRIT)
|
||||
// radios don't pick up whispers very well
|
||||
raw_message = stars(raw_message)
|
||||
else if(message_mode == MODE_L_HAND || message_mode == MODE_R_HAND)
|
||||
// try to avoid being heard double
|
||||
if (loc == speaker && ismob(speaker))
|
||||
var/mob/M = speaker
|
||||
var/idx = M.get_held_index_of_item(src)
|
||||
// left hands are odd slots
|
||||
if (idx && (idx % 2) == (message_mode == MODE_L_HAND))
|
||||
return
|
||||
|
||||
talk_into(speaker, raw_message, , spans, language=message_language)
|
||||
|
||||
// Checks if this radio can receive on the given frequency.
|
||||
/obj/item/radio/proc/can_receive(freq, level)
|
||||
// deny checks
|
||||
if (!on || !listening || wires.is_cut(WIRE_RX))
|
||||
return FALSE
|
||||
if (freq == FREQ_SYNDICATE && !syndie)
|
||||
return FALSE
|
||||
if (freq == FREQ_CENTCOM)
|
||||
return independent // hard-ignores the z-level check
|
||||
if (!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(!position || !(position.z in level))
|
||||
return FALSE
|
||||
|
||||
// allow checks: are we listening on that frequency?
|
||||
if (freq == frequency)
|
||||
return TRUE
|
||||
for(var/ch_name in channels)
|
||||
if(channels[ch_name] & FREQ_LISTENING)
|
||||
//the GLOB.radiochannels list is located in communications.dm
|
||||
if(GLOB.radiochannels[ch_name] == text2num(freq) || syndie)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/item/radio/examine(mob/user)
|
||||
. = ..()
|
||||
if (unscrewed)
|
||||
. += "<span class='notice'>It can be attached and modified.</span>"
|
||||
else
|
||||
. += "<span class='notice'>It cannot be modified or attached.</span>"
|
||||
|
||||
/obj/item/radio/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
unscrewed = !unscrewed
|
||||
if(unscrewed)
|
||||
to_chat(user, "<span class='notice'>The radio can now be attached and modified!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The radio can no longer be modified or attached!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
emped++ //There's been an EMP; better count it
|
||||
var/curremp = emped //Remember which EMP this was
|
||||
if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice
|
||||
to_chat(loc, "<span class='warning'>\The [src] overloads.</span>")
|
||||
broadcasting = FALSE
|
||||
listening = FALSE
|
||||
for (var/ch_name in channels)
|
||||
channels[ch_name] = 0
|
||||
on = FALSE
|
||||
spawn(200)
|
||||
if(emped == curremp) //Don't fix it if it's been EMP'd again
|
||||
emped = 0
|
||||
if (!istype(src, /obj/item/radio/intercom)) // intercoms will turn back on on their own
|
||||
on = TRUE
|
||||
|
||||
///////////////////////////////
|
||||
//////////Borg Radios//////////
|
||||
///////////////////////////////
|
||||
//Giving borgs their own radio to have some more room to work with -Sieve
|
||||
|
||||
/obj/item/radio/borg
|
||||
name = "cyborg radio"
|
||||
subspace_switchable = TRUE
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/borg/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/borg/syndicate
|
||||
syndie = 1
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
|
||||
/obj/item/radio/borg/syndicate/Initialize()
|
||||
. = ..()
|
||||
set_frequency(FREQ_SYNDICATE)
|
||||
|
||||
/obj/item/radio/borg/attackby(obj/item/W, mob/user, params)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(keyslot)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
|
||||
if(keyslot)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "<span class='notice'>You pop out the encryption key in the radio.</span>")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This radio doesn't have any encryption keys!</span>")
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey/))
|
||||
if(keyslot)
|
||||
to_chat(user, "<span class='warning'>The radio can't hold another key!</span>")
|
||||
return
|
||||
|
||||
if(!keyslot)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
keyslot = W
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
|
||||
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
|
||||
listening = 0 // And it's nice to have a subtype too for future features.
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/radio/internal
|
||||
var/obj/item/implant/radio/implant
|
||||
|
||||
/obj/item/radio/internal/Initialize(mapload, obj/item/implant/radio/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/radio/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "tanks", name, 420, 200, master_ui, state)
|
||||
ui = new(user, src, ui_key, "tanks", name, 400, 120, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/tank/ui_data(mob/user)
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
mob_species = /datum/species/pod
|
||||
flavour_text = "<span class='big bold'>You are a sentient ecosystem,</span><b> an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \
|
||||
seed vaults and spread them across the universe to every planet they could chart. You are in one such seed vault. Your goal is to cultivate and spread life wherever it will go while waiting \
|
||||
for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago.</b>"
|
||||
short_desc = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed."
|
||||
flavour_text = "Your masters, benevolent as they were, created uncounted seed vaults and spread them across \
|
||||
the universe to every planet they could chart. You are in one such seed vault. \
|
||||
Your goal is to cultivate and spread life wherever it will go while waiting for contact from your creators. \
|
||||
Estimated time of last contact: Deployment, 5000 millennia ago."
|
||||
assignedrole = "Lifebringer"
|
||||
|
||||
/obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn)
|
||||
@@ -47,8 +49,10 @@
|
||||
death = FALSE
|
||||
anchored = FALSE
|
||||
density = FALSE
|
||||
flavour_text = "<span class='big bold'>You are an ash walker.</span><b> Your tribe worships <span class='danger'>the Necropolis</span>. The wastes are sacred ground, its monsters a blessed bounty. You would never leave its beautiful expanse. \
|
||||
You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest.</b>"
|
||||
short_desc = "You are an ash walker. Your tribe worships the Necropolis."
|
||||
flavour_text = "The wastes are sacred ground, its monsters a blessed bounty. You would never leave its sacred ground. \
|
||||
You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. \
|
||||
Fresh sacrifices for your nest."
|
||||
assignedrole = "Ash Walker"
|
||||
|
||||
/obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn)
|
||||
@@ -87,8 +91,9 @@
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
mob_species = /datum/species/shadow
|
||||
flavour_text = "<span class='big bold'>You are cursed.</span><b> Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \
|
||||
did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland.</b>"
|
||||
short_desc = "You are cursed."
|
||||
flavour_text = "Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \
|
||||
did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland."
|
||||
assignedrole = "Exile"
|
||||
|
||||
/obj/effect/mob_spawn/human/exile/Destroy()
|
||||
@@ -124,9 +129,10 @@
|
||||
var/has_owner = FALSE
|
||||
var/can_transfer = TRUE //if golems can switch bodies to this new shell
|
||||
var/mob/living/owner = null //golem's owner if it has one
|
||||
flavour_text = "<span class='big bold'>You are a Free Golem.</span><b> Your family worships <span class='danger'>The Liberator</span>. In his infinite and divine wisdom, he set your clan free to \
|
||||
short_desc = "You are a Free Golem. Your family worships The Liberator."
|
||||
flavour_text = "In his infinite and divine wisdom, he set your clan free to \
|
||||
travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \
|
||||
golems, so that no golem may ever be forced to serve again.</b>"
|
||||
golems, so that no golem may ever be forced to serve again."
|
||||
|
||||
/obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null)
|
||||
if(species) //spawners list uses object name to register so this goes before ..()
|
||||
@@ -137,8 +143,9 @@
|
||||
if(!mapload && A)
|
||||
notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_GOLEM, ignore_dnr_observers = TRUE)
|
||||
if(has_owner && creator)
|
||||
flavour_text = "<span class='big bold'>You are a Golem.</span><b> You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \
|
||||
Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost.</b>"
|
||||
short_desc = "You are a golem."
|
||||
flavour_text = "You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools."
|
||||
important_info = "Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
|
||||
owner = creator
|
||||
|
||||
/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn, name)
|
||||
@@ -211,8 +218,9 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You've been stranded in this godless prison of a planet for longer than you can remember.</span><b> Each day you barely scrape by, and between the terrible \
|
||||
conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
|
||||
short_desc = "You've been stranded in this godless prison of a planet for longer than you can remember."
|
||||
flavour_text = "Each day you barely scrape by, and between the terrible conditions of your makeshift shelter, \
|
||||
the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
|
||||
the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... "
|
||||
assignedrole = "Hermit"
|
||||
|
||||
@@ -223,20 +231,20 @@
|
||||
if(1)
|
||||
flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \
|
||||
only one pod left when you got to the escape bay. You took it and launched it alone, and the crowd of terrified faces crowding at the airlock door as your pod's engines burst to \
|
||||
life and sent you to this hell are forever branded into your memory.</b>"
|
||||
life and sent you to this hell are forever branded into your memory."
|
||||
outfit.uniform = /obj/item/clothing/under/assistantformal
|
||||
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
if(2)
|
||||
flavour_text += "you're an exile from the Tiger Cooperative. Their technological fanaticism drove you to question the power and beliefs of the Exolitics, and they saw you as a \
|
||||
heretic and subjected you to hours of horrible torture. You were hours away from execution when a high-ranking friend of yours in the Cooperative managed to secure you a pod, \
|
||||
scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since.</b>"
|
||||
scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since."
|
||||
outfit.uniform = /obj/item/clothing/under/rank/prisoner
|
||||
outfit.shoes = /obj/item/clothing/shoes/sneakers/orange
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
if(3)
|
||||
flavour_text += "you were a doctor on one of Nanotrasen's space stations, but you left behind that damn corporation's tyranny and everything it stood for. From a metaphorical hell \
|
||||
to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there.</b>"
|
||||
to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there."
|
||||
outfit.uniform = /obj/item/clothing/under/rank/medical
|
||||
outfit.suit = /obj/item/clothing/suit/toggle/labcoat
|
||||
outfit.back = /obj/item/storage/backpack/medic
|
||||
@@ -244,7 +252,7 @@
|
||||
if(4)
|
||||
flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so <i>kindly</i> put it. It seems that they were right when you, on a tour \
|
||||
at one of Nanotrasen's state-of-the-art research facilities, were in one of the escape pods alone and saw the red button. It was big and shiny, and it caught your eye. You pressed \
|
||||
it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now.</b>"
|
||||
it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now."
|
||||
outfit.uniform = /obj/item/clothing/under/color/grey/glorf
|
||||
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
@@ -283,8 +291,9 @@
|
||||
outfit = /datum/outfit/lavalandprisoner
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
flavour_text = "<b>Good. It seems as though your ship crashed. <span class='big bold'>You're a prisoner,</span> sentenced to hard work in one of Nanotrasen's labor camps, but it seems as \
|
||||
though fate has other plans for you. You remember that you were convicted of "
|
||||
short_desc = "You're a prisoner, sentenced to hard work in one of Nanotrasen's labor camps, but it seems as \
|
||||
though fate has other plans for you."
|
||||
flavour_text = "Good. It seems as though your ship crashed. You remember that you were convicted of "
|
||||
assignedrole = "Escaped Prisoner"
|
||||
|
||||
/obj/effect/mob_spawn/human/prisoner_transport/special(mob/living/L)
|
||||
@@ -296,7 +305,7 @@
|
||||
var/list/crimes = list("murder", "larceny", "embezzlement", "unionization", "dereliction of duty", "kidnapping", "gross incompetence", "grand theft", "collaboration with the Syndicate", \
|
||||
"worship of a forbidden deity", "interspecies relations", "mutiny")
|
||||
flavour_text += "[pick(crimes)]. but regardless of that, it seems like your crime doesn't matter now. You don't know where you are, but you know that it's out to kill you, and you're not going \
|
||||
to lose this opportunity. Find a way to get out of this mess and back to where you rightfully belong - your [pick("house", "apartment", "spaceship", "station")]</b>."
|
||||
to lose this opportunity. Find a way to get out of this mess and back to where you rightfully belong - your [pick("house", "apartment", "spaceship", "station")]."
|
||||
|
||||
/datum/outfit/lavalandprisoner
|
||||
name = "Lavaland Prisoner"
|
||||
@@ -323,8 +332,9 @@
|
||||
roundstart = FALSE
|
||||
random = TRUE
|
||||
outfit = /datum/outfit/hotelstaff
|
||||
flavour_text = "<span class='big bold'>You are a staff member of a top-of-the-line space hotel!</span><b> Cater to guests and <font size=6><b>DON'T</b></font> leave the hotel, lest the manager fire you for\
|
||||
dereliction of duty!</b>"
|
||||
short_desc = "You are a staff member of a top-of-the-line space hotel!"
|
||||
flavour_text = "You are a staff member of a top-of-the-line space hotel! Cater to guests and make sure the manager doesn't fire you."
|
||||
important_info = "DON'T leave the hotel"
|
||||
assignedrole = "Hotel Staff"
|
||||
|
||||
/datum/outfit/hotelstaff
|
||||
@@ -341,8 +351,10 @@
|
||||
mob_name = "hotel security member"
|
||||
job_description = "Hotel Security"
|
||||
outfit = /datum/outfit/hotelstaff/security
|
||||
flavour_text = "<span class='big bold'>You are a peacekeeper</span><b> assigned to this hotel to protect the interests of the company while keeping the peace between \
|
||||
guests and the staff. Do <font size=6>NOT</font> leave the hotel, as that is grounds for contract termination.</b>"
|
||||
short_desc = "You are a peacekeeper."
|
||||
flavour_text = "You have been assigned to this hotel to protect the interests of the company while keeping the peace between \
|
||||
guests and the staff."
|
||||
important_info = "Do NOT leave the hotel, as that is grounds for contract termination."
|
||||
objectives = "Do not leave your assigned hotel. Try and keep the peace between staff and guests, non-lethal force heavily advised if possible."
|
||||
|
||||
/datum/outfit/hotelstaff/security
|
||||
@@ -381,7 +393,8 @@
|
||||
/obj/effect/mob_spawn/human/demonic_friend/Initialize(mapload, datum/mind/owner_mind, obj/effect/proc_holder/spell/targeted/summon_friend/summoning_spell)
|
||||
. = ..()
|
||||
owner = owner_mind
|
||||
flavour_text = "<span class='big bold'>You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil.</span><b> Be aware that if you do not live up to [owner.name]'s expectations, they can send you back to hell with a single thought. [owner.name]'s death will also return you to hell.</b>"
|
||||
flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil."
|
||||
important_info = "Be aware that if you do not live up to [owner.name]'s expectations, they can send you back to hell with a single thought. [owner.name]'s death will also return you to hell."
|
||||
var/area/A = get_area(src)
|
||||
if(!mapload && A)
|
||||
notify_ghosts("\A friendship shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
|
||||
@@ -439,9 +452,9 @@
|
||||
|
||||
/obj/effect/mob_spawn/human/syndicate/battlecruiser
|
||||
name = "Syndicate Battlecruiser Ship Operative"
|
||||
flavour_text = "<span class='big bold'>You are a crewmember aboard the syndicate flagship: the SBC Starfury.</span><span class='big'> <span class='danger'><b>Your job is to follow your captain's orders, maintain the ship, and keep the engine running.</b></span> If you are not familiar with how the supermatter engine functions: <b>do not attempt to start it.</b><br>\
|
||||
<br>\
|
||||
<span class='danger'><b>The armory is not a candy store, and your role is not to assault the station directly, leave that work to the assault operatives.</b></span></font>"
|
||||
short_desc = "You are a crewmember aboard the syndicate flagship: the SBC Starfury."
|
||||
flavour_text = "Your job is to follow your captain's orders, maintain the ship, and keep the engine running. If you are not familiar with how the supermatter engine functions: do not attempt to start it."
|
||||
important_info = "The armory is not a candy store, and your role is not to assault the station directly, leave that work to the assault operatives."
|
||||
outfit = /datum/outfit/syndicate_empty/SBC
|
||||
|
||||
/datum/outfit/syndicate_empty/SBC
|
||||
@@ -451,10 +464,9 @@
|
||||
belt = /obj/item/storage/belt/military/assault
|
||||
|
||||
/obj/effect/mob_spawn/human/syndicate/battlecruiser/assault
|
||||
name = "Syndicate Battlecruiser Assault Operative"
|
||||
flavour_text = "<span class='big bold'>You are an assault operative aboard the syndicate flagship: the SBC Starfury.</span><span class='big'> <span class='danger'><b>Your job is to follow your captain's orders, keep intruders out of the ship, and assault Space Station 13.</b></span> There is an armory, multiple assault ships, and beam cannons to attack the station with.<br>\
|
||||
<br>\
|
||||
<span class='danger'><b>Work as a team with your fellow operatives and work out a plan of attack. If you are overwhelmed, escape back to your ship!</b></span></span>"
|
||||
short_desc = "You are an assault operative aboard the syndicate flagship: the SBC Starfury."
|
||||
flavour_text = "Your job is to follow your captain's orders, keep intruders out of the ship, and assault Space Station 13. There is an armory, multiple assault ships, and beam cannons to attack the station with."
|
||||
important_info = "Work as a team with your fellow operatives and work out a plan of attack. If you are overwhelmed, escape back to your ship!"
|
||||
outfit = /datum/outfit/syndicate_empty/SBC/assault
|
||||
|
||||
/datum/outfit/syndicate_empty/SBC/assault
|
||||
@@ -470,9 +482,9 @@
|
||||
|
||||
/obj/effect/mob_spawn/human/syndicate/battlecruiser/captain
|
||||
name = "Syndicate Battlecruiser Captain"
|
||||
flavour_text = "<span class='big bold'>You are the captain aboard the syndicate flagship: the SBC Starfury.</span><span class='big'> <span class='danger'><b>Your job is to oversee your crew, defend the ship, and destroy Space Station 13.</b></span> The ship has an armory, multiple ships, beam cannons, and multiple crewmembers to accomplish this goal.<br>\
|
||||
<br>\
|
||||
<span class='danger'><b>As the captain, this whole operation falls on your shoulders.</b></span> You do not need to nuke the station, causing sufficient damage and preventing your ship from being destroyed will be enough.</span>"
|
||||
short_desc = "You are the captain aboard the syndicate flagship: the SBC Starfury."
|
||||
flavour_text = "Your job is to oversee your crew, defend the ship, and destroy Space Station 13. The ship has an armory, multiple ships, beam cannons, and multiple crewmembers to accomplish this goal."
|
||||
important_info = "As the captain, this whole operation falls on your shoulders. You do not need to nuke the station, causing sufficient damage and preventing your ship from being destroyed will be enough."
|
||||
outfit = /datum/outfit/syndicate_empty/SBC/assault/captain
|
||||
id_access_list = list(150,151)
|
||||
|
||||
@@ -498,10 +510,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are a security officer working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
short_desc = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station."
|
||||
flavour_text = "You vaguely recall rushing into a cryogenics pod due to an oncoming radiation storm. \
|
||||
The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
important_info = "Work as a team with your fellow survivors and do not abandon them."
|
||||
uniform = /obj/item/clothing/under/rank/security
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
id = /obj/item/card/id/away/old/sec
|
||||
@@ -525,10 +538,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are an engineer working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
short_desc = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station."
|
||||
flavour_text = "You vaguely recall rushing into a cryogenics pod due to an oncoming radiation storm. The last thing \
|
||||
you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
important_info = "Work as a team with your fellow survivors and do not abandon them."
|
||||
uniform = /obj/item/clothing/under/rank/engineer
|
||||
shoes = /obj/item/clothing/shoes/workboots
|
||||
id = /obj/item/card/id/away/old/eng
|
||||
@@ -550,10 +564,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are a scientist working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
short_desc = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station."
|
||||
flavour_text = "You vaguely recall rushing into a cryogenics pod due to an oncoming radiation storm. \
|
||||
The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
important_info = "Work as a team with your fellow survivors and do not abandon them."
|
||||
uniform = /obj/item/clothing/under/rank/scientist
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
id = /obj/item/card/id/away/old/sci
|
||||
@@ -580,7 +595,8 @@
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
show_flavour = FALSE //Flavour only exists for spawners menu
|
||||
flavour_text = "<span class='big bold'>You are a space pirate.</span><b> The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot.</b>"
|
||||
short_desc = "You are a space pirate."
|
||||
flavour_text = "The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot."
|
||||
assignedrole = "Space Pirate"
|
||||
var/rank = "Mate"
|
||||
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
#define TANK_DISPENSER_CAPACITY 10
|
||||
|
||||
/obj/structure/tank_dispenser
|
||||
name = "tank dispenser"
|
||||
desc = "A simple yet bulky storage device for gas tanks. Holds up to 10 oxygen tanks and 10 plasma tanks."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "dispenser"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
max_integrity = 300
|
||||
var/oxygentanks = TANK_DISPENSER_CAPACITY
|
||||
var/plasmatanks = TANK_DISPENSER_CAPACITY
|
||||
|
||||
/obj/structure/tank_dispenser/oxygen
|
||||
plasmatanks = 0
|
||||
|
||||
/obj/structure/tank_dispenser/plasma
|
||||
oxygentanks = 0
|
||||
|
||||
/obj/structure/tank_dispenser/Initialize()
|
||||
. = ..()
|
||||
for(var/i in 1 to oxygentanks)
|
||||
new /obj/item/tank/internals/oxygen(src)
|
||||
for(var/i in 1 to plasmatanks)
|
||||
new /obj/item/tank/internals/plasma(src)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/tank_dispenser/update_icon()
|
||||
cut_overlays()
|
||||
switch(oxygentanks)
|
||||
if(1 to 3)
|
||||
add_overlay("oxygen-[oxygentanks]")
|
||||
if(4 to TANK_DISPENSER_CAPACITY)
|
||||
add_overlay("oxygen-4")
|
||||
switch(plasmatanks)
|
||||
if(1 to 4)
|
||||
add_overlay("plasma-[plasmatanks]")
|
||||
if(5 to TANK_DISPENSER_CAPACITY)
|
||||
add_overlay("plasma-5")
|
||||
|
||||
/obj/structure/tank_dispenser/attackby(obj/item/I, mob/user, params)
|
||||
var/full
|
||||
if(istype(I, /obj/item/tank/internals/plasma))
|
||||
if(plasmatanks < TANK_DISPENSER_CAPACITY)
|
||||
plasmatanks++
|
||||
else
|
||||
full = TRUE
|
||||
else if(istype(I, /obj/item/tank/internals/oxygen))
|
||||
if(oxygentanks < TANK_DISPENSER_CAPACITY)
|
||||
oxygentanks++
|
||||
else
|
||||
full = TRUE
|
||||
else if(istype(I, /obj/item/wrench))
|
||||
default_unfasten_wrench(user, I, time = 20)
|
||||
return
|
||||
else if(user.a_intent != INTENT_HARM)
|
||||
to_chat(user, "<span class='notice'>[I] does not fit into [src].</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
if(full)
|
||||
to_chat(user, "<span class='notice'>[src] can't hold any more of [I].</span>")
|
||||
return
|
||||
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You put [I] in [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/structure/tank_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "tank_dispenser", name, 275, 100, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/tank_dispenser/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["oxygen"] = oxygentanks
|
||||
data["plasma"] = plasmatanks
|
||||
|
||||
return data
|
||||
|
||||
/obj/structure/tank_dispenser/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("plasma")
|
||||
var/obj/item/tank/internals/plasma/tank = locate() in src
|
||||
if(tank && Adjacent(usr))
|
||||
usr.put_in_hands(tank)
|
||||
plasmatanks--
|
||||
. = TRUE
|
||||
if("oxygen")
|
||||
var/obj/item/tank/internals/oxygen/tank = locate() in src
|
||||
if(tank && Adjacent(usr))
|
||||
usr.put_in_hands(tank)
|
||||
oxygentanks--
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/structure/tank_dispenser/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
for(var/X in src)
|
||||
var/obj/item/I = X
|
||||
I.forceMove(loc)
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
#undef TANK_DISPENSER_CAPACITY
|
||||
#define TANK_DISPENSER_CAPACITY 10
|
||||
|
||||
/obj/structure/tank_dispenser
|
||||
name = "tank dispenser"
|
||||
desc = "A simple yet bulky storage device for gas tanks. Holds up to 10 oxygen tanks and 10 plasma tanks."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "dispenser"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
max_integrity = 300
|
||||
var/oxygentanks = TANK_DISPENSER_CAPACITY
|
||||
var/plasmatanks = TANK_DISPENSER_CAPACITY
|
||||
|
||||
/obj/structure/tank_dispenser/oxygen
|
||||
plasmatanks = 0
|
||||
|
||||
/obj/structure/tank_dispenser/plasma
|
||||
oxygentanks = 0
|
||||
|
||||
/obj/structure/tank_dispenser/Initialize()
|
||||
. = ..()
|
||||
for(var/i in 1 to oxygentanks)
|
||||
new /obj/item/tank/internals/oxygen(src)
|
||||
for(var/i in 1 to plasmatanks)
|
||||
new /obj/item/tank/internals/plasma(src)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/tank_dispenser/update_icon()
|
||||
cut_overlays()
|
||||
switch(oxygentanks)
|
||||
if(1 to 3)
|
||||
add_overlay("oxygen-[oxygentanks]")
|
||||
if(4 to TANK_DISPENSER_CAPACITY)
|
||||
add_overlay("oxygen-4")
|
||||
switch(plasmatanks)
|
||||
if(1 to 4)
|
||||
add_overlay("plasma-[plasmatanks]")
|
||||
if(5 to TANK_DISPENSER_CAPACITY)
|
||||
add_overlay("plasma-5")
|
||||
|
||||
/obj/structure/tank_dispenser/attackby(obj/item/I, mob/user, params)
|
||||
var/full
|
||||
if(istype(I, /obj/item/tank/internals/plasma))
|
||||
if(plasmatanks < TANK_DISPENSER_CAPACITY)
|
||||
plasmatanks++
|
||||
else
|
||||
full = TRUE
|
||||
else if(istype(I, /obj/item/tank/internals/oxygen))
|
||||
if(oxygentanks < TANK_DISPENSER_CAPACITY)
|
||||
oxygentanks++
|
||||
else
|
||||
full = TRUE
|
||||
else if(istype(I, /obj/item/wrench))
|
||||
default_unfasten_wrench(user, I, time = 20)
|
||||
return
|
||||
else if(user.a_intent != INTENT_HARM)
|
||||
to_chat(user, "<span class='notice'>[I] does not fit into [src].</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
if(full)
|
||||
to_chat(user, "<span class='notice'>[src] can't hold any more of [I].</span>")
|
||||
return
|
||||
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You put [I] in [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/structure/tank_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "tank_dispenser", name, 275, 103, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/tank_dispenser/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["oxygen"] = oxygentanks
|
||||
data["plasma"] = plasmatanks
|
||||
|
||||
return data
|
||||
|
||||
/obj/structure/tank_dispenser/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("plasma")
|
||||
var/obj/item/tank/internals/plasma/tank = locate() in src
|
||||
if(tank && Adjacent(usr))
|
||||
usr.put_in_hands(tank)
|
||||
plasmatanks--
|
||||
. = TRUE
|
||||
if("oxygen")
|
||||
var/obj/item/tank/internals/oxygen/tank = locate() in src
|
||||
if(tank && Adjacent(usr))
|
||||
usr.put_in_hands(tank)
|
||||
oxygentanks--
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/structure/tank_dispenser/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
for(var/X in src)
|
||||
var/obj/item/I = X
|
||||
I.forceMove(loc)
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
#undef TANK_DISPENSER_CAPACITY
|
||||
|
||||
+322
-319
@@ -1,319 +1,322 @@
|
||||
#define RESTART_COUNTER_PATH "data/round_counter.txt"
|
||||
|
||||
GLOBAL_VAR(restart_counter)
|
||||
|
||||
GLOBAL_VAR(topic_status_lastcache)
|
||||
GLOBAL_LIST(topic_status_cache)
|
||||
|
||||
//This happens after the Master subsystem new(s) (it's a global datum)
|
||||
//So subsystems globals exist, but are not initialised
|
||||
/world/New()
|
||||
|
||||
log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
|
||||
|
||||
SetupExternalRSC()
|
||||
|
||||
GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl
|
||||
|
||||
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
|
||||
|
||||
TgsNew()
|
||||
|
||||
GLOB.revdata = new
|
||||
|
||||
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
|
||||
|
||||
//SetupLogs depends on the RoundID, so lets check
|
||||
//DB schema and set RoundID if we can
|
||||
SSdbcore.CheckSchemaVersion()
|
||||
SSdbcore.SetRoundID()
|
||||
SetupLogs()
|
||||
|
||||
#ifndef USE_CUSTOM_ERROR_HANDLER
|
||||
world.log = file("[GLOB.log_directory]/dd.log")
|
||||
#endif
|
||||
|
||||
load_admins()
|
||||
LoadVerbs(/datum/verbs/menu)
|
||||
if(CONFIG_GET(flag/usewhitelist))
|
||||
load_whitelist()
|
||||
LoadBans()
|
||||
reload_custom_roundstart_items_list()//Cit change - loads donator items. Remind me to remove when I port over bay's loadout system
|
||||
|
||||
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
|
||||
|
||||
if(fexists(RESTART_COUNTER_PATH))
|
||||
GLOB.restart_counter = text2num(trim(file2text(RESTART_COUNTER_PATH)))
|
||||
fdel(RESTART_COUNTER_PATH)
|
||||
|
||||
if(NO_INIT_PARAMETER in params)
|
||||
return
|
||||
|
||||
cit_initialize()
|
||||
|
||||
Master.Initialize(10, FALSE, TRUE)
|
||||
|
||||
if(TEST_RUN_PARAMETER in params)
|
||||
HandleTestRun()
|
||||
|
||||
/world/proc/HandleTestRun()
|
||||
//trigger things to run the whole process
|
||||
Master.sleep_offline_after_initializations = FALSE
|
||||
SSticker.start_immediately = TRUE
|
||||
CONFIG_SET(number/round_end_countdown, 0)
|
||||
var/datum/callback/cb
|
||||
#ifdef UNIT_TESTS
|
||||
cb = CALLBACK(GLOBAL_PROC, /proc/RunUnitTests)
|
||||
#else
|
||||
cb = VARSET_CALLBACK(SSticker, force_ending, TRUE)
|
||||
#endif
|
||||
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS))
|
||||
|
||||
/world/proc/SetupExternalRSC()
|
||||
#if (PRELOAD_RSC == 0)
|
||||
GLOB.external_rsc_urls = world.file2list("[global.config.directory]/external_rsc_urls.txt","\n")
|
||||
var/i=1
|
||||
while(i<=GLOB.external_rsc_urls.len)
|
||||
if(GLOB.external_rsc_urls[i])
|
||||
i++
|
||||
else
|
||||
GLOB.external_rsc_urls.Cut(i,i+1)
|
||||
#endif
|
||||
|
||||
/world/proc/SetupLogs()
|
||||
var/override_dir = params[OVERRIDE_LOG_DIRECTORY_PARAMETER]
|
||||
if(!override_dir)
|
||||
var/realtime = world.realtime
|
||||
var/texttime = time2text(realtime, "YYYY/MM/DD")
|
||||
GLOB.log_directory = "data/logs/[texttime]/round-"
|
||||
GLOB.picture_logging_prefix = "L_[time2text(realtime, "YYYYMMDD")]_"
|
||||
GLOB.picture_log_directory = "data/picture_logs/[texttime]/round-"
|
||||
if(GLOB.round_id)
|
||||
GLOB.log_directory += "[GLOB.round_id]"
|
||||
GLOB.picture_logging_prefix += "R_[GLOB.round_id]_"
|
||||
GLOB.picture_log_directory += "[GLOB.round_id]"
|
||||
else
|
||||
var/timestamp = replacetext(TIME_STAMP("hh:mm:ss", FALSE), ":", ".")
|
||||
GLOB.log_directory += "[timestamp]"
|
||||
GLOB.picture_log_directory += "[timestamp]"
|
||||
GLOB.picture_logging_prefix += "T_[timestamp]_"
|
||||
else
|
||||
GLOB.log_directory = "data/logs/[override_dir]"
|
||||
GLOB.picture_logging_prefix = "O_[override_dir]_"
|
||||
GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
|
||||
|
||||
GLOB.world_game_log = "[GLOB.log_directory]/game.log"
|
||||
GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
|
||||
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
|
||||
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
|
||||
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
|
||||
GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
|
||||
GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log"
|
||||
GLOB.sql_error_log = "[GLOB.log_directory]/sql.log"
|
||||
GLOB.world_qdel_log = "[GLOB.log_directory]/qdel.log"
|
||||
GLOB.world_map_error_log = "[GLOB.log_directory]/map_errors.log"
|
||||
GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
|
||||
GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log"
|
||||
GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
|
||||
GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log"
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
|
||||
start_log(GLOB.test_log)
|
||||
#endif
|
||||
start_log(GLOB.world_game_log)
|
||||
start_log(GLOB.world_attack_log)
|
||||
start_log(GLOB.world_pda_log)
|
||||
start_log(GLOB.world_telecomms_log)
|
||||
start_log(GLOB.world_manifest_log)
|
||||
start_log(GLOB.world_href_log)
|
||||
start_log(GLOB.world_qdel_log)
|
||||
start_log(GLOB.world_runtime_log)
|
||||
start_log(GLOB.world_job_debug_log)
|
||||
start_log(GLOB.subsystem_log)
|
||||
|
||||
GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
|
||||
if(fexists(GLOB.config_error_log))
|
||||
fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
|
||||
fdel(GLOB.config_error_log)
|
||||
|
||||
if(GLOB.round_id)
|
||||
log_game("Round ID: [GLOB.round_id]")
|
||||
|
||||
// This was printed early in startup to the world log and config_error.log,
|
||||
// but those are both private, so let's put the commit info in the runtime
|
||||
// log which is ultimately public.
|
||||
log_runtime(GLOB.revdata.get_log_message())
|
||||
|
||||
/world/Topic(T, addr, master, key)
|
||||
TGS_TOPIC //redirect to server tools if necessary
|
||||
|
||||
if(!SSfail2topic)
|
||||
return "Server not initialized."
|
||||
else if(SSfail2topic.IsRateLimited(addr))
|
||||
return "Rate limited."
|
||||
|
||||
if(length(T) > CONFIG_GET(number/topic_max_size))
|
||||
return "Payload too large!"
|
||||
|
||||
var/static/list/topic_handlers = TopicHandlers()
|
||||
|
||||
var/list/input = params2list(T)
|
||||
var/datum/world_topic/handler
|
||||
for(var/I in topic_handlers)
|
||||
if(I in input)
|
||||
handler = topic_handlers[I]
|
||||
break
|
||||
|
||||
if((!handler || initial(handler.log)) && config && CONFIG_GET(flag/log_world_topic))
|
||||
log_topic("\"[T]\", from:[addr], master:[master], key:[key]")
|
||||
|
||||
if(!handler)
|
||||
return
|
||||
|
||||
handler = new handler()
|
||||
return handler.TryRun(input, addr)
|
||||
|
||||
/world/proc/AnnouncePR(announcement, list/payload)
|
||||
var/static/list/PRcounts = list() //PR id -> number of times announced this round
|
||||
var/id = "[payload["pull_request"]["id"]]"
|
||||
if(!PRcounts[id])
|
||||
PRcounts[id] = 1
|
||||
else
|
||||
++PRcounts[id]
|
||||
if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
|
||||
return
|
||||
|
||||
var/final_composed = "<span class='announce'>PR: [announcement]</span>"
|
||||
for(var/client/C in GLOB.clients)
|
||||
C.AnnouncePR(final_composed)
|
||||
|
||||
/world/proc/FinishTestRun()
|
||||
set waitfor = FALSE
|
||||
var/list/fail_reasons
|
||||
if(GLOB)
|
||||
if(GLOB.total_runtimes != 0)
|
||||
fail_reasons = list("Total runtimes: [GLOB.total_runtimes]")
|
||||
#ifdef UNIT_TESTS
|
||||
if(GLOB.failed_any_test)
|
||||
LAZYADD(fail_reasons, "Unit Tests failed!")
|
||||
#endif
|
||||
if(!GLOB.log_directory)
|
||||
LAZYADD(fail_reasons, "Missing GLOB.log_directory!")
|
||||
else
|
||||
fail_reasons = list("Missing GLOB!")
|
||||
if(!fail_reasons)
|
||||
text2file("Success!", "[GLOB.log_directory]/clean_run.lk")
|
||||
else
|
||||
log_world("Test run failed!\n[fail_reasons.Join("\n")]")
|
||||
sleep(0) //yes, 0, this'll let Reboot finish and prevent byond memes
|
||||
qdel(src) //shut it down
|
||||
|
||||
/world/Reboot(reason = 0, fast_track = FALSE)
|
||||
TgsReboot()
|
||||
if (reason || fast_track) //special reboot, do none of the normal stuff
|
||||
if (usr)
|
||||
log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
|
||||
message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
|
||||
to_chat(world, "<span class='boldannounce'>Rebooting World immediately due to host request</span>")
|
||||
else
|
||||
to_chat(world, "<span class='boldannounce'>Rebooting world...</span>")
|
||||
Master.Shutdown() //run SS shutdowns
|
||||
|
||||
if(TEST_RUN_PARAMETER in params)
|
||||
FinishTestRun()
|
||||
return
|
||||
|
||||
if(TgsAvailable())
|
||||
var/do_hard_reboot
|
||||
// check the hard reboot counter
|
||||
var/ruhr = CONFIG_GET(number/rounds_until_hard_restart)
|
||||
switch(ruhr)
|
||||
if(-1)
|
||||
do_hard_reboot = FALSE
|
||||
if(0)
|
||||
do_hard_reboot = TRUE
|
||||
else
|
||||
if(GLOB.restart_counter >= ruhr)
|
||||
do_hard_reboot = TRUE
|
||||
else
|
||||
text2file("[++GLOB.restart_counter]", RESTART_COUNTER_PATH)
|
||||
do_hard_reboot = FALSE
|
||||
|
||||
if(do_hard_reboot)
|
||||
log_world("World hard rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
|
||||
shutdown_logging() // See comment below.
|
||||
TgsEndProcess()
|
||||
|
||||
log_world("World rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
|
||||
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
..()
|
||||
|
||||
/world/proc/update_status()
|
||||
|
||||
var/list/features = list()
|
||||
|
||||
/*if(GLOB.master_mode) CIT CHANGE - hides the gamemode from the hub entry, removes some useless info from the hub entry
|
||||
features += GLOB.master_mode
|
||||
|
||||
if (!GLOB.enter_allowed)
|
||||
features += "closed"*/
|
||||
|
||||
var/s = ""
|
||||
var/hostedby
|
||||
if(config)
|
||||
var/server_name = CONFIG_GET(string/servername)
|
||||
if (server_name)
|
||||
s += "<b>[server_name]</b> — "
|
||||
/*features += "[CONFIG_GET(flag/norespawn) ? "no " : ""]respawn" CIT CHANGE - removes some useless info from the hub entry
|
||||
if(CONFIG_GET(flag/allow_vote_mode))
|
||||
features += "vote"
|
||||
if(CONFIG_GET(flag/allow_ai))
|
||||
features += "AI allowed"*/
|
||||
hostedby = CONFIG_GET(string/hostedby)
|
||||
|
||||
s += "<b>[station_name()]</b>";
|
||||
s += " ("
|
||||
s += "<a href=\"https://citadel-station.net/home/\">" //Change this to wherever you want the hub to link to. CIT CHANGE - links to cit's website on the hub
|
||||
s += "Citadel" //Replace this with something else. Or ever better, delete it and uncomment the game version. CIT CHANGE - modifies the hub entry link
|
||||
s += "</a>"
|
||||
s += ")\]" //CIT CHANGE - encloses the server title in brackets to make the hub entry fancier
|
||||
s += "<br>[CONFIG_GET(string/servertagline)]<br>" //CIT CHANGE - adds a tagline!
|
||||
|
||||
var/n = 0
|
||||
for (var/mob/M in GLOB.player_list)
|
||||
if (M.client)
|
||||
n++
|
||||
|
||||
if(SSmapping.config) // this just stops the runtime, honk.
|
||||
features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
|
||||
|
||||
if(get_security_level())//CIT CHANGE - makes the hub entry show the security level
|
||||
features += "[get_security_level()] alert"
|
||||
|
||||
if (n > 1)
|
||||
features += "~[n] players"
|
||||
else if (n > 0)
|
||||
features += "~[n] player"
|
||||
|
||||
if (!host && hostedby)
|
||||
features += "hosted by <b>[hostedby]</b>"
|
||||
|
||||
if (features)
|
||||
s += "\[[jointext(features, ", ")]" //CIT CHANGE - replaces the colon here with a left bracket
|
||||
|
||||
status = s
|
||||
|
||||
/world/proc/update_hub_visibility(new_visibility)
|
||||
if(new_visibility == GLOB.hub_visibility)
|
||||
return
|
||||
GLOB.hub_visibility = new_visibility
|
||||
if(GLOB.hub_visibility)
|
||||
hub_password = "kMZy3U5jJHSiBQjr"
|
||||
else
|
||||
hub_password = "SORRYNOPASSWORD"
|
||||
|
||||
/world/proc/incrementMaxZ()
|
||||
maxz++
|
||||
SSmobs.MaxZChanged()
|
||||
SSidlenpcpool.MaxZChanged()
|
||||
#define RESTART_COUNTER_PATH "data/round_counter.txt"
|
||||
|
||||
GLOBAL_VAR(restart_counter)
|
||||
|
||||
GLOBAL_VAR(topic_status_lastcache)
|
||||
GLOBAL_LIST(topic_status_cache)
|
||||
|
||||
//This happens after the Master subsystem new(s) (it's a global datum)
|
||||
//So subsystems globals exist, but are not initialised
|
||||
/world/New()
|
||||
|
||||
log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
|
||||
|
||||
SetupExternalRSC()
|
||||
|
||||
GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl
|
||||
|
||||
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
|
||||
|
||||
TgsNew()
|
||||
|
||||
GLOB.revdata = new
|
||||
|
||||
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
|
||||
|
||||
//SetupLogs depends on the RoundID, so lets check
|
||||
//DB schema and set RoundID if we can
|
||||
SSdbcore.CheckSchemaVersion()
|
||||
SSdbcore.SetRoundID()
|
||||
SetupLogs()
|
||||
|
||||
#ifndef USE_CUSTOM_ERROR_HANDLER
|
||||
world.log = file("[GLOB.log_directory]/dd.log")
|
||||
#endif
|
||||
|
||||
load_admins()
|
||||
LoadVerbs(/datum/verbs/menu)
|
||||
if(CONFIG_GET(flag/usewhitelist))
|
||||
load_whitelist()
|
||||
LoadBans()
|
||||
reload_custom_roundstart_items_list()//Cit change - loads donator items. Remind me to remove when I port over bay's loadout system
|
||||
|
||||
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
|
||||
|
||||
if(fexists(RESTART_COUNTER_PATH))
|
||||
GLOB.restart_counter = text2num(trim(file2text(RESTART_COUNTER_PATH)))
|
||||
fdel(RESTART_COUNTER_PATH)
|
||||
|
||||
if(NO_INIT_PARAMETER in params)
|
||||
return
|
||||
|
||||
cit_initialize()
|
||||
|
||||
Master.Initialize(10, FALSE, TRUE)
|
||||
|
||||
if(TEST_RUN_PARAMETER in params)
|
||||
HandleTestRun()
|
||||
|
||||
/world/proc/HandleTestRun()
|
||||
//trigger things to run the whole process
|
||||
Master.sleep_offline_after_initializations = FALSE
|
||||
SSticker.start_immediately = TRUE
|
||||
CONFIG_SET(number/round_end_countdown, 0)
|
||||
var/datum/callback/cb
|
||||
#ifdef UNIT_TESTS
|
||||
cb = CALLBACK(GLOBAL_PROC, /proc/RunUnitTests)
|
||||
#else
|
||||
cb = VARSET_CALLBACK(SSticker, force_ending, TRUE)
|
||||
#endif
|
||||
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS))
|
||||
|
||||
/world/proc/SetupExternalRSC()
|
||||
#if (PRELOAD_RSC == 0)
|
||||
GLOB.external_rsc_urls = world.file2list("[global.config.directory]/external_rsc_urls.txt","\n")
|
||||
var/i=1
|
||||
while(i<=GLOB.external_rsc_urls.len)
|
||||
if(GLOB.external_rsc_urls[i])
|
||||
i++
|
||||
else
|
||||
GLOB.external_rsc_urls.Cut(i,i+1)
|
||||
#endif
|
||||
|
||||
/world/proc/SetupLogs()
|
||||
var/override_dir = params[OVERRIDE_LOG_DIRECTORY_PARAMETER]
|
||||
if(!override_dir)
|
||||
var/realtime = world.realtime
|
||||
var/texttime = time2text(realtime, "YYYY/MM/DD")
|
||||
GLOB.log_directory = "data/logs/[texttime]/round-"
|
||||
GLOB.picture_logging_prefix = "L_[time2text(realtime, "YYYYMMDD")]_"
|
||||
GLOB.picture_log_directory = "data/picture_logs/[texttime]/round-"
|
||||
if(GLOB.round_id)
|
||||
GLOB.log_directory += "[GLOB.round_id]"
|
||||
GLOB.picture_logging_prefix += "R_[GLOB.round_id]_"
|
||||
GLOB.picture_log_directory += "[GLOB.round_id]"
|
||||
else
|
||||
var/timestamp = replacetext(TIME_STAMP("hh:mm:ss", FALSE), ":", ".")
|
||||
GLOB.log_directory += "[timestamp]"
|
||||
GLOB.picture_log_directory += "[timestamp]"
|
||||
GLOB.picture_logging_prefix += "T_[timestamp]_"
|
||||
else
|
||||
GLOB.log_directory = "data/logs/[override_dir]"
|
||||
GLOB.picture_logging_prefix = "O_[override_dir]_"
|
||||
GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
|
||||
|
||||
GLOB.world_game_log = "[GLOB.log_directory]/game.log"
|
||||
GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
|
||||
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
|
||||
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
|
||||
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
|
||||
GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
|
||||
GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log"
|
||||
GLOB.sql_error_log = "[GLOB.log_directory]/sql.log"
|
||||
GLOB.world_qdel_log = "[GLOB.log_directory]/qdel.log"
|
||||
GLOB.world_map_error_log = "[GLOB.log_directory]/map_errors.log"
|
||||
GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
|
||||
GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log"
|
||||
GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
|
||||
GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
|
||||
GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log"
|
||||
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
|
||||
start_log(GLOB.test_log)
|
||||
#endif
|
||||
start_log(GLOB.world_game_log)
|
||||
start_log(GLOB.world_attack_log)
|
||||
start_log(GLOB.world_pda_log)
|
||||
start_log(GLOB.world_telecomms_log)
|
||||
start_log(GLOB.world_manifest_log)
|
||||
start_log(GLOB.world_href_log)
|
||||
start_log(GLOB.world_qdel_log)
|
||||
start_log(GLOB.world_runtime_log)
|
||||
start_log(GLOB.world_job_debug_log)
|
||||
start_log(GLOB.tgui_log)
|
||||
start_log(GLOB.subsystem_log)
|
||||
|
||||
GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
|
||||
if(fexists(GLOB.config_error_log))
|
||||
fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
|
||||
fdel(GLOB.config_error_log)
|
||||
|
||||
if(GLOB.round_id)
|
||||
log_game("Round ID: [GLOB.round_id]")
|
||||
|
||||
// This was printed early in startup to the world log and config_error.log,
|
||||
// but those are both private, so let's put the commit info in the runtime
|
||||
// log which is ultimately public.
|
||||
log_runtime(GLOB.revdata.get_log_message())
|
||||
|
||||
/world/Topic(T, addr, master, key)
|
||||
TGS_TOPIC //redirect to server tools if necessary
|
||||
|
||||
if(!SSfail2topic)
|
||||
return "Server not initialized."
|
||||
else if(SSfail2topic.IsRateLimited(addr))
|
||||
return "Rate limited."
|
||||
|
||||
if(length(T) > CONFIG_GET(number/topic_max_size))
|
||||
return "Payload too large!"
|
||||
|
||||
var/static/list/topic_handlers = TopicHandlers()
|
||||
|
||||
var/list/input = params2list(T)
|
||||
var/datum/world_topic/handler
|
||||
for(var/I in topic_handlers)
|
||||
if(I in input)
|
||||
handler = topic_handlers[I]
|
||||
break
|
||||
|
||||
if((!handler || initial(handler.log)) && config && CONFIG_GET(flag/log_world_topic))
|
||||
log_topic("\"[T]\", from:[addr], master:[master], key:[key]")
|
||||
|
||||
if(!handler)
|
||||
return
|
||||
|
||||
handler = new handler()
|
||||
return handler.TryRun(input, addr)
|
||||
|
||||
/world/proc/AnnouncePR(announcement, list/payload)
|
||||
var/static/list/PRcounts = list() //PR id -> number of times announced this round
|
||||
var/id = "[payload["pull_request"]["id"]]"
|
||||
if(!PRcounts[id])
|
||||
PRcounts[id] = 1
|
||||
else
|
||||
++PRcounts[id]
|
||||
if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
|
||||
return
|
||||
|
||||
var/final_composed = "<span class='announce'>PR: [announcement]</span>"
|
||||
for(var/client/C in GLOB.clients)
|
||||
C.AnnouncePR(final_composed)
|
||||
|
||||
/world/proc/FinishTestRun()
|
||||
set waitfor = FALSE
|
||||
var/list/fail_reasons
|
||||
if(GLOB)
|
||||
if(GLOB.total_runtimes != 0)
|
||||
fail_reasons = list("Total runtimes: [GLOB.total_runtimes]")
|
||||
#ifdef UNIT_TESTS
|
||||
if(GLOB.failed_any_test)
|
||||
LAZYADD(fail_reasons, "Unit Tests failed!")
|
||||
#endif
|
||||
if(!GLOB.log_directory)
|
||||
LAZYADD(fail_reasons, "Missing GLOB.log_directory!")
|
||||
else
|
||||
fail_reasons = list("Missing GLOB!")
|
||||
if(!fail_reasons)
|
||||
text2file("Success!", "[GLOB.log_directory]/clean_run.lk")
|
||||
else
|
||||
log_world("Test run failed!\n[fail_reasons.Join("\n")]")
|
||||
sleep(0) //yes, 0, this'll let Reboot finish and prevent byond memes
|
||||
qdel(src) //shut it down
|
||||
|
||||
/world/Reboot(reason = 0, fast_track = FALSE)
|
||||
TgsReboot()
|
||||
if (reason || fast_track) //special reboot, do none of the normal stuff
|
||||
if (usr)
|
||||
log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
|
||||
message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
|
||||
to_chat(world, "<span class='boldannounce'>Rebooting World immediately due to host request</span>")
|
||||
else
|
||||
to_chat(world, "<span class='boldannounce'>Rebooting world...</span>")
|
||||
Master.Shutdown() //run SS shutdowns
|
||||
|
||||
if(TEST_RUN_PARAMETER in params)
|
||||
FinishTestRun()
|
||||
return
|
||||
|
||||
if(TgsAvailable())
|
||||
var/do_hard_reboot
|
||||
// check the hard reboot counter
|
||||
var/ruhr = CONFIG_GET(number/rounds_until_hard_restart)
|
||||
switch(ruhr)
|
||||
if(-1)
|
||||
do_hard_reboot = FALSE
|
||||
if(0)
|
||||
do_hard_reboot = TRUE
|
||||
else
|
||||
if(GLOB.restart_counter >= ruhr)
|
||||
do_hard_reboot = TRUE
|
||||
else
|
||||
text2file("[++GLOB.restart_counter]", RESTART_COUNTER_PATH)
|
||||
do_hard_reboot = FALSE
|
||||
|
||||
if(do_hard_reboot)
|
||||
log_world("World hard rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
|
||||
shutdown_logging() // See comment below.
|
||||
TgsEndProcess()
|
||||
|
||||
log_world("World rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
|
||||
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
..()
|
||||
|
||||
/world/proc/update_status()
|
||||
|
||||
var/list/features = list()
|
||||
|
||||
/*if(GLOB.master_mode) CIT CHANGE - hides the gamemode from the hub entry, removes some useless info from the hub entry
|
||||
features += GLOB.master_mode
|
||||
|
||||
if (!GLOB.enter_allowed)
|
||||
features += "closed"*/
|
||||
|
||||
var/s = ""
|
||||
var/hostedby
|
||||
if(config)
|
||||
var/server_name = CONFIG_GET(string/servername)
|
||||
if (server_name)
|
||||
s += "<b>[server_name]</b> — "
|
||||
/*features += "[CONFIG_GET(flag/norespawn) ? "no " : ""]respawn" CIT CHANGE - removes some useless info from the hub entry
|
||||
if(CONFIG_GET(flag/allow_vote_mode))
|
||||
features += "vote"
|
||||
if(CONFIG_GET(flag/allow_ai))
|
||||
features += "AI allowed"*/
|
||||
hostedby = CONFIG_GET(string/hostedby)
|
||||
|
||||
s += "<b>[station_name()]</b>";
|
||||
s += " ("
|
||||
s += "<a href=\"https://citadel-station.net/home/\">" //Change this to wherever you want the hub to link to. CIT CHANGE - links to cit's website on the hub
|
||||
s += "Citadel" //Replace this with something else. Or ever better, delete it and uncomment the game version. CIT CHANGE - modifies the hub entry link
|
||||
s += "</a>"
|
||||
s += ")\]" //CIT CHANGE - encloses the server title in brackets to make the hub entry fancier
|
||||
s += "<br>[CONFIG_GET(string/servertagline)]<br>" //CIT CHANGE - adds a tagline!
|
||||
|
||||
var/n = 0
|
||||
for (var/mob/M in GLOB.player_list)
|
||||
if (M.client)
|
||||
n++
|
||||
|
||||
if(SSmapping.config) // this just stops the runtime, honk.
|
||||
features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
|
||||
|
||||
if(get_security_level())//CIT CHANGE - makes the hub entry show the security level
|
||||
features += "[get_security_level()] alert"
|
||||
|
||||
if (n > 1)
|
||||
features += "~[n] players"
|
||||
else if (n > 0)
|
||||
features += "~[n] player"
|
||||
|
||||
if (!host && hostedby)
|
||||
features += "hosted by <b>[hostedby]</b>"
|
||||
|
||||
if (features)
|
||||
s += "\[[jointext(features, ", ")]" //CIT CHANGE - replaces the colon here with a left bracket
|
||||
|
||||
status = s
|
||||
|
||||
/world/proc/update_hub_visibility(new_visibility)
|
||||
if(new_visibility == GLOB.hub_visibility)
|
||||
return
|
||||
GLOB.hub_visibility = new_visibility
|
||||
if(GLOB.hub_visibility)
|
||||
hub_password = "kMZy3U5jJHSiBQjr"
|
||||
else
|
||||
hub_password = "SORRYNOPASSWORD"
|
||||
|
||||
/world/proc/incrementMaxZ()
|
||||
maxz++
|
||||
SSmobs.MaxZChanged()
|
||||
SSidlenpcpool.MaxZChanged()
|
||||
|
||||
Reference in New Issue
Block a user