mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 11:05:03 +01:00
Merge remote-tracking branch 'upstream/master' into tgui-filter
This commit is contained in:
@@ -167,7 +167,7 @@
|
||||
/turf/simulated/floor/wood,
|
||||
/area/ruin/powered/snow_cabin)
|
||||
"aL" = (
|
||||
/obj/structure/displaycase/captain,
|
||||
/obj/mecha/working/ripley/mining,
|
||||
/turf/simulated/floor/wood,
|
||||
/area/ruin/powered/snow_cabin)
|
||||
"aM" = (
|
||||
@@ -392,12 +392,6 @@
|
||||
/obj/structure/filingcabinet,
|
||||
/turf/simulated/floor/pod/dark,
|
||||
/area/ruin/powered/snow_biodome)
|
||||
"UM" = (
|
||||
/obj/machinery/computer/monitor/secret{
|
||||
dir = 1
|
||||
},
|
||||
/turf/simulated/floor/pod/dark,
|
||||
/area/ruin/powered/snow_biodome)
|
||||
"Wg" = (
|
||||
/turf/simulated/wall/r_wall,
|
||||
/area/ruin/powered/snow_biodome)
|
||||
@@ -484,7 +478,7 @@ HP
|
||||
tl
|
||||
PK
|
||||
gz
|
||||
UM
|
||||
HP
|
||||
Wg
|
||||
ak
|
||||
ak
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
"an" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDNW";
|
||||
invisibility = 100;
|
||||
location = "SDNE"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
@@ -292,15 +291,13 @@
|
||||
"aU" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDSW";
|
||||
invisibility = 100;
|
||||
location = "SDNW"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/syndicate_depot/outer)
|
||||
"aV" = (
|
||||
/obj/machinery/light{
|
||||
dir = 4;
|
||||
icon_state = "tube1"
|
||||
dir = 4
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/syndicate_depot/outer)
|
||||
@@ -429,8 +426,7 @@
|
||||
/area/syndicate_depot/core)
|
||||
"bo" = (
|
||||
/obj/machinery/light{
|
||||
dir = 4;
|
||||
icon_state = "tube1"
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/spawner/random_spawners/syndicate/loot,
|
||||
/turf/simulated/floor/plasteel{
|
||||
@@ -512,7 +508,6 @@
|
||||
id = "syndi_depot_rear";
|
||||
idle_power_usage = 0;
|
||||
name = "mysterious button";
|
||||
normaldoorcontrol = 0;
|
||||
pixel_x = 24;
|
||||
use_power = 0
|
||||
},
|
||||
@@ -663,8 +658,8 @@
|
||||
/obj/machinery/turretid/syndicate{
|
||||
name = "external turret controls";
|
||||
pixel_x = -32;
|
||||
pixel_y = 0;
|
||||
req_access = list(150)
|
||||
req_access = null;
|
||||
req_access_txt = "150"
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
icon_state = "dark"
|
||||
@@ -745,9 +740,8 @@
|
||||
/area/syndicate_depot/core)
|
||||
"ce" = (
|
||||
/obj/machinery/light/small{
|
||||
tag = "icon-bulb1 (EAST)";
|
||||
icon_state = "bulb1";
|
||||
dir = 4
|
||||
dir = 4;
|
||||
tag = "icon-bulb1 (EAST)"
|
||||
},
|
||||
/turf/simulated/floor/mineral/silver,
|
||||
/area/syndicate_depot/core)
|
||||
@@ -757,7 +751,6 @@
|
||||
id = "syndi_depot_rear";
|
||||
idle_power_usage = 0;
|
||||
name = "mysterious button";
|
||||
normaldoorcontrol = 0;
|
||||
use_power = 0
|
||||
},
|
||||
/obj/structure/sign/poster/contraband/syndicate_recruitment,
|
||||
@@ -774,8 +767,8 @@
|
||||
/area/syndicate_depot/core)
|
||||
"ci" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-2";
|
||||
d2 = 2
|
||||
d2 = 2;
|
||||
icon_state = "0-2"
|
||||
},
|
||||
/obj/machinery/power/smes/upgraded{
|
||||
charge = 5e+006;
|
||||
@@ -845,7 +838,6 @@
|
||||
"cr" = (
|
||||
/obj/structure/sink{
|
||||
dir = 4;
|
||||
icon_state = "sink";
|
||||
pixel_x = 12
|
||||
},
|
||||
/turf/simulated/floor/mineral/silver,
|
||||
@@ -1154,7 +1146,6 @@
|
||||
"dc" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDSE";
|
||||
invisibility = 100;
|
||||
location = "SDSW"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
@@ -1179,7 +1170,6 @@
|
||||
"df" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDNE";
|
||||
invisibility = 100;
|
||||
location = "SDSE"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
|
||||
@@ -137,51 +137,56 @@
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 110, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"rate" = round(target_pressure),
|
||||
"max_rate" = MAX_OUTPUT_PRESSURE,
|
||||
"gas_unit" = "kPa",
|
||||
"step" = 10 // This is for the TGUI <NumberInput> step. It's here since multiple pumps share the same UI, but need different values.
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
if("max_rate")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
|
||||
if("min_rate")
|
||||
target_pressure = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_rate")
|
||||
target_pressure = clamp(text2num(params["rate"]), 0 , MAX_OUTPUT_PRESSURE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/proc/toggle()
|
||||
if(powered())
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["pressure"])
|
||||
var/pressure = href_list["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure))
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/attackby(obj/item/W, mob/user, params)
|
||||
if(!istype(W, /obj/item/wrench))
|
||||
|
||||
@@ -192,51 +192,51 @@ Thus, the two variables affect pump operation are set in New():
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/binary/pump/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 110, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
/obj/machinery/atmospherics/binary/pump/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"rate" = round(target_pressure),
|
||||
"max_rate" = MAX_OUTPUT_PRESSURE,
|
||||
"gas_unit" = "kPa",
|
||||
"step" = 10 // This is for the TGUI <NumberInput> step. It's here since multiple pumps share the same UI, but need different values.
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/binary/pump/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["pressure"])
|
||||
var/pressure = href_list["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure))
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
if("max_rate")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
|
||||
if("min_rate")
|
||||
target_pressure = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_rate")
|
||||
target_pressure = clamp(text2num(params["rate"]), 0 , MAX_OUTPUT_PRESSURE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/power_change()
|
||||
var/old_stat = stat
|
||||
|
||||
@@ -188,51 +188,51 @@ Thus, the two variables affect pump operation are set in New():
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/binary/volume_pump/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 310, 115, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 110, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["rate"] = round(transfer_rate)
|
||||
data["max_rate"] = round(MAX_TRANSFER_RATE)
|
||||
/obj/machinery/atmospherics/binary/volume_pump/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"rate" = round(transfer_rate),
|
||||
"max_rate" = round(MAX_TRANSFER_RATE),
|
||||
"gas_unit" = "L/s",
|
||||
"step" = 1 // This is for the TGUI <NumberInput> step. It's here since multiple pumps share the same UI, but need different values.
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/binary/volume_pump/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["rate"])
|
||||
var/rate = href_list["rate"]
|
||||
if(rate == "max")
|
||||
rate = MAX_TRANSFER_RATE
|
||||
. = TRUE
|
||||
else if(rate == "input")
|
||||
rate = input("New transfer rate (0-[MAX_TRANSFER_RATE] L/s):", name, transfer_rate) as num|null
|
||||
if(!isnull(rate))
|
||||
. = TRUE
|
||||
else if(text2num(rate) != null)
|
||||
rate = text2num(rate)
|
||||
. = TRUE
|
||||
if(.)
|
||||
transfer_rate = clamp(rate, 0, MAX_TRANSFER_RATE)
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
if("max_rate")
|
||||
transfer_rate = MAX_TRANSFER_RATE
|
||||
. = TRUE
|
||||
|
||||
if("min_rate")
|
||||
transfer_rate = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_rate")
|
||||
transfer_rate = clamp(text2num(params["rate"]), 0 , MAX_TRANSFER_RATE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/power_change()
|
||||
var/old_stat = stat
|
||||
|
||||
@@ -92,3 +92,8 @@
|
||||
// Firelock states
|
||||
#define FD_OPEN 1
|
||||
#define FD_CLOSED 2
|
||||
|
||||
// Computer login types
|
||||
#define LOGIN_TYPE_NORMAL 1
|
||||
#define LOGIN_TYPE_AI 2
|
||||
#define LOGIN_TYPE_ROBOT 3
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// TGUI defines
|
||||
#define TGUI_MODAL_INPUT_MAX_LENGTH 1024
|
||||
#define TGUI_MODAL_INPUT_MAX_LENGTH_NAME 64 // Names for generally anything don't go past 32, let alone 64.
|
||||
|
||||
#define TGUI_MODAL_OPEN 1
|
||||
#define TGUI_MODAL_DELEGATE 2
|
||||
#define TGUI_MODAL_ANSWER 3
|
||||
#define TGUI_MODAL_CLOSE 4
|
||||
@@ -95,7 +95,7 @@ proc/isDay(var/month, var/day)
|
||||
/proc/seconds_to_time(var/seconds as num)
|
||||
var/numSeconds = seconds % 60
|
||||
var/numMinutes = (seconds - numSeconds) / 60
|
||||
return "[numMinutes] [numMinutes > 1 ? "minutes" : "minute"] and [numSeconds] seconds."
|
||||
return "[numMinutes] [numMinutes > 1 ? "minutes" : "minute"] and [numSeconds] seconds"
|
||||
|
||||
//Take a value in seconds and makes it display like a clock
|
||||
/proc/seconds_to_clock(var/seconds as num)
|
||||
|
||||
+13
-5
@@ -182,13 +182,14 @@
|
||||
|
||||
// TURRETCONTROL
|
||||
|
||||
// These two will be changed with TGUI turrets/turretcontrol.
|
||||
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
|
||||
Topic(src, list("src" = UID(), "command"="enable", "value"="[!enabled]"), 1) // 1 meaning no window (consistency!)
|
||||
/obj/machinery/turretid/AICtrlClick(mob/living/silicon/ai/user) //turns off/on Turrets
|
||||
enabled = !enabled
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
|
||||
Topic(src, list("src" = UID(), "command"="lethal", "value"="[!lethal]"), 1) // 1 meaning no window (consistency!)
|
||||
|
||||
if(lethal_is_configurable)
|
||||
lethal = !lethal
|
||||
updateTurrets()
|
||||
|
||||
// AIRLOCKS
|
||||
|
||||
@@ -230,6 +231,13 @@
|
||||
to_chat(user, "<span class='notice'>The door bolt lights have been enabled.</span>")
|
||||
update_icon()
|
||||
|
||||
// FIRE ALARMS
|
||||
|
||||
/obj/machinery/firealarm/AICtrlClick()
|
||||
if(enabled)
|
||||
reset()
|
||||
else
|
||||
alarm()
|
||||
|
||||
// AI-CONTROLLED SLIP GENERATOR IN AI CORE
|
||||
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
/obj/machinery/ai_slipper/BorgAltClick() //Dispenses liquid if on
|
||||
Activate()
|
||||
|
||||
/obj/machinery/firealarm/BorgCtrlClick()
|
||||
AICtrlClick()
|
||||
|
||||
/*
|
||||
As with AI, these are not used in click code,
|
||||
because the code for robots is specific, not generic.
|
||||
|
||||
@@ -93,6 +93,11 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return S
|
||||
WARNING("couldn't find dock with id: [id]")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/secondsToRefuel()
|
||||
var/elapsed = world.time - SSticker.round_start_time
|
||||
var/remaining = round((config.shuttle_refuel_delay - elapsed) / 10)
|
||||
return remaining > 0 ? remaining : 0
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
|
||||
if(!emergency)
|
||||
WARNING("requestEvac(): There is no emergency shuttle, but the shuttle was called. Using the backup shuttle instead.")
|
||||
@@ -107,7 +112,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return
|
||||
emergency = backup_shuttle
|
||||
|
||||
if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay)
|
||||
if(secondsToRefuel())
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
|
||||
return
|
||||
|
||||
@@ -131,7 +136,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
|
||||
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH)
|
||||
to_chat(user, "You must provide a reason.")
|
||||
to_chat(user, "Reason is too short. [CALL_SHUTTLE_REASON_LENGTH] character minimum.")
|
||||
return
|
||||
|
||||
var/area/signal_origin = get_area(user)
|
||||
@@ -192,7 +197,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/obj/machinery/computer/communications/C = thing
|
||||
if(C.stat & BROKEN)
|
||||
continue
|
||||
else if(istype(thing, /datum/computer_file/program/comm) || istype(thing, /obj/item/circuitboard/communications))
|
||||
else if(istype(thing, /obj/item/circuitboard/communications))
|
||||
continue
|
||||
|
||||
var/turf/T = get_turf(thing)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
name = "Biodome Winter"
|
||||
id = "biodome-winter"
|
||||
description = "For those getaways where you want to get back to nature, but you don't want to leave the fortified military compound where you spend your days. \
|
||||
Includes a unique(*) laser pistol display case, and the recently introduced I.C.E(tm)."
|
||||
Includes the recently introduced I.C.E(tm)."
|
||||
suffix = "lavaland_biodome_winter.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/biodome/clown
|
||||
|
||||
@@ -6,44 +6,47 @@
|
||||
qdel(src)
|
||||
owner = new_owner
|
||||
|
||||
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = FALSE, datum/topic_state/state = GLOB.ghost_state, datum/nanoui/master_ui = null)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/datum/spawners_menu/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui_state/state = GLOB.tgui_observer_state, datum/tgui/master_ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "spawners_menu.tmpl", "Spawners Menu", 700, 600, master_ui, state = state)
|
||||
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state = state)
|
||||
ui.open()
|
||||
|
||||
/datum/spawners_menu/ui_data(mob/user)
|
||||
/datum/spawners_menu/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["spawners"] = list()
|
||||
for(var/spawner in GLOB.mob_spawners)
|
||||
var/list/this = list()
|
||||
this["name"] = spawner
|
||||
this["desc"] = ""
|
||||
this["important_info"] = ""
|
||||
this["fluff"] = ""
|
||||
this["uids"] = list()
|
||||
for(var/spawner_obj in GLOB.mob_spawners[spawner])
|
||||
for(var/spawner_obj in GLOB.mob_spawners[spawner])//each spawner can contain multiple actual spawners, we use only one desc/info
|
||||
this["uids"] += "\ref[spawner_obj]"
|
||||
if(!this["desc"])
|
||||
if(!this["desc"]) //haven't set descriptions yet
|
||||
if(istype(spawner_obj, /obj/effect/mob_spawn))
|
||||
var/obj/effect/mob_spawn/MS = spawner_obj
|
||||
this["desc"] = MS.flavour_text
|
||||
this["desc"] = MS.description
|
||||
this["important_info"] = MS.important_info
|
||||
this["fluff"] = MS.flavour_text
|
||||
else
|
||||
var/obj/O = spawner_obj
|
||||
this["desc"] = O.desc
|
||||
this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner])
|
||||
data["spawners"] += list(this)
|
||||
|
||||
return data
|
||||
|
||||
/datum/spawners_menu/Topic(href, href_list)
|
||||
/datum/spawners_menu/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
var/spawners = replacetext(href_list["uid"], ",", ";")
|
||||
return
|
||||
var/spawners = replacetext(params["ID"], ",", ";")
|
||||
var/list/possible_spawners = params2list(spawners)
|
||||
var/obj/effect/mob_spawn/MS = locate(pick(possible_spawners))
|
||||
if(!MS || !istype(MS))
|
||||
log_runtime(EXCEPTION("A ghost tried to interact with an invalid spawner, or the spawner didn't exist."))
|
||||
return
|
||||
switch(href_list["action"])
|
||||
switch(action)
|
||||
if("jump")
|
||||
owner.forceMove(get_turf(MS))
|
||||
. = TRUE
|
||||
|
||||
+343
-403
@@ -7,6 +7,11 @@
|
||||
|
||||
#define NEGATE_MUTATION_THRESHOLD 30 // Occupants with over ## percent radiation threshold will not gain mutations
|
||||
|
||||
#define PAGE_UI "ui"
|
||||
#define PAGE_SE "se"
|
||||
#define PAGE_BUFFER "buffer"
|
||||
#define PAGE_REJUVENATORS "rejuvenators"
|
||||
|
||||
//list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0),
|
||||
/datum/dna2/record
|
||||
var/datum/dna/dna = null
|
||||
@@ -161,6 +166,7 @@
|
||||
occupant = usr
|
||||
icon_state = "scanner_occupied"
|
||||
add_fingerprint(usr)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/dna_scannernew/MouseDrop_T(atom/movable/O, mob/user)
|
||||
if(!istype(O))
|
||||
@@ -214,6 +220,7 @@
|
||||
return
|
||||
|
||||
beaker = I
|
||||
SStgui.update_uis(src)
|
||||
I.forceMove(src)
|
||||
user.visible_message("[user] adds \a [I] to \the [src]!", "You add \a [I] to \the [src]!")
|
||||
return
|
||||
@@ -260,6 +267,7 @@
|
||||
M.forceMove(src)
|
||||
occupant = M
|
||||
icon_state = "scanner_occupied"
|
||||
SStgui.update_uis(src)
|
||||
|
||||
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
|
||||
if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
|
||||
@@ -281,6 +289,7 @@
|
||||
occupant.forceMove(loc)
|
||||
occupant = null
|
||||
icon_state = "scanner_open"
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/dna_scannernew/force_eject_occupant()
|
||||
go_out(null, TRUE)
|
||||
@@ -296,6 +305,7 @@
|
||||
occupant = null
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
// Checks if occupants can be irradiated/mutated - prevents exploits where wearing full rad protection would still let you gain mutations
|
||||
/obj/machinery/dna_scannernew/proc/radiation_check()
|
||||
@@ -333,12 +343,11 @@
|
||||
var/injector_ready = FALSE //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
|
||||
var/obj/machinery/dna_scannernew/connected = null
|
||||
var/obj/item/disk/data/disk = null
|
||||
var/selected_menu_key = null
|
||||
var/selected_menu_key = PAGE_UI
|
||||
anchored = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 400
|
||||
var/waiting_for_user_input = 0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/disk/data)) //INSERT SOME diskS
|
||||
@@ -347,7 +356,7 @@
|
||||
I.forceMove(src)
|
||||
disk = I
|
||||
to_chat(user, "You insert [I].")
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src()
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
@@ -399,35 +408,18 @@
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/**
|
||||
* The ui_interact proc is used to open and update Nano UIs
|
||||
* If ui_interact is not used then the UI will not update correctly
|
||||
* ui_interact is currently defined for /atom/movable
|
||||
*
|
||||
* @param user /mob The mob who is interacting with this ui
|
||||
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
|
||||
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
/obj/machinery/computer/scan_consolenew/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
if(user == connected.occupant)
|
||||
return
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "dna_modifier.tmpl", "DNA Modifier Console", 660, 700)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "DNAModifier", name, 660, 700, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_data(mob/user, datum/topic_state/state)
|
||||
/obj/machinery/computer/scan_consolenew/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["selectedMenuKey"] = selected_menu_key
|
||||
data["locked"] = connected.locked
|
||||
@@ -501,9 +493,12 @@
|
||||
for(var/datum/reagent/R in connected.beaker.reagents.reagent_list)
|
||||
data["beakerVolume"] += R.volume
|
||||
|
||||
// Transfer modal information if there is one
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
|
||||
/obj/machinery/computer/scan_consolenew/tgui_act(action, params)
|
||||
if(..())
|
||||
return FALSE // don't update uis
|
||||
if(!istype(usr.loc, /turf))
|
||||
@@ -512,405 +507,350 @@
|
||||
return FALSE // don't update uis
|
||||
if(irradiating) // Make sure that it isn't already irradiating someone...
|
||||
return FALSE // don't update uis
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["selectMenuKey"])
|
||||
selected_menu_key = href_list["selectMenuKey"]
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["toggleLock"])
|
||||
if((connected && connected.occupant))
|
||||
connected.locked = !(connected.locked)
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["pulseRadiation"])
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
if(!connected.occupant)
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
var/radiation = (((radiation_intensity * 3) + radiation_duration * 3) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
|
||||
if(prob(95))
|
||||
if(prob(75))
|
||||
randmutb(connected.occupant)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
else
|
||||
if(prob(95))
|
||||
randmutg(connected.occupant)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["radiationDuration"])
|
||||
if(text2num(href_list["radiationDuration"]) > 0)
|
||||
if(radiation_duration < 20)
|
||||
radiation_duration += 2
|
||||
else
|
||||
if(radiation_duration > 2)
|
||||
radiation_duration -= 2
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["radiationIntensity"])
|
||||
if(text2num(href_list["radiationIntensity"]) > 0)
|
||||
if(radiation_intensity < 10)
|
||||
radiation_intensity++
|
||||
else
|
||||
if(radiation_intensity > 1)
|
||||
radiation_intensity--
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) > 0)
|
||||
if(selected_ui_target < 15)
|
||||
selected_ui_target++
|
||||
selected_ui_target_hex = selected_ui_target
|
||||
switch(selected_ui_target)
|
||||
if(10)
|
||||
selected_ui_target_hex = "A"
|
||||
if(11)
|
||||
selected_ui_target_hex = "B"
|
||||
if(12)
|
||||
selected_ui_target_hex = "C"
|
||||
if(13)
|
||||
selected_ui_target_hex = "D"
|
||||
if(14)
|
||||
selected_ui_target_hex = "E"
|
||||
if(15)
|
||||
selected_ui_target_hex = "F"
|
||||
else
|
||||
selected_ui_target = 0
|
||||
selected_ui_target_hex = 0
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) < 1)
|
||||
if(selected_ui_target > 0)
|
||||
selected_ui_target--
|
||||
selected_ui_target_hex = selected_ui_target
|
||||
switch(selected_ui_target)
|
||||
if(10)
|
||||
selected_ui_target_hex = "A"
|
||||
if(11)
|
||||
selected_ui_target_hex = "B"
|
||||
if(12)
|
||||
selected_ui_target_hex = "C"
|
||||
if(13)
|
||||
selected_ui_target_hex = "D"
|
||||
if(14)
|
||||
selected_ui_target_hex = "E"
|
||||
else
|
||||
selected_ui_target = 15
|
||||
selected_ui_target_hex = "F"
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["selectUIBlock"] && href_list["selectUISubblock"]) // This chunk of code updates selected block / sub-block based on click
|
||||
var/select_block = text2num(href_list["selectUIBlock"])
|
||||
var/select_subblock = text2num(href_list["selectUISubblock"])
|
||||
if((select_block <= DNA_UI_LENGTH) && (select_block >= 1))
|
||||
selected_ui_block = select_block
|
||||
if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
||||
selected_ui_subblock = select_subblock
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["pulseUIRadiation"])
|
||||
var/block = connected.occupant.dna.GetUISubBlock(selected_ui_block, selected_ui_subblock)
|
||||
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
if(!connected.occupant)
|
||||
return TRUE
|
||||
|
||||
if(prob((80 + (radiation_duration / 2))))
|
||||
var/radiation = (radiation_intensity + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation,IRRADIATE,0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
|
||||
block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration)
|
||||
connected.occupant.dna.SetUISubBlock(selected_ui_block, selected_ui_subblock, block)
|
||||
connected.occupant.UpdateAppearance()
|
||||
else
|
||||
var/radiation = ((radiation_intensity * 2) + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
|
||||
if(prob(20 + radiation_intensity))
|
||||
randmutb(connected.occupant)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
connected.occupant.UpdateAppearance()
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
if(href_list["injectRejuvenators"])
|
||||
if(!connected.occupant)
|
||||
return FALSE
|
||||
var/inject_amount = round(text2num(href_list["injectRejuvenators"]), 5) // round to nearest 5
|
||||
if(inject_amount < 0) // Since the user can actually type the commands himself, some sanity checking
|
||||
inject_amount = 0
|
||||
if(inject_amount > 50)
|
||||
inject_amount = 50
|
||||
connected.beaker.reagents.trans_to(connected.occupant, inject_amount)
|
||||
connected.beaker.reagents.reaction(connected.occupant)
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
if(href_list["selectSEBlock"] && href_list["selectSESubblock"]) // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
|
||||
var/select_block = text2num(href_list["selectSEBlock"])
|
||||
var/select_subblock = text2num(href_list["selectSESubblock"])
|
||||
if((select_block <= DNA_SE_LENGTH) && (select_block >= 1))
|
||||
selected_se_block = select_block
|
||||
if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
||||
selected_se_subblock = select_subblock
|
||||
//testing("User selected block [selected_se_block] (sent [select_block]), subblock [selected_se_subblock] (sent [select_block]).")
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["pulseSERadiation"])
|
||||
var/block = connected.occupant.dna.GetSESubBlock(selected_se_block, selected_se_subblock)
|
||||
//var/original_block=block
|
||||
//testing("Irradiating SE block [selected_se_block]:[selected_se_subblock] ([block])...")
|
||||
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
if(connected.occupant)
|
||||
if(prob((80 + ((radiation_duration / 2) + (connected.precision_coeff ** 3)))))
|
||||
var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return 1
|
||||
|
||||
var/real_SE_block=selected_se_block
|
||||
block = miniscramble(block, radiation_intensity, radiation_duration)
|
||||
if(prob(20))
|
||||
if(selected_se_block > 1 && selected_se_block < DNA_SE_LENGTH/2)
|
||||
real_SE_block++
|
||||
else if(selected_se_block > DNA_SE_LENGTH/2 && selected_se_block < DNA_SE_LENGTH)
|
||||
real_SE_block--
|
||||
|
||||
//testing("Irradiated SE block [real_SE_block]:[selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
|
||||
connected.occupant.dna.SetSESubBlock(real_SE_block, selected_se_subblock, block)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
var/radiation = (((radiation_intensity * 2) + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return 1
|
||||
|
||||
if(prob(80 - radiation_duration))
|
||||
//testing("Random bad mut!")
|
||||
randmutb(connected.occupant)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
//testing("Random identity mut!")
|
||||
connected.occupant.UpdateAppearance()
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["ejectBeaker"])
|
||||
if(connected.beaker)
|
||||
var/obj/item/reagent_containers/glass/B = connected.beaker
|
||||
B.forceMove(connected.loc)
|
||||
connected.beaker = null
|
||||
if(tgui_act_modal(action, params))
|
||||
return TRUE
|
||||
|
||||
if(href_list["ejectOccupant"])
|
||||
connected.eject_occupant(usr)
|
||||
return TRUE
|
||||
|
||||
// Transfer Buffer Management
|
||||
if(href_list["bufferOption"])
|
||||
var/bufferOption = href_list["bufferOption"]
|
||||
|
||||
// These bufferOptions do not require a bufferId
|
||||
if(bufferOption == "wipeDisk")
|
||||
if((isnull(disk)) || (disk.read_only))
|
||||
//temphtml = "Invalid disk. Please try again."
|
||||
return FALSE
|
||||
|
||||
disk.buf = null
|
||||
//temphtml = "Data saved."
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "ejectDisk")
|
||||
if(!disk)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("selectMenuKey")
|
||||
var/key = params["key"]
|
||||
if(!(key in list(PAGE_UI, PAGE_SE, PAGE_BUFFER, PAGE_REJUVENATORS)))
|
||||
return
|
||||
disk.forceMove(get_turf(src))
|
||||
disk = null
|
||||
return TRUE
|
||||
|
||||
// All bufferOptions from here on require a bufferId
|
||||
if(!href_list["bufferId"])
|
||||
return FALSE
|
||||
|
||||
var/bufferId = text2num(href_list["bufferId"])
|
||||
|
||||
if(bufferId < 1 || bufferId > 3)
|
||||
return FALSE // Not a valid buffer id
|
||||
|
||||
if(bufferOption == "saveUI")
|
||||
if(connected.occupant && connected.occupant.dna)
|
||||
var/datum/dna2/record/databuf = new
|
||||
databuf.types = DNA2_BUF_UI // DNA2_BUF_UE
|
||||
databuf.dna = connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
databuf.name = "Unique Identifier"
|
||||
buffers[bufferId] = databuf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "saveUIAndUE")
|
||||
if(connected.occupant && connected.occupant.dna)
|
||||
var/datum/dna2/record/databuf = new
|
||||
databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
|
||||
databuf.dna = connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
databuf.name = "Unique Identifier + Unique Enzymes"
|
||||
buffers[bufferId] = databuf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "saveSE")
|
||||
if(connected.occupant && connected.occupant.dna)
|
||||
var/datum/dna2/record/databuf = new
|
||||
databuf.types = DNA2_BUF_SE
|
||||
databuf.dna = connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name = connected.occupant.dna.real_name
|
||||
databuf.name = "Structural Enzymes"
|
||||
buffers[bufferId] = databuf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "clear")
|
||||
buffers[bufferId] = new /datum/dna2/record()
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "changeLabel")
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null)
|
||||
buf.name = text
|
||||
buffers[bufferId] = buf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "transfer")
|
||||
if(!connected.occupant || (NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna)
|
||||
return TRUE
|
||||
|
||||
irradiating = 2
|
||||
selected_menu_key = key
|
||||
if("toggleLock")
|
||||
if(connected && connected.occupant)
|
||||
connected.locked = !(connected.locked)
|
||||
if("pulseRadiation")
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
sleep(2 SECONDS)
|
||||
SStgui.update_uis(src)
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
var/radiation = (rand(20,50) / connected.damage_coeff)
|
||||
if(!connected.occupant)
|
||||
return
|
||||
|
||||
var/radiation = (((radiation_intensity * 3) + radiation_duration * 3) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
return
|
||||
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
|
||||
if((buf.types & DNA2_BUF_UI))
|
||||
if((buf.types & DNA2_BUF_UE))
|
||||
connected.occupant.real_name = buf.dna.real_name
|
||||
connected.occupant.name = buf.dna.real_name
|
||||
connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
|
||||
else if(buf.types & DNA2_BUF_SE)
|
||||
connected.occupant.dna.SE = buf.dna.SE.Copy()
|
||||
connected.occupant.dna.UpdateSE()
|
||||
domutcheck(connected.occupant, connected)
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "createInjector")
|
||||
if(injector_ready && !waiting_for_user_input)
|
||||
|
||||
var/success = 1
|
||||
var/obj/item/dnainjector/I = new /obj/item/dnainjector
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
buf = buf.copy()
|
||||
if(href_list["createBlockInjector"])
|
||||
waiting_for_user_input=1
|
||||
var/list/selectedbuf
|
||||
if(buf.types & DNA2_BUF_SE)
|
||||
selectedbuf=buf.dna.SE
|
||||
else
|
||||
selectedbuf=buf.dna.UI
|
||||
var/blk = input(usr,"Select Block","Block") as null|anything in all_dna_blocks(selectedbuf)
|
||||
success = setInjectorBlock(I,blk,buf)
|
||||
if(prob(95))
|
||||
if(prob(75))
|
||||
randmutb(connected.occupant)
|
||||
else
|
||||
I.buf = buf
|
||||
waiting_for_user_input = 0
|
||||
if(success)
|
||||
I.forceMove(loc)
|
||||
I.name += " ([buf.name])"
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
injector_ready = FALSE
|
||||
spawn(300)
|
||||
injector_ready = TRUE
|
||||
return TRUE
|
||||
randmuti(connected.occupant)
|
||||
else
|
||||
if(prob(95))
|
||||
randmutg(connected.occupant)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
if("radiationDuration")
|
||||
radiation_duration = clamp(text2num(params["value"]), 1, 20)
|
||||
if("radiationIntensity")
|
||||
radiation_intensity = clamp(text2num(params["value"]), 1, 10)
|
||||
////////////////////////////////////////////////////////
|
||||
if("changeUITarget")
|
||||
selected_ui_target = clamp(text2num(params["value"]), 1, 15)
|
||||
selected_ui_target_hex = num2text(selected_ui_target, 1, 16)
|
||||
if("selectUIBlock") // This chunk of code updates selected block / sub-block based on click
|
||||
var/select_block = text2num(params["block"])
|
||||
var/select_subblock = text2num(params["subblock"])
|
||||
if(!select_block || !select_subblock)
|
||||
return
|
||||
|
||||
if(bufferOption == "loadDisk")
|
||||
if((isnull(disk)) || (!disk.buf))
|
||||
//temphtml = "Invalid disk. Please try again."
|
||||
return FALSE
|
||||
selected_ui_block = clamp(select_block, 1, DNA_UI_LENGTH)
|
||||
selected_ui_subblock = clamp(select_subblock, 1, DNA_BLOCK_SIZE)
|
||||
if("pulseUIRadiation")
|
||||
var/block = connected.occupant.dna.GetUISubBlock(selected_ui_block, selected_ui_subblock)
|
||||
|
||||
buffers[bufferId] = disk.buf.copy()
|
||||
//temphtml = "Data loaded."
|
||||
return TRUE
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
|
||||
if(bufferOption == "saveDisk")
|
||||
if((isnull(disk)) || (disk.read_only))
|
||||
//temphtml = "Invalid disk. Please try again."
|
||||
return FALSE
|
||||
SStgui.update_uis(src)
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
disk.buf = buf.copy()
|
||||
disk.name = "data disk - '[buf.dna.real_name]'"
|
||||
//temphtml = "Data saved."
|
||||
return TRUE
|
||||
if(!connected.occupant)
|
||||
return
|
||||
|
||||
if(prob((80 + (radiation_duration / 2))))
|
||||
var/radiation = (radiation_intensity + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation,IRRADIATE,0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration)
|
||||
connected.occupant.dna.SetUISubBlock(selected_ui_block, selected_ui_subblock, block)
|
||||
connected.occupant.UpdateAppearance()
|
||||
else
|
||||
var/radiation = ((radiation_intensity * 2) + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
if(prob(20 + radiation_intensity))
|
||||
randmutb(connected.occupant)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
connected.occupant.UpdateAppearance()
|
||||
////////////////////////////////////////////////////////
|
||||
if("injectRejuvenators")
|
||||
if(!connected.occupant || !connected.beaker)
|
||||
return
|
||||
var/inject_amount = clamp(round(text2num(params["amount"]), 5), 0, 50) // round to nearest 5 and clamp to 0-50
|
||||
if(!inject_amount)
|
||||
return
|
||||
connected.beaker.reagents.trans_to(connected.occupant, inject_amount)
|
||||
connected.beaker.reagents.reaction(connected.occupant)
|
||||
////////////////////////////////////////////////////////
|
||||
if("selectSEBlock") // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
|
||||
var/select_block = text2num(params["block"])
|
||||
var/select_subblock = text2num(params["subblock"])
|
||||
if(!select_block || !select_subblock)
|
||||
return
|
||||
|
||||
selected_se_block = clamp(select_block, 1, DNA_SE_LENGTH)
|
||||
selected_se_subblock = clamp(select_subblock, 1, DNA_BLOCK_SIZE)
|
||||
if("pulseSERadiation")
|
||||
var/block = connected.occupant.dna.GetSESubBlock(selected_se_block, selected_se_subblock)
|
||||
//var/original_block=block
|
||||
//testing("Irradiating SE block [selected_se_block]:[selected_se_subblock] ([block])...")
|
||||
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
|
||||
SStgui.update_uis(src)
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
if(connected.occupant)
|
||||
if(prob((80 + ((radiation_duration / 2) + (connected.precision_coeff ** 3)))))
|
||||
var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return 1
|
||||
|
||||
var/real_SE_block=selected_se_block
|
||||
block = miniscramble(block, radiation_intensity, radiation_duration)
|
||||
if(prob(20))
|
||||
if(selected_se_block > 1 && selected_se_block < DNA_SE_LENGTH/2)
|
||||
real_SE_block++
|
||||
else if(selected_se_block > DNA_SE_LENGTH/2 && selected_se_block < DNA_SE_LENGTH)
|
||||
real_SE_block--
|
||||
|
||||
//testing("Irradiated SE block [real_SE_block]:[selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
|
||||
connected.occupant.dna.SetSESubBlock(real_SE_block, selected_se_subblock, block)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
var/radiation = (((radiation_intensity * 2) + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
if(prob(80 - radiation_duration))
|
||||
//testing("Random bad mut!")
|
||||
randmutb(connected.occupant)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
//testing("Random identity mut!")
|
||||
connected.occupant.UpdateAppearance()
|
||||
if("ejectBeaker")
|
||||
if(connected.beaker)
|
||||
var/obj/item/reagent_containers/glass/B = connected.beaker
|
||||
B.forceMove(connected.loc)
|
||||
connected.beaker = null
|
||||
if("ejectOccupant")
|
||||
connected.eject_occupant()
|
||||
// Transfer Buffer Management
|
||||
if("bufferOption")
|
||||
var/bufferOption = params["option"]
|
||||
var/bufferId = text2num(params["id"])
|
||||
if(bufferId < 1 || bufferId > 3) // Not a valid buffer id
|
||||
return
|
||||
|
||||
var/datum/dna2/record/buffer = buffers[bufferId]
|
||||
switch(bufferOption)
|
||||
if("saveUI")
|
||||
if(connected.occupant && connected.occupant.dna)
|
||||
var/datum/dna2/record/databuf = new
|
||||
databuf.types = DNA2_BUF_UI // DNA2_BUF_UE
|
||||
databuf.dna = connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
databuf.name = "Unique Identifier"
|
||||
buffers[bufferId] = databuf
|
||||
if("saveUIAndUE")
|
||||
if(connected.occupant && connected.occupant.dna)
|
||||
var/datum/dna2/record/databuf = new
|
||||
databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
|
||||
databuf.dna = connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
databuf.name = "Unique Identifier + Unique Enzymes"
|
||||
buffers[bufferId] = databuf
|
||||
if("saveSE")
|
||||
if(connected.occupant && connected.occupant.dna)
|
||||
var/datum/dna2/record/databuf = new
|
||||
databuf.types = DNA2_BUF_SE
|
||||
databuf.dna = connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name = connected.occupant.dna.real_name
|
||||
databuf.name = "Structural Enzymes"
|
||||
buffers[bufferId] = databuf
|
||||
if("clear")
|
||||
buffers[bufferId] = new /datum/dna2/record()
|
||||
if("changeLabel")
|
||||
tgui_modal_input(src, "changeBufferLabel", "Please enter the new buffer label:", null, list("id" = bufferId), buffer.name, TGUI_MODAL_INPUT_MAX_LENGTH_NAME)
|
||||
if("transfer")
|
||||
if(!connected.occupant || (NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna)
|
||||
return
|
||||
|
||||
irradiating = 2
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
|
||||
SStgui.update_uis(src)
|
||||
sleep(2 SECONDS)
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
var/radiation = (rand(20,50) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
|
||||
if((buf.types & DNA2_BUF_UI))
|
||||
if((buf.types & DNA2_BUF_UE))
|
||||
connected.occupant.real_name = buf.dna.real_name
|
||||
connected.occupant.name = buf.dna.real_name
|
||||
connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
|
||||
else if(buf.types & DNA2_BUF_SE)
|
||||
connected.occupant.dna.SE = buf.dna.SE.Copy()
|
||||
connected.occupant.dna.UpdateSE()
|
||||
domutcheck(connected.occupant, connected)
|
||||
if("createInjector")
|
||||
if(!injector_ready)
|
||||
return
|
||||
if(text2num(params["block"]) > 0)
|
||||
var/list/choices = all_dna_blocks((buffer.types & DNA2_BUF_SE) ? buffer.dna.SE : buffer.dna.UI)
|
||||
tgui_modal_choice(src, "createInjectorBlock", "Please select the block to create an injector from:", null, list("id" = bufferId), null, choices)
|
||||
else
|
||||
create_injector(bufferId, TRUE)
|
||||
if("loadDisk")
|
||||
if(isnull(disk) || disk.read_only)
|
||||
return
|
||||
buffers[bufferId] = disk.buf.copy()
|
||||
if("saveDisk")
|
||||
if(isnull(disk) || disk.read_only)
|
||||
return
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
disk.buf = buf.copy()
|
||||
disk.name = "data disk - '[buf.dna.real_name]'"
|
||||
if("wipeDisk")
|
||||
if(isnull(disk) || disk.read_only)
|
||||
return
|
||||
disk.buf = null
|
||||
if("ejectDisk")
|
||||
if(!disk)
|
||||
return
|
||||
disk.forceMove(get_turf(src))
|
||||
disk = null
|
||||
|
||||
/**
|
||||
* Creates a blank injector with the name of the buffer at the given buffer_id
|
||||
*
|
||||
* Arguments:
|
||||
* * buffer_id - The ID of the buffer
|
||||
* * copy_buffer - Whether the injector should copy the buffer contents
|
||||
*/
|
||||
/obj/machinery/computer/scan_consolenew/proc/create_injector(buffer_id, copy_buffer = FALSE)
|
||||
if(buffer_id < 1 || buffer_id > length(buffers))
|
||||
return
|
||||
|
||||
// Cooldown
|
||||
injector_ready = FALSE
|
||||
addtimer(CALLBACK(src, .proc/injector_cooldown_finish), 30 SECONDS)
|
||||
|
||||
// Create it
|
||||
var/datum/dna2/record/buf = buffers[buffer_id]
|
||||
var/obj/item/dnainjector/I = new()
|
||||
I.forceMove(loc)
|
||||
I.name += " ([buf.name])"
|
||||
if(copy_buffer)
|
||||
I.buf = buf.copy()
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
return I
|
||||
|
||||
/**
|
||||
* Called when the injector creation cooldown finishes
|
||||
*/
|
||||
/obj/machinery/computer/scan_consolenew/proc/injector_cooldown_finish()
|
||||
injector_ready = TRUE
|
||||
|
||||
/**
|
||||
* Called in tgui_act() to process modal actions
|
||||
*
|
||||
* Arguments:
|
||||
* * action - The action passed by tgui
|
||||
* * params - The params passed by tgui
|
||||
*/
|
||||
/obj/machinery/computer/scan_consolenew/proc/tgui_act_modal(action, params)
|
||||
. = TRUE
|
||||
var/id = params["id"] // The modal's ID
|
||||
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
if(TGUI_MODAL_ANSWER)
|
||||
var/answer = params["answer"]
|
||||
switch(id)
|
||||
if("createInjectorBlock")
|
||||
var/buffer_id = text2num(arguments["id"])
|
||||
if(buffer_id < 1 || buffer_id > length(buffers))
|
||||
return
|
||||
var/datum/dna2/record/buf = buffers[buffer_id]
|
||||
var/obj/item/dnainjector/I = create_injector(buffer_id)
|
||||
setInjectorBlock(I, answer, buf.copy())
|
||||
if("changeBufferLabel")
|
||||
var/buffer_id = text2num(arguments["id"])
|
||||
if(buffer_id < 1 || buffer_id > length(buffers))
|
||||
return
|
||||
var/datum/dna2/record/buf = buffers[buffer_id]
|
||||
buf.name = answer
|
||||
buffers[buffer_id] = buf
|
||||
else
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
|
||||
#undef PAGE_UI
|
||||
#undef PAGE_SE
|
||||
#undef PAGE_BUFFER
|
||||
#undef PAGE_REJUVENATORS
|
||||
|
||||
/////////////////////////// DNA MACHINES
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12.<BR>"
|
||||
intercepttext += "Message ends."
|
||||
if(2)
|
||||
var/nukecode = "[rand(10000, 99999)]"
|
||||
var/nukecode = rand(10000, 99999)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
|
||||
if(bomb && bomb.r_code)
|
||||
if(is_station_level(bomb.z))
|
||||
@@ -40,7 +40,7 @@
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
to_chat(aiPlayer, "Laws Updated: [law]")
|
||||
|
||||
print_command_report(intercepttext, interceptname)
|
||||
print_command_report(intercepttext, interceptname, FALSE)
|
||||
GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg', from = "[command_name()] Update")
|
||||
|
||||
/datum/station_state
|
||||
|
||||
@@ -17,7 +17,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, [owner.p_they()] can send you back to hell with a single thought. [owner.name]'s death will also return you to hell.</b>"
|
||||
description = "Be someone's loyal friend/slave. If they die, you die as well." //best I could think of in the moment, not sure how this role plays in practise, have never seen it.
|
||||
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. Be aware that if you do not live up to [owner.name]'s expectations, [owner.p_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 = TRUE)
|
||||
|
||||
@@ -507,7 +507,7 @@ proc/display_roundstart_logout_report()
|
||||
message_text += G.get_report()
|
||||
message_text += "<hr>"
|
||||
|
||||
print_command_report(message_text, "[command_name()] Orders")
|
||||
print_command_report(message_text, "[command_name()] Orders", FALSE)
|
||||
|
||||
/datum/game_mode/proc/declare_station_goal_completion()
|
||||
for(var/V in station_goals)
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
mob_name = "a swarmer"
|
||||
death = FALSE
|
||||
roundstart = FALSE
|
||||
flavour_text = {"
|
||||
<b>You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.</b>
|
||||
<b>Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.</b>
|
||||
<b>Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.</b>
|
||||
<b>Objectives:</b>
|
||||
important_info = "Follow your objectives, do not make the station inhospitable or try and kill crew."
|
||||
flavour_text = "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate."
|
||||
description = {" Your goal is to create more of yourself by consuming the station. Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful. Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.
|
||||
Objectives:
|
||||
1. Consume resources and replicate until there are no more resources left.
|
||||
2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
|
||||
3. Biological resources will be harvested at a later date; do not harm them.
|
||||
"}
|
||||
3. Biological resources will be harvested at a later date; do not harm them."}
|
||||
|
||||
/obj/effect/mob_spawn/swarmer/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
var/swarmer_report = "<font size=3><b>[command_name()] High-Priority Update</b></span>"
|
||||
swarmer_report += "<br><br>Our long-range sensors have detected an odd signal emanating from your station's gateway. We recommend immediate investigation of your gateway, as something may have come \
|
||||
through."
|
||||
print_command_report(swarmer_report, "Classified [command_name()] Update")
|
||||
print_command_report(swarmer_report, "Classified [command_name()] Update", FALSE)
|
||||
GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
|
||||
|
||||
/datum/event/spawn_swarmer/start()
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
if("Protector")
|
||||
pickedtype = /mob/living/simple_animal/hostile/guardian/protector
|
||||
|
||||
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user)
|
||||
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user, user)
|
||||
G.summoner = user
|
||||
G.summoned = TRUE
|
||||
G.key = key
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
layer = LYING_MOB_LAYER
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam
|
||||
melee_damage_lower = 7
|
||||
melee_damage_upper = 7
|
||||
melee_damage_lower = 12
|
||||
melee_damage_upper = 12
|
||||
attacktext = "shocks"
|
||||
melee_damage_type = BURN
|
||||
attack_sound = 'sound/machines/defib_zap.ogg'
|
||||
damage_transfer = 0.7
|
||||
damage_transfer = 0.6
|
||||
range = 7
|
||||
playstyle_string = "As a <b>Lightning</b> type, you will apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them."
|
||||
magic_fluff_string = "..And draw the Tesla, a shocking, lethal source of power."
|
||||
@@ -18,6 +18,17 @@
|
||||
var/list/enemychains = list()
|
||||
var/successfulshocks = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/New(loc, mob/living/user)
|
||||
. = ..()
|
||||
if(!user)
|
||||
return
|
||||
summoner = user
|
||||
if(!(NO_SHOCK in summoner.mutations))
|
||||
summoner.mutations.Add(NO_SHOCK)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
return FALSE //You are lightning, you should not be hurt by such things.
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/AttackingTarget()
|
||||
. = ..()
|
||||
if(. && isliving(target) && target != src && target != summoner)
|
||||
@@ -106,3 +117,8 @@
|
||||
)
|
||||
L.adjustFireLoss(1.2) //adds up very rapidly
|
||||
. = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/death(gibbed)
|
||||
if(summoner && (NO_SHOCK in summoner.mutations))
|
||||
summoner.mutations.Remove(NO_SHOCK)
|
||||
return ..()
|
||||
|
||||
@@ -103,7 +103,7 @@ proc/issyndicate(mob/living/M as mob)
|
||||
|
||||
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
var/nuke_code = rand(10000, 99999)
|
||||
var/leader_selected = 0
|
||||
var/agent_number = 1
|
||||
var/spawnpos = 1
|
||||
|
||||
@@ -14,29 +14,29 @@ GLOBAL_VAR(bomb_set)
|
||||
icon_state = "nuclearbomb0"
|
||||
density = 1
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/deployable = 0
|
||||
var/extended = 0
|
||||
var/lighthack = 0
|
||||
var/extended = FALSE
|
||||
var/lighthack = FALSE
|
||||
var/timeleft = 120
|
||||
var/timing = 0
|
||||
var/timing = FALSE
|
||||
var/exploded = FALSE
|
||||
var/r_code = "ADMIN"
|
||||
var/code = ""
|
||||
var/yes_code = 0
|
||||
var/safety = 1
|
||||
var/code
|
||||
var/yes_code = FALSE
|
||||
var/safety = TRUE
|
||||
var/obj/item/disk/nuclear/auth = null
|
||||
var/removal_stage = NUKE_INTACT
|
||||
var/lastentered
|
||||
var/is_syndicate = 0
|
||||
var/is_syndicate = FALSE
|
||||
use_power = NO_POWER_USE
|
||||
var/previous_level = ""
|
||||
var/datum/wires/nuclearbomb/wires = null
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate
|
||||
is_syndicate = 1
|
||||
is_syndicate = TRUE
|
||||
|
||||
/obj/machinery/nuclearbomb/New()
|
||||
..()
|
||||
r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn.
|
||||
r_code = rand(10000, 99999.0) // Creates a random code upon object spawn.
|
||||
wires = new/datum/wires/nuclearbomb(src)
|
||||
previous_level = get_security_level()
|
||||
GLOB.poi_list |= src
|
||||
@@ -49,25 +49,24 @@ GLOBAL_VAR(bomb_set)
|
||||
|
||||
/obj/machinery/nuclearbomb/process()
|
||||
if(timing)
|
||||
GLOB.bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
|
||||
GLOB.bomb_set = TRUE // So long as there is one nuke timing, it means one nuke is armed.
|
||||
timeleft = max(timeleft - 2, 0) // 2 seconds per process()
|
||||
if(timeleft <= 0)
|
||||
INVOKE_ASYNC(src, .proc/explode)
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/attackby(obj/item/O as obj, mob/user as mob, params)
|
||||
if(istype(O, /obj/item/disk/nuclear))
|
||||
if(extended)
|
||||
if(!user.drop_item())
|
||||
to_chat(user, "<span class='notice'>\The [O] is stuck to your hand!</span>")
|
||||
to_chat(user, "<span class='notice'>[O] is stuck to your hand!</span>")
|
||||
return
|
||||
O.forceMove(src)
|
||||
auth = O
|
||||
add_fingerprint(user)
|
||||
return attack_hand(user)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You need to deploy \the [src] first. Right click on the sprite, select 'Make Deployable' then click on \the [src] with an empty hand.</span>")
|
||||
to_chat(user, "<span class='notice'>You need to deploy [src] first.</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -171,181 +170,157 @@ GLOBAL_VAR(bomb_set)
|
||||
removal_stage = NUKE_SEALANT_OPEN
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_ghost(mob/user as mob)
|
||||
if(extended)
|
||||
attack_hand(user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
|
||||
if(extended)
|
||||
if(panel_open)
|
||||
wires.Interact(user)
|
||||
else
|
||||
ui_interact(user)
|
||||
else if(deployable)
|
||||
if(removal_stage != NUKE_MOBILE)
|
||||
anchored = 1
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
if(!lighthack)
|
||||
flick("nuclearbombc", src)
|
||||
icon_state = "nuclearbomb1"
|
||||
extended = 1
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "nuclear_bomb.tmpl", "Nuke Control Panel", 450, 550, state = GLOB.physical_state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_data(mob/user, datum/topic_state/state)
|
||||
var/data[0]
|
||||
data["is_syndicate"] = is_syndicate
|
||||
data["hacking"] = 0
|
||||
data["auth"] = is_auth(user)
|
||||
if(is_auth(user))
|
||||
if(yes_code)
|
||||
data["authstatus"] = timing ? "Functional/Set" : "Functional"
|
||||
else
|
||||
data["authstatus"] = "Auth. S2"
|
||||
if(panel_open)
|
||||
wires.Interact(user)
|
||||
else
|
||||
if(timing)
|
||||
data["authstatus"] = "Set"
|
||||
else
|
||||
data["authstatus"] = "Auth. S1"
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/nuclearbomb/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "NuclearBomb", name, 450, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/nuclearbomb/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["extended"] = extended
|
||||
data["authdisk"] = is_auth(user)
|
||||
data["diskname"] = auth ? auth.name : FALSE
|
||||
data["authcode"] = yes_code
|
||||
data["authfull"] = data["authdisk"] && data["authcode"]
|
||||
data["safe"] = safety ? "Safe" : "Engaged"
|
||||
data["time"] = timeleft
|
||||
data["timer"] = timing
|
||||
data["safety"] = safety
|
||||
data["anchored"] = anchored
|
||||
data["yescode"] = yes_code
|
||||
data["message"] = "AUTH"
|
||||
if(is_auth(user))
|
||||
data["message"] = code
|
||||
if(yes_code)
|
||||
data["message"] = "*****"
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/nuclearbomb/verb/make_deployable()
|
||||
set category = "Object"
|
||||
set name = "Make Deployable"
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat || !usr.canmove || usr.restrained())
|
||||
return
|
||||
|
||||
if(deployable)
|
||||
to_chat(usr, "<span class='warning'>You close several panels to make [src] undeployable.</span>")
|
||||
deployable = 0
|
||||
data["codemsg"] = "CLEAR CODE"
|
||||
else if(code)
|
||||
data["codemsg"] = "RE-ENTER CODE"
|
||||
else
|
||||
data["codemsg"] = "ENTER CODE"
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You adjust some panels to make [src] deployable.</span>")
|
||||
deployable = 1
|
||||
return
|
||||
data["codemsg"] = "-----"
|
||||
return data
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/is_auth(var/mob/user)
|
||||
if(auth)
|
||||
return 1
|
||||
return TRUE
|
||||
else if(user.can_admin_interact())
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/nuclearbomb/Topic(href, href_list)
|
||||
/obj/machinery/nuclearbomb/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["auth"])
|
||||
if(auth)
|
||||
auth.loc = loc
|
||||
yes_code = 0
|
||||
auth = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/disk/nuclear))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
auth = I
|
||||
if(is_auth(usr))
|
||||
if(href_list["type"])
|
||||
if(href_list["type"] == "E")
|
||||
return
|
||||
. = TRUE
|
||||
if(exploded)
|
||||
return
|
||||
switch(action)
|
||||
if("deploy")
|
||||
if(removal_stage != NUKE_MOBILE)
|
||||
anchored = TRUE
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
if(!lighthack)
|
||||
flick("nuclearbombc", src)
|
||||
icon_state = "nuclearbomb1"
|
||||
extended = TRUE
|
||||
return
|
||||
if("auth")
|
||||
if(auth)
|
||||
if(!usr.get_active_hand() && Adjacent(usr))
|
||||
usr.put_in_hands(auth)
|
||||
else
|
||||
auth.forceMove(get_turf(src))
|
||||
yes_code = FALSE
|
||||
auth = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/disk/nuclear))
|
||||
usr.drop_item()
|
||||
I.forceMove(src)
|
||||
auth = I
|
||||
return
|
||||
if(!is_auth(usr)) // All requests below here require NAD inserted.
|
||||
return FALSE
|
||||
switch(action)
|
||||
if("code")
|
||||
if(yes_code) // Clear code
|
||||
code = null
|
||||
yes_code = FALSE
|
||||
return
|
||||
// If no code set, enter new one
|
||||
var/tempcode = input(usr, "Code", "Input Code", null) as num|null
|
||||
if(tempcode)
|
||||
code = min(max(round(tempcode), 0), 999999)
|
||||
if(code == r_code)
|
||||
yes_code = 1
|
||||
yes_code = TRUE
|
||||
code = null
|
||||
else
|
||||
code = "ERROR"
|
||||
return
|
||||
|
||||
if(!yes_code) // All requests below here require both NAD inserted AND code correct
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("toggle_anchor")
|
||||
if(removal_stage == NUKE_MOBILE)
|
||||
anchored = FALSE
|
||||
visible_message("<span class='warning'>[src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
else if(isinspace())
|
||||
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
|
||||
return FALSE
|
||||
else
|
||||
if(href_list["type"] == "R")
|
||||
yes_code = 0
|
||||
code = null
|
||||
else
|
||||
lastentered = text("[]", href_list["type"])
|
||||
if(text2num(lastentered) == null)
|
||||
var/turf/LOC = get_turf(usr)
|
||||
message_admins("[key_name_admin(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: <a href='?_src_=vars;Vars=[UID()]'>[lastentered]</a>! ([LOC ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[LOC.x];Y=[LOC.y];Z=[LOC.z]'>JMP</a>" : "null"])", 0)
|
||||
log_admin("EXPLOIT: [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered]!")
|
||||
else
|
||||
code += lastentered
|
||||
if(length(code) > 5)
|
||||
code = "ERROR"
|
||||
if(yes_code)
|
||||
if(href_list["time"])
|
||||
var/time = text2num(href_list["time"])
|
||||
timeleft += time
|
||||
timeleft = min(max(round(src.timeleft), 120), 600)
|
||||
if(href_list["timer"])
|
||||
if(timing == -1.0)
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
if(safety)
|
||||
to_chat(usr, "<span class='warning'>The safety is still on.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
timing = !(timing)
|
||||
if(timing)
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb2"
|
||||
if(!safety)
|
||||
message_admins("[key_name_admin(usr)] engaged a nuclear bomb (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
if(!is_syndicate)
|
||||
set_security_level("delta")
|
||||
GLOB.bomb_set = 1 //There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke/N
|
||||
else
|
||||
GLOB.bomb_set = 0
|
||||
anchored = !(anchored)
|
||||
if(anchored)
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>The anchoring bolts slide back into the depths of [src].</span>")
|
||||
return
|
||||
if("set_time")
|
||||
var/time = input(usr, "Detonation time (seconds, min 120, max 600)", "Input Time", 120) as num|null
|
||||
if(time)
|
||||
timeleft = min(max(round(time), 120), 600)
|
||||
if("toggle_safety")
|
||||
safety = !(safety)
|
||||
if(safety)
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
timing = FALSE
|
||||
GLOB.bomb_set = FALSE
|
||||
if("toggle_armed")
|
||||
if(safety)
|
||||
to_chat(usr, "<span class='notice'>The safety is still on.</span>")
|
||||
return
|
||||
timing = !(timing)
|
||||
if(timing)
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb2"
|
||||
if(!safety)
|
||||
message_admins("[key_name_admin(usr)] engaged a nuclear bomb [ADMIN_JMP(src)]")
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
GLOB.bomb_set = 0
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb1"
|
||||
if(href_list["safety"])
|
||||
safety = !(safety)
|
||||
if(safety)
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
timing = 0
|
||||
GLOB.bomb_set = 0
|
||||
if(href_list["anchor"])
|
||||
if(removal_stage == NUKE_MOBILE)
|
||||
anchored = 0
|
||||
visible_message("<span class='warning'>\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
if(!isinspace())
|
||||
anchored = !(anchored)
|
||||
if(anchored)
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>The anchoring bolts slide back into the depths of [src].</span>")
|
||||
set_security_level("delta")
|
||||
GLOB.bomb_set = TRUE // There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
|
||||
GLOB.bomb_set = TRUE
|
||||
else
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
GLOB.bomb_set = FALSE
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb1"
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
/obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B)
|
||||
if(timing == -1.0)
|
||||
if(exploded)
|
||||
return
|
||||
if(timing) //boom
|
||||
INVOKE_ASYNC(src, .proc/explode)
|
||||
@@ -360,11 +335,11 @@ GLOBAL_VAR(bomb_set)
|
||||
#define NUKERANGE 80
|
||||
/obj/machinery/nuclearbomb/proc/explode()
|
||||
if(safety)
|
||||
timing = 0
|
||||
timing = FALSE
|
||||
return
|
||||
timing = -1.0
|
||||
yes_code = 0
|
||||
safety = 1
|
||||
exploded = TRUE
|
||||
yes_code = FALSE
|
||||
safety = TRUE
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb3"
|
||||
playsound(src,'sound/machines/alarm.ogg',100,0,5)
|
||||
|
||||
@@ -279,6 +279,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
var/blood = 0
|
||||
var/old_bloodtotal = 0 //used to see if we increased our blood total
|
||||
var/old_bloodusable = 0 //used to see if we increased our blood usable
|
||||
var/blood_volume_warning = 9999 //Blood volume threshold for warnings
|
||||
if(owner.is_muzzled())
|
||||
to_chat(owner, "<span class='warning'>[owner.wear_mask] prevents you from biting [H]!</span>")
|
||||
draining = null
|
||||
@@ -291,13 +292,10 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
H.LAssailant = owner
|
||||
while(do_mob(owner, H, 50))
|
||||
if(!(owner.mind in SSticker.mode.vampires))
|
||||
to_chat(owner, "<span class='warning'>Your fangs have disappeared!</span>")
|
||||
to_chat(owner, "<span class='userdanger'>Your fangs have disappeared!</span>")
|
||||
return
|
||||
old_bloodtotal = bloodtotal
|
||||
old_bloodusable = bloodusable
|
||||
if(!H.blood_volume)
|
||||
to_chat(owner, "<span class='warning'>They've got no blood left to give.</span>")
|
||||
break
|
||||
if(H.stat < DEAD)
|
||||
if(H.ckey || H.player_ghosted) //Requires ckey regardless if monkey or humanoid, or the body has been ghosted before it died
|
||||
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
|
||||
@@ -312,6 +310,17 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
|
||||
check_vampire_upgrade()
|
||||
H.blood_volume = max(H.blood_volume - 25, 0)
|
||||
//Blood level warnings (Code 'borrowed' from Fulp)
|
||||
if(H.blood_volume)
|
||||
if(H.blood_volume <= BLOOD_VOLUME_BAD && blood_volume_warning > BLOOD_VOLUME_BAD)
|
||||
to_chat(owner, "<span class='danger'>Your victim's blood volume is dangerously low.</span>")
|
||||
else if(H.blood_volume <= BLOOD_VOLUME_OKAY && blood_volume_warning > BLOOD_VOLUME_OKAY)
|
||||
to_chat(owner, "<span class='warning'>Your victim's blood is at an unsafe level.</span>")
|
||||
blood_volume_warning = H.blood_volume //Set to blood volume, so that you only get the message once
|
||||
else
|
||||
to_chat(owner, "<span class='warning'>You have bled your victim dry!</span>")
|
||||
break
|
||||
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/V = owner
|
||||
if(!H.ckey && !H.player_ghosted)//Only runs if there is no ckey and the body has not being ghosted while alive
|
||||
|
||||
@@ -510,3 +510,26 @@ proc/get_all_job_icons() //For all existing HUD icons
|
||||
return rankName
|
||||
|
||||
return "Unknown" //Return unknown if none of the above apply
|
||||
|
||||
proc/get_accesslist_static_data(num_min_region = REGION_GENERAL, num_max_region = REGION_COMMAND)
|
||||
var/list/retval
|
||||
for(var/i in num_min_region to num_max_region)
|
||||
var/list/accesses = list()
|
||||
var/list/available_accesses
|
||||
if(i == REGION_CENTCOMM) // Override necessary, because get_region_accesses(REGION_CENTCOM) returns BOTH CC and crew accesses.
|
||||
available_accesses = get_all_centcom_access()
|
||||
else
|
||||
available_accesses = get_region_accesses(i)
|
||||
for(var/access in available_accesses)
|
||||
var/access_desc = (i == REGION_CENTCOMM) ? get_centcom_access_desc(access) : get_access_desc(access)
|
||||
if (access_desc)
|
||||
accesses += list(list(
|
||||
"desc" = replacetext(access_desc, " ", " "),
|
||||
"ref" = access,
|
||||
))
|
||||
retval += list(list(
|
||||
"name" = get_region_accesses_name(i),
|
||||
"regid" = i,
|
||||
"accesses" = accesses
|
||||
))
|
||||
return retval
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
ACCESS_HEADS, ACCESS_CONSTRUCTION, ACCESS_SEC_DOORS,
|
||||
ACCESS_CE, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_MINISAT, ACCESS_MECHANIC, ACCESS_MINERAL_STOREROOM)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_ENGINEERING
|
||||
outfit = /datum/outfit/job/chief_engineer
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
|
||||
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_PSYCHIATRIST, ACCESS_MAINT_TUNNELS, ACCESS_PARAMEDIC, ACCESS_MINERAL_STOREROOM)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_MEDICAL
|
||||
outfit = /datum/outfit/job/cmo
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
|
||||
ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_GATEWAY, ACCESS_XENOARCH, ACCESS_MINISAT, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM, ACCESS_NETWORK)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_SCIENCE
|
||||
// All science-y guys get bonuses for maxing out their tech.
|
||||
required_objectives = list(
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
|
||||
ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_PILOT, ACCESS_WEAPONS)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_SECURITY
|
||||
disabilities_allowed = 0
|
||||
outfit = /datum/outfit/job/hos
|
||||
@@ -64,7 +64,7 @@
|
||||
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_WEAPONS)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 600
|
||||
exp_type = EXP_TYPE_CREW
|
||||
exp_type = EXP_TYPE_SECURITY
|
||||
outfit = /datum/outfit/job/warden
|
||||
|
||||
/datum/outfit/job/warden
|
||||
|
||||
@@ -13,7 +13,7 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
|
||||
access = list() //See get_access()
|
||||
minimal_access = list() //See get_access()
|
||||
minimal_player_age = 30
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_COMMAND
|
||||
disabilities_allowed = 0
|
||||
outfit = /datum/outfit/job/captain
|
||||
@@ -67,7 +67,7 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
|
||||
req_admin_notify = 1
|
||||
is_command = 1
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_COMMAND
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
|
||||
|
||||
@@ -104,59 +104,46 @@
|
||||
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
|
||||
src.ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 540, 300)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "GasFreezer", "Gas Cooling System", 540, 200)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
data["on"] = on ? 1 : 0
|
||||
data["gasPressure"] = round(air_contents.return_pressure())
|
||||
data["gasTemperature"] = round(air_contents.temperature)
|
||||
data["gasTemperatureCelsius"] = round(air_contents.temperature - T0C,1)
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(air_contents.return_pressure())
|
||||
data["temperature"] = round(air_contents.temperature)
|
||||
data["temperatureCelsius"] = round(air_contents.temperature - T0C, 1)
|
||||
if(air_contents.total_moles() == 0 && air_contents.temperature == 0)
|
||||
data["gasTemperatureCelsius"] = 0
|
||||
data["minGasTemperature"] = round(min_temperature)
|
||||
data["maxGasTemperature"] = round(T20C)
|
||||
data["targetGasTemperature"] = round(current_temperature)
|
||||
data["targetGasTemperatureCelsius"] = round(current_temperature - T0C,1)
|
||||
|
||||
var/temp_class = "good"
|
||||
if(air_contents.temperature > (T0C - 20))
|
||||
temp_class = "bad"
|
||||
else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
|
||||
temp_class = "average"
|
||||
data["gasTemperatureClass"] = temp_class
|
||||
data["temperatureCelsius"] = 0
|
||||
data["min"] = round(min_temperature)
|
||||
data["max"] = round(T20C)
|
||||
data["target"] = round(current_temperature)
|
||||
data["targetCelsius"] = round(current_temperature - T0C, 1)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/Topic(href, href_list)
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["toggleStatus"])
|
||||
src.on = !src.on
|
||||
update_icon()
|
||||
else if(href_list["minimum"])
|
||||
current_temperature = min_temperature
|
||||
else if(href_list["maximum"])
|
||||
current_temperature = T20C
|
||||
else if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
if(amount > 0)
|
||||
src.current_temperature = min(T20C, src.current_temperature+amount)
|
||||
else
|
||||
src.current_temperature = max(min_temperature, src.current_temperature+amount)
|
||||
src.add_fingerprint(usr)
|
||||
return 1
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
. = TRUE
|
||||
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
update_icon()
|
||||
if("minimum")
|
||||
current_temperature = min_temperature
|
||||
if("maximum")
|
||||
current_temperature = T20C
|
||||
if("temp")
|
||||
var/amount = params["temp"]
|
||||
amount = text2num(amount)
|
||||
current_temperature = clamp(amount, T20C, min_temperature)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer/power_change()
|
||||
..()
|
||||
@@ -273,57 +260,46 @@
|
||||
if(panel_open)
|
||||
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
src.ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 540, 300)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "GasFreezer", "Gas Heating System", 540, 200)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
data["on"] = on ? 1 : 0
|
||||
data["gasPressure"] = round(air_contents.return_pressure())
|
||||
data["gasTemperature"] = round(air_contents.temperature)
|
||||
data["gasTemperatureCelsius"] = round(air_contents.temperature - T0C,1)
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(air_contents.return_pressure())
|
||||
data["temperature"] = round(air_contents.temperature)
|
||||
data["temperatureCelsius"] = round(air_contents.temperature - T0C, 1)
|
||||
if(air_contents.total_moles() == 0 && air_contents.temperature == 0)
|
||||
data["gasTemperatureCelsius"] = 0
|
||||
data["minGasTemperature"] = round(T20C)
|
||||
data["maxGasTemperature"] = round(T20C+max_temperature)
|
||||
data["targetGasTemperature"] = round(current_temperature)
|
||||
data["targetGasTemperatureCelsius"] = round(current_temperature - T0C,1)
|
||||
|
||||
var/temp_class = "normal"
|
||||
if(air_contents.temperature > (T20C+40))
|
||||
temp_class = "bad"
|
||||
data["gasTemperatureClass"] = temp_class
|
||||
data["temperatureCelsius"] = 0
|
||||
data["min"] = round(T20C)
|
||||
data["max"] = round(T20C + max_temperature)
|
||||
data["target"] = round(current_temperature)
|
||||
data["targetCelsius"] = round(current_temperature - T0C, 1)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/Topic(href, href_list)
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["toggleStatus"])
|
||||
src.on = !src.on
|
||||
update_icon()
|
||||
else if(href_list["minimum"])
|
||||
current_temperature = T20C
|
||||
else if(href_list["maximum"])
|
||||
current_temperature = max_temperature + T20C
|
||||
else if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
if(amount > 0)
|
||||
src.current_temperature = min((T20C+max_temperature), src.current_temperature+amount)
|
||||
else
|
||||
src.current_temperature = max(T20C, src.current_temperature+amount)
|
||||
src.add_fingerprint(usr)
|
||||
return 1
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
. = TRUE
|
||||
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
update_icon()
|
||||
if("minimum")
|
||||
current_temperature = T20C
|
||||
if("maximum")
|
||||
current_temperature = max_temperature + T20C
|
||||
if("temp")
|
||||
var/amount = params["temp"]
|
||||
amount = text2num(amount)
|
||||
current_temperature = clamp(amount, T20C, T20C + max_temperature)
|
||||
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater/power_change()
|
||||
..()
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/sleeper/attack_ghost(mob/user)
|
||||
return attack_hand(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/sleeper/attack_hand(mob/user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
@@ -135,17 +135,17 @@
|
||||
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/sleeper/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper", 550, 770)
|
||||
ui = new(user, src, ui_key, "Sleeper", "Sleeper", 550, 775)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/sleeper/ui_data(mob/user, datum/topic_state/state)
|
||||
/obj/machinery/sleeper/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["amounts"] = amounts
|
||||
data["hasOccupant"] = occupant ? 1 : 0
|
||||
var/occupantData[0]
|
||||
var/crisis = 0
|
||||
@@ -210,9 +210,13 @@
|
||||
if(beaker)
|
||||
data["isBeakerLoaded"] = 1
|
||||
if(beaker.reagents)
|
||||
data["beakerMaxSpace"] = beaker.reagents.maximum_volume
|
||||
data["beakerFreeSpace"] = round(beaker.reagents.maximum_volume - beaker.reagents.total_volume)
|
||||
else
|
||||
data["beakerMaxSpace"] = 0
|
||||
data["beakerFreeSpace"] = 0
|
||||
else
|
||||
data["isBeakerLoaded"] = FALSE
|
||||
|
||||
var/chemicals[0]
|
||||
for(var/re in possible_chems)
|
||||
@@ -234,51 +238,52 @@
|
||||
if(temp.id in occupant.reagents.overdose_list())
|
||||
overdosing = 1
|
||||
|
||||
// Because I don't know how to do this on the nano side
|
||||
pretty_amount = round(reagent_amount, 0.05)
|
||||
|
||||
chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("chemical" = temp.id), "occ_amount" = reagent_amount, "pretty_amount" = pretty_amount, "injectable" = injectable, "overdosing" = overdosing, "od_warning" = caution)))
|
||||
data["chemicals"] = chemicals
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/Topic(href, href_list)
|
||||
if(!controls_inside && usr == occupant)
|
||||
return 0
|
||||
|
||||
/obj/machinery/sleeper/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
return
|
||||
if(!controls_inside && usr == occupant)
|
||||
return
|
||||
if(panel_open)
|
||||
to_chat(usr, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return 0
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon/ai)))
|
||||
if(href_list["chemical"])
|
||||
if(occupant)
|
||||
if(occupant.stat == DEAD)
|
||||
to_chat(usr, "<span class='danger'>This person has no life for to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.</span>")
|
||||
else if(occupant.health > min_health || (href_list["chemical"] in emergency_chems))
|
||||
inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"]))
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!</span>")
|
||||
|
||||
if(href_list["removebeaker"])
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("chemical")
|
||||
if(!occupant)
|
||||
return
|
||||
if(occupant.stat == DEAD)
|
||||
to_chat(usr, "<span class='danger'>This person has no life to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.</span>")
|
||||
return
|
||||
var/chemical = params["chemid"]
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!length(chemical) || amount <= 0)
|
||||
return
|
||||
if(occupant.health > min_health || (chemical in emergency_chems))
|
||||
inject_chemical(usr, chemical, amount)
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!</span>")
|
||||
if("removebeaker")
|
||||
remove_beaker()
|
||||
|
||||
if(href_list["togglefilter"])
|
||||
if("togglefilter")
|
||||
toggle_filter()
|
||||
|
||||
if(href_list["ejectify"])
|
||||
if("ejectify")
|
||||
eject()
|
||||
|
||||
if(href_list["auto_eject_dead_on"])
|
||||
if("auto_eject_dead_on")
|
||||
auto_eject_dead = TRUE
|
||||
|
||||
if(href_list["auto_eject_dead_off"])
|
||||
if("auto_eject_dead_off")
|
||||
auto_eject_dead = FALSE
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1
|
||||
else
|
||||
return FALSE
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/reagent_containers/glass))
|
||||
@@ -290,6 +295,7 @@
|
||||
beaker = I
|
||||
I.forceMove(src)
|
||||
user.visible_message("[user] adds \a [I] to [src]!", "You add \a [I] to [src]!")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
else
|
||||
@@ -328,6 +334,7 @@
|
||||
to_chat(M, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
add_fingerprint(user)
|
||||
qdel(G)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
return ..()
|
||||
@@ -374,9 +381,11 @@
|
||||
occupant = null
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
SStgui.update_uis(src)
|
||||
if(A == beaker)
|
||||
beaker = null
|
||||
updateUsrDialog()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/sleeper/emp_act(severity)
|
||||
if(filtering)
|
||||
@@ -394,7 +403,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/sleeper/proc/toggle_filter()
|
||||
if(filtering)
|
||||
if(filtering || !beaker)
|
||||
filtering = 0
|
||||
else
|
||||
filtering = 1
|
||||
@@ -410,29 +419,28 @@
|
||||
// eject trash the occupant dropped
|
||||
for(var/atom/movable/A in contents - component_parts - list(beaker))
|
||||
A.forceMove(loc)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/sleeper/force_eject_occupant()
|
||||
go_out()
|
||||
|
||||
/obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount)
|
||||
/obj/machinery/sleeper/proc/inject_chemical(mob/living/user, chemical, amount)
|
||||
if(!(chemical in possible_chems))
|
||||
to_chat(user, "<span class='notice'>The sleeper does not offer that chemical!</span>")
|
||||
return
|
||||
if(!(amount in amounts))
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
if(occupant.reagents)
|
||||
if(occupant.reagents.get_reagent_amount(chemical) + amount <= max_chem)
|
||||
occupant.reagents.add_reagent(chemical, amount)
|
||||
return
|
||||
else
|
||||
to_chat(user, "You can not inject any more of this chemical.")
|
||||
return
|
||||
else
|
||||
to_chat(user, "The patient rejects the chemicals!")
|
||||
return
|
||||
else
|
||||
to_chat(user, "There's no occupant in the sleeper!")
|
||||
return
|
||||
|
||||
/obj/machinery/sleeper/verb/eject()
|
||||
set name = "Eject Sleeper"
|
||||
@@ -459,6 +467,7 @@
|
||||
filtering = 0
|
||||
beaker.forceMove(usr.loc)
|
||||
beaker = null
|
||||
SStgui.update_uis(src)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
@@ -511,6 +520,7 @@
|
||||
add_fingerprint(user)
|
||||
if(user.pulling == L)
|
||||
user.stop_pulling()
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -547,6 +557,7 @@
|
||||
for(var/obj/O in src)
|
||||
qdel(O)
|
||||
add_fingerprint(usr)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
icon_state = "body_scanner_1"
|
||||
add_fingerprint(user)
|
||||
qdel(TYPECAST_YOUR_SHIT)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
return ..()
|
||||
@@ -127,12 +128,13 @@
|
||||
occupant = H
|
||||
icon_state = "bodyscanner"
|
||||
add_fingerprint(user)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/bodyscanner/attack_ai(user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/bodyscanner/attack_ghost(user)
|
||||
return attack_hand(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/bodyscanner/attack_hand(user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
@@ -145,7 +147,7 @@
|
||||
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/bodyscanner/relaymove(mob/user)
|
||||
if(user.incapacitated())
|
||||
@@ -171,6 +173,7 @@
|
||||
// eject trash the occupant dropped
|
||||
for(var/atom/movable/A in contents - component_parts)
|
||||
A.forceMove(loc)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/bodyscanner/force_eject_occupant()
|
||||
go_out()
|
||||
@@ -192,17 +195,16 @@
|
||||
new /obj/effect/gibspawner/generic(get_turf(loc)) //I REPLACE YOUR TECHNOLOGY WITH FLESH!
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/bodyscanner/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/bodyscanner/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "adv_med.tmpl", "Body Scanner", 690, 600)
|
||||
ui = new(user, src, ui_key, "BodyScanner", "Body Scanner", 690, 600)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/bodyscanner/ui_data(mob/user, datum/topic_state/state)
|
||||
/obj/machinery/bodyscanner/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["occupied"] = occupant ? TRUE : FALSE
|
||||
|
||||
var/occupantData[0]
|
||||
if(occupant)
|
||||
@@ -236,9 +238,9 @@
|
||||
occupantData["hasBorer"] = occupant.has_brain_worms()
|
||||
|
||||
var/bloodData[0]
|
||||
bloodData["hasBlood"] = 0
|
||||
bloodData["hasBlood"] = FALSE
|
||||
if(!(NO_BLOOD in occupant.dna.species.species_traits))
|
||||
bloodData["hasBlood"] = 1
|
||||
bloodData["hasBlood"] = TRUE
|
||||
bloodData["volume"] = occupant.blood_volume
|
||||
bloodData["percent"] = round(((occupant.blood_volume / BLOOD_VOLUME_NORMAL)*100))
|
||||
bloodData["pulse"] = occupant.get_pulse(GETPULSE_TOOL)
|
||||
@@ -282,19 +284,19 @@
|
||||
if(E.status & ORGAN_BROKEN)
|
||||
organStatus["broken"] = E.broken_description
|
||||
if(E.is_robotic())
|
||||
organStatus["robotic"] = 1
|
||||
organStatus["robotic"] = TRUE
|
||||
if(E.status & ORGAN_SPLINTED)
|
||||
organStatus["splinted"] = 1
|
||||
organStatus["splinted"] = TRUE
|
||||
if(E.status & ORGAN_DEAD)
|
||||
organStatus["dead"] = 1
|
||||
organStatus["dead"] = TRUE
|
||||
|
||||
organData["status"] = organStatus
|
||||
|
||||
if(istype(E, /obj/item/organ/external/chest) && occupant.is_lung_ruptured())
|
||||
organData["lungRuptured"] = 1
|
||||
organData["lungRuptured"] = TRUE
|
||||
|
||||
if(E.internal_bleeding)
|
||||
organData["internalBleeding"] = 1
|
||||
organData["internalBleeding"] = TRUE
|
||||
|
||||
extOrganData.Add(list(organData))
|
||||
|
||||
@@ -319,27 +321,33 @@
|
||||
|
||||
occupantData["blind"] = (BLINDNESS in occupant.mutations)
|
||||
occupantData["colourblind"] = (COLOURBLIND in occupant.mutations)
|
||||
occupantData["nearsighted"] = (NEARSIGHTED in occupant.mutations)
|
||||
occupantData["nearsighted"] = (NEARSIGHTED in occupant.mutations)
|
||||
|
||||
data["occupant"] = occupantData
|
||||
return data
|
||||
|
||||
/obj/machinery/bodyscanner/Topic(href, href_list)
|
||||
/obj/machinery/bodyscanner/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(href_list["ejectify"])
|
||||
eject()
|
||||
|
||||
if(href_list["print_p"])
|
||||
visible_message("<span class='notice'>[src] rattles and prints out a sheet of paper.</span>")
|
||||
var/obj/item/paper/P = new /obj/item/paper(loc)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
P.info = "<CENTER><B>Body Scan - [href_list["name"]]</B></CENTER><BR>"
|
||||
P.info += "<b>Time of scan:</b> [station_time_timestamp()]<br><br>"
|
||||
P.info += "[generate_printing_text()]"
|
||||
P.info += "<br><br><b>Notes:</b><br>"
|
||||
P.name = "Body Scan - [href_list["name"]]"
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("ejectify")
|
||||
eject()
|
||||
if("print_p")
|
||||
visible_message("<span class='notice'>[src] rattles and prints out a sheet of paper.</span>")
|
||||
var/obj/item/paper/P = new /obj/item/paper(loc)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE)
|
||||
var/name = occupant ? occupant.name : "Unknown"
|
||||
P.info = "<CENTER><B>Body Scan - [name]</B></CENTER><BR>"
|
||||
P.info += "<b>Time of scan:</b> [station_time_timestamp()]<br><br>"
|
||||
P.info += "[generate_printing_text()]"
|
||||
P.info += "<br><br><b>Notes:</b><br>"
|
||||
P.name = "Body Scan - [name]"
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/bodyscanner/proc/generate_printing_text()
|
||||
var/dat = ""
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
list("name" = "\[SPECIAL\]", "icon" = "whiters")
|
||||
)
|
||||
possibleseccolor = list( // no point in having the N2O and "whiters" ones in these lists
|
||||
list("name" = "\[None\]", "icon" = "none"),
|
||||
list("name" = "\[N2\]", "icon" = "red-c"),
|
||||
list("name" = "\[O2\]", "icon" = "blue-c"),
|
||||
list("name" = "\[Toxin (Bio)\]", "icon" = "orange-c"),
|
||||
@@ -19,6 +20,7 @@
|
||||
list("name" = "\[CAUTION\]", "icon" = "yellow-c")
|
||||
)
|
||||
possibletertcolor = list(
|
||||
list("name" = "\[None\]", "icon" = "none"),
|
||||
list("name" = "\[N2\]", "icon" = "red-c-1"),
|
||||
list("name" = "\[O2\]", "icon" = "blue-c-1"),
|
||||
list("name" = "\[Toxin (Bio)\]", "icon" = "orange-c-1"),
|
||||
@@ -27,6 +29,7 @@
|
||||
list("name" = "\[CAUTION\]", "icon" = "yellow-c-1")
|
||||
)
|
||||
possiblequartcolor = list(
|
||||
list("name" = "\[None\]", "icon" = "none"),
|
||||
list("name" = "\[N2\]", "icon" = "red-c-2"),
|
||||
list("name" = "\[O2\]", "icon" = "blue-c-2"),
|
||||
list("name" = "\[Toxin (Bio)\]", "icon" = "orange-c-2"),
|
||||
@@ -34,12 +37,6 @@
|
||||
list("name" = "\[Air\]", "icon" = "grey-c-2"),
|
||||
list("name" = "\[CAUTION\]", "icon" = "yellow-c-2")
|
||||
)
|
||||
|
||||
possibledecals = list( //var that stores all possible decals, used by ui
|
||||
list("name" = "Low temperature canister", "icon" = "cold"),
|
||||
list("name" = "High temperature canister", "icon" = "hot"),
|
||||
list("name" = "Plasma containing canister", "icon" = "plasma")
|
||||
)
|
||||
GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister
|
||||
@@ -52,22 +49,17 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
|
||||
var/menu = 0
|
||||
//used by nanoui: 0 = main menu, 1 = relabel
|
||||
|
||||
var/valve_open = 0
|
||||
var/release_pressure = ONE_ATMOSPHERE
|
||||
|
||||
var/list/canister_color //variable that stores colours
|
||||
var/list/decals //list that stores the decals
|
||||
var/list/color_index // list which stores tgui color indexes for the recoloring options, to enable previously-set colors to show up right
|
||||
|
||||
//lists for check_change()
|
||||
var/list/oldcolor
|
||||
var/list/olddecals
|
||||
|
||||
//passed to the ui to render the color lists
|
||||
var/list/colorcontainer
|
||||
var/list/possibledecals
|
||||
|
||||
var/can_label = 1
|
||||
var/filled = 0.5
|
||||
@@ -82,18 +74,12 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
|
||||
/obj/machinery/portable_atmospherics/canister/New()
|
||||
..()
|
||||
canister_color = list(
|
||||
"prim" = "yellow",
|
||||
"sec" = "none",
|
||||
"ter" = "none",
|
||||
"quart" = "none")
|
||||
"prim" = "yellow",
|
||||
"sec" = "none",
|
||||
"ter" = "none",
|
||||
"quart" = "none"
|
||||
)
|
||||
oldcolor = new /list()
|
||||
decals = list("cold" = 0, "hot" = 0, "plasma" = 0)
|
||||
colorcontainer = list()
|
||||
possibledecals = list()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/init_data_vars()
|
||||
//passed to the ui to render the color lists
|
||||
colorcontainer = list(
|
||||
"prim" = list(
|
||||
"options" = GLOB.canister_icon_container.possiblemaincolor,
|
||||
@@ -112,26 +98,8 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
|
||||
"name" = "Quaternary color",
|
||||
)
|
||||
)
|
||||
|
||||
//var/anycolor used by the nanoUI, 0: no color applied. 1: color applied
|
||||
for(var/C in colorcontainer)
|
||||
if(C == "prim") continue
|
||||
var/list/L = colorcontainer[C]
|
||||
if(!(canister_color[C]) || (canister_color[C] == "none"))
|
||||
L.Add(list("anycolor" = 0))
|
||||
else
|
||||
L.Add(list("anycolor" = 1))
|
||||
colorcontainer[C] = L
|
||||
|
||||
possibledecals = list()
|
||||
|
||||
var/i
|
||||
var/list/L = GLOB.canister_icon_container.possibledecals
|
||||
for(i=1;i<=L.len;i++)
|
||||
var/list/LL = L[i]
|
||||
LL = LL.Copy() //make sure we don't edit the datum list
|
||||
LL.Add(list("active" = decals[LL["icon"]])) //"active" used by nanoUI
|
||||
possibledecals.Add(LL)
|
||||
color_index = list()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/check_change()
|
||||
var/old_flag = update_flag
|
||||
@@ -155,10 +123,6 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
|
||||
update_flag |= 64
|
||||
oldcolor = canister_color.Copy()
|
||||
|
||||
if(list2params(olddecals) != list2params(decals))
|
||||
update_flag |= 128
|
||||
olddecals = decals.Copy()
|
||||
|
||||
if(update_flag == old_flag)
|
||||
return 1
|
||||
else
|
||||
@@ -174,17 +138,16 @@ update_flag
|
||||
16 = tank_pressure < 15*ONE_ATMOS
|
||||
32 = tank_pressure go boom.
|
||||
64 = colors
|
||||
128 = decals
|
||||
(note: colors and decals has to be applied every icon update)
|
||||
(note: colors has to be applied every icon update)
|
||||
*/
|
||||
|
||||
if(src.destroyed)
|
||||
src.overlays = 0
|
||||
src.icon_state = text("[]-1", src.canister_color["prim"])//yes, I KNOW the colours don't reflect when the can's borked, whatever.
|
||||
if(destroyed)
|
||||
overlays = 0
|
||||
icon_state = text("[]-1", canister_color["prim"])//yes, I KNOW the colours don't reflect when the can's borked, whatever.
|
||||
return
|
||||
|
||||
if(icon_state != src.canister_color["prim"])
|
||||
icon_state = src.canister_color["prim"]
|
||||
if(icon_state != canister_color["prim"])
|
||||
icon_state = canister_color["prim"]
|
||||
|
||||
if(check_change()) //Returns 1 if no change needed to icons.
|
||||
return
|
||||
@@ -192,14 +155,12 @@ update_flag
|
||||
overlays.Cut()
|
||||
|
||||
for(var/C in canister_color)
|
||||
if(C == "prim") continue
|
||||
if(canister_color[C] == "none") continue
|
||||
if(C == "prim")
|
||||
continue
|
||||
if(canister_color[C] == "none")
|
||||
continue
|
||||
overlays.Add(canister_color[C])
|
||||
|
||||
for(var/D in decals)
|
||||
if(decals[D])
|
||||
overlays.Add("decal-" + D)
|
||||
|
||||
if(update_flag & 1)
|
||||
overlays += "can-open"
|
||||
if(update_flag & 2)
|
||||
@@ -213,35 +174,9 @@ update_flag
|
||||
else if(update_flag & 32)
|
||||
overlays += "can-o3"
|
||||
|
||||
update_flag &= ~196 //the flags 128 and 64 represent change, not states. As such, we have to reset them to be able to detect a change on the next go.
|
||||
update_flag &= ~68 //the flag 64 represents change, not states. As such, we have to reset them to be able to detect a change on the next go.
|
||||
return
|
||||
|
||||
//template modification exploit prevention, used in Topic()
|
||||
/obj/machinery/portable_atmospherics/canister/proc/is_a_color(var/inputVar, var/checkColor = "all")
|
||||
if(checkColor == "prim" || checkColor == "all")
|
||||
for(var/list/L in GLOB.canister_icon_container.possiblemaincolor)
|
||||
if(L["icon"] == inputVar)
|
||||
return 1
|
||||
if(checkColor == "sec" || checkColor == "all")
|
||||
for(var/list/L in GLOB.canister_icon_container.possibleseccolor)
|
||||
if(L["icon"] == inputVar)
|
||||
return 1
|
||||
if(checkColor == "ter" || checkColor == "all")
|
||||
for(var/list/L in GLOB.canister_icon_container.possibletertcolor)
|
||||
if(L["icon"] == inputVar)
|
||||
return 1
|
||||
if(checkColor == "quart" || checkColor == "all")
|
||||
for(var/list/L in GLOB.canister_icon_container.possiblequartcolor)
|
||||
if(L["icon"] == inputVar)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/is_a_decal(var/inputVar)
|
||||
for(var/list/L in GLOB.canister_icon_container.possibledecals)
|
||||
if(L["icon"] == inputVar)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
..()
|
||||
if(exposed_temperature > temperature_resistance)
|
||||
@@ -271,7 +206,7 @@ update_flag
|
||||
|
||||
stat |= BROKEN
|
||||
density = FALSE
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
|
||||
playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
|
||||
update_icon()
|
||||
|
||||
if(holding)
|
||||
@@ -297,7 +232,7 @@ update_flag
|
||||
|
||||
var/transfer_moles = 0
|
||||
if((air_contents.temperature > 0) && (pressure_delta > 0))
|
||||
transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
transfer_moles = pressure_delta * environment.volume / (air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
@@ -307,7 +242,7 @@ update_flag
|
||||
else
|
||||
loc.assume_air(removed)
|
||||
air_update_turf()
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
|
||||
|
||||
if(air_contents.return_pressure() < 1)
|
||||
@@ -315,20 +250,20 @@ update_flag
|
||||
else
|
||||
can_label = 0
|
||||
|
||||
src.updateDialog()
|
||||
updateDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/return_air()
|
||||
return air_contents
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/return_temperature()
|
||||
var/datum/gas_mixture/GM = src.return_air()
|
||||
var/datum/gas_mixture/GM = return_air()
|
||||
if(GM && GM.volume>0)
|
||||
return GM.temperature
|
||||
return 0
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/return_pressure()
|
||||
var/datum/gas_mixture/GM = src.return_air()
|
||||
var/datum/gas_mixture/GM = return_air()
|
||||
if(GM && GM.volume>0)
|
||||
return GM.return_pressure()
|
||||
return 0
|
||||
@@ -343,141 +278,114 @@ update_flag
|
||||
else if(valve_open && holding)
|
||||
investigate_log("[key_name(user)] started a transfer into [holding].<br>", "atmos")
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob)
|
||||
src.add_hiddenprint(user)
|
||||
return src.attack_hand(user)
|
||||
/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user)
|
||||
add_hiddenprint(user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/attack_ghost(var/mob/user as mob)
|
||||
return src.ui_interact(user)
|
||||
/obj/machinery/portable_atmospherics/canister/attack_ghost(var/mob/user)
|
||||
return tgui_interact(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob)
|
||||
return src.ui_interact(user)
|
||||
/obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user)
|
||||
return tgui_interact(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.physical_state)
|
||||
if(src.destroyed)
|
||||
return
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/portable_atmospherics/canister/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400, state = state)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "Canister", name, 600, 350, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/ui_data(mob/user, datum/topic_state/state)
|
||||
init_data_vars() //set up var/colorcontainer and var/possibledecals
|
||||
|
||||
// this is the data which will be sent to the ui
|
||||
var/data[0]
|
||||
data["name"] = name
|
||||
data["menu"] = menu ? 1 : 0
|
||||
data["canLabel"] = can_label ? 1 : 0
|
||||
data["canister_color"] = canister_color
|
||||
data["colorContainer"] = colorcontainer.Copy()
|
||||
colorcontainer.Cut()
|
||||
data["possibleDecals"] = possibledecals.Copy()
|
||||
possibledecals.Cut()
|
||||
/obj/machinery/portable_atmospherics/canister/tgui_data()
|
||||
var/data = list()
|
||||
data["portConnected"] = connected_port ? 1 : 0
|
||||
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
|
||||
data["releasePressure"] = round(release_pressure ? release_pressure : 0)
|
||||
data["minReleasePressure"] = round(ONE_ATMOSPHERE/10)
|
||||
data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE)
|
||||
data["defaultReleasePressure"] = ONE_ATMOSPHERE
|
||||
data["minReleasePressure"] = round(ONE_ATMOSPHERE / 10)
|
||||
data["maxReleasePressure"] = round(ONE_ATMOSPHERE * 10)
|
||||
data["valveOpen"] = valve_open ? 1 : 0
|
||||
|
||||
data["name"] = name
|
||||
data["canLabel"] = can_label ? 1 : 0
|
||||
data["colorContainer"] = colorcontainer.Copy()
|
||||
data["color_index"] = color_index
|
||||
data["hasHoldingTank"] = holding ? 1 : 0
|
||||
if(holding)
|
||||
data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure()))
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/Topic(href, href_list)
|
||||
/obj/machinery/portable_atmospherics/canister/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["choice"] == "menu")
|
||||
menu = text2num(href_list["mode_target"])
|
||||
|
||||
if(href_list["toggle"])
|
||||
var/logmsg
|
||||
if(valve_open)
|
||||
if(holding)
|
||||
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the [holding]<br>"
|
||||
else
|
||||
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the <font color='red'><b>air</b></font><br>"
|
||||
else
|
||||
if(holding)
|
||||
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting the transfer into the [holding]<br>"
|
||||
else
|
||||
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting the transfer into the <font color='red'><b>air</b></font><br>"
|
||||
if(air_contents.toxins > 0)
|
||||
message_admins("[key_name_admin(usr)] opened a canister that contains plasma in [get_area(src)]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] opened a canister that contains plasma at [get_area(src)]: [x], [y], [z]")
|
||||
if(air_contents.sleeping_agent > 0)
|
||||
message_admins("[key_name_admin(usr)] opened a canister that contains N2O in [get_area(src)]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] opened a canister that contains N2O at [get_area(src)]: [x], [y], [z]")
|
||||
investigate_log(logmsg, "atmos")
|
||||
release_log += logmsg
|
||||
valve_open = !valve_open
|
||||
|
||||
if(href_list["remove_tank"])
|
||||
if(holding)
|
||||
if(valve_open)
|
||||
valve_open = 0
|
||||
release_log += "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the [holding]<br>"
|
||||
holding.loc = loc
|
||||
holding = null
|
||||
|
||||
if(href_list["pressure_adj"])
|
||||
var/diff = text2num(href_list["pressure_adj"])
|
||||
if(diff > 0)
|
||||
release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff)
|
||||
else
|
||||
release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff)
|
||||
|
||||
if(href_list["rename"])
|
||||
if(can_label)
|
||||
var/T = sanitize(copytext(input("Choose canister label", "Name", name) as text|null,1,MAX_NAME_LEN))
|
||||
if(can_label) //Exploit prevention
|
||||
if(T)
|
||||
name = T
|
||||
return
|
||||
var/can_min_release_pressure = round(ONE_ATMOSPHERE / 10)
|
||||
var/can_max_release_pressure = round(ONE_ATMOSPHERE * 10)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("relabel")
|
||||
if(can_label)
|
||||
var/T = sanitize(copytext(input("Choose canister label", "Name", name) as text|null, 1, MAX_NAME_LEN))
|
||||
if(can_label) //Exploit prevention
|
||||
if(T)
|
||||
name = T
|
||||
else
|
||||
name = "canister"
|
||||
else
|
||||
name = "canister"
|
||||
to_chat(usr, "<span class='warning'>As you attempted to rename it the pressure rose!</span>")
|
||||
. = FALSE
|
||||
if("pressure")
|
||||
var/pressure = params["pressure"]
|
||||
if(pressure == "reset")
|
||||
pressure = ONE_ATMOSPHERE
|
||||
else if(pressure == "min")
|
||||
pressure = can_min_release_pressure
|
||||
else if(pressure == "max")
|
||||
pressure = can_max_release_pressure
|
||||
else if(pressure == "input")
|
||||
pressure = input("New release pressure ([can_min_release_pressure]-[can_max_release_pressure] kPa):", name, release_pressure) as num|null
|
||||
if(isnull(pressure))
|
||||
. = FALSE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
if(.)
|
||||
release_pressure = clamp(round(pressure), can_min_release_pressure, can_max_release_pressure)
|
||||
investigate_log("was set to [release_pressure] kPa by [key_name(usr)].", "atmos")
|
||||
if("valve")
|
||||
var/logmsg
|
||||
valve_open = !valve_open
|
||||
if(valve_open)
|
||||
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting a transfer into the [holding || "air"].<br>"
|
||||
if(!holding)
|
||||
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting a transfer into the air.<br>"
|
||||
if(air_contents.toxins > 0)
|
||||
message_admins("[key_name_admin(usr)] opened a canister that contains plasma in [get_area(src)]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] opened a canister that contains plasma at [get_area(src)]: [x], [y], [z]")
|
||||
if(air_contents.sleeping_agent > 0)
|
||||
message_admins("[key_name_admin(usr)] opened a canister that contains N2O in [get_area(src)]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
log_admin("[key_name(usr)] opened a canister that contains N2O at [get_area(src)]: [x], [y], [z]")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>As you attempted to rename it the pressure rose!</span>")
|
||||
|
||||
if(href_list["choice"] == "Primary color")
|
||||
if(is_a_color(href_list["icon"],"prim"))
|
||||
canister_color["prim"] = href_list["icon"]
|
||||
if(href_list["choice"] == "Secondary color")
|
||||
if(href_list["icon"] == "none")
|
||||
canister_color["sec"] = "none"
|
||||
else if(is_a_color(href_list["icon"],"sec"))
|
||||
canister_color["sec"] = href_list["icon"]
|
||||
if(href_list["choice"] == "Tertiary color")
|
||||
if(href_list["icon"] == "none")
|
||||
canister_color["ter"] = "none"
|
||||
else if(is_a_color(href_list["icon"],"ter"))
|
||||
canister_color["ter"] = href_list["icon"]
|
||||
if(href_list["choice"] == "Quaternary color")
|
||||
if(href_list["icon"] == "none")
|
||||
canister_color["quart"] = "none"
|
||||
else if(is_a_color(href_list["icon"],"quart"))
|
||||
canister_color["quart"] = href_list["icon"]
|
||||
|
||||
if(href_list["choice"] == "decals")
|
||||
if(is_a_decal(href_list["icon"]))
|
||||
decals[href_list["icon"]] = (decals[href_list["icon"]] == 0)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
logmsg = "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the [holding || "air"].<br>"
|
||||
investigate_log(logmsg, "atmos")
|
||||
release_log += logmsg
|
||||
if("eject")
|
||||
if(holding)
|
||||
if(valve_open)
|
||||
if(air_contents && (air_contents.toxins > 0 || air_contents.sleeping_agent > 0))
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] removed [holding] from [src] with valve still open at [ADMIN_VERBOSEJMP(src)] releasing contents into the <span class='boldannounce'>air</span>.")
|
||||
release_log += "[key_name(usr)] removed the [holding], leaving the valve open and transferring into the air<br>"
|
||||
investigate_log("[key_name(usr)] removed the [holding], leaving the valve open and transferring into the <span class='boldannounce'>air</span>.", "atmos")
|
||||
replace_tank(usr, FALSE)
|
||||
if("recolor")
|
||||
if(can_label)
|
||||
var/ctype = params["ctype"]
|
||||
var/cnum = text2num(params["nc"])
|
||||
if(isnull(colorcontainer[ctype]))
|
||||
message_admins("[key_name_admin(usr)] passed an invalid ctype var to a canister.")
|
||||
return
|
||||
var/newcolor = sanitize_integer(cnum, 0, length(colorcontainer[ctype]["options"]))
|
||||
color_index[ctype] = newcolor
|
||||
newcolor++ // javascript starts arrays at 0, byond (for some reason) starts them at 1, this converts JS values to byond values
|
||||
canister_color[ctype] = colorcontainer[ctype]["options"][newcolor]["icon"]
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/toxins
|
||||
name = "Canister \[Toxin (Plasma)\]"
|
||||
@@ -513,19 +421,18 @@ update_flag
|
||||
..()
|
||||
|
||||
canister_color["prim"] = "orange"
|
||||
decals["plasma"] = 1
|
||||
src.air_contents.toxins = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
|
||||
air_contents.toxins = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/oxygen/New()
|
||||
..()
|
||||
|
||||
canister_color["prim"] = "blue"
|
||||
src.air_contents.oxygen = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
|
||||
air_contents.oxygen = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/sleeping_agent/New()
|
||||
@@ -534,25 +441,25 @@ update_flag
|
||||
canister_color["prim"] = "redws"
|
||||
air_contents.sleeping_agent = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/nitrogen/New()
|
||||
..()
|
||||
|
||||
canister_color["prim"] = "red"
|
||||
src.air_contents.nitrogen = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
|
||||
air_contents.nitrogen = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/carbon_dioxide/New()
|
||||
..()
|
||||
|
||||
canister_color["prim"] = "black"
|
||||
src.air_contents.carbon_dioxide = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
|
||||
air_contents.carbon_dioxide = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -560,17 +467,17 @@ update_flag
|
||||
..()
|
||||
|
||||
canister_color["prim"] = "grey"
|
||||
src.air_contents.oxygen = (O2STANDARD*src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
|
||||
src.air_contents.nitrogen = (N2STANDARD*src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
|
||||
air_contents.oxygen = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
air_contents.nitrogen = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
|
||||
src.update_icon()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/custom_mix/New()
|
||||
..()
|
||||
|
||||
canister_color["prim"] = "whiters"
|
||||
src.update_icon() // Otherwise new canisters do not have their icon updated with the pressure light, likely want to add this to the canister class constructor, avoiding at current time to refrain from screwing up code for other canisters. --DZD
|
||||
update_icon() // Otherwise new canisters do not have their icon updated with the pressure light, likely want to add this to the canister class constructor, avoiding at current time to refrain from screwing up code for other canisters. --DZD
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/welder_act(mob/user, obj/item/I)
|
||||
|
||||
+120
-128
@@ -24,7 +24,7 @@
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
var/busy = 0
|
||||
var/busy = FALSE
|
||||
var/prod_coeff
|
||||
var/datum/wires/autolathe/wires = null
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
var/list/datum/design/matching_designs
|
||||
var/temp_search
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
var/list/recipiecache = list()
|
||||
|
||||
var/list/categories = list("Tools", "Electronics", "Construction", "Communication", "Security", "Machinery", "Medical", "Miscellaneous", "Dinnerware", "Imported")
|
||||
|
||||
@@ -79,63 +79,121 @@
|
||||
if(panel_open)
|
||||
wires.Interact(user)
|
||||
else
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/autolathe/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/autolathe/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "autolathe.tmpl", name, 800, 550)
|
||||
ui = new(user, src, ui_key, "Autolathe", name, 750, 700, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/autolathe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
|
||||
/obj/machinery/autolathe/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["categories"] = categories
|
||||
if(!recipiecache.len)
|
||||
var/list/recipes = list()
|
||||
for(var/v in files.known_designs)
|
||||
var/datum/design/D = files.known_designs[v]
|
||||
var/list/cost_list = design_cost_data(D)
|
||||
var/list/matreq = list()
|
||||
for(var/list/x in cost_list)
|
||||
if(!x["amount"])
|
||||
continue
|
||||
if(x["name"] == "metal") // Do not use MAT_METAL or MAT_GLASS here.
|
||||
matreq["metal"] = x["amount"]
|
||||
if(x["name"] == "glass")
|
||||
matreq["glass"] = x["amount"]
|
||||
var/obj/item/I = D.build_path
|
||||
var/maxmult = 1
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
maxmult = D.maxstack
|
||||
recipes.Add(list(list(
|
||||
"name" = D.name,
|
||||
"category" = D.category,
|
||||
"uid" = D.UID(),
|
||||
"requirements" = matreq,
|
||||
"hacked" = ("hacked" in D.category) ? TRUE : FALSE,
|
||||
"max_multiplier" = maxmult,
|
||||
"image" = "[icon2base64(icon(initial(I.icon), initial(I.icon_state), SOUTH, 1))]"
|
||||
)))
|
||||
recipiecache = recipes
|
||||
data["recipes"] = recipiecache
|
||||
return data
|
||||
|
||||
/obj/machinery/autolathe/tgui_data(mob/user)
|
||||
var/list/data = list() //..()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/data[0]
|
||||
data["screen"] = screen
|
||||
data["total_amount"] = materials.total_amount
|
||||
data["max_amount"] = materials.max_amount
|
||||
data["fill_percent"] = round((materials.total_amount / materials.max_amount) * 100)
|
||||
data["metal_amount"] = materials.amount(MAT_METAL)
|
||||
data["glass_amount"] = materials.amount(MAT_GLASS)
|
||||
switch(screen)
|
||||
if(AUTOLATHE_MAIN_MENU)
|
||||
data["uid"] = UID()
|
||||
data["categories"] = categories
|
||||
if(AUTOLATHE_CATEGORY_MENU)
|
||||
data["selected_category"] = selected_category
|
||||
var/list/designs = list()
|
||||
data["designs"] = designs
|
||||
for(var/v in files.known_designs)
|
||||
var/datum/design/D = files.known_designs[v]
|
||||
if(!(selected_category in D.category))
|
||||
continue
|
||||
var/list/design = list()
|
||||
designs[++designs.len] = design
|
||||
design["name"] = D.name
|
||||
design["id"] = D.id
|
||||
design["disabled"] = disabled || !can_build(D) ? "disabled" : null
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
design["max_multiplier"] = min(D.maxstack, D.materials[MAT_METAL] ? round(materials.amount(MAT_METAL) / D.materials[MAT_METAL]) : INFINITY, D.materials[MAT_GLASS] ? round(materials.amount(MAT_GLASS) / D.materials[MAT_GLASS]) : INFINITY)
|
||||
else
|
||||
design["max_multiplier"] = null
|
||||
design["materials"] = design_cost_data(D)
|
||||
if(AUTOLATHE_SEARCH_MENU)
|
||||
data["search"] = temp_search
|
||||
var/list/designs = list()
|
||||
data["designs"] = designs
|
||||
for(var/datum/design/D in matching_designs)
|
||||
var/list/design = list()
|
||||
designs[++designs.len] = design
|
||||
design["name"] = D.name
|
||||
design["id"] = D.id
|
||||
design["disabled"] = disabled || !can_build(D) ? "disabled" : null
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
design["max_multiplier"] = min(D.maxstack, D.materials[MAT_METAL] ? round(materials.amount(MAT_METAL) / D.materials[MAT_METAL]) : INFINITY, D.materials[MAT_GLASS] ? round(materials.amount(MAT_GLASS) / D.materials[MAT_GLASS]) : INFINITY)
|
||||
else
|
||||
design["max_multiplier"] = null
|
||||
design["materials"] = design_cost_data(D)
|
||||
|
||||
data = queue_data(data)
|
||||
data["busyname"] = FALSE
|
||||
data["busyamt"] = 1
|
||||
if(length(being_built) > 0)
|
||||
var/datum/design/D = being_built[1]
|
||||
data["busyname"] = istype(D) && D.name ? D.name : FALSE
|
||||
data["busyamt"] = length(being_built) > 1 ? being_built[2] : 1
|
||||
data["showhacked"] = hacked ? TRUE : FALSE
|
||||
data["buildQueue"] = queue
|
||||
data["buildQueueLen"] = queue.len
|
||||
return data
|
||||
|
||||
/obj/machinery/autolathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return FALSE
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("clear_queue")
|
||||
queue = list()
|
||||
if("remove_from_queue")
|
||||
var/index = text2num(params["remove_from_queue"])
|
||||
if(isnum(index) && ISINRANGE(index, 1, queue.len))
|
||||
remove_from_queue(index)
|
||||
to_chat(usr, "<span class='notice'>Removed item from queue.</span>")
|
||||
if("make")
|
||||
BuildTurf = loc
|
||||
var/datum/design/design_last_ordered
|
||||
design_last_ordered = locateUID(params["make"])
|
||||
if(!istype(design_last_ordered))
|
||||
to_chat(usr, "<span class='warning'>Invalid design</span>")
|
||||
return
|
||||
if(!(design_last_ordered.build_type & AUTOLATHE))
|
||||
to_chat(usr, "<span class='warning'>Invalid design (not buildable in autolathe, report this error.)</span>")
|
||||
return
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(design_last_ordered.materials["$metal"] > materials.amount(MAT_METAL))
|
||||
to_chat(usr, "<span class='warning'>Invalid design (not enough metal)</span>")
|
||||
return
|
||||
if(design_last_ordered.materials["$glass"] > materials.amount(MAT_GLASS))
|
||||
to_chat(usr, "<span class='warning'>Invalid design (not enough glass)</span>")
|
||||
return
|
||||
if(!hacked && ("hacked" in design_last_ordered.category))
|
||||
to_chat(usr, "<span class='warning'>Invalid design (lathe requires hacking)</span>")
|
||||
return
|
||||
//multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier
|
||||
var/multiplier = text2num(params["multiplier"])
|
||||
var/max_multiplier = min(design_last_ordered.maxstack, design_last_ordered.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/design_last_ordered.materials[MAT_METAL]):INFINITY,design_last_ordered.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/design_last_ordered.materials[MAT_GLASS]):INFINITY)
|
||||
var/is_stack = ispath(design_last_ordered.build_path, /obj/item/stack)
|
||||
|
||||
if(!is_stack && (multiplier > 1))
|
||||
return
|
||||
if(!(multiplier in list(1, 10, 25, max_multiplier))) //"enough materials ?" is checked in the build proc
|
||||
message_admins("Player [key_name_admin(usr)] attempted to pass invalid multiplier [multiplier] to an autolathe in tgui_act. Possible href exploit.")
|
||||
return
|
||||
if((queue.len + 1) < queue_max_len)
|
||||
add_to_queue(design_last_ordered, multiplier)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>The autolathe queue is full!</span>")
|
||||
if(!busy)
|
||||
busy = TRUE
|
||||
process_queue()
|
||||
busy = FALSE
|
||||
|
||||
/obj/machinery/autolathe/proc/design_cost_data(datum/design/D)
|
||||
var/list/data = list()
|
||||
var/coeff = get_coeff(D)
|
||||
@@ -185,14 +243,21 @@
|
||||
if(istype(O, /obj/item/disk/design_disk))
|
||||
var/obj/item/disk/design_disk/D = O
|
||||
if(D.blueprint)
|
||||
if(!(D.blueprint.build_type & AUTOLATHE)) // otherwise, would silently fail in AddDesign2Known
|
||||
to_chat(user, "<span class='warning'>This design is not compatible with the autolathe.</span>")
|
||||
return 1
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a design from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
playsound(get_turf(src), 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
busy = 1
|
||||
busy = TRUE
|
||||
if(do_after(user, 14.4, target = src))
|
||||
if(!("Imported" in D.blueprint.category)) // R&D should always ensure this is set on design disks, but it doesn't.
|
||||
D.blueprint.category += "Imported" // now it will actually show up in the list.
|
||||
files.AddDesign2Known(D.blueprint)
|
||||
busy = 0
|
||||
recipiecache = list()
|
||||
SStgui.close_uis(src) // forces all connected users to re-open the TGUI. Imported entries won't show otherwise due to static_data
|
||||
busy = FALSE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>That disk does not have a design on it!</span>")
|
||||
return 1
|
||||
@@ -222,7 +287,6 @@
|
||||
to_chat(user, "<span class='alert'>The autolathe is busy. Please wait for completion of previous operation.</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", I))
|
||||
SSnanoui.update_uis(src)
|
||||
I.play_tool_sound(user, I.tool_volume)
|
||||
|
||||
/obj/machinery/autolathe/wirecutter_act(mob/user, obj/item/I)
|
||||
@@ -254,7 +318,7 @@
|
||||
if(MAT_GLASS)
|
||||
flick("autolathe_r", src)//plays glass insertion animation
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/autolathe/attack_ghost(mob/user)
|
||||
interact(user)
|
||||
@@ -264,79 +328,6 @@
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/autolathe/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["menu"])
|
||||
screen = text2num(href_list["menu"])
|
||||
|
||||
if(href_list["category"])
|
||||
selected_category = href_list["category"]
|
||||
screen = AUTOLATHE_CATEGORY_MENU
|
||||
|
||||
if(href_list["make"])
|
||||
BuildTurf = loc
|
||||
|
||||
/////////////////
|
||||
//href protection
|
||||
var/datum/design/design_last_ordered
|
||||
design_last_ordered = files.FindDesignByID(href_list["make"]) //check if it's a valid design
|
||||
if(!design_last_ordered)
|
||||
return
|
||||
if(!(design_last_ordered.build_type & AUTOLATHE))
|
||||
return
|
||||
|
||||
//multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier
|
||||
var/multiplier = text2num(href_list["multiplier"])
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(design_last_ordered.maxstack, design_last_ordered.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/design_last_ordered.materials[MAT_METAL]):INFINITY,design_last_ordered.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/design_last_ordered.materials[MAT_GLASS]):INFINITY)
|
||||
var/is_stack = ispath(design_last_ordered.build_path, /obj/item/stack)
|
||||
|
||||
if(!is_stack && (multiplier > 1))
|
||||
return
|
||||
if(!(multiplier in list(1, 10, 25, max_multiplier))) //"enough materials ?" is checked in the build proc
|
||||
return
|
||||
/////////////////
|
||||
|
||||
if((queue.len + 1) < queue_max_len)
|
||||
add_to_queue(design_last_ordered,multiplier)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>The autolathe queue is full!</span>")
|
||||
if(!busy)
|
||||
busy = 1
|
||||
process_queue()
|
||||
busy = 0
|
||||
|
||||
if(href_list["remove_from_queue"])
|
||||
var/index = text2num(href_list["remove_from_queue"])
|
||||
if(isnum(index) && ISINRANGE(index, 1, queue.len))
|
||||
remove_from_queue(index)
|
||||
if(href_list["queue_move"] && href_list["index"])
|
||||
var/index = text2num(href_list["index"])
|
||||
var/new_index = index + text2num(href_list["queue_move"])
|
||||
if(isnum(index) && isnum(new_index))
|
||||
if(ISINRANGE(new_index, 1, queue.len))
|
||||
queue.Swap(index,new_index)
|
||||
if(href_list["clear_queue"])
|
||||
queue = list()
|
||||
if(href_list["search"])
|
||||
if(href_list["to_search"])
|
||||
temp_search = href_list["to_search"]
|
||||
if(!temp_search)
|
||||
return
|
||||
matching_designs.Cut()
|
||||
|
||||
for(var/v in files.known_designs)
|
||||
var/datum/design/D = files.known_designs[v]
|
||||
if(findtext(D.name, temp_search))
|
||||
matching_designs.Add(D)
|
||||
|
||||
screen = AUTOLATHE_SEARCH_MENU
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
|
||||
/obj/machinery/autolathe/RefreshParts()
|
||||
var/tot_rating = 0
|
||||
prod_coeff = 0
|
||||
@@ -371,7 +362,7 @@
|
||||
else
|
||||
var/list/materials_used = list(MAT_METAL=metal_cost/coeff, MAT_GLASS=glass_cost/coeff)
|
||||
materials.use_amount(materials_used)
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
sleep(32/coeff)
|
||||
if(is_stack)
|
||||
var/obj/item/stack/S = new D.build_path(BuildTurf)
|
||||
@@ -380,7 +371,7 @@
|
||||
var/obj/item/new_item = new D.build_path(BuildTurf)
|
||||
new_item.materials[MAT_METAL] /= coeff
|
||||
new_item.materials[MAT_GLASS] /= coeff
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
desc = initial(desc)
|
||||
|
||||
/obj/machinery/autolathe/proc/can_build(datum/design/D, multiplier = 1, custom_metal, custom_glass)
|
||||
@@ -455,7 +446,6 @@
|
||||
D = listgetindex(listgetindex(queue, 1),1)
|
||||
multiplier = listgetindex(listgetindex(queue,1),2)
|
||||
being_built = new /list()
|
||||
//visible_message("[bicon(src)] <b>\The [src]</b> beeps, \"Queue processing finished successfully.\"")
|
||||
|
||||
/obj/machinery/autolathe/proc/adjust_hacked(hack)
|
||||
hacked = hack
|
||||
@@ -468,6 +458,8 @@
|
||||
for(var/datum/design/D in files.known_designs)
|
||||
if("hacked" in D.category)
|
||||
files.known_designs -= D.id
|
||||
SStgui.close_uis(src) // forces all connected users to re-open the TGUI, thus adding/removing hacked entries from lists
|
||||
recipiecache = list()
|
||||
|
||||
/obj/machinery/autolathe/proc/check_hacked_callback()
|
||||
if(!wires.is_cut(WIRE_AUTOLATHE_HACK))
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
add_fingerprint(user)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/operating/attack_hand(mob/user)
|
||||
if(..(user))
|
||||
@@ -52,16 +51,15 @@
|
||||
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)//ui is mostly copy pasta from the sleeper ui
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/operating/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "op_computer.tmpl", "Patient Monitor", 650, 455)
|
||||
ui = new(user, src, ui_key, "OperatingComputer", "Patient Monitor", 650, 455, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/computer/operating/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
var/mob/living/carbon/human/occupant
|
||||
if(table)
|
||||
@@ -136,38 +134,43 @@
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/computer/operating/Topic(href, href_list)
|
||||
/obj/machinery/computer/operating/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["verboseOn"])
|
||||
verbose=1
|
||||
if(href_list["verboseOff"])
|
||||
verbose=0
|
||||
if(href_list["healthOn"])
|
||||
healthAnnounce=1
|
||||
if(href_list["healthOff"])
|
||||
healthAnnounce=0
|
||||
if(href_list["critOn"])
|
||||
crit=1
|
||||
if(href_list["critOff"])
|
||||
crit=0
|
||||
if(href_list["oxyOn"])
|
||||
oxy=1
|
||||
if(href_list["oxyOff"])
|
||||
oxy=0
|
||||
if(href_list["oxy_adj"]!=0)
|
||||
oxyAlarm=oxyAlarm+text2num(href_list["oxy_adj"])
|
||||
if(href_list["choiceOn"])
|
||||
choice=1
|
||||
if(href_list["choiceOff"])
|
||||
choice=0
|
||||
if(href_list["health_adj"]!=0)
|
||||
healthAlarm=healthAlarm+text2num(href_list["health_adj"])
|
||||
return
|
||||
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("verboseOn")
|
||||
verbose = TRUE
|
||||
if("verboseOff")
|
||||
verbose = FALSE
|
||||
if("healthOn")
|
||||
healthAnnounce = TRUE
|
||||
if("healthOff")
|
||||
healthAnnounce = FALSE
|
||||
if("critOn")
|
||||
crit = TRUE
|
||||
if("critOff")
|
||||
crit = FALSE
|
||||
if("oxyOn")
|
||||
oxy = TRUE
|
||||
if("oxyOff")
|
||||
oxy = FALSE
|
||||
if("oxy_adj")
|
||||
oxyAlarm = clamp(text2num(params["new"]), -100, 100)
|
||||
if("choiceOn")
|
||||
choice = TRUE
|
||||
if("choiceOff")
|
||||
choice = FALSE
|
||||
if("health_adj")
|
||||
healthAlarm = clamp(text2num(params["new"]), -100, 100)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/operating/process()
|
||||
|
||||
@@ -178,6 +181,7 @@
|
||||
atom_say("New patient detected, loading stats")
|
||||
victim = table.victim
|
||||
atom_say("[victim.real_name], [victim.dna.blood_type] blood, [victim.stat ? "Non-Responsive" : "Awake"]")
|
||||
SStgui.update_uis(src)
|
||||
if(nextTick < world.time)
|
||||
nextTick=world.time + OP_COMPUTER_COOLDOWN
|
||||
if(crit && victim.health <= -50 )
|
||||
|
||||
@@ -22,23 +22,22 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/aifixer/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ai_fixer.tmpl", "AI System Integrity Restorer", 550, 500)
|
||||
ui = new(user, src, ui_key, "AIFixer", name, 550, 500, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_data(mob/user, datum/topic_state/state)
|
||||
/obj/machinery/computer/aifixer/tgui_data(mob/user, datum/topic_state/state)
|
||||
var/data[0]
|
||||
data["occupant"] = (occupant ? occupant.name : null) // a null occupant isn't passed on if this is below the if.
|
||||
if(occupant)
|
||||
data["occupant"] = occupant.name
|
||||
data["reference"] = "\ref[occupant]"
|
||||
data["integrity"] = (occupant.health+100)/2
|
||||
data["stat"] = occupant.stat
|
||||
@@ -48,45 +47,49 @@
|
||||
|
||||
var/laws[0]
|
||||
for(var/datum/ai_law/law in occupant.laws.all_laws())
|
||||
laws.Add(list(list("law" = law.law, "number" = law.get_index())))
|
||||
|
||||
if(law in occupant.laws.ion_laws) // If we're an ion law, give it an ion index code
|
||||
laws.Add(ionnum() + ". " + law.law)
|
||||
else
|
||||
laws.Add(num2text(law.get_index()) + ". " + law.law)
|
||||
data["laws"] = laws
|
||||
data["has_laws"] = length(laws)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/aifixer/Topic(href, href_list)
|
||||
/obj/machinery/computer/aifixer/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
switch(action)
|
||||
if("fix")
|
||||
if(active) // Prevent from starting a fix while fixing.
|
||||
to_chat(usr, "<span class='warning'>You are already fixing this AI!</span>")
|
||||
return
|
||||
active = TRUE
|
||||
INVOKE_ASYNC(src, .proc/fix_ai)
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["fix"])
|
||||
active = 1
|
||||
while(occupant.health < 100)
|
||||
occupant.adjustOxyLoss(-1, FALSE)
|
||||
occupant.adjustFireLoss(-1, FALSE)
|
||||
occupant.adjustToxLoss(-1, FALSE)
|
||||
occupant.adjustBruteLoss(-1, FALSE)
|
||||
occupant.updatehealth()
|
||||
if(occupant.health >= 0 && occupant.stat == DEAD)
|
||||
occupant.update_revive()
|
||||
occupant.lying = 0
|
||||
update_icon()
|
||||
sleep(10)
|
||||
active = 0
|
||||
add_fingerprint(usr)
|
||||
if("wireless")
|
||||
occupant.control_disabled = !occupant.control_disabled
|
||||
|
||||
if(href_list["wireless"])
|
||||
var/wireless = text2num(href_list["wireless"])
|
||||
if(wireless == 0 || wireless == 1)
|
||||
occupant.control_disabled = wireless
|
||||
if("radio")
|
||||
occupant.aiRadio.disabledAi = !occupant.aiRadio.disabledAi
|
||||
|
||||
if(href_list["radio"])
|
||||
var/radio = text2num(href_list["radio"])
|
||||
if(radio == 0 || radio == 1)
|
||||
occupant.aiRadio.disabledAi = radio
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
update_icon()
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/fix_ai() // Can we fix it? Probrably.
|
||||
while(occupant.health < 100)
|
||||
occupant.adjustOxyLoss(-1, FALSE)
|
||||
occupant.adjustFireLoss(-1, FALSE)
|
||||
occupant.adjustToxLoss(-1, FALSE)
|
||||
occupant.adjustBruteLoss(-1, FALSE)
|
||||
occupant.updatehealth()
|
||||
if(occupant.health >= 0 && occupant.stat == DEAD)
|
||||
occupant.update_revive()
|
||||
occupant.lying = FALSE
|
||||
update_icon()
|
||||
sleep(10)
|
||||
active = FALSE
|
||||
|
||||
/obj/machinery/computer/aifixer/update_icon()
|
||||
..()
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define MENU_MAIN 1
|
||||
#define MENU_RECORDS 2
|
||||
|
||||
/obj/machinery/computer/cloning
|
||||
name = "cloning console"
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
@@ -6,11 +9,11 @@
|
||||
circuit = /obj/item/circuitboard/cloning
|
||||
req_access = list(ACCESS_HEADS) //Only used for record deletion right now.
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/list/pods = list() //Linked cloning pods.
|
||||
var/temp = ""
|
||||
var/scantemp = "Scanner ready."
|
||||
var/menu = 1 //Which menu screen to display
|
||||
var/list/records = list()
|
||||
var/list/pods = null //Linked cloning pods.
|
||||
var/list/temp = null
|
||||
var/list/scantemp = null
|
||||
var/menu = MENU_MAIN //Which menu screen to display
|
||||
var/list/records = null
|
||||
var/datum/dna2/record/active_record = null
|
||||
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
|
||||
var/loading = 0 // Nice loading text
|
||||
@@ -24,6 +27,9 @@
|
||||
|
||||
/obj/machinery/computer/cloning/Initialize()
|
||||
..()
|
||||
pods = list()
|
||||
records = list()
|
||||
set_scan_temp("Scanner ready.", "good")
|
||||
updatemodules()
|
||||
|
||||
/obj/machinery/computer/cloning/Destroy()
|
||||
@@ -91,7 +97,7 @@
|
||||
W.loc = src
|
||||
src.diskette = W
|
||||
to_chat(user, "You insert [W].")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
else if(istype(W, /obj/item/multitool))
|
||||
var/obj/item/multitool/M = W
|
||||
@@ -117,19 +123,21 @@
|
||||
return
|
||||
|
||||
updatemodules()
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/cloning/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
/obj/machinery/computer/cloning/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
// Set up the Nano UI
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
var/datum/asset/cloning/assets = get_asset_datum(/datum/asset/cloning)
|
||||
assets.send(user)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "cloning_console.tmpl", "Cloning Console UI", 640, 520)
|
||||
ui = new(user, src, ui_key, "CloningConsole", "Cloning Console", 640, 520)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/cloning/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/computer/cloning/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["menu"] = src.menu
|
||||
data["scanner"] = sanitize("[src.scanner]")
|
||||
@@ -143,7 +151,18 @@
|
||||
if(pod.efficiency > 5)
|
||||
canpodautoprocess = 1
|
||||
|
||||
tempods.Add(list(list("pod" = "\ref[pod]", "name" = sanitize(capitalize(pod.name)), "biomass" = pod.biomass)))
|
||||
var/status = "idle"
|
||||
if(pod.mess)
|
||||
status = "mess"
|
||||
else if(pod.occupant && !(pod.stat & NOPOWER))
|
||||
status = "cloning"
|
||||
tempods.Add(list(list(
|
||||
"pod" = "\ref[pod]",
|
||||
"name" = sanitize(capitalize(pod.name)),
|
||||
"biomass" = pod.biomass,
|
||||
"status" = status,
|
||||
"progress" = (pod.occupant && pod.occupant.stat != DEAD) ? pod.get_completion() : 0
|
||||
)))
|
||||
data["pods"] = tempods
|
||||
|
||||
data["loading"] = loading
|
||||
@@ -168,188 +187,190 @@
|
||||
temprecords.Add(list(list("record" = "\ref[R]", "realname" = sanitize(tempRealName))))
|
||||
data["records"] = temprecords
|
||||
|
||||
if(src.menu == 3)
|
||||
if(src.active_record)
|
||||
data["activerecord"] = "\ref[src.active_record]"
|
||||
var/obj/item/implant/health/H = null
|
||||
if(src.active_record.implant)
|
||||
H = locate(src.active_record.implant)
|
||||
if(selected_pod && (selected_pod in pods) && selected_pod.biomass >= CLONE_BIOMASS)
|
||||
data["podready"] = 1
|
||||
else
|
||||
data["podready"] = 0
|
||||
|
||||
if((H) && (istype(H)))
|
||||
data["health"] = H.sensehealth()
|
||||
data["realname"] = sanitize(src.active_record.dna.real_name)
|
||||
data["unidentity"] = src.active_record.dna.uni_identity
|
||||
data["strucenzymes"] = src.active_record.dna.struc_enzymes
|
||||
if(selected_pod && (selected_pod in pods) && selected_pod.biomass >= CLONE_BIOMASS)
|
||||
data["podready"] = 1
|
||||
else
|
||||
data["podready"] = 0
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/cloning/Topic(href, href_list)
|
||||
/obj/machinery/computer/cloning/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(loading)
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(href_list["scan"] && scanner && scanner.occupant)
|
||||
scantemp = "Scanner ready."
|
||||
|
||||
loading = 1
|
||||
|
||||
spawn(20)
|
||||
if(can_brainscan() && scan_mode)
|
||||
scan_mob(scanner.occupant, scan_brain = 1)
|
||||
else
|
||||
scan_mob(scanner.occupant)
|
||||
|
||||
loading = 0
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
if(href_list["task"])
|
||||
switch(href_list["task"])
|
||||
if("autoprocess")
|
||||
autoprocess = 1
|
||||
SSnanoui.update_uis(src)
|
||||
if("stopautoprocess")
|
||||
autoprocess = 0
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
//No locking an open scanner.
|
||||
else if((href_list["lock"]) && (!isnull(src.scanner)))
|
||||
if((!src.scanner.locked) && (src.scanner.occupant))
|
||||
src.scanner.locked = 1
|
||||
else
|
||||
src.scanner.locked = 0
|
||||
|
||||
else if(href_list["view_rec"])
|
||||
src.active_record = locate(href_list["view_rec"])
|
||||
if(istype(src.active_record,/datum/dna2/record))
|
||||
if((isnull(src.active_record.ckey)))
|
||||
qdel(src.active_record)
|
||||
src.temp = "<span class=\"bad\">Error: Record corrupt.</span>"
|
||||
else
|
||||
src.menu = 3
|
||||
else
|
||||
src.active_record = null
|
||||
src.temp = "<span class=\"bad\">Error: Record missing.</span>"
|
||||
|
||||
else if(href_list["del_rec"])
|
||||
if((!src.active_record) || (src.menu < 3))
|
||||
return
|
||||
if(src.menu == 3) //If we are viewing a record, confirm deletion
|
||||
src.temp = "Please confirm that you want to delete the record?"
|
||||
src.menu = 4
|
||||
|
||||
else if(src.menu == 4)
|
||||
var/obj/item/card/id/C = usr.get_active_hand()
|
||||
if(istype(C)||istype(C, /obj/item/pda))
|
||||
if(src.check_access(C))
|
||||
src.records.Remove(src.active_record)
|
||||
qdel(src.active_record)
|
||||
src.temp = "Record deleted."
|
||||
src.menu = 2
|
||||
. = TRUE
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
if(TGUI_MODAL_ANSWER)
|
||||
if(params["id"] == "del_rec" && active_record)
|
||||
var/obj/item/card/id/C = usr.get_active_hand()
|
||||
if(!istype(C) && !istype(C, /obj/item/pda))
|
||||
set_temp("ID not in hand.", "danger")
|
||||
return
|
||||
if(check_access(C))
|
||||
records.Remove(active_record)
|
||||
qdel(active_record)
|
||||
set_temp("Record deleted.", "success")
|
||||
menu = MENU_RECORDS
|
||||
else
|
||||
src.temp = "<span class=\"bad\">Error: Access denied.</span>"
|
||||
|
||||
else if(href_list["disk"]) //Load or eject.
|
||||
switch(href_list["disk"])
|
||||
if("load")
|
||||
if((isnull(src.diskette)) || isnull(src.diskette.buf))
|
||||
src.temp = "<span class=\"bad\">Error: The disk's data could not be read.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
if(isnull(src.active_record))
|
||||
src.temp = "<span class=\"bad\">Error: No active record was found.</span>"
|
||||
src.menu = 1
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
src.active_record = src.diskette.buf.copy()
|
||||
|
||||
src.temp = "Load successful."
|
||||
|
||||
if("eject")
|
||||
if(!isnull(src.diskette))
|
||||
src.diskette.loc = src.loc
|
||||
src.diskette = null
|
||||
|
||||
else if(href_list["save_disk"]) //Save to disk!
|
||||
if((isnull(src.diskette)) || (src.diskette.read_only) || (isnull(src.active_record)))
|
||||
src.temp = "<span class=\"bad\">Error: The data could not be saved.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_temp("Access denied.", "danger")
|
||||
return
|
||||
|
||||
// DNA2 makes things a little simpler.
|
||||
src.diskette.buf=src.active_record.copy()
|
||||
src.diskette.buf.types=0
|
||||
switch(href_list["save_disk"]) //Save as Ui/Ui+Ue/Se
|
||||
if("ui")
|
||||
src.diskette.buf.types=DNA2_BUF_UI
|
||||
if("ue")
|
||||
src.diskette.buf.types=DNA2_BUF_UI|DNA2_BUF_UE
|
||||
if("se")
|
||||
src.diskette.buf.types=DNA2_BUF_SE
|
||||
src.diskette.name = "data disk - '[src.active_record.dna.real_name]'"
|
||||
src.temp = "Save \[[href_list["save_disk"]]\] successful."
|
||||
switch(action)
|
||||
if("scan")
|
||||
if(!scanner || !scanner.occupant || loading)
|
||||
return
|
||||
set_scan_temp("Scanner ready.", "good")
|
||||
loading = TRUE
|
||||
|
||||
else if(href_list["refresh"])
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
else if(href_list["selectpod"])
|
||||
var/obj/machinery/clonepod/selected = locate(href_list["selectpod"])
|
||||
if(istype(selected) && (selected in pods))
|
||||
selected_pod = selected
|
||||
|
||||
else if(href_list["clone"])
|
||||
var/datum/dna2/record/C = locate(href_list["clone"])
|
||||
//Look for that player! They better be dead!
|
||||
if(istype(C))
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!pods.len)
|
||||
temp = "<span class=\"bad\">Error: No cloning pod detected.</span>"
|
||||
else
|
||||
var/obj/machinery/clonepod/pod = selected_pod
|
||||
var/cloneresult
|
||||
if(!selected_pod)
|
||||
temp = "<span class=\"bad\">Error: No cloning pod selected.</span>"
|
||||
else if(pod.occupant)
|
||||
temp = "<span class=\"bad\">Error: The cloning pod is currently occupied.</span>"
|
||||
else if(pod.biomass < CLONE_BIOMASS)
|
||||
temp = "<span class=\"bad\">Error: Not enough biomass.</span>"
|
||||
else if(pod.mess)
|
||||
temp = "<span class=\"bad\">Error: The cloning pod is malfunctioning.</span>"
|
||||
else if(!config.revival_cloning)
|
||||
temp = "<span class=\"bad\">Error: Unable to initiate cloning cycle.</span>"
|
||||
spawn(20)
|
||||
if(can_brainscan() && scan_mode)
|
||||
scan_mob(scanner.occupant, scan_brain = TRUE)
|
||||
else
|
||||
cloneresult = pod.growclone(C)
|
||||
if(cloneresult)
|
||||
if(cloneresult > 0)
|
||||
temp = "Initiating cloning cycle..."
|
||||
records.Remove(C)
|
||||
qdel(C)
|
||||
menu = 1
|
||||
scan_mob(scanner.occupant)
|
||||
loading = FALSE
|
||||
SStgui.update_uis(src)
|
||||
if("autoprocess")
|
||||
autoprocess = text2num(params["on"]) > 0
|
||||
if("lock")
|
||||
if(isnull(scanner) || !scanner.occupant) //No locking an open scanner.
|
||||
return
|
||||
scanner.locked = !scanner.locked
|
||||
if("view_rec")
|
||||
var/ref = params["ref"]
|
||||
if(!length(ref))
|
||||
return
|
||||
active_record = locate(ref)
|
||||
if(istype(active_record))
|
||||
if(isnull(active_record.ckey))
|
||||
qdel(active_record)
|
||||
set_temp("Error: Record corrupt.", "danger")
|
||||
else
|
||||
var/obj/item/implant/health/H = null
|
||||
if(active_record.implant)
|
||||
H = locate(active_record.implant)
|
||||
var/list/payload = list(
|
||||
activerecord = "\ref[active_record]",
|
||||
health = (H && istype(H)) ? H.sensehealth() : "",
|
||||
realname = sanitize(active_record.dna.real_name),
|
||||
unidentity = active_record.dna.uni_identity,
|
||||
strucenzymes = active_record.dna.struc_enzymes,
|
||||
)
|
||||
tgui_modal_message(src, action, "", null, payload)
|
||||
else
|
||||
active_record = null
|
||||
set_temp("Error: Record missing.", "danger")
|
||||
if("del_rec")
|
||||
if(!active_record)
|
||||
return
|
||||
tgui_modal_boolean(src, action, "Please confirm that you want to delete the record by holding your ID and pressing Delete:", yes_text = "Delete", no_text = "Cancel")
|
||||
if("disk") // Disk management.
|
||||
if(!length(params["option"]))
|
||||
return
|
||||
switch(params["option"])
|
||||
if("load")
|
||||
if(isnull(diskette) || isnull(diskette.buf))
|
||||
set_temp("Error: The disk's data could not be read.", "danger")
|
||||
return
|
||||
else if(isnull(active_record))
|
||||
set_temp("Error: No active record was found.", "danger")
|
||||
menu = MENU_MAIN
|
||||
return
|
||||
|
||||
active_record = diskette.buf.copy()
|
||||
set_temp("Successfully loaded from disk.", "success")
|
||||
if("save")
|
||||
if(isnull(diskette) || diskette.read_only || isnull(active_record))
|
||||
set_temp("Error: The data could not be saved.", "danger")
|
||||
return
|
||||
|
||||
// DNA2 makes things a little simpler.
|
||||
var/types
|
||||
switch(params["savetype"]) // Save as Ui/Ui+Ue/Se
|
||||
if("ui")
|
||||
types = DNA2_BUF_UI
|
||||
if("ue")
|
||||
types = DNA2_BUF_UI|DNA2_BUF_UE
|
||||
if("se")
|
||||
types = DNA2_BUF_SE
|
||||
else
|
||||
set_temp("Error: Invalid save format.", "danger")
|
||||
return
|
||||
diskette.buf = active_record.copy()
|
||||
diskette.buf.types = types
|
||||
diskette.name = "data disk - '[active_record.dna.real_name]'"
|
||||
set_temp("Successfully saved to disk.", "success")
|
||||
if("eject")
|
||||
if(!isnull(diskette))
|
||||
diskette.loc = loc
|
||||
diskette = null
|
||||
if("refresh")
|
||||
SStgui.update_uis(src)
|
||||
if("selectpod")
|
||||
var/ref = params["ref"]
|
||||
if(!length(ref))
|
||||
return
|
||||
var/obj/machinery/clonepod/selected = locate(ref)
|
||||
if(istype(selected) && (selected in pods))
|
||||
selected_pod = selected
|
||||
if("clone")
|
||||
var/ref = params["ref"]
|
||||
if(!length(ref))
|
||||
return
|
||||
var/datum/dna2/record/C = locate(ref)
|
||||
//Look for that player! They better be dead!
|
||||
if(istype(C))
|
||||
tgui_modal_clear(src)
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!length(pods))
|
||||
set_temp("Error: No cloning pod detected.", "danger")
|
||||
else
|
||||
var/obj/machinery/clonepod/pod = selected_pod
|
||||
var/cloneresult
|
||||
if(!selected_pod)
|
||||
set_temp("Error: No cloning pod selected.", "danger")
|
||||
else if(pod.occupant)
|
||||
set_temp("Error: The cloning pod is currently occupied.", "danger")
|
||||
else if(pod.biomass < CLONE_BIOMASS)
|
||||
set_temp("Error: Not enough biomass.", "danger")
|
||||
else if(pod.mess)
|
||||
set_temp("Error: The cloning pod is malfunctioning.", "danger")
|
||||
else if(!config.revival_cloning)
|
||||
set_temp("Error: Unable to initiate cloning cycle.", "danger")
|
||||
else
|
||||
temp = "[C.name] => <font class='bad'>Initialisation failure.</font>"
|
||||
|
||||
cloneresult = pod.growclone(C)
|
||||
if(cloneresult)
|
||||
set_temp("Initiating cloning cycle...", "success")
|
||||
records.Remove(C)
|
||||
qdel(C)
|
||||
menu = MENU_MAIN
|
||||
else
|
||||
set_temp("Error: Initialisation failure.", "danger")
|
||||
else
|
||||
set_temp("Error: Data corruption.", "danger")
|
||||
if("menu")
|
||||
menu = clamp(text2num(params["num"]), MENU_MAIN, MENU_RECORDS)
|
||||
if("toggle_mode")
|
||||
if(loading)
|
||||
return
|
||||
if(can_brainscan())
|
||||
scan_mode = !scan_mode
|
||||
else
|
||||
scan_mode = FALSE
|
||||
if("eject")
|
||||
if(usr.incapacitated() || !scanner || loading)
|
||||
return
|
||||
scanner.eject_occupant(usr)
|
||||
scanner.add_fingerprint(usr)
|
||||
if("cleartemp")
|
||||
temp = null
|
||||
else
|
||||
temp = "<span class=\"bad\">Error: Data corruption.</span>"
|
||||
|
||||
else if(href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
temp = ""
|
||||
scantemp = "Scanner ready."
|
||||
else if(href_list["toggle_mode"])
|
||||
if(can_brainscan())
|
||||
scan_mode = !scan_mode
|
||||
else
|
||||
scan_mode = 0
|
||||
return FALSE
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject as mob, var/scan_brain = 0)
|
||||
if(stat & NOPOWER)
|
||||
@@ -360,46 +381,46 @@
|
||||
return
|
||||
if(isnull(subject) || (!(ishuman(subject))) || (!subject.dna))
|
||||
if(isalien(subject))
|
||||
scantemp = "<span class=\"bad\">Error: Xenomorphs are not scannable.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Xenomorphs are not scannable.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
// can add more conditions for specific non-human messages here
|
||||
else
|
||||
scantemp = "<span class=\"bad\">Error: Subject species is not scannable.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject species is not scannable.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if(subject.get_int_organ(/obj/item/organ/internal/brain))
|
||||
var/obj/item/organ/internal/brain/Brn = subject.get_int_organ(/obj/item/organ/internal/brain)
|
||||
if(istype(Brn))
|
||||
if(NO_SCAN in Brn.dna.species.species_traits)
|
||||
scantemp = "<span class=\"bad\">Error: [Brn.dna.species.name_plural] are not scannable.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("[Brn.dna.species.name_plural] are not scannable.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if(!subject.get_int_organ(/obj/item/organ/internal/brain))
|
||||
scantemp = "<span class=\"bad\">Error: No brain detected in subject.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("No brain detected in subject.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if(subject.suiciding)
|
||||
scantemp = "<span class=\"bad\">Error: Subject has committed suicide and is not scannable.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject has committed suicide and is not scannable.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if((!subject.ckey) || (!subject.client))
|
||||
scantemp = "<span class=\"bad\">Error: Subject's brain is not responding. Further attempts after a short delay may succeed.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject's brain is not responding. Further attempts after a short delay may succeed.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if((NOCLONE in subject.mutations) && src.scanner.scan_level < 2)
|
||||
scantemp = "<span class=\"bad\">Error: Subject has incompatible genetic mutations.</span>"
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject has incompatible genetic mutations.", "bad")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if(!isnull(find_record(subject.ckey)))
|
||||
scantemp = "Subject already in database."
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject already in database.")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/clonepod/pod in pods)
|
||||
if(pod.occupant && pod.clonemind == subject.mind)
|
||||
scantemp = "Subject already getting cloned."
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject already getting cloned.")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
subject.dna.check_integrity()
|
||||
@@ -434,8 +455,8 @@
|
||||
R.mind = "\ref[subject.mind]"
|
||||
|
||||
src.records += R
|
||||
scantemp = "Subject successfully scanned. " + extra_info
|
||||
SSnanoui.update_uis(src)
|
||||
set_scan_temp("Subject successfully scanned. [extra_info]", "good")
|
||||
SStgui.update_uis(src)
|
||||
|
||||
//Find a specific record by key.
|
||||
/obj/machinery/computer/cloning/proc/find_record(var/find_key)
|
||||
@@ -451,3 +472,30 @@
|
||||
|
||||
/obj/machinery/computer/cloning/proc/can_brainscan()
|
||||
return (scanner && scanner.scan_level > 3)
|
||||
|
||||
/**
|
||||
* Sets a temporary message to display to the user
|
||||
*
|
||||
* Arguments:
|
||||
* * text - Text to display, null/empty to clear the message from the UI
|
||||
* * style - The style of the message: (color name), info, success, warning, danger
|
||||
*/
|
||||
/obj/machinery/computer/cloning/proc/set_temp(text = "", style = "info", update_now = FALSE)
|
||||
temp = list(text = text, style = style)
|
||||
if(update_now)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/**
|
||||
* Sets a temporary scan message to display to the user
|
||||
*
|
||||
* Arguments:
|
||||
* * text - Text to display, null/empty to clear the message from the UI
|
||||
* * color - The color of the message: (color name)
|
||||
*/
|
||||
/obj/machinery/computer/cloning/proc/set_scan_temp(text = "", color = "", update_now = FALSE)
|
||||
scantemp = list(text = text, color = color)
|
||||
if(update_now)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
#undef MENU_MAIN
|
||||
#undef MENU_RECORDS
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
#define COMM_SCREEN_MAIN 1
|
||||
#define COMM_SCREEN_STAT 2
|
||||
#define COMM_SCREEN_MESSAGES 3
|
||||
#define COMM_SCREEN_SECLEVEL 4
|
||||
|
||||
#define COMM_AUTHENTICATION_NONE 0
|
||||
#define COMM_AUTHENTICATION_MIN 1
|
||||
#define COMM_AUTHENTICATION_MAX 2
|
||||
|
||||
#define COMM_MSGLEN_MINIMUM 6
|
||||
#define COMM_CCMSGLEN_MINIMUM 20
|
||||
|
||||
// The communications computer
|
||||
/obj/machinery/computer/communications
|
||||
name = "communications console"
|
||||
desc = "This can be used for various important functions. Still under developement."
|
||||
desc = "This allows the Captain to contact Central Command, or change the alert level. It also allows the command staff to call the Escape Shuttle."
|
||||
icon_keyboard = "tech_key"
|
||||
icon_screen = "comm"
|
||||
req_access = list(ACCESS_HEADS)
|
||||
circuit = /obj/item/circuitboard/communications
|
||||
var/prints_intercept = 1
|
||||
var/authenticated = COMM_AUTHENTICATION_NONE
|
||||
var/list/messagetitle = list()
|
||||
var/list/messagetext = list()
|
||||
var/currmsg = 0
|
||||
var/aicurrmsg = 0
|
||||
var/currmsg
|
||||
|
||||
var/authenticated = COMM_AUTHENTICATION_NONE
|
||||
var/menu_state = COMM_SCREEN_MAIN
|
||||
var/ai_menu_state = COMM_SCREEN_MAIN
|
||||
var/message_cooldown = 0
|
||||
var/centcomm_message_cooldown = 0
|
||||
var/aicurrmsg
|
||||
|
||||
var/message_cooldown
|
||||
var/centcomm_message_cooldown
|
||||
var/tmp_alertlevel = 0
|
||||
|
||||
var/stat_msg1
|
||||
var/stat_msg2
|
||||
var/display_type="blank"
|
||||
var/display_type = "blank"
|
||||
var/display_icon
|
||||
|
||||
var/datum/announcement/priority/crew_announcement = new
|
||||
|
||||
@@ -70,123 +74,113 @@
|
||||
feedback_inc("alert_comms_blue",1)
|
||||
tmp_alertlevel = 0
|
||||
|
||||
/obj/machinery/computer/communications/Topic(href, href_list)
|
||||
if(..(href, href_list))
|
||||
return 1
|
||||
|
||||
if(!is_secure_level(src.z))
|
||||
/obj/machinery/computer/communications/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!is_secure_level(z))
|
||||
to_chat(usr, "<span class='warning'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["login"])
|
||||
. = TRUE
|
||||
|
||||
if(action == "auth")
|
||||
if(!ishuman(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return FALSE
|
||||
// Logout function.
|
||||
if(authenticated != COMM_AUTHENTICATION_NONE)
|
||||
authenticated = COMM_AUTHENTICATION_NONE
|
||||
crew_announcement.announcer = null
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
return
|
||||
|
||||
// Login function.
|
||||
var/list/access = usr.get_access()
|
||||
if(allowed(usr))
|
||||
authenticated = COMM_AUTHENTICATION_MIN
|
||||
|
||||
if(ACCESS_CAPTAIN in access)
|
||||
authenticated = COMM_AUTHENTICATION_MAX
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/obj/item/card/id = H.get_idcard(TRUE)
|
||||
if(istype(id))
|
||||
crew_announcement.announcer = GetNameAndAssignmentFromId(id)
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
if(href_list["logout"])
|
||||
authenticated = COMM_AUTHENTICATION_NONE
|
||||
crew_announcement.announcer = ""
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
SSnanoui.update_uis(src)
|
||||
if(authenticated == COMM_AUTHENTICATION_NONE)
|
||||
to_chat(usr, "<span class='warning'>You need to wear your ID.</span>")
|
||||
return
|
||||
|
||||
// All functions below this point require authentication.
|
||||
if(!is_authenticated(usr))
|
||||
return 1
|
||||
return FALSE
|
||||
|
||||
switch(href_list["operation"])
|
||||
switch(action)
|
||||
if("main")
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
|
||||
if("changeseclevel")
|
||||
setMenuState(usr,COMM_SCREEN_SECLEVEL)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("newalertlevel")
|
||||
if(isAI(usr) || isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>Firewalls prevent you from changing the alert level.</span>")
|
||||
return 1
|
||||
return
|
||||
else if(usr.can_admin_interact())
|
||||
change_security_level(text2num(href_list["level"]))
|
||||
return 1
|
||||
change_security_level(text2num(params["level"]))
|
||||
return
|
||||
else if(!ishuman(usr))
|
||||
to_chat(usr, "<span class='warning'>Security measures prevent you from changing the alert level.</span>")
|
||||
return 1
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/L = usr
|
||||
var/obj/item/card = L.get_active_hand()
|
||||
var/obj/item/card/id/I = (card && card.GetID()) || L.wear_id || L.wear_pda
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/pda = I
|
||||
I = pda.id
|
||||
if(I && istype(I))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/obj/item/card/id/I = H.get_idcard(TRUE)
|
||||
if(istype(I))
|
||||
if(ACCESS_CAPTAIN in I.access)
|
||||
change_security_level(text2num(href_list["level"]))
|
||||
change_security_level(text2num(params["level"]))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You are not authorized to do this.</span>")
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You need to swipe your ID.</span>")
|
||||
to_chat(usr, "<span class='warning'>You need to wear your ID.</span>")
|
||||
|
||||
if("announce")
|
||||
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||
if(message_cooldown)
|
||||
if(message_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Please allow at least one minute to pass between announcements.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement")
|
||||
if(!input || message_cooldown || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
if(!input || message_cooldown > world.time || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
return
|
||||
if(length(input) < COMM_MSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
crew_announcement.Announce(input)
|
||||
message_cooldown = 1
|
||||
spawn(600)//One minute cooldown
|
||||
message_cooldown = 0
|
||||
message_cooldown = world.time + 600 //One minute
|
||||
|
||||
if("callshuttle")
|
||||
var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","")
|
||||
if(!input || ..() || !is_authenticated(usr))
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
call_shuttle_proc(usr, input)
|
||||
if(SSshuttle.emergency.timer)
|
||||
post_status("shuttle")
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("cancelshuttle")
|
||||
if(isAI(usr) || isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>Firewalls prevent you from recalling the shuttle.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
return
|
||||
var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No")
|
||||
if(response == "Yes")
|
||||
cancel_call_proc(usr)
|
||||
if(SSshuttle.emergency.timer)
|
||||
post_status("shuttle")
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("messagelist")
|
||||
currmsg = 0
|
||||
if(href_list["msgid"])
|
||||
setCurrentMessage(usr, text2num(href_list["msgid"]))
|
||||
setMenuState(usr,COMM_SCREEN_MESSAGES)
|
||||
currmsg = null
|
||||
aicurrmsg = null
|
||||
if(params["msgid"])
|
||||
setCurrentMessage(usr, text2num(params["msgid"]))
|
||||
setMenuState(usr, COMM_SCREEN_MESSAGES)
|
||||
|
||||
if("delmessage")
|
||||
if(href_list["msgid"])
|
||||
currmsg = text2num(href_list["msgid"])
|
||||
if(params["msgid"])
|
||||
currmsg = text2num(params["msgid"])
|
||||
var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No")
|
||||
if(response == "Yes")
|
||||
if(currmsg)
|
||||
@@ -196,95 +190,95 @@
|
||||
messagetitle.Remove(title)
|
||||
messagetext.Remove(text)
|
||||
if(currmsg == id)
|
||||
currmsg = 0
|
||||
currmsg = null
|
||||
if(aicurrmsg == id)
|
||||
aicurrmsg = 0
|
||||
setMenuState(usr,COMM_SCREEN_MESSAGES)
|
||||
aicurrmsg = null
|
||||
setMenuState(usr, COMM_SCREEN_MESSAGES)
|
||||
|
||||
if("status")
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
// Status display stuff
|
||||
if("setstat")
|
||||
display_type=href_list["statdisp"]
|
||||
display_type = params["statdisp"]
|
||||
switch(display_type)
|
||||
if("message")
|
||||
display_icon = null
|
||||
post_status("message", stat_msg1, stat_msg2, usr)
|
||||
if("alert")
|
||||
post_status("alert", href_list["alert"], user = usr)
|
||||
display_icon = params["alert"]
|
||||
post_status("alert", params["alert"], user = usr)
|
||||
else
|
||||
post_status(href_list["statdisp"], user = usr)
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
display_icon = null
|
||||
post_status(params["statdisp"], user = usr)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg1")
|
||||
stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1)
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg2")
|
||||
stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2)
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
if("nukerequest")
|
||||
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||
if(centcomm_message_cooldown)
|
||||
if(centcomm_message_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","")
|
||||
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
Nuke_request(input, usr)
|
||||
to_chat(usr, "<span class='notice'>Request sent.</span>")
|
||||
log_game("[key_name(usr)] has requested the nuclear codes from Centcomm")
|
||||
GLOB.priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg')
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(6000)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
centcomm_message_cooldown = world.time + 6000 // 10 minutes
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("MessageCentcomm")
|
||||
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||
if(centcomm_message_cooldown)
|
||||
if(centcomm_message_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
Centcomm_announce(input, usr)
|
||||
print_centcom_report(input, station_time_timestamp() + " Captain's Message")
|
||||
to_chat(usr, "Message transmitted.")
|
||||
log_game("[key_name(usr)] has made a Centcomm announcement: [input]")
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(6000)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
centcomm_message_cooldown = world.time + 6000 // 10 minutes
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
// OMG SYNDICATE ...LETTERHEAD
|
||||
if("MessageSyndicate")
|
||||
if((is_authenticated(usr) == COMM_AUTHENTICATION_MAX) && (src.emagged))
|
||||
if(centcomm_message_cooldown)
|
||||
if(centcomm_message_cooldown > world.time)
|
||||
to_chat(usr, "Arrays recycling. Please stand by.")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
Syndicate_announce(input, usr)
|
||||
to_chat(usr, "Message transmitted.")
|
||||
log_game("[key_name(usr)] has made a Syndicate announcement: [input]")
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(6000)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
centcomm_message_cooldown = world.time + 6000 // 10 minutes
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("RestoreBackup")
|
||||
to_chat(usr, "Backup routing data restored!")
|
||||
src.emagged = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("RestartNanoMob")
|
||||
if(SSmob_hunt)
|
||||
@@ -298,14 +292,13 @@
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.</span>")
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer/communications/emag_act(user as mob)
|
||||
if(!emagged)
|
||||
src.emagged = 1
|
||||
to_chat(user, "<span class='notice'>You scramble the communication routing circuits!</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/computer/communications/attack_ai(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
@@ -321,28 +314,25 @@
|
||||
to_chat(user, "<span class='warning'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/communications/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui)
|
||||
/obj/machinery/computer/communications/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "comm_console.tmpl", "Communications Console", 400, 500)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "CommunicationsComputer", name, 500, 600, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/communications/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
/obj/machinery/computer/communications/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["is_ai"] = isAI(user) || isrobot(user)
|
||||
data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state
|
||||
data["emagged"] = emagged
|
||||
data["authenticated"] = is_authenticated(user, 0)
|
||||
data["screen"] = getMenuState(usr)
|
||||
data["authmax"] = data["authenticated"] == COMM_AUTHENTICATION_MAX ? TRUE : FALSE
|
||||
|
||||
data["stat_display"] = list(
|
||||
"type" = display_type,
|
||||
"icon" = display_icon,
|
||||
"line_1" = (stat_msg1 ? stat_msg1 : "-----"),
|
||||
"line_2" = (stat_msg2 ? stat_msg2 : "-----"),
|
||||
|
||||
@@ -360,12 +350,20 @@
|
||||
)
|
||||
)
|
||||
|
||||
data["security_level"] = GLOB.security_level
|
||||
data["security_level"] = GLOB.security_level
|
||||
switch(GLOB.security_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
data["security_level_color"] = "green";
|
||||
if(SEC_LEVEL_BLUE)
|
||||
data["security_level_color"] = "blue";
|
||||
if(SEC_LEVEL_RED)
|
||||
data["security_level_color"] = "red";
|
||||
else
|
||||
data["security_level_color"] = "purple";
|
||||
data["str_security_level"] = capitalize(get_security_level())
|
||||
data["levels"] = list(
|
||||
list("id" = SEC_LEVEL_GREEN, "name" = "Green"),
|
||||
list("id" = SEC_LEVEL_BLUE, "name" = "Blue"),
|
||||
//SEC_LEVEL_RED = list("name"="Red"),
|
||||
list("id" = SEC_LEVEL_GREEN, "name" = "Green", "icon" = "dove"),
|
||||
list("id" = SEC_LEVEL_BLUE, "name" = "Blue", "icon" = "eye"),
|
||||
)
|
||||
|
||||
var/list/msg_data = list()
|
||||
@@ -373,27 +371,30 @@
|
||||
msg_data.Add(list(list("title" = messagetitle[i], "body" = messagetext[i], "id" = i)))
|
||||
|
||||
data["messages"] = msg_data
|
||||
|
||||
data["current_message"] = null
|
||||
data["current_message_title"] = null
|
||||
if((data["is_ai"] && aicurrmsg) || (!data["is_ai"] && currmsg))
|
||||
data["current_message"] = data["is_ai"] ? messagetext[aicurrmsg] : messagetext[currmsg]
|
||||
data["current_message_title"] = data["is_ai"] ? messagetitle[aicurrmsg] : messagetitle[currmsg]
|
||||
|
||||
data["lastCallLoc"] = SSshuttle.emergencyLastCallLoc ? format_text(SSshuttle.emergencyLastCallLoc.name) : null
|
||||
data["msg_cooldown"] = message_cooldown ? (round((message_cooldown - world.time) / 10)) : 0
|
||||
data["cc_cooldown"] = centcomm_message_cooldown ? (round((centcomm_message_cooldown - world.time) / 10)) : 0
|
||||
|
||||
var/shuttle[0]
|
||||
switch(SSshuttle.emergency.mode)
|
||||
if(SHUTTLE_IDLE, SHUTTLE_RECALL)
|
||||
shuttle["callStatus"] = 2 //#define
|
||||
else
|
||||
shuttle["callStatus"] = 1
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/secondsToRefuel = SSshuttle.secondsToRefuel()
|
||||
data["esc_callable"] = SSshuttle.emergency.mode == SHUTTLE_IDLE && !secondsToRefuel ? TRUE : FALSE
|
||||
data["esc_recallable"] = SSshuttle.emergency.mode == SHUTTLE_CALL ? TRUE : FALSE
|
||||
data["esc_status"] = FALSE
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||
var/timeleft = SSshuttle.emergency.timeLeft()
|
||||
shuttle["eta"] = "[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
|
||||
data["shuttle"] = shuttle
|
||||
|
||||
data["esc_status"] = SSshuttle.emergency.mode == SHUTTLE_CALL ? "ETA:" : "RECALLING:"
|
||||
data["esc_status"] += " [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
else if(secondsToRefuel)
|
||||
data["esc_status"] = "Refueling: [secondsToRefuel / 60 % 60]:[add_zero(num2text(secondsToRefuel % 60), 2)]"
|
||||
data["esc_section"] = data["esc_status"] || data["esc_callable"] || data["esc_recallable"] || data["lastCallLoc"]
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/computer/communications/proc/setCurrentMessage(var/mob/user,var/value)
|
||||
if(isAI(user) || isrobot(user))
|
||||
aicurrmsg = value
|
||||
@@ -412,12 +413,6 @@
|
||||
else
|
||||
menu_state=value
|
||||
|
||||
/obj/machinery/computer/communications/proc/getMenuState(var/mob/user)
|
||||
if(isAI(user) || isrobot(user))
|
||||
return ai_menu_state
|
||||
else
|
||||
return menu_state
|
||||
|
||||
/proc/call_shuttle_proc(var/mob/user, var/reason)
|
||||
if(GLOB.sent_strike_team == 1)
|
||||
to_chat(user, "<span class='warning'>Central Command will not allow the shuttle to be called. Consider all contracts terminated.</span>")
|
||||
@@ -521,24 +516,16 @@
|
||||
SSshuttle.autoEvac()
|
||||
return ..()
|
||||
|
||||
/proc/print_command_report(text = "", title = "Central Command Update")
|
||||
/proc/print_command_report(text = "", title = "Central Command Update", add_to_records = TRUE)
|
||||
for(var/obj/machinery/computer/communications/C in GLOB.shuttle_caller_list)
|
||||
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_contact(C.z))
|
||||
var/obj/item/paper/P = new /obj/item/paper(C.loc)
|
||||
P.name = "paper- '[title]'"
|
||||
P.info = text
|
||||
P.update_icon()
|
||||
C.messagetitle.Add("[title]")
|
||||
C.messagetext.Add(text)
|
||||
for(var/datum/computer_file/program/comm/P in GLOB.shuttle_caller_list)
|
||||
var/turf/T = get_turf(P.computer)
|
||||
if(T && P.program_state != PROGRAM_STATE_KILLED && is_station_contact(T.z))
|
||||
if(P.computer)
|
||||
var/obj/item/computer_hardware/printer/printer = P.computer.all_components[MC_PRINT]
|
||||
if(printer)
|
||||
printer.print_text(text, "paper- '[title]'")
|
||||
P.messagetitle.Add("[title]")
|
||||
P.messagetext.Add(text)
|
||||
if(add_to_records)
|
||||
C.messagetitle.Add("[title]")
|
||||
C.messagetext.Add(text)
|
||||
|
||||
/proc/print_centcom_report(text = "", title = "Incoming Message")
|
||||
for(var/obj/machinery/computer/communications/C in GLOB.shuttle_caller_list)
|
||||
@@ -549,12 +536,5 @@
|
||||
P.update_icon()
|
||||
C.messagetitle.Add("[title]")
|
||||
C.messagetext.Add(text)
|
||||
for(var/datum/computer_file/program/comm/P in GLOB.shuttle_caller_list)
|
||||
var/turf/T = get_turf(P.computer)
|
||||
if(T && P.program_state != PROGRAM_STATE_KILLED && is_admin_level(T.z))
|
||||
if(P.computer)
|
||||
var/obj/item/computer_hardware/printer/printer = P.computer.all_components[MC_PRINT]
|
||||
if(printer)
|
||||
printer.print_text(text, "paper- '[title]'")
|
||||
P.messagetitle.Add("[title]")
|
||||
P.messagetext.Add(text)
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#define MED_DATA_MAIN 1 // Main menu
|
||||
#define MED_DATA_R_LIST 2 // Record list
|
||||
#define MED_DATA_MAINT 3 // Records maintenance
|
||||
#define MED_DATA_RECORD 4 // Record
|
||||
#define MED_DATA_V_DATA 5 // Virus database
|
||||
#define MED_DATA_MEDBOT 6 // Medbot monitor
|
||||
|
||||
#define FIELD(N, V, E) list(field = N, value = V, edit = E)
|
||||
#define MED_FIELD(N, V, E, LB) list(field = N, value = V, edit = E, line_break = LB)
|
||||
|
||||
/obj/machinery/computer/med_data //TODO:SANITY
|
||||
name = "medical records console"
|
||||
desc = "This can be used to check medical records."
|
||||
@@ -18,11 +20,45 @@
|
||||
var/screen = null
|
||||
var/datum/data/record/active1 = null
|
||||
var/datum/data/record/active2 = null
|
||||
var/temp = null
|
||||
var/list/temp = null
|
||||
var/printing = null
|
||||
// The below are used to make modal generation more convenient
|
||||
var/static/list/field_edit_questions
|
||||
var/static/list/field_edit_choices
|
||||
|
||||
light_color = LIGHT_COLOR_DARKBLUE
|
||||
|
||||
/obj/machinery/computer/med_data/Initialize()
|
||||
..()
|
||||
field_edit_questions = list(
|
||||
// General
|
||||
"sex" = "Please select new sex:",
|
||||
"age" = "Please input new age:",
|
||||
"fingerprint" = "Please input new fingerprint hash:",
|
||||
"p_stat" = "Please select new physical status:",
|
||||
"m_stat" = "Please select new mental status:",
|
||||
// Medical
|
||||
"blood_type" = "Please select new blood type:",
|
||||
"b_dna" = "Please input new DNA:",
|
||||
"mi_dis" = "Please input new minor disabilities:",
|
||||
"mi_dis_d" = "Please summarize minor disabilities:",
|
||||
"ma_dis" = "Please input new major disabilities:",
|
||||
"ma_dis_d" = "Please summarize major disabilities:",
|
||||
"alg" = "Please input new allergies:",
|
||||
"alg_d" = "Please summarize allergies:",
|
||||
"cdi" = "Please input new current diseases:",
|
||||
"cdi_d" = "Please summarize current diseases:",
|
||||
"notes" = "Please input new important notes:",
|
||||
)
|
||||
field_edit_choices = list(
|
||||
// General
|
||||
"sex" = list("Male", "Female"),
|
||||
"p_stat" = list("*Deceased*", "*SSD*", "Active", "Physically Unfit", "Disabled"),
|
||||
"m_stat" = list("*Insane*", "*Unstable*", "*Watch*", "Stable"),
|
||||
// Medical
|
||||
"blood_type" = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"),
|
||||
)
|
||||
|
||||
/obj/machinery/computer/med_data/Destroy()
|
||||
active1 = null
|
||||
active2 = null
|
||||
@@ -33,7 +69,7 @@
|
||||
usr.drop_item()
|
||||
O.forceMove(src)
|
||||
scan = O
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -44,20 +80,25 @@
|
||||
to_chat(user, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
|
||||
return
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/med_data/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/med_data/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "med_data.tmpl", name, 800, 380)
|
||||
ui = new(user, src, ui_key, "MedicalRecords", "Medical Records", 800, 380, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_autoupdate(FALSE)
|
||||
|
||||
/obj/machinery/computer/med_data/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/computer/med_data/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["temp"] = temp
|
||||
data["scan"] = scan ? scan.name : null
|
||||
data["authenticated"] = authenticated
|
||||
data["rank"] = rank
|
||||
data["screen"] = screen
|
||||
data["printing"] = printing
|
||||
data["isAI"] = isAI(user)
|
||||
data["isRobot"] = isrobot(user)
|
||||
if(authenticated)
|
||||
switch(screen)
|
||||
if(MED_DATA_R_LIST)
|
||||
@@ -72,17 +113,17 @@
|
||||
if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))
|
||||
var/list/fields = list()
|
||||
general["fields"] = fields
|
||||
fields[++fields.len] = list("field" = "Name:", "value" = active1.fields["name"], "edit" = null)
|
||||
fields[++fields.len] = list("field" = "ID:", "value" = active1.fields["id"], "edit" = null)
|
||||
fields[++fields.len] = list("field" = "Sex:", "value" = active1.fields["sex"], "edit" = "sex")
|
||||
fields[++fields.len] = list("field" = "Age:", "value" = active1.fields["age"], "edit" = "age")
|
||||
fields[++fields.len] = list("field" = "Fingerprint:", "value" = active1.fields["fingerprint"], "edit" = "fingerprint")
|
||||
fields[++fields.len] = list("field" = "Physical Status:", "value" = active1.fields["p_stat"], "edit" = "p_stat")
|
||||
fields[++fields.len] = list("field" = "Mental Status:", "value" = active1.fields["m_stat"], "edit" = "m_stat")
|
||||
fields[++fields.len] = FIELD("Name", active1.fields["name"], null)
|
||||
fields[++fields.len] = FIELD("ID", active1.fields["id"], null)
|
||||
fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex")
|
||||
fields[++fields.len] = FIELD("Age", active1.fields["age"], "age")
|
||||
fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint")
|
||||
fields[++fields.len] = FIELD("Physical Status", active1.fields["p_stat"], "p_stat")
|
||||
fields[++fields.len] = FIELD("Mental Status", active1.fields["m_stat"], "m_stat")
|
||||
var/list/photos = list()
|
||||
general["photos"] = photos
|
||||
photos[++photos.len] = list("photo" = active1.fields["photo-south"])
|
||||
photos[++photos.len] = list("photo" = active1.fields["photo-west"])
|
||||
photos[++photos.len] = active1.fields["photo-south"]
|
||||
photos[++photos.len] = active1.fields["photo-west"]
|
||||
general["has_photos"] = (active1.fields["photo-south"] || active1.fields["photo-west"] ? 1 : 0)
|
||||
general["empty"] = 0
|
||||
else
|
||||
@@ -93,17 +134,17 @@
|
||||
if(istype(active2, /datum/data/record) && GLOB.data_core.medical.Find(active2))
|
||||
var/list/fields = list()
|
||||
medical["fields"] = fields
|
||||
fields[++fields.len] = list("field" = "Blood Type:", "value" = active2.fields["blood_type"], "edit" = "blood_type", "line_break" = 0)
|
||||
fields[++fields.len] = list("field" = "DNA:", "value" = active2.fields["b_dna"], "edit" = "b_dna", "line_break" = 1)
|
||||
fields[++fields.len] = list("field" = "Minor Disabilities:", "value" = active2.fields["mi_dis"], "edit" = "mi_dis", "line_break" = 0)
|
||||
fields[++fields.len] = list("field" = "Details:", "value" = active2.fields["mi_dis_d"], "edit" = "mi_dis_d", "line_break" = 1)
|
||||
fields[++fields.len] = list("field" = "Major Disabilities:", "value" = active2.fields["ma_dis"], "edit" = "ma_dis", "line_break" = 0)
|
||||
fields[++fields.len] = list("field" = "Details:", "value" = active2.fields["ma_dis_d"], "edit" = "ma_dis_d", "line_break" = 1)
|
||||
fields[++fields.len] = list("field" = "Allergies:", "value" = active2.fields["alg"], "edit" = "alg", "line_break" = 0)
|
||||
fields[++fields.len] = list("field" = "Details:", "value" = active2.fields["alg_d"], "edit" = "alg_d", "line_break" = 1)
|
||||
fields[++fields.len] = list("field" = "Current Diseases:", "value" = active2.fields["cdi"], "edit" = "cdi", "line_break" = 0)
|
||||
fields[++fields.len] = list("field" = "Details:", "value" = active2.fields["cdi_d"], "edit" = "cdi_d", "line_break" = 1)
|
||||
fields[++fields.len] = list("field" = "Important Notes:", "value" = active2.fields["notes"], "edit" = "notes", "line_break" = 0)
|
||||
fields[++fields.len] = MED_FIELD("Blood Type", active2.fields["blood_type"], "blood_type", FALSE)
|
||||
fields[++fields.len] = MED_FIELD("DNA", active2.fields["b_dna"], "b_dna", TRUE)
|
||||
fields[++fields.len] = MED_FIELD("Minor Disabilities", active2.fields["mi_dis"], "mi_dis", FALSE)
|
||||
fields[++fields.len] = MED_FIELD("Details", active2.fields["mi_dis_d"], "mi_dis_d", TRUE)
|
||||
fields[++fields.len] = MED_FIELD("Major Disabilities", active2.fields["ma_dis"], "ma_dis", FALSE)
|
||||
fields[++fields.len] = MED_FIELD("Details", active2.fields["ma_dis_d"], "ma_dis_d", TRUE)
|
||||
fields[++fields.len] = MED_FIELD("Allergies", active2.fields["alg"], "alg", FALSE)
|
||||
fields[++fields.len] = MED_FIELD("Details", active2.fields["alg_d"], "alg_d", TRUE)
|
||||
fields[++fields.len] = MED_FIELD("Current Diseases", active2.fields["cdi"], "cdi", FALSE)
|
||||
fields[++fields.len] = MED_FIELD("Details", active2.fields["cdi_d"], "cdi_d", TRUE)
|
||||
fields[++fields.len] = MED_FIELD("Important Notes", active2.fields["notes"], "notes", TRUE)
|
||||
if(!active2.fields["comments"] || !islist(active2.fields["comments"]))
|
||||
active2.fields["comments"] = list()
|
||||
medical["comments"] = active2.fields["comments"]
|
||||
@@ -127,7 +168,9 @@
|
||||
var/turf/T = get_turf(M)
|
||||
if(T)
|
||||
var/medbot = list()
|
||||
var/area/A = get_area(T)
|
||||
medbot["name"] = M.name
|
||||
medbot["area"] = A.name
|
||||
medbot["x"] = T.x
|
||||
medbot["y"] = T.y
|
||||
medbot["on"] = M.on
|
||||
@@ -138,395 +181,290 @@
|
||||
else
|
||||
medbot["use_beaker"] = 0
|
||||
data["medbots"] += list(medbot)
|
||||
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/med_data/Topic(href, href_list)
|
||||
/obj/machinery/computer/med_data/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(!GLOB.data_core.general.Find(active1))
|
||||
active1 = null
|
||||
if(!GLOB.data_core.medical.Find(active2))
|
||||
active2 = null
|
||||
|
||||
if(href_list["temp"])
|
||||
temp = null
|
||||
. = TRUE
|
||||
if(tgui_act_modal(action, params))
|
||||
return
|
||||
|
||||
if(href_list["temp_action"])
|
||||
if(href_list["temp_action"])
|
||||
var/temp_href = splittext(href_list["temp_action"], "=")
|
||||
switch(temp_href[1])
|
||||
if("del_all2")
|
||||
for(var/datum/data/record/R in GLOB.data_core.medical)
|
||||
qdel(R)
|
||||
setTemp("<h3>All records deleted.</h3>")
|
||||
if("p_stat")
|
||||
if(active1)
|
||||
switch(temp_href[2])
|
||||
if("deceased")
|
||||
active1.fields["p_stat"] = "*Deceased*"
|
||||
if("ssd")
|
||||
active1.fields["p_stat"] = "*SSD*"
|
||||
if("active")
|
||||
active1.fields["p_stat"] = "Active"
|
||||
if("unfit")
|
||||
active1.fields["p_stat"] = "Physically Unfit"
|
||||
if("disabled")
|
||||
active1.fields["p_stat"] = "Disabled"
|
||||
if("m_stat")
|
||||
if(active1)
|
||||
switch(temp_href[2])
|
||||
if("insane")
|
||||
active1.fields["m_stat"] = "*Insane*"
|
||||
if("unstable")
|
||||
active1.fields["m_stat"] = "*Unstable*"
|
||||
if("watch")
|
||||
active1.fields["m_stat"] = "*Watch*"
|
||||
if("stable")
|
||||
active1.fields["m_stat"] = "Stable"
|
||||
if("blood_type")
|
||||
if(active2)
|
||||
switch(temp_href[2])
|
||||
if("an")
|
||||
active2.fields["blood_type"] = "A-"
|
||||
if("bn")
|
||||
active2.fields["blood_type"] = "B-"
|
||||
if("abn")
|
||||
active2.fields["blood_type"] = "AB-"
|
||||
if("on")
|
||||
active2.fields["blood_type"] = "O-"
|
||||
if("ap")
|
||||
active2.fields["blood_type"] = "A+"
|
||||
if("bp")
|
||||
active2.fields["blood_type"] = "B+"
|
||||
if("abp")
|
||||
active2.fields["blood_type"] = "AB+"
|
||||
if("op")
|
||||
active2.fields["blood_type"] = "O+"
|
||||
if("del_r2")
|
||||
QDEL_NULL(active2)
|
||||
|
||||
if(href_list["scan"])
|
||||
if(scan)
|
||||
scan.forceMove(loc)
|
||||
if(ishuman(usr) && !usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
switch(action)
|
||||
if("cleartemp")
|
||||
temp = null
|
||||
if("scan")
|
||||
if(scan)
|
||||
scan.forceMove(loc)
|
||||
if(ishuman(usr) && !usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/card/id))
|
||||
usr.drop_item()
|
||||
I.forceMove(src)
|
||||
scan = I
|
||||
if("login")
|
||||
var/login_type = text2num(params["login_type"])
|
||||
if(login_type == LOGIN_TYPE_NORMAL && istype(scan))
|
||||
if(check_access(scan))
|
||||
authenticated = scan.registered_name
|
||||
rank = scan.assignment
|
||||
else if(login_type == LOGIN_TYPE_AI && isAI(usr))
|
||||
authenticated = usr.name
|
||||
rank = "AI"
|
||||
else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr))
|
||||
authenticated = usr.name
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
rank = "[R.modtype] [R.braintype]"
|
||||
if(authenticated)
|
||||
active1 = null
|
||||
active2 = null
|
||||
screen = MED_DATA_R_LIST
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/card/id))
|
||||
usr.drop_item()
|
||||
I.forceMove(src)
|
||||
scan = I
|
||||
. = FALSE
|
||||
|
||||
if(href_list["login"])
|
||||
if(isAI(usr))
|
||||
authenticated = usr.name
|
||||
rank = "AI"
|
||||
else if(isrobot(usr))
|
||||
authenticated = usr.name
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
rank = "[R.modtype] [R.braintype]"
|
||||
else if(istype(scan, /obj/item/card/id))
|
||||
if(check_access(scan))
|
||||
authenticated = scan.registered_name
|
||||
rank = scan.assignment
|
||||
|
||||
if(authenticated)
|
||||
active1 = null
|
||||
active2 = null
|
||||
screen = MED_DATA_MAIN
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(authenticated)
|
||||
if(href_list["logout"])
|
||||
authenticated = null
|
||||
screen = null
|
||||
active1 = null
|
||||
active2 = null
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("logout")
|
||||
if(scan)
|
||||
scan.forceMove(loc)
|
||||
if(ishuman(usr) && !usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
authenticated = null
|
||||
screen = null
|
||||
active1 = null
|
||||
active2 = null
|
||||
if("screen")
|
||||
screen = clamp(text2num(params["screen"]) || 0, MED_DATA_R_LIST, MED_DATA_MEDBOT)
|
||||
active1 = null
|
||||
active2 = null
|
||||
if("vir")
|
||||
var/type = text2path(params["vir"] || "")
|
||||
if(!ispath(type, /datum/disease))
|
||||
return
|
||||
|
||||
if(href_list["screen"])
|
||||
screen = text2num(href_list["screen"])
|
||||
if(screen < 1)
|
||||
screen = MED_DATA_MAIN
|
||||
var/datum/disease/D = new type(0)
|
||||
var/list/payload = list(
|
||||
name = D.name,
|
||||
max_stages = D.max_stages,
|
||||
spread_text = D.spread_text,
|
||||
cure = D.cure_text || "None",
|
||||
desc = D.desc,
|
||||
severity = D.severity
|
||||
);
|
||||
tgui_modal_message(src, "virus", "", null, payload)
|
||||
qdel(D)
|
||||
if("del_all")
|
||||
for(var/datum/data/record/R in GLOB.data_core.medical)
|
||||
qdel(R)
|
||||
set_temp("All medical records deleted.")
|
||||
if("del_r")
|
||||
if(active2)
|
||||
set_temp("Medical record deleted.")
|
||||
qdel(active2)
|
||||
if("d_rec")
|
||||
var/datum/data/record/general_record = locate(params["d_rec"] || "")
|
||||
if(!GLOB.data_core.general.Find(general_record))
|
||||
set_temp("Record not found.", "danger")
|
||||
return
|
||||
|
||||
active1 = null
|
||||
active2 = null
|
||||
var/datum/data/record/medical_record
|
||||
for(var/datum/data/record/M in GLOB.data_core.medical)
|
||||
if(M.fields["name"] == general_record.fields["name"] && M.fields["id"] == general_record.fields["id"])
|
||||
medical_record = M
|
||||
break
|
||||
|
||||
if(href_list["vir"])
|
||||
var/type = href_list["vir"]
|
||||
var/datum/disease/D = new type(0)
|
||||
var/afs = ""
|
||||
for(var/mob/M in D.viable_mobtypes)
|
||||
afs += "[initial(M.name)];"
|
||||
var/severity = D.severity
|
||||
switch(severity)
|
||||
if("Harmful", "Minor")
|
||||
severity = "<span class='good'>[severity]</span>"
|
||||
if("Medium")
|
||||
severity = "<span class='average'>[severity]</span>"
|
||||
if("Dangerous!")
|
||||
severity = "<span class='bad'>[severity]</span>"
|
||||
if("BIOHAZARD THREAT!")
|
||||
severity = "<h4><span class='bad'>[severity]</span></h4>"
|
||||
setTemp({"<b>Name:</b> [D.name]
|
||||
<BR><b>Number of stages:</b> [D.max_stages]
|
||||
<BR><b>Spread:</b> [D.spread_text] Transmission
|
||||
<BR><b>Possible Cure:</b> [(D.cure_text||"none")]
|
||||
<BR><b>Affected Lifeforms:</b>[afs]<BR>
|
||||
<BR><b>Notes:</b> [D.desc]<BR>
|
||||
<BR><b>Severity:</b> [severity]"})
|
||||
qdel(D)
|
||||
|
||||
if(href_list["del_all"])
|
||||
var/list/buttons = list()
|
||||
buttons[++buttons.len] = list("name" = "Yes", "icon" = "check", "href" = "del_all2=1")
|
||||
buttons[++buttons.len] = list("name" = "No", "icon" = "times", "href" = null)
|
||||
setTemp("<h3>Are you sure you wish to delete all records?</h3>", buttons)
|
||||
|
||||
if(href_list["field"])
|
||||
if(..())
|
||||
return 1
|
||||
var/a1 = active1
|
||||
var/a2 = active2
|
||||
switch(href_list["field"])
|
||||
if("fingerprint")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please input fingerprint hash:", "Med. records", active1.fields["fingerprint"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active1 != a1)
|
||||
return 1
|
||||
active1.fields["fingerprint"] = t1
|
||||
if("sex")
|
||||
if(istype(active1, /datum/data/record))
|
||||
if(active1.fields["sex"] == "Male")
|
||||
active1.fields["sex"] = "Female"
|
||||
else
|
||||
active1.fields["sex"] = "Male"
|
||||
if("age")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/t1 = input("Please input age:", "Med. records", active1.fields["age"], null) as num
|
||||
if(!t1 || ..() || active1 != a1)
|
||||
return 1
|
||||
active1.fields["age"] = t1
|
||||
if("mi_dis")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please input minor disabilities list:", "Med. records", active2.fields["mi_dis"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["mi_dis"] = t1
|
||||
if("mi_dis_d")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please summarize minor dis.:", "Med. records", active2.fields["mi_dis_d"], null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["mi_dis_d"] = t1
|
||||
if("ma_dis")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please input major diabilities list:", "Med. records", active2.fields["ma_dis"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["ma_dis"] = t1
|
||||
if("ma_dis_d")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please summarize major dis.:", "Med. records", active2.fields["ma_dis_d"], null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["ma_dis_d"] = t1
|
||||
if("alg")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please state allergies:", "Med. records", active2.fields["alg"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["alg"] = t1
|
||||
if("alg_d")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please summarize allergies:", "Med. records", active2.fields["alg_d"], null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["alg_d"] = t1
|
||||
if("cdi")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please state diseases:", "Med. records", active2.fields["cdi"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["cdi"] = t1
|
||||
if("cdi_d")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please summarize diseases:", "Med. records", active2.fields["cdi_d"], null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["cdi_d"] = t1
|
||||
if("notes")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(html_encode(trim(input("Please summarize notes:", "Med. records", html_decode(active2.fields["notes"]), null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["notes"] = t1
|
||||
if("p_stat")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/list/buttons = list()
|
||||
buttons[++buttons.len] = list("name" = "*Deceased*", "icon" = "stethoscope", "href" = "p_stat=deceased", "status" = (active1.fields["p_stat"] == "*Deceased*" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "*SSD*", "icon" = "stethoscope", "href" = "p_stat=ssd", "status" = (active1.fields["p_stat"] == "*SSD*" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "Active", "icon" = "stethoscope", "href" = "p_stat=active", "status" = (active1.fields["p_stat"] == "Active" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "Physically Unfit", "icon" = "stethoscope", "href" = "p_stat=unfit", "status" = (active1.fields["p_stat"] == "Physically Unfit" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "Disabled", "icon" = "stethoscope", "href" = "p_stat=disabled", "status" = (active1.fields["p_stat"] == "Disabled" ? "selected" : null))
|
||||
setTemp("<h3>Physical Condition</h3>", buttons)
|
||||
if("m_stat")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/list/buttons = list()
|
||||
buttons[++buttons.len] = list("name" = "*Insane*", "icon" = "stethoscope", "href" = "m_stat=insane", "status" = (active1.fields["m_stat"] == "*Insane*" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "*Unstable*", "icon" = "stethoscope", "href" = "m_stat=unstable", "status" = (active1.fields["m_stat"] == "*Unstable*" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "*Watch*", "icon" = "stethoscope", "href" = "m_stat=watch", "status" = (active1.fields["m_stat"] == "*Watch*" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "Stable", "icon" = "stethoscope", "href" = "m_stat=stable", "status" = (active1.fields["m_stat"] == "Stable" ? "selected" : null))
|
||||
setTemp("<h3>Mental Condition</h3>", buttons)
|
||||
if("blood_type")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/list/buttons = list()
|
||||
buttons[++buttons.len] = list("name" = "A-", "icon" = "tint", "href" = "blood_type=an", "status" = (active2.fields["blood_type"] == "A-" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "A+", "icon" = "tint", "href" = "blood_type=ap", "status" = (active2.fields["blood_type"] == "A+" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "B-", "icon" = "tint", "href" = "blood_type=bn", "status" = (active2.fields["blood_type"] == "B-" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "B+", "icon" = "tint", "href" = "blood_type=bp", "status" = (active2.fields["blood_type"] == "B+" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "AB-", "icon" = "tint", "href" = "blood_type=abn", "status" = (active2.fields["blood_type"] == "AB-" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "AB+", "icon" = "tint", "href" = "blood_type=abp", "status" = (active2.fields["blood_type"] == "AB+" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "O-", "icon" = "tint", "href" = "blood_type=on", "status" = (active2.fields["blood_type"] == "O-" ? "selected" : null))
|
||||
buttons[++buttons.len] = list("name" = "O+", "icon" = "tint", "href" = "blood_type=op", "status" = (active2.fields["blood_type"] == "O+" ? "selected" : null))
|
||||
setTemp("<h3>Blood Type</h3>", buttons)
|
||||
if("b_dna")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(trim(sanitize(input("Please input DNA hash:", "Med. records", active2.fields["b_dna"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["b_dna"] = t1
|
||||
if("vir_name")
|
||||
var/datum/data/record/v = locate(href_list["edit_vir"])
|
||||
if(v)
|
||||
var/t1 = copytext(trim(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active1 != a1)
|
||||
return 1
|
||||
v.fields["name"] = t1
|
||||
if("vir_desc")
|
||||
var/datum/data/record/v = locate(href_list["edit_vir"])
|
||||
if(v)
|
||||
var/t1 = copytext(trim(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active1 != a1)
|
||||
return 1
|
||||
v.fields["description"] = t1
|
||||
|
||||
if(href_list["del_r"])
|
||||
if(active2)
|
||||
var/list/buttons = list()
|
||||
buttons[++buttons.len] = list("name" = "Yes", "icon" = "check", "href" = "del_r2=1", "status" = null)
|
||||
buttons[++buttons.len] = list("name" = "No", "icon" = "times", "href" = null, "status" = null)
|
||||
setTemp("<h3>Are you sure you wish to delete the record (Medical Portion Only)?</h3>", buttons)
|
||||
|
||||
if(href_list["d_rec"])
|
||||
var/datum/data/record/R = locate(href_list["d_rec"])
|
||||
var/datum/data/record/M = locate(href_list["d_rec"])
|
||||
if(!GLOB.data_core.general.Find(R))
|
||||
setTemp("<h3 class='bad'>Record not found!</h3>")
|
||||
return 1
|
||||
for(var/datum/data/record/E in GLOB.data_core.medical)
|
||||
if(E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])
|
||||
M = E
|
||||
active1 = R
|
||||
active2 = M
|
||||
screen = MED_DATA_RECORD
|
||||
|
||||
if(href_list["new"])
|
||||
if(istype(active1, /datum/data/record) && !istype(active2, /datum/data/record))
|
||||
var/datum/data/record/R = new /datum/data/record()
|
||||
R.fields["name"] = active1.fields["name"]
|
||||
R.fields["id"] = active1.fields["id"]
|
||||
R.name = "Medical Record #[R.fields["id"]]"
|
||||
R.fields["blood_type"] = "Unknown"
|
||||
R.fields["b_dna"] = "Unknown"
|
||||
R.fields["mi_dis"] = "None"
|
||||
R.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
R.fields["ma_dis"] = "None"
|
||||
R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
R.fields["alg"] = "None"
|
||||
R.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
R.fields["cdi"] = "None"
|
||||
R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
R.fields["notes"] = "No notes."
|
||||
GLOB.data_core.medical += R
|
||||
active2 = R
|
||||
active1 = general_record
|
||||
active2 = medical_record
|
||||
screen = MED_DATA_RECORD
|
||||
|
||||
if(href_list["add_c"])
|
||||
if(!istype(active2, /datum/data/record))
|
||||
return 1
|
||||
var/a2 = active2
|
||||
var/t1 = copytext(trim(sanitize(input("Add Comment:", "Med. records", null, null) as message)), 1, MAX_MESSAGE_LEN)
|
||||
if(!t1 || ..() || active2 != a2)
|
||||
return 1
|
||||
active2.fields["comments"] += "Made by [authenticated] ([rank]) on [GLOB.current_date_string] [station_time_timestamp()]<BR>[t1]"
|
||||
|
||||
if(href_list["del_c"])
|
||||
var/index = min(max(text2num(href_list["del_c"]) + 1, 1), length(active2.fields["comments"]))
|
||||
if(istype(active2, /datum/data/record) && active2.fields["comments"][index])
|
||||
active2.fields["comments"] -= active2.fields["comments"][index]
|
||||
|
||||
if(href_list["search"])
|
||||
var/t1 = clean_input("Search String: (Name, DNA, or ID)", "Med. records", null, null)
|
||||
if(!t1 || ..())
|
||||
return 1
|
||||
active1 = null
|
||||
active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in GLOB.data_core.medical)
|
||||
if(t1 == lowertext(R.fields["name"]) || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))
|
||||
if("new")
|
||||
if(istype(active1, /datum/data/record) && !istype(active2, /datum/data/record))
|
||||
var/datum/data/record/R = new /datum/data/record()
|
||||
R.fields["name"] = active1.fields["name"]
|
||||
R.fields["id"] = active1.fields["id"]
|
||||
R.name = "Medical Record #[R.fields["id"]]"
|
||||
R.fields["blood_type"] = "Unknown"
|
||||
R.fields["b_dna"] = "Unknown"
|
||||
R.fields["mi_dis"] = "None"
|
||||
R.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
R.fields["ma_dis"] = "None"
|
||||
R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
R.fields["alg"] = "None"
|
||||
R.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
R.fields["cdi"] = "None"
|
||||
R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
R.fields["notes"] = "No notes."
|
||||
GLOB.data_core.medical += R
|
||||
active2 = R
|
||||
if(!active2)
|
||||
setTemp("<h3 class='bad'>Could not locate record [t1].</h3>")
|
||||
else
|
||||
screen = MED_DATA_RECORD
|
||||
set_temp("Medical record created.", "success")
|
||||
if("del_c")
|
||||
var/index = text2num(params["del_c"] || "")
|
||||
if(!index || !istype(active2, /datum/data/record))
|
||||
return
|
||||
|
||||
var/list/comments = active2.fields["comments"]
|
||||
index = clamp(index, 1, length(comments))
|
||||
if(comments[index])
|
||||
comments.Cut(index, index + 1)
|
||||
if("search")
|
||||
active1 = null
|
||||
active2 = null
|
||||
var/t1 = lowertext(params["t1"] || "")
|
||||
if(!length(t1))
|
||||
return
|
||||
|
||||
for(var/datum/data/record/R in GLOB.data_core.medical)
|
||||
if(t1 == lowertext(R.fields["name"]) || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))
|
||||
active2 = R
|
||||
break
|
||||
if(!active2)
|
||||
set_temp("Medical record not found. You must enter the person's exact name, ID or DNA.", "danger")
|
||||
return
|
||||
for(var/datum/data/record/E in GLOB.data_core.general)
|
||||
if(E.fields["name"] == active2.fields["name"] && E.fields["id"] == active2.fields["id"])
|
||||
active1 = E
|
||||
break
|
||||
screen = MED_DATA_RECORD
|
||||
if("print_p")
|
||||
if(!printing)
|
||||
printing = TRUE
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE)
|
||||
SStgui.update_uis(src)
|
||||
addtimer(CALLBACK(src, .proc/print_finish), 5 SECONDS)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
if(href_list["print_p"])
|
||||
if(!printing)
|
||||
printing = 1
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
sleep(50)
|
||||
var/obj/item/paper/P = new /obj/item/paper(loc)
|
||||
P.info = "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))
|
||||
P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
|
||||
<BR>\nSex: [active1.fields["sex"]]
|
||||
<BR>\nAge: [active1.fields["age"]]
|
||||
<BR>\nFingerprint: [active1.fields["fingerprint"]]
|
||||
<BR>\nPhysical Status: [active1.fields["p_stat"]]
|
||||
<BR>\nMental Status: [active1.fields["m_stat"]]<BR>"}
|
||||
/**
|
||||
* Called in tgui_act() to process modal actions
|
||||
*
|
||||
* Arguments:
|
||||
* * action - The action passed by tgui
|
||||
* * params - The params passed by tgui
|
||||
*/
|
||||
/obj/machinery/computer/med_data/proc/tgui_act_modal(action, params)
|
||||
. = TRUE
|
||||
var/id = params["id"] // The modal's ID
|
||||
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
if(TGUI_MODAL_OPEN)
|
||||
switch(id)
|
||||
if("edit")
|
||||
var/field = arguments["field"]
|
||||
if(!length(field) || !field_edit_questions[field])
|
||||
return
|
||||
var/question = field_edit_questions[field]
|
||||
var/choices = field_edit_choices[field]
|
||||
if(length(choices))
|
||||
tgui_modal_choice(src, id, question, arguments = arguments, value = arguments["value"], choices = choices)
|
||||
else
|
||||
tgui_modal_input(src, id, question, arguments = arguments, value = arguments["value"])
|
||||
if("add_c")
|
||||
tgui_modal_input(src, id, "Please enter your message:")
|
||||
else
|
||||
P.info += "<B>General Record Lost!</B><BR>"
|
||||
if(istype(active2, /datum/data/record) && GLOB.data_core.medical.Find(active2))
|
||||
P.info += {"<BR>\n<CENTER><B>Medical Data</B></CENTER>
|
||||
<BR>\nBlood Type: [active2.fields["blood_type"]]
|
||||
<BR>\nDNA: [active2.fields["b_dna"]]<BR>\n
|
||||
<BR>\nMinor Disabilities: [active2.fields["mi_dis"]]
|
||||
<BR>\nDetails: [active2.fields["mi_dis_d"]]<BR>\n
|
||||
<BR>\nMajor Disabilities: [active2.fields["ma_dis"]]
|
||||
<BR>\nDetails: [active2.fields["ma_dis_d"]]<BR>\n
|
||||
<BR>\nAllergies: [active2.fields["alg"]]
|
||||
<BR>\nDetails: [active2.fields["alg_d"]]<BR>\n
|
||||
<BR>\nCurrent Diseases: [active2.fields["cdi"]] (per disease info placed in log/comment section)
|
||||
<BR>\nDetails: [active2.fields["cdi_d"]]<BR>\n
|
||||
<BR>\nImportant Notes:
|
||||
<BR>\n\t[active2.fields["notes"]]<BR>\n
|
||||
<BR>\n
|
||||
<CENTER><B>Comments/Log</B></CENTER><BR>"}
|
||||
for(var/c in active2.fields["comments"])
|
||||
P.info += "[c]<BR>"
|
||||
else
|
||||
P.info += "<B>Medical Record Lost!</B><BR>"
|
||||
P.info += "</TT>"
|
||||
P.name = "paper- 'Medical Record: [active1.fields["name"]]'"
|
||||
printing = 0
|
||||
return 1
|
||||
return FALSE
|
||||
if(TGUI_MODAL_ANSWER)
|
||||
var/answer = params["answer"]
|
||||
switch(id)
|
||||
if("edit")
|
||||
var/field = arguments["field"]
|
||||
if(!length(field) || !field_edit_questions[field])
|
||||
return
|
||||
var/list/choices = field_edit_choices[field]
|
||||
if(length(choices) && !(answer in choices))
|
||||
return
|
||||
|
||||
/obj/machinery/computer/med_data/proc/setTemp(text, list/buttons = list())
|
||||
temp = list("text" = text, "buttons" = buttons, "has_buttons" = buttons.len > 0)
|
||||
if(field == "age")
|
||||
var/new_age = text2num(answer)
|
||||
if(new_age < AGE_MIN || new_age > AGE_MAX)
|
||||
set_temp("Invalid age. It must be between [AGE_MIN] and [AGE_MAX].", "danger")
|
||||
return
|
||||
answer = new_age
|
||||
|
||||
if(istype(active2) && (field in active2.fields))
|
||||
active2.fields[field] = answer
|
||||
else if(istype(active1) && (field in active1.fields))
|
||||
active1.fields[field] = answer
|
||||
if("add_c")
|
||||
if(!length(answer) || !istype(active2) || !length(authenticated))
|
||||
return
|
||||
active2.fields["comments"] += list(list(
|
||||
header = "Made by [authenticated] ([rank]) on [GLOB.current_date_string] [station_time_timestamp()]",
|
||||
text = answer
|
||||
))
|
||||
else
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called when the print timer finishes
|
||||
*/
|
||||
/obj/machinery/computer/med_data/proc/print_finish()
|
||||
var/obj/item/paper/P = new /obj/item/paper(loc)
|
||||
P.info = "<center></b>Medical Record</b></center><br>"
|
||||
if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))
|
||||
P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
|
||||
<br>\nSex: [active1.fields["sex"]]
|
||||
<br>\nAge: [active1.fields["age"]]
|
||||
<br>\nFingerprint: [active1.fields["fingerprint"]]
|
||||
<br>\nPhysical Status: [active1.fields["p_stat"]]
|
||||
<br>\nMental Status: [active1.fields["m_stat"]]<br>"}
|
||||
else
|
||||
P.info += "</b>General Record Lost!</b><br>"
|
||||
if(istype(active2, /datum/data/record) && GLOB.data_core.medical.Find(active2))
|
||||
P.info += {"<br>\n<center></b>Medical Data</b></center>
|
||||
<br>\nBlood Type: [active2.fields["blood_type"]]
|
||||
<br>\nDNA: [active2.fields["b_dna"]]<br>\n
|
||||
<br>\nMinor Disabilities: [active2.fields["mi_dis"]]
|
||||
<br>\nDetails: [active2.fields["mi_dis_d"]]<br>\n
|
||||
<br>\nMajor Disabilities: [active2.fields["ma_dis"]]
|
||||
<br>\nDetails: [active2.fields["ma_dis_d"]]<br>\n
|
||||
<br>\nAllergies: [active2.fields["alg"]]
|
||||
<br>\nDetails: [active2.fields["alg_d"]]<br>\n
|
||||
<br>\nCurrent Diseases: [active2.fields["cdi"]] (per disease info placed in log/comment section)
|
||||
<br>\nDetails: [active2.fields["cdi_d"]]<br>\n
|
||||
<br>\nImportant Notes:
|
||||
<br>\n\t[active2.fields["notes"]]<br>\n
|
||||
<br>\n
|
||||
<center></b>Comments/Log</b></center><br>"}
|
||||
for(var/c in active2.fields["comments"])
|
||||
P.info += "[c]<br>"
|
||||
else
|
||||
P.info += "</b>Medical Record Lost!</b><br>"
|
||||
P.info += "</tt>"
|
||||
P.name = "paper - 'Medical Record: [active1.fields["name"]]'"
|
||||
printing = FALSE
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/**
|
||||
* Sets a temporary message to display to the user
|
||||
*
|
||||
* Arguments:
|
||||
* * text - Text to display, null/empty to clear the message from the UI
|
||||
* * style - The style of the message: (color name), info, success, warning, danger, virus
|
||||
*/
|
||||
/obj/machinery/computer/med_data/proc/set_temp(text = "", style = "info", update_now = FALSE)
|
||||
temp = list(text = text, style = style)
|
||||
if(update_now)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/computer/med_data/emp_act(severity)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
@@ -564,9 +502,10 @@
|
||||
icon_screen = "medlaptop"
|
||||
density = 0
|
||||
|
||||
#undef MED_DATA_MAIN
|
||||
#undef MED_DATA_R_LIST
|
||||
#undef MED_DATA_MAINT
|
||||
#undef MED_DATA_RECORD
|
||||
#undef MED_DATA_V_DATA
|
||||
#undef MED_DATA_MEDBOT
|
||||
#undef FIELD
|
||||
#undef MED_FIELD
|
||||
|
||||
@@ -20,221 +20,210 @@
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/robotics/proc/is_authenticated(var/mob/user as mob)
|
||||
/obj/machinery/computer/robotics/proc/is_authenticated(mob/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.can_admin_interact())
|
||||
return 1
|
||||
else if(allowed(user))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
if(allowed(user))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/**
|
||||
* Does this borg show up in the console
|
||||
*
|
||||
* Returns TRUE if a robot will show up in the console
|
||||
* Returns FALSE if a robot will not show up in the console
|
||||
* Arguments:
|
||||
* * R - The [mob/living/silicon/robot] to be checked
|
||||
*/
|
||||
/obj/machinery/computer/robotics/proc/console_shows(mob/living/silicon/robot/R)
|
||||
if(!istype(R))
|
||||
return FALSE
|
||||
if(istype(R, /mob/living/silicon/robot/drone))
|
||||
return FALSE
|
||||
if(R.scrambledcodes)
|
||||
return FALSE
|
||||
if(!atoms_share_level(src, R))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Check if a user can send a lockdown/detonate command to a specific borg
|
||||
*
|
||||
* Returns TRUE if a user can send the command (does not guarantee it will work)
|
||||
* Returns FALSE if a user cannot
|
||||
* Arguments:
|
||||
* * user - The [mob/user] to be checked
|
||||
* * R - The [mob/living/silicon/robot] to be checked
|
||||
* * telluserwhy - Bool of whether the user should be sent a to_chat message if they don't have access
|
||||
*/
|
||||
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R, telluserwhy = FALSE)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(!console_shows(R))
|
||||
return FALSE
|
||||
if(isAI(user))
|
||||
if(R.connected_ai != user)
|
||||
if(telluserwhy)
|
||||
to_chat(user, "<span class='warning'>AIs can only control cyborgs which are linked to them.</span>")
|
||||
return FALSE
|
||||
if(isrobot(user))
|
||||
if(R != user)
|
||||
if(telluserwhy)
|
||||
to_chat(user, "<span class='warning'>Cyborgs cannot control other cyborgs.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Check if the user is the right kind of entity to be able to hack borgs
|
||||
*
|
||||
* Returns TRUE if a user is a traitor AI, or aghost
|
||||
* Returns FALSE otherwise
|
||||
* Arguments:
|
||||
* * user - The [mob/user] to be checked
|
||||
*/
|
||||
/obj/machinery/computer/robotics/proc/can_hack_any(mob/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.can_admin_interact())
|
||||
return TRUE
|
||||
if(!isAI(user))
|
||||
return FALSE
|
||||
return (user.mind.special_role && user.mind.original == user)
|
||||
|
||||
/**
|
||||
* Check if the user is allowed to hack a specific borg
|
||||
*
|
||||
* Returns TRUE if a user can hack the specific cyborg
|
||||
* Returns FALSE if a user cannot
|
||||
* Arguments:
|
||||
* * user - The [mob/user] to be checked
|
||||
* * R - The [mob/living/silicon/robot] to be checked
|
||||
*/
|
||||
/obj/machinery/computer/robotics/proc/can_hack(mob/user, mob/living/silicon/robot/R)
|
||||
if(!can_hack_any(user))
|
||||
return FALSE
|
||||
if(!istype(R))
|
||||
return FALSE
|
||||
if(R.emagged)
|
||||
return FALSE
|
||||
if(R.connected_ai != user)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/robotics/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "robot_control.tmpl", "Robotic Control Console", 400, 500)
|
||||
ui = new(user, src, ui_key, "RoboticsControlConsole", name, 500, 460, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/robotics/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
var/list/robots = get_cyborgs(user)
|
||||
if(robots.len)
|
||||
data["robots"] = robots
|
||||
/obj/machinery/computer/robotics/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["auth"] = is_authenticated(user)
|
||||
data["can_hack"] = can_hack_any(user)
|
||||
data["cyborgs"] = list()
|
||||
data["safety"] = safety
|
||||
// Also applies for cyborgs. Hides the manual self-destruct button.
|
||||
data["is_ai"] = issilicon(user)
|
||||
data["allowed"] = is_authenticated(user)
|
||||
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
||||
if(!console_shows(R))
|
||||
continue
|
||||
var/area/A = get_area(R)
|
||||
var/turf/T = get_turf(R)
|
||||
var/list/cyborg_data = list(
|
||||
name = R.name,
|
||||
uid = R.UID(),
|
||||
locked_down = R.lockcharge,
|
||||
locstring = "[A.name] ([T.x], [T.y])",
|
||||
status = R.stat,
|
||||
health = round(R.health * 100 / R.maxHealth, 0.1),
|
||||
charge = R.cell ? round(R.cell.percent()) : null,
|
||||
cell_capacity = R.cell ? R.cell.maxcharge : null,
|
||||
module = R.module ? R.module.name : "No Module Detected",
|
||||
synchronization = R.connected_ai,
|
||||
is_hacked = R.connected_ai && R.emagged,
|
||||
hackable = can_hack(user, R),
|
||||
)
|
||||
data["cyborgs"] += list(cyborg_data)
|
||||
data["show_detonate_all"] = (data["auth"] && length(data["cyborgs"]) > 0 && ishuman(user))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/robotics/Topic(href, href_list)
|
||||
/obj/machinery/computer/robotics/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
var/mob/user = usr
|
||||
if(!is_authenticated(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
// Destroys the cyborg
|
||||
if(href_list["detonate"])
|
||||
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["detonate"])
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
if(isAI(user) && (target.connected_ai != user))
|
||||
to_chat(user, "<span class='warning'>Access Denied. This robot is not linked to you.</span>")
|
||||
return
|
||||
// Cyborgs may blow up themselves via the console
|
||||
if((isrobot(user) && user != target) || !is_authenticated(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return
|
||||
var/choice = input("Really detonate [target.name]?") in list ("Yes", "No")
|
||||
if(choice != "Yes")
|
||||
return
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
|
||||
// Antagonistic cyborgs? Left here for downstream
|
||||
if(target.mind && target.mind.special_role && target.emagged)
|
||||
to_chat(target, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.")
|
||||
target.ResetSecurityCodes()
|
||||
else
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] detonated [key_name_admin(target)] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[target.x];Y=[target.y];Z=[target.z]'>JMP</a>)!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(target)]!</span>")
|
||||
to_chat(target, "<span class='danger'>Self-destruct command received.</span>")
|
||||
if(target.connected_ai)
|
||||
to_chat(target.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [target.name]</span><br>")
|
||||
spawn(10)
|
||||
target.self_destruct()
|
||||
|
||||
// Locks or unlocks the cyborg
|
||||
else if(href_list["lockdown"])
|
||||
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
|
||||
if(isAI(user) && (target.connected_ai != user))
|
||||
to_chat(user, "<span class='warning'>Access Denied. This robot is not linked to you.</span>")
|
||||
return
|
||||
|
||||
if(isrobot(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return
|
||||
|
||||
var/choice = input("Really [target.lockcharge ? "unlock" : "lockdown"] [target.name] ?") in list ("Yes", "No")
|
||||
if(choice != "Yes")
|
||||
return
|
||||
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] [target.canmove ? "locked down" : "released"] [key_name_admin(target)]!</span>")
|
||||
log_game("[key_name(usr)] [target.canmove ? "locked down" : "released"] [key_name(target)]!")
|
||||
target.SetLockdown(!target.lockcharge)
|
||||
to_chat(target, "[!target.lockcharge ? "<span class='notice'>Your lockdown has been lifted!</span>" : "<span class='alert'>You have been locked down!</span>"]")
|
||||
if(target.connected_ai)
|
||||
to_chat(target.connected_ai, "[!target.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted</span>" : "<span class='alert'>ALERT - Cyborg lockdown detected</span>"]: <a href='?src=[target.connected_ai.UID()];track=[html_encode(target.name)]'>[target.name]</a></span><br>")
|
||||
|
||||
// Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
|
||||
else if(href_list["hack"])
|
||||
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"])
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
|
||||
// Antag AI checks
|
||||
if(!istype(user, /mob/living/silicon/ai) || !(user.mind.special_role && user.mind.original == user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return
|
||||
|
||||
if(target.connected_ai != user)
|
||||
to_chat(user, "<span class='warning'>Access Denied. This robot is not linked to you.</span>")
|
||||
return
|
||||
|
||||
if(target.emagged)
|
||||
to_chat(user, "<span class='warning'>Robot is already hacked.</span>")
|
||||
return
|
||||
|
||||
var/choice = input("Really hack [target.name]? This cannot be undone.") in list("Yes", "No")
|
||||
if(choice != "Yes")
|
||||
return
|
||||
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [key_name_admin(target)] using robotic console!</span>")
|
||||
log_game("[key_name(usr)] emagged [key_name(target)] using robotic console!")
|
||||
target.emagged = 1
|
||||
to_chat(target, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
|
||||
|
||||
// Arms the emergency self-destruct system
|
||||
else if(href_list["arm"])
|
||||
if(istype(user, /mob/living/silicon))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return
|
||||
|
||||
safety = !safety
|
||||
to_chat(user, "<span class='notice'>You [safety ? "disarm" : "arm"] the emergency self destruct.</span>")
|
||||
|
||||
// Destroys all accessible cyborgs if safety is disabled
|
||||
else if(href_list["nuke"])
|
||||
if(istype(user, /mob/living/silicon))
|
||||
to_chat(user, "Access Denied")
|
||||
return
|
||||
if(safety)
|
||||
to_chat(user, "Self-destruct aborted - safety active")
|
||||
return
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] detonated all cyborgs!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated all cyborgs!</span>")
|
||||
|
||||
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
||||
if(istype(R, /mob/living/silicon/robot/drone))
|
||||
continue
|
||||
// Ignore antagonistic cyborgs
|
||||
if(R.scrambledcodes)
|
||||
continue
|
||||
. = FALSE
|
||||
if(!is_authenticated(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
switch(action)
|
||||
if("arm") // Arms the emergency self-destruct system
|
||||
if(issilicon(usr))
|
||||
to_chat(usr, "<span class='danger'>Access Denied (silicon detected)</span>")
|
||||
return
|
||||
safety = !safety
|
||||
to_chat(usr, "<span class='notice'>You [safety ? "disarm" : "arm"] the emergency self destruct.</span>")
|
||||
. = TRUE
|
||||
if("nuke") // Destroys all accessible cyborgs if safety is disabled
|
||||
if(issilicon(usr))
|
||||
to_chat(usr, "<span class='danger'>Access Denied (silicon detected)</span>")
|
||||
return
|
||||
if(safety)
|
||||
to_chat(usr, "<span class='danger'>Self-destruct aborted - safety active</span>")
|
||||
return
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] detonated all cyborgs!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated all cyborgs!</span>")
|
||||
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
||||
if(istype(R, /mob/living/silicon/robot/drone))
|
||||
continue
|
||||
// Ignore antagonistic cyborgs
|
||||
if(R.scrambledcodes)
|
||||
continue
|
||||
to_chat(R, "<span class='danger'>Self-destruct command received.</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
R.self_destruct()
|
||||
. = TRUE
|
||||
if("killbot") // destroys one specific cyborg
|
||||
var/mob/living/silicon/robot/R = locateUID(params["uid"])
|
||||
if(!can_control(usr, R, TRUE))
|
||||
return
|
||||
if(R.mind && R.mind.special_role && R.emagged)
|
||||
to_chat(R, "<span class='userdanger'>Extreme danger! Termination codes detected. Scrambling security codes and automatic AI unlink triggered.</span>")
|
||||
R.ResetSecurityCodes()
|
||||
. = TRUE
|
||||
return
|
||||
var/turf/T = get_turf(R)
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] detonated [key_name_admin(R)] ([ADMIN_COORDJMP(T)])!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
|
||||
to_chat(R, "<span class='danger'>Self-destruct command received.</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
spawn(10)
|
||||
R.self_destruct()
|
||||
|
||||
// Proc: get_cyborgs()
|
||||
// Parameters: 1 (operator - mob which is operating the console.)
|
||||
// Description: Returns NanoUI-friendly list of accessible cyborgs.
|
||||
/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator)
|
||||
var/list/robots = list()
|
||||
|
||||
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
||||
// Ignore drones
|
||||
if(istype(R, /mob/living/silicon/robot/drone))
|
||||
continue
|
||||
// Ignore antagonistic cyborgs
|
||||
if(R.scrambledcodes)
|
||||
continue
|
||||
|
||||
var/list/robot = list()
|
||||
robot["name"] = R.name
|
||||
if(R.stat)
|
||||
robot["status"] = "Not Responding"
|
||||
else if(!R.canmove)
|
||||
robot["status"] = "Lockdown"
|
||||
else
|
||||
robot["status"] = "Operational"
|
||||
|
||||
if(R.cell)
|
||||
robot["cell"] = 1
|
||||
robot["cell_capacity"] = R.cell.maxcharge
|
||||
robot["cell_current"] = R.cell.charge
|
||||
robot["cell_percentage"] = round(R.cell.percent())
|
||||
else
|
||||
robot["cell"] = 0
|
||||
|
||||
var/turf/pos = get_turf(R)
|
||||
var/area/bot_area = get_area(R)
|
||||
robot["xpos"] = pos.x
|
||||
robot["ypos"] = pos.y
|
||||
robot["zpos"] = pos.z
|
||||
robot["area"] = format_text(bot_area.name)
|
||||
|
||||
robot["health"] = round(R.health * 100 / R.maxHealth,0.1)
|
||||
|
||||
robot["module"] = R.module ? R.module.name : "None"
|
||||
robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None"
|
||||
robot["hackable"] = 0
|
||||
// Antag AIs know whether linked cyborgs are hacked or not.
|
||||
if(operator && istype(operator, /mob/living/silicon/ai) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator))
|
||||
robot["hacked"] = R.emagged ? 1 : 0
|
||||
robot["hackable"] = R.emagged? 0 : 1
|
||||
robots.Add(list(robot))
|
||||
return robots
|
||||
|
||||
// Proc: get_cyborg_by_name()
|
||||
// Parameters: 1 (name - Cyborg we are trying to find)
|
||||
// Description: Helper proc for finding cyborg by name
|
||||
/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name)
|
||||
if(!name)
|
||||
return
|
||||
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
||||
if(R.name == name)
|
||||
return R
|
||||
R.self_destruct()
|
||||
. = TRUE
|
||||
if("stopbot") // lock or unlock the borg
|
||||
if(isrobot(usr))
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
return
|
||||
var/mob/living/silicon/robot/R = locateUID(params["uid"])
|
||||
if(!can_control(usr, R, TRUE))
|
||||
return
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!</span>")
|
||||
log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!")
|
||||
R.SetLockdown(!R.lockcharge)
|
||||
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "[!R.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted</span>" : "<span class='alert'>ALERT - Cyborg lockdown detected</span>"]: <a href='?src=[R.connected_ai.UID()];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
|
||||
. = TRUE
|
||||
if("hackbot") // AIs hacking/emagging a borg
|
||||
var/mob/living/silicon/robot/R = locateUID(params["uid"])
|
||||
if(!can_hack(usr, R))
|
||||
return
|
||||
var/choice = input("Really hack [R.name]? This cannot be undone.") in list("Yes", "No")
|
||||
if(choice != "Yes")
|
||||
return
|
||||
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [key_name_admin(R)] using robotic console!</span>")
|
||||
R.emagged = TRUE
|
||||
to_chat(R, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
|
||||
. = TRUE
|
||||
|
||||
+48
-67
@@ -103,7 +103,7 @@
|
||||
beaker.forceMove(drop_location())
|
||||
beaker = null
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(atom/movable/O as mob|obj, mob/living/user as mob)
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(atom/movable/O, mob/living/user)
|
||||
if(O.loc == user) //no you can't pull things out of your ass
|
||||
return
|
||||
if(user.incapacitated()) //are you cuffed, dying, lying, stunned or other
|
||||
@@ -140,6 +140,7 @@
|
||||
add_attack_logs(user, L, "put into a cryo cell at [COORD(src)].", ATKLOG_ALL)
|
||||
if(user.pulling == L)
|
||||
user.stop_pulling()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/process()
|
||||
..()
|
||||
@@ -177,14 +178,14 @@
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob)
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user)
|
||||
if(user.stat)
|
||||
return
|
||||
go_out()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/attack_ghost(mob/user)
|
||||
return attack_hand(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/attack_hand(mob/user)
|
||||
if(user == occupant)
|
||||
@@ -194,36 +195,18 @@
|
||||
to_chat(usr, "<span class='boldnotice'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
|
||||
/**
|
||||
* The ui_interact proc is used to open and update Nano UIs
|
||||
* If ui_interact is not used then the UI will not update correctly
|
||||
* ui_interact is currently defined for /atom/movable (which is inherited by /obj and /mob)
|
||||
*
|
||||
* @param user /mob The mob who is interacting with this ui
|
||||
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
|
||||
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 480)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "Cryo", "Cryo Cell", 520, 490)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["isOperating"] = on
|
||||
data["hasOccupant"] = occupant ? 1 : 0
|
||||
data["hasOccupant"] = occupant ? TRUE : FALSE
|
||||
|
||||
var/occupantData[0]
|
||||
if(occupant)
|
||||
@@ -246,7 +229,7 @@
|
||||
else if(air_contents.temperature > TCRYO)
|
||||
data["cellTemperatureStatus"] = "average"
|
||||
|
||||
data["isBeakerLoaded"] = beaker ? 1 : 0
|
||||
data["isBeakerLoaded"] = beaker ? TRUE : FALSE
|
||||
data["beakerLabel"] = null
|
||||
data["beakerVolume"] = 0
|
||||
if(beaker)
|
||||
@@ -259,48 +242,44 @@
|
||||
data["auto_eject_dead"] = (auto_eject_prefs & AUTO_EJECT_DEAD) ? TRUE : FALSE
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/Topic(href, href_list)
|
||||
if(usr == occupant)
|
||||
return 0 // don't update UIs attached to this object
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/tgui_act(action, params)
|
||||
if(..() || usr == occupant)
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(..())
|
||||
return 0 // don't update UIs attached to this object
|
||||
|
||||
if(href_list["switchOn"])
|
||||
on = TRUE
|
||||
update_icon()
|
||||
|
||||
if(href_list["switchOff"])
|
||||
on = FALSE
|
||||
update_icon()
|
||||
|
||||
if(href_list["auto_eject_healthy_on"])
|
||||
auto_eject_prefs |= AUTO_EJECT_HEALTHY
|
||||
|
||||
if(href_list["auto_eject_healthy_off"])
|
||||
auto_eject_prefs &= ~AUTO_EJECT_HEALTHY
|
||||
|
||||
if(href_list["auto_eject_dead_on"])
|
||||
auto_eject_prefs |= AUTO_EJECT_DEAD
|
||||
|
||||
if(href_list["auto_eject_dead_off"])
|
||||
auto_eject_prefs &= ~AUTO_EJECT_DEAD
|
||||
|
||||
if(href_list["ejectBeaker"])
|
||||
if(beaker)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("switchOn")
|
||||
on = TRUE
|
||||
update_icon()
|
||||
if("switchOff")
|
||||
on = FALSE
|
||||
update_icon()
|
||||
if("auto_eject_healthy_on")
|
||||
auto_eject_prefs |= AUTO_EJECT_HEALTHY
|
||||
if("auto_eject_healthy_off")
|
||||
auto_eject_prefs &= ~AUTO_EJECT_HEALTHY
|
||||
if("auto_eject_dead_on")
|
||||
auto_eject_prefs |= AUTO_EJECT_DEAD
|
||||
if("auto_eject_dead_off")
|
||||
auto_eject_prefs &= ~AUTO_EJECT_DEAD
|
||||
if("ejectBeaker")
|
||||
if(!beaker)
|
||||
return
|
||||
beaker.forceMove(get_step(loc, SOUTH))
|
||||
beaker = null
|
||||
|
||||
if(href_list["ejectOccupant"])
|
||||
if(!occupant || isslime(usr) || ispAI(usr))
|
||||
return 0 // don't update UIs attached to this object
|
||||
add_attack_logs(usr, occupant, "ejected from cryo cell at [COORD(src)]", ATKLOG_ALL)
|
||||
go_out()
|
||||
if("ejectOccupant")
|
||||
if(!occupant || isslime(usr) || ispAI(usr))
|
||||
return
|
||||
add_attack_logs(usr, occupant, "ejected from cryo cell at [COORD(src)]", ATKLOG_ALL)
|
||||
go_out()
|
||||
else
|
||||
return FALSE
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1 // update UIs attached to this object
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/G as obj, var/mob/user as mob, params)
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/G, var/mob/user, params)
|
||||
if(istype(G, /obj/item/reagent_containers/glass))
|
||||
var/obj/item/reagent_containers/B = G
|
||||
if(beaker)
|
||||
@@ -313,6 +292,7 @@
|
||||
beaker = B
|
||||
add_attack_logs(user, null, "Added [B] containing [B.reagents.log_list()] to a cryo cell at [COORD(src)]")
|
||||
user.visible_message("[user] adds \a [B] to [src]!", "You add \a [B] to [src]!")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
if(exchange_parts(user, G))
|
||||
@@ -357,7 +337,7 @@
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
var/image/pickle = image(occupant.icon, occupant.icon_state)
|
||||
var/mutable_appearance/pickle = mutable_appearance(occupant.icon, occupant.icon_state)
|
||||
pickle.overlays = occupant.overlays
|
||||
pickle.pixel_y = 22
|
||||
|
||||
@@ -455,8 +435,9 @@
|
||||
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
|
||||
if(AUTO_EJECT_DEAD)
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 40)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob)
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M)
|
||||
if(!istype(M))
|
||||
to_chat(usr, "<span class='danger'>The cryo cell cannot handle such a lifeform!</span>")
|
||||
return
|
||||
@@ -530,7 +511,7 @@
|
||||
/datum/data/function/proc/reset()
|
||||
return
|
||||
|
||||
/datum/data/function/proc/r_input(href, href_list, mob/user as mob)
|
||||
/datum/data/function/proc/r_input(href, href_list, mob/user)
|
||||
return
|
||||
|
||||
/datum/data/function/proc/display()
|
||||
|
||||
@@ -784,6 +784,9 @@
|
||||
if(free_cryopods.len)
|
||||
target_cryopod = safepick(free_cryopods)
|
||||
if(target_cryopod.check_occupant_allowed(person_to_cryo))
|
||||
var/turf/T = get_turf(person_to_cryo)
|
||||
var/obj/effect/portal/SP = new /obj/effect/portal(T, null, null, 40)
|
||||
SP.name = "NT SSD Teleportation Portal"
|
||||
target_cryopod.take_occupant(person_to_cryo, 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -36,9 +36,10 @@
|
||||
var/crimes = CELL_NONE
|
||||
var/time = 0
|
||||
var/officer = CELL_NONE
|
||||
var/prisoner_name = ""
|
||||
var/prisoner_charge = ""
|
||||
var/prisoner_time = ""
|
||||
var/prisoner_name
|
||||
var/prisoner_charge
|
||||
var/prisoner_time
|
||||
var/prisoner_hasrecord = FALSE
|
||||
|
||||
/obj/machinery/door_timer/New()
|
||||
GLOB.celltimers_list += src
|
||||
@@ -82,10 +83,15 @@
|
||||
|
||||
var/datum/data/record/R = find_security_record("name", occupant)
|
||||
|
||||
var/announcetext = "Detainee [occupant] ([prisoner_drank]) has been incarcerated for [seconds_to_time(timetoset / 10)] for the charges of: '[crimes]'. \
|
||||
var/timetext = seconds_to_time(timetoset / 10)
|
||||
var/announcetext = "Detainee [occupant] ([prisoner_drank]) has been incarcerated for [timetext] for the crime of: '[crimes]'. \
|
||||
Arresting Officer: [usr.name].[R ? "" : " Detainee record not found, manual record update required."]"
|
||||
Radio.autosay(announcetext, name, "Security", list(z))
|
||||
|
||||
// Notify the actual criminal being brigged. This is a QOL thing to ensure they always know the charges against them.
|
||||
// Announcing it on radio isn't enough, as they're unlikely to have sec radio.
|
||||
notify_prisoner("You have been incarcerated for [timetext] for the crime of: '[crimes]'.")
|
||||
|
||||
if(prisoner_trank != "unknown" && prisoner_trank != "Civilian")
|
||||
SSjobs.notify_dept_head(prisoner_trank, announcetext)
|
||||
|
||||
@@ -104,6 +110,13 @@
|
||||
update_all_mob_security_hud()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door_timer/proc/notify_prisoner(notifytext)
|
||||
for(var/mob/living/carbon/human/H in range(4, get_turf(src)))
|
||||
if(occupant == H.name)
|
||||
to_chat(H, "[src] beeps, \"[notifytext]\"")
|
||||
return
|
||||
atom_say("[src] beeps, \"[occupant]: [notifytext]\"")
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
..()
|
||||
|
||||
@@ -261,13 +274,11 @@
|
||||
|
||||
return
|
||||
|
||||
//Allows AIs to use door_timer, see human attack_hand function below
|
||||
/obj/machinery/door_timer/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/door_timer/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
//Allows humans to use door_timer
|
||||
//Opens dialog window when someone clicks on door timer
|
||||
@@ -276,71 +287,109 @@
|
||||
/obj/machinery/door_timer/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/door_timer/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "brig_timer.tmpl", "Brig Timer", 500, 400)
|
||||
ui = new(user, src, ui_key, "BrigTimer", name, 500, 450, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(TRUE)
|
||||
|
||||
/obj/machinery/door_timer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
/obj/machinery/door_timer/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["spns"] = list()
|
||||
for(var/mob/living/carbon/human/H in range(4, get_turf(src)))
|
||||
if(H.handcuffed)
|
||||
data["spns"] += H.name
|
||||
return data
|
||||
|
||||
/obj/machinery/door_timer/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["cell_id"] = name
|
||||
data["occupant"] = occupant
|
||||
data["crimes"] = crimes
|
||||
data["brigged_by"] = officer
|
||||
data["time_set"] = seconds_to_clock(time / 10)
|
||||
data["time_set"] = seconds_to_clock(timetoset / 10)
|
||||
data["time_left"] = seconds_to_clock(timeleft())
|
||||
data["timing"] = timing
|
||||
data["isAllowed"] = allowed(user)
|
||||
data["prisoner_name"] = prisoner_name
|
||||
data["prisoner_charge"] = prisoner_charge
|
||||
data["prisoner_time"] = prisoner_time
|
||||
|
||||
data["prisoner_hasrec"] = prisoner_hasrecord
|
||||
return data
|
||||
|
||||
/obj/machinery/door_timer/Topic(href, href_list)
|
||||
if(!allowed(usr) && !usr.can_admin_interact())
|
||||
return 1
|
||||
/obj/machinery/door_timer/allowed(mob/user)
|
||||
if(user.can_admin_interact())
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
if(href_list["flash"])
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
to_chat(usr, "<span class='warning'>Flash still charging.</span>")
|
||||
/obj/machinery/door_timer/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("prisoner_name")
|
||||
if(params["prisoner_name"])
|
||||
prisoner_name = params["prisoner_name"]
|
||||
else
|
||||
F.flash()
|
||||
|
||||
if(href_list["release"])
|
||||
if(timing)
|
||||
timer_end()
|
||||
Radio.autosay("Timer stopped manually from cell control.", name, "Security", list(z))
|
||||
ui_interact(usr)
|
||||
|
||||
if(href_list["prisoner_name"])
|
||||
prisoner_name = input("Prisoner Name:", name, prisoner_name) as text|null
|
||||
|
||||
if(href_list["prisoner_charge"])
|
||||
prisoner_charge = input("Prisoner Charge:", name, prisoner_charge) as text|null
|
||||
|
||||
if(href_list["prisoner_time"])
|
||||
prisoner_time = input("Prisoner Time (in minutes):", name, prisoner_time) as num|null
|
||||
prisoner_time = min(max(round(prisoner_time), 0), 60)
|
||||
|
||||
if(href_list["set_timer"])
|
||||
if(!prisoner_name || !prisoner_charge || !prisoner_time)
|
||||
return
|
||||
timeset(prisoner_time * 60)
|
||||
occupant = prisoner_name
|
||||
crimes = prisoner_charge
|
||||
prisoner_name = ""
|
||||
prisoner_charge = ""
|
||||
prisoner_time = ""
|
||||
timing = TRUE
|
||||
timer_start()
|
||||
ui_interact(usr)
|
||||
update_icon()
|
||||
prisoner_name = input("Prisoner Name:", name, prisoner_name) as text|null
|
||||
if(prisoner_name)
|
||||
var/datum/data/record/R = find_security_record("name", prisoner_name)
|
||||
if(istype(R))
|
||||
prisoner_hasrecord = TRUE
|
||||
else
|
||||
prisoner_hasrecord = FALSE
|
||||
if("prisoner_charge")
|
||||
prisoner_charge = input("Prisoner Charge:", name, prisoner_charge) as text|null
|
||||
if("prisoner_time")
|
||||
prisoner_time = input("Prisoner Time (in minutes):", name, prisoner_time) as num|null
|
||||
prisoner_time = min(max(round(prisoner_time), 0), 60)
|
||||
if("start")
|
||||
if(!prisoner_name || !prisoner_charge || !prisoner_time)
|
||||
return FALSE
|
||||
timeset(prisoner_time * 60)
|
||||
occupant = prisoner_name
|
||||
crimes = prisoner_charge
|
||||
prisoner_name = null
|
||||
prisoner_charge = null
|
||||
prisoner_time = null
|
||||
timing = TRUE
|
||||
timer_start()
|
||||
update_icon()
|
||||
if("restart_timer")
|
||||
if(timing)
|
||||
var/reset_reason = sanitize(copytext(input(usr, "Reason for resetting timer:", name, "") as text|null, 1, MAX_MESSAGE_LEN))
|
||||
if(!reset_reason)
|
||||
to_chat(usr, "<span class='warning'>Cancelled reset: reason field is required.</span>")
|
||||
return FALSE
|
||||
releasetime = world.timeofday + timetoset
|
||||
var/resettext = isobserver(usr) ? "for: [reset_reason]." : "by [usr.name] for: [reset_reason]."
|
||||
Radio.autosay("Prisoner [occupant] had their timer reset [resettext]", name, "Security", list(z))
|
||||
notify_prisoner("Your brig timer has been reset for: '[reset_reason]'.")
|
||||
var/datum/data/record/R = find_security_record("name", occupant)
|
||||
if(istype(R))
|
||||
R.fields["comments"] += "Autogenerated by [name] on [GLOB.current_date_string] [station_time_timestamp()]<BR>Timer reset [resettext]"
|
||||
else
|
||||
. = FALSE
|
||||
if("stop")
|
||||
if(timing)
|
||||
timer_end()
|
||||
var/stoptext = isobserver(usr) ? "from cell control." : "by [usr.name]."
|
||||
Radio.autosay("Timer stopped manually [stoptext]", name, "Security", list(z))
|
||||
else
|
||||
. = FALSE
|
||||
if("flash")
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
to_chat(usr, "<span class='warning'>Flash still charging.</span>")
|
||||
else
|
||||
F.flash()
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
//icon update function
|
||||
|
||||
@@ -33,6 +33,7 @@ FIRE ALARM
|
||||
var/last_process = 0
|
||||
var/wiresexposed = 0
|
||||
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
|
||||
var/enabled = FALSE
|
||||
|
||||
var/report_fire_alarms = TRUE // Should triggered fire alarms also trigger an actual alarm?
|
||||
var/show_alert_level = TRUE // Should fire alarms display the current alert level?
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
// Reasonable defaults, in case someone manually spawns us
|
||||
var/lasercolor = "r" //Something to do with lasertag turrets, blame Sieve for not adding a comment.
|
||||
installation = /obj/item/gun/energy/laser/tag/red
|
||||
targetting_is_configurable = FALSE
|
||||
lethal_is_configurable = FALSE
|
||||
shot_delay = 30
|
||||
iconholder = 1
|
||||
has_cover = FALSE
|
||||
always_up = TRUE
|
||||
raised = TRUE
|
||||
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
|
||||
|
||||
/obj/machinery/porta_turret/tag/red
|
||||
|
||||
@@ -18,43 +26,15 @@
|
||||
icon_state = "[lasercolor]grey_target_prism"
|
||||
|
||||
/obj/machinery/porta_turret/tag/weapon_setup(var/obj/item/gun/energy/E)
|
||||
switch(E.type)
|
||||
if(/obj/item/gun/energy/laser/tag/blue)
|
||||
eprojectile = /obj/item/gun/energy/laser/tag/blue
|
||||
lasercolor = "b"
|
||||
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
|
||||
check_arrest = 0
|
||||
check_records = 0
|
||||
check_weapons = 1
|
||||
check_access = 0
|
||||
check_anomalies = 0
|
||||
shot_delay = 30
|
||||
return
|
||||
|
||||
if(/obj/item/gun/energy/laser/tag/red)
|
||||
eprojectile = /obj/item/gun/energy/laser/tag/red
|
||||
lasercolor = "r"
|
||||
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
|
||||
check_arrest = 0
|
||||
check_records = 0
|
||||
check_weapons = 1
|
||||
check_access = 0
|
||||
check_anomalies = 0
|
||||
shot_delay = 30
|
||||
iconholder = 1
|
||||
|
||||
/obj/machinery/porta_turret/tag/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/porta_turret/tag/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
data["access"] = !isLocked(user)
|
||||
data["locked"] = locked
|
||||
data["enabled"] = enabled
|
||||
data["is_lethal"] = 0
|
||||
/obj/machinery/porta_turret/tag/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"locked" = isLocked(user), // does the current user have access?
|
||||
"on" = enabled, // is turret turned on?
|
||||
"lethal" = FALSE,
|
||||
"lethal_is_configurable" = lethal_is_configurable
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/porta_turret/tag/update_icon()
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
name = "turret"
|
||||
icon = 'icons/obj/turrets.dmi'
|
||||
icon_state = "turretCover"
|
||||
anchored = 1
|
||||
density = 0
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE //this turret uses and requires power
|
||||
idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power
|
||||
active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power
|
||||
power_channel = EQUIP //drains power from the EQUIPMENT channel
|
||||
armor = list(melee = 50, bullet = 30, laser = 30, energy = 30, bomb = 30, bio = 0, rad = 0, fire = 90, acid = 90)
|
||||
var/raised = 0 //if the turret cover is "open" and the turret is raised
|
||||
var/raising= 0 //if the turret is currently opening or closing its cover
|
||||
var/raised = FALSE //if the turret cover is "open" and the turret is raised
|
||||
var/raising= FALSE //if the turret is currently opening or closing its cover
|
||||
var/health = 80 //the turret's health
|
||||
var/locked = 1 //if the turret's behaviour control access is locked
|
||||
var/controllock = 0 //if the turret responds to control panels
|
||||
var/locked = TRUE //if the turret's behaviour control access is locked
|
||||
var/controllock = FALSE //if the turret responds to control panels. TRUE = does NOT respond
|
||||
|
||||
var/installation = /obj/item/gun/energy/gun/turret //the type of weapon installed
|
||||
var/gun_charge = 0 //the charge of the gun inserted
|
||||
@@ -31,68 +31,49 @@
|
||||
var/last_fired = 0 //1: if the turret is cooling down from a shot, 0: turret is ready to fire
|
||||
var/shot_delay = 15 //1.5 seconds between each shot
|
||||
|
||||
var/check_arrest = 1 //checks if the perp is set to arrest
|
||||
var/check_records = 1 //checks if a security record exists at all
|
||||
var/check_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
var/check_access = 1 //if this is active, the turret shoots everything that does not meet the access requirements
|
||||
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg
|
||||
var/ailock = 0 // AI cannot use this
|
||||
var/targetting_is_configurable = TRUE // if false, you cannot change who this turret attacks via its UI
|
||||
var/check_arrest = TRUE //checks if the perp is set to arrest
|
||||
var/check_records = TRUE //checks if a security record exists at all
|
||||
var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
var/check_access = TRUE //if this is active, the turret shoots everything that does not meet the access requirements
|
||||
var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg
|
||||
var/check_borgs = FALSE //if TRUE, target all cyborgs.
|
||||
var/ailock = FALSE // if TRUE, AI cannot use this
|
||||
|
||||
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
|
||||
var/attacked = FALSE //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
|
||||
|
||||
var/enabled = 1 //determines if the turret is on
|
||||
var/lethal = 0 //whether in lethal or stun mode
|
||||
var/disabled = 0
|
||||
var/enabled = TRUE //determines if the turret is on
|
||||
var/lethal = FALSE //whether in lethal or stun mode
|
||||
var/lethal_is_configurable = TRUE // if false, its lethal setting cannot be changed
|
||||
var/disabled = FALSE
|
||||
|
||||
var/shot_sound //what sound should play when the turret fires
|
||||
var/eshot_sound //what sound should play when the emagged turret fires
|
||||
|
||||
var/datum/effect_system/spark_spread/spark_system //the spark system, used for generating... sparks?
|
||||
|
||||
var/wrenching = 0
|
||||
var/wrenching = FALSE
|
||||
var/last_target //last target fired at, prevents turrets from erratically firing at all valid targets in range
|
||||
|
||||
var/screen = 0 // Screen 0: main control, screen 1: access levels
|
||||
var/one_access = 0 // Determines if access control is set to req_one_access or req_access
|
||||
var/one_access = FALSE // Determines if access control is set to req_one_access or req_access
|
||||
var/region_min = REGION_GENERAL
|
||||
var/region_max = REGION_COMMAND
|
||||
|
||||
var/syndicate = 0 //is the turret a syndicate turret?
|
||||
var/syndicate = FALSE //is the turret a syndicate turret?
|
||||
var/faction = ""
|
||||
var/emp_vulnerable = 1 // Can be empd
|
||||
var/emp_vulnerable = TRUE // Can be empd
|
||||
var/scan_range = 7
|
||||
var/always_up = 0 //Will stay active
|
||||
var/has_cover = 1 //Hides the cover
|
||||
var/always_up = FALSE //Will stay active
|
||||
var/has_cover = TRUE //Hides the cover
|
||||
|
||||
/obj/machinery/porta_turret/centcom
|
||||
name = "Centcom Turret"
|
||||
enabled = 0
|
||||
ailock = 1
|
||||
check_synth = 0
|
||||
check_access = 1
|
||||
check_arrest = 1
|
||||
check_records = 1
|
||||
check_weapons = 1
|
||||
check_anomalies = 1
|
||||
|
||||
/obj/machinery/porta_turret/centcom/pulse
|
||||
name = "Pulse Turret"
|
||||
health = 200
|
||||
enabled = 1
|
||||
lethal = 1
|
||||
req_access = list(ACCESS_CENT_COMMANDER)
|
||||
installation = /obj/item/gun/energy/pulse/turret
|
||||
|
||||
/obj/machinery/porta_turret/stationary
|
||||
ailock = 1
|
||||
lethal = 1
|
||||
installation = /obj/item/gun/energy/laser
|
||||
|
||||
/obj/machinery/porta_turret/Initialize(mapload)
|
||||
. = ..()
|
||||
if(req_access && req_access.len)
|
||||
req_access.Cut()
|
||||
req_one_access = list(ACCESS_SECURITY, ACCESS_HEADS)
|
||||
one_access = 1
|
||||
one_access = TRUE
|
||||
|
||||
//Sets up a spark system
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
@@ -110,7 +91,7 @@
|
||||
if(req_one_access && req_one_access.len)
|
||||
req_one_access.Cut()
|
||||
req_access = list(ACCESS_CENT_SPECOPS)
|
||||
one_access = 0
|
||||
one_access = FALSE
|
||||
|
||||
/obj/machinery/porta_turret/proc/setup()
|
||||
var/obj/item/gun/energy/E = new installation //All energy-based weapons are applicable
|
||||
@@ -185,152 +166,151 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
else
|
||||
icon_state = "turretCover"
|
||||
|
||||
/obj/machinery/porta_turret/proc/isLocked(mob/user)
|
||||
if(ailock && (isrobot(user) || isAI(user)))
|
||||
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
|
||||
return 1
|
||||
|
||||
if(locked && !(isrobot(user) || isAI(user) || isobserver(user)))
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/porta_turret/attack_ai(mob/user)
|
||||
if(isLocked(user))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/porta_turret/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/porta_turret/attack_hand(mob/user)
|
||||
if(isLocked(user))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/porta_turret/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 320)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/porta_turret/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
data["access"] = !isLocked(user)
|
||||
data["screen"] = screen
|
||||
data["locked"] = locked
|
||||
data["enabled"] = enabled
|
||||
data["lethal_control"] = !syndicate ? 1 : 0
|
||||
data["lethal"] = lethal
|
||||
|
||||
if(data["access"] && !syndicate)
|
||||
var/settings[0]
|
||||
settings[++settings.len] = list("category" = "Neutralize All Non-Synthetics", "setting" = "check_synth", "value" = check_synth)
|
||||
settings[++settings.len] = list("category" = "Check Weapon Authorization", "setting" = "check_weapons", "value" = check_weapons)
|
||||
settings[++settings.len] = list("category" = "Check Security Records", "setting" = "check_records", "value" = check_records)
|
||||
settings[++settings.len] = list("category" = "Check Arrest Status", "setting" = "check_arrest", "value" = check_arrest)
|
||||
settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access)
|
||||
settings[++settings.len] = list("category" = "Check Misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies)
|
||||
data["settings"] = settings
|
||||
|
||||
if(!syndicate)
|
||||
data["one_access"] = one_access
|
||||
var/accesses[0]
|
||||
var/list/access_list = get_all_accesses()
|
||||
for(var/access in access_list)
|
||||
var/name = get_access_desc(access)
|
||||
var/active
|
||||
if(one_access)
|
||||
active = (access in req_one_access)
|
||||
else
|
||||
active = (access in req_access)
|
||||
accesses[++accesses.len] = list("name" = name, "active" = active, "number" = access)
|
||||
data["accesses"] = accesses
|
||||
return data
|
||||
|
||||
/obj/machinery/porta_turret/proc/HasController()
|
||||
var/area/A = get_area(src)
|
||||
return A && A.turret_controls.len > 0
|
||||
|
||||
/obj/machinery/porta_turret/CanUseTopic(var/mob/user)
|
||||
/obj/machinery/porta_turret/proc/access_is_configurable()
|
||||
return targetting_is_configurable && !HasController()
|
||||
|
||||
/obj/machinery/porta_turret/proc/isLocked(mob/user)
|
||||
if(HasController())
|
||||
to_chat(user, "<span class='notice'>Turrets can only be controlled using the assigned turret controller.</span>")
|
||||
return STATUS_CLOSE
|
||||
return TRUE
|
||||
if(isrobot(user) || isAI(user))
|
||||
if(ailock)
|
||||
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
if(isobserver(user))
|
||||
if(user.can_admin_interact())
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
if(locked)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
if(isLocked(user))
|
||||
return STATUS_CLOSE
|
||||
/obj/machinery/porta_turret/attack_ai(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
if(!anchored)
|
||||
to_chat(usr, "<span class='notice'>\The [src] has to be secured first!</span>")
|
||||
return STATUS_CLOSE
|
||||
/obj/machinery/porta_turret/attack_ghost(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
return ..()
|
||||
/obj/machinery/porta_turret/attack_hand(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/porta_turret/Topic(href, href_list, var/nowindow = 0)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["command"] && href_list["value"])
|
||||
var/value = text2num(href_list["value"])
|
||||
if(href_list["command"] == "enable")
|
||||
enabled = value
|
||||
else if(syndicate)
|
||||
return 1
|
||||
else if(href_list["command"] == "screen")
|
||||
screen = value
|
||||
else if(href_list["command"] == "lethal")
|
||||
lethal = value
|
||||
else if(href_list["command"] == "check_synth")
|
||||
check_synth = value
|
||||
else if(href_list["command"] == "check_weapons")
|
||||
check_weapons = value
|
||||
else if(href_list["command"] == "check_records")
|
||||
check_records = value
|
||||
else if(href_list["command"] == "check_arrest")
|
||||
check_arrest = value
|
||||
else if(href_list["command"] == "check_access")
|
||||
check_access = value
|
||||
else if(href_list["command"] == "check_anomalies")
|
||||
check_anomalies = value
|
||||
|
||||
if(!syndicate)
|
||||
if(href_list["one_access"])
|
||||
toggle_one_access(href_list["one_access"])
|
||||
|
||||
if(href_list["access"])
|
||||
toggle_access(href_list["access"])
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/porta_turret/proc/toggle_one_access(var/access)
|
||||
one_access = text2num(access)
|
||||
|
||||
if(one_access == 1)
|
||||
req_one_access = req_access.Copy()
|
||||
req_access.Cut()
|
||||
else if(one_access == 0)
|
||||
req_access = req_one_access.Copy()
|
||||
req_one_access.Cut()
|
||||
|
||||
/obj/machinery/porta_turret/proc/toggle_access(var/access)
|
||||
var/required = text2num(access)
|
||||
if(!(required in get_all_accesses()))
|
||||
/obj/machinery/porta_turret/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
if(HasController())
|
||||
to_chat(user, "<span class='notice'>[src] can only be controlled using the assigned turret controller.</span>")
|
||||
return
|
||||
if(!anchored)
|
||||
to_chat(user, "<span class='notice'>[src] has to be secured first!</span>")
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "PortableTurret", name, 500, access_is_configurable() ? 800 : 400)
|
||||
ui.open()
|
||||
|
||||
if(one_access)
|
||||
if((required in req_one_access))
|
||||
req_one_access -= required
|
||||
else
|
||||
req_one_access += required
|
||||
else
|
||||
if((required in req_access))
|
||||
req_access -= required
|
||||
else
|
||||
req_access += required
|
||||
/obj/machinery/porta_turret/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"locked" = isLocked(user), // does the current user have access?
|
||||
"on" = enabled,
|
||||
"targetting_is_configurable" = targetting_is_configurable, // If false, targetting settings don't show up
|
||||
"lethal" = lethal,
|
||||
"lethal_is_configurable" = lethal_is_configurable,
|
||||
"check_weapons" = check_weapons,
|
||||
"neutralize_noaccess" = check_access,
|
||||
"one_access" = one_access,
|
||||
"selectedAccess" = one_access ? req_one_access : req_access,
|
||||
"access_is_configurable" = access_is_configurable(),
|
||||
"neutralize_norecord" = check_records,
|
||||
"neutralize_criminals" = check_arrest,
|
||||
"neutralize_all" = check_synth,
|
||||
"neutralize_unidentified" = check_anomalies,
|
||||
"neutralize_cyborgs" = check_borgs
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/porta_turret/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["regions"] = get_accesslist_static_data(region_min, region_max)
|
||||
return data
|
||||
|
||||
/obj/machinery/porta_turret/tgui_act(action, params)
|
||||
if (..())
|
||||
return
|
||||
if(isLocked(usr))
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("power")
|
||||
enabled = !enabled
|
||||
if("lethal")
|
||||
if(lethal_is_configurable)
|
||||
lethal = !lethal
|
||||
if(targetting_is_configurable)
|
||||
switch(action)
|
||||
if("authweapon")
|
||||
check_weapons = !check_weapons
|
||||
if("authaccess")
|
||||
check_access = !check_access
|
||||
if("authnorecord")
|
||||
check_records = !check_records
|
||||
if("autharrest")
|
||||
check_arrest = !check_arrest
|
||||
if("authxeno")
|
||||
check_anomalies = !check_anomalies
|
||||
if("authsynth")
|
||||
check_synth = !check_synth
|
||||
if("authborgs")
|
||||
check_borgs = !check_borgs
|
||||
if("set")
|
||||
var/access = text2num(params["access"])
|
||||
if(one_access)
|
||||
if(!(access in req_one_access))
|
||||
req_one_access += access
|
||||
else
|
||||
req_one_access -= access
|
||||
else
|
||||
if(!(access in req_access))
|
||||
req_access += access
|
||||
else
|
||||
req_access -= access
|
||||
if(access_is_configurable())
|
||||
switch(action)
|
||||
if("grant_region")
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region))
|
||||
return
|
||||
if(one_access)
|
||||
req_one_access |= get_region_accesses(region)
|
||||
else
|
||||
req_access |= get_region_accesses(region)
|
||||
if("deny_region")
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region))
|
||||
return
|
||||
if(one_access)
|
||||
req_one_access -= get_region_accesses(region)
|
||||
else
|
||||
req_access -= get_region_accesses(region)
|
||||
if("clear_all")
|
||||
if(one_access)
|
||||
req_one_access = list()
|
||||
else
|
||||
req_access = list()
|
||||
if("grant_all")
|
||||
if(one_access)
|
||||
req_one_access = get_all_accesses()
|
||||
else
|
||||
req_access = get_all_accesses()
|
||||
if("one_access")
|
||||
if(one_access)
|
||||
req_one_access = list()
|
||||
else
|
||||
req_access = list()
|
||||
one_access = !one_access
|
||||
|
||||
/obj/machinery/porta_turret/power_change()
|
||||
if(powered() || !use_power)
|
||||
@@ -379,23 +359,25 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
"<span class='notice'>You begin [anchored ? "un" : ""]securing the turret.</span>" \
|
||||
)
|
||||
|
||||
wrenching = 1
|
||||
wrenching = TRUE
|
||||
if(do_after(user, 50 * I.toolspeed, target = src))
|
||||
//This code handles moving the turret around. After all, it's a portable turret!
|
||||
if(!anchored)
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
anchored = 1
|
||||
anchored = TRUE
|
||||
update_icon()
|
||||
to_chat(user, "<span class='notice'>You secure the exterior bolts on the turret.</span>")
|
||||
else if(anchored)
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
anchored = 0
|
||||
anchored = FALSE
|
||||
to_chat(user, "<span class='notice'>You unsecure the exterior bolts on the turret.</span>")
|
||||
update_icon()
|
||||
wrenching = 0
|
||||
wrenching = FALSE
|
||||
|
||||
else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
|
||||
if(allowed(user))
|
||||
if(HasController())
|
||||
to_chat(user, "<span class='notice'>Turrets regulated by a nearby turret controller are not unlockable.</span>")
|
||||
else if(allowed(user))
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
|
||||
updateUsrDialog()
|
||||
@@ -409,9 +391,9 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
playsound(src.loc, 'sound/weapons/smash.ogg', 60, 1)
|
||||
if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off
|
||||
if(!attacked && !emagged)
|
||||
attacked = 1
|
||||
attacked = TRUE
|
||||
spawn(60)
|
||||
attacked = 0
|
||||
attacked = FALSE
|
||||
|
||||
..()
|
||||
|
||||
@@ -445,12 +427,12 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>You short out [src]'s threat assessment circuits.</span>")
|
||||
visible_message("[src] hums oddly...")
|
||||
emagged = 1
|
||||
emagged = TRUE
|
||||
iconholder = 1
|
||||
controllock = 1
|
||||
enabled = 0 //turns off the turret temporarily
|
||||
controllock = TRUE
|
||||
enabled = FALSE //turns off the turret temporarily
|
||||
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
|
||||
enabled = 1 //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
|
||||
enabled = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
|
||||
|
||||
/obj/machinery/porta_turret/take_damage(force)
|
||||
if(!raised && !raising)
|
||||
@@ -470,9 +452,9 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
|
||||
if(enabled)
|
||||
if(!attacked && !emagged)
|
||||
attacked = 1
|
||||
attacked = TRUE
|
||||
spawn(60)
|
||||
attacked = 0
|
||||
attacked = FALSE
|
||||
|
||||
..()
|
||||
|
||||
@@ -489,12 +471,12 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
check_access = prob(20) // check_access is a pretty big deal, so it's least likely to get turned on
|
||||
check_anomalies = prob(50)
|
||||
if(prob(5))
|
||||
emagged = 1
|
||||
emagged = TRUE
|
||||
|
||||
enabled=0
|
||||
spawn(rand(60,600))
|
||||
spawn(rand(60, 600))
|
||||
if(!enabled)
|
||||
enabled=1
|
||||
enabled = TRUE
|
||||
|
||||
..()
|
||||
|
||||
@@ -585,8 +567,8 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
if(get_turf(L) == get_turf(src))
|
||||
return TURRET_NOT_TARGET
|
||||
|
||||
if(!emagged && !syndicate && (issilicon(L) || isbot(L))) // Don't target silica
|
||||
return TURRET_NOT_TARGET
|
||||
if(!emagged && !syndicate && (issilicon(L) || isbot(L)))
|
||||
return (check_borgs && isrobot(L)) ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET
|
||||
|
||||
if(L.stat && !emagged) //if the perp is dead/dying, no need to bother really
|
||||
return TURRET_NOT_TARGET //move onto next potential victim!
|
||||
@@ -643,7 +625,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
set_raised_raising(raised, 1)
|
||||
set_raised_raising(raised, TRUE)
|
||||
playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
|
||||
update_icon()
|
||||
|
||||
@@ -653,7 +635,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
sleep(10)
|
||||
qdel(flick_holder)
|
||||
|
||||
set_raised_raising(1, 0)
|
||||
set_raised_raising(TRUE, FALSE)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/porta_turret/proc/popDown() //pops the turret down
|
||||
@@ -664,7 +646,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
set_raised_raising(raised, 1)
|
||||
set_raised_raising(raised, TRUE)
|
||||
playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
|
||||
update_icon()
|
||||
|
||||
@@ -674,7 +656,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
sleep(10)
|
||||
qdel(flick_holder)
|
||||
|
||||
set_raised_raising(0, 0)
|
||||
set_raised_raising(FALSE, FALSE)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/porta_turret/on_assess_perp(mob/living/carbon/human/perp)
|
||||
@@ -739,6 +721,27 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
A.throw_at(target, scan_range, 1)
|
||||
return A
|
||||
|
||||
/obj/machinery/porta_turret/centcom
|
||||
name = "Centcom Turret"
|
||||
enabled = FALSE
|
||||
ailock = TRUE
|
||||
check_synth = FALSE
|
||||
check_access = TRUE
|
||||
check_arrest = TRUE
|
||||
check_records = TRUE
|
||||
check_weapons = TRUE
|
||||
check_anomalies = TRUE
|
||||
region_max = REGION_CENTCOMM // Non-turretcontrolled turrets at CC can have their access customized to check for CC accesses.
|
||||
|
||||
/obj/machinery/porta_turret/centcom/pulse
|
||||
name = "Pulse Turret"
|
||||
health = 200
|
||||
enabled = TRUE
|
||||
lethal = TRUE
|
||||
lethal_is_configurable = FALSE
|
||||
req_access = list(ACCESS_CENT_COMMANDER)
|
||||
installation = /obj/item/gun/energy/pulse/turret
|
||||
|
||||
/datum/turret_checks
|
||||
var/enabled
|
||||
var/lethal
|
||||
@@ -748,6 +751,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
var/check_arrest
|
||||
var/check_weapons
|
||||
var/check_anomalies
|
||||
var/check_borgs
|
||||
var/ailock
|
||||
|
||||
/obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC)
|
||||
@@ -763,6 +767,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
check_arrest = TC.check_arrest
|
||||
check_weapons = TC.check_weapons
|
||||
check_anomalies = TC.check_anomalies
|
||||
check_borgs = TC.check_borgs
|
||||
ailock = TC.ailock
|
||||
|
||||
power_change()
|
||||
@@ -791,7 +796,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
if(istype(I, /obj/item/wrench) && !anchored)
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
to_chat(user, "<span class='notice'>You secure the external bolts.</span>")
|
||||
anchored = 1
|
||||
anchored = TRUE
|
||||
build_step = 1
|
||||
return
|
||||
|
||||
@@ -816,7 +821,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
else if(istype(I, /obj/item/wrench))
|
||||
playsound(loc, I.usesound, 75, 1)
|
||||
to_chat(user, "<span class='notice'>You unfasten the external bolts.</span>")
|
||||
anchored = 0
|
||||
anchored = FALSE
|
||||
build_step = 0
|
||||
return
|
||||
|
||||
@@ -841,8 +846,10 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
gun_charge = E.cell.charge //the gun's charge is stored in gun_charge
|
||||
to_chat(user, "<span class='notice'>You add [I] to the turret.</span>")
|
||||
|
||||
if(istype(installation, /obj/item/gun/energy/laser/tag/blue) || istype(installation, /obj/item/gun/energy/laser/tag/red))
|
||||
target_type = /obj/machinery/porta_turret/tag
|
||||
if(istype(E, /obj/item/gun/energy/laser/tag/blue))
|
||||
target_type = /obj/machinery/porta_turret/tag/blue
|
||||
else if(istype(E, /obj/item/gun/energy/laser/tag/red))
|
||||
target_type = /obj/machinery/porta_turret/tag/red
|
||||
else
|
||||
target_type = /obj/machinery/porta_turret
|
||||
|
||||
@@ -934,7 +941,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
Turret.name = finish_name
|
||||
Turret.installation = installation
|
||||
Turret.gun_charge = gun_charge
|
||||
Turret.enabled = 0
|
||||
Turret.enabled = FALSE
|
||||
Turret.setup()
|
||||
|
||||
qdel(src)
|
||||
@@ -981,25 +988,27 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
var/icon_state_active = "syndieturret1"
|
||||
var/icon_state_destroyed = "syndieturret2"
|
||||
|
||||
syndicate = 1
|
||||
syndicate = TRUE
|
||||
installation = null
|
||||
always_up = 1
|
||||
always_up = TRUE
|
||||
use_power = NO_POWER_USE
|
||||
has_cover = 0
|
||||
raised = 1
|
||||
has_cover = FALSE
|
||||
raised = TRUE
|
||||
scan_range = 9
|
||||
|
||||
faction = "syndicate"
|
||||
emp_vulnerable = 0
|
||||
emp_vulnerable = FALSE
|
||||
|
||||
lethal = 1
|
||||
check_arrest = 0
|
||||
check_records = 0
|
||||
check_weapons = 0
|
||||
check_access = 0
|
||||
check_anomalies = 1
|
||||
check_synth = 1
|
||||
ailock = 1
|
||||
lethal = TRUE
|
||||
lethal_is_configurable = FALSE
|
||||
targetting_is_configurable = FALSE
|
||||
check_arrest = FALSE
|
||||
check_records = FALSE
|
||||
check_weapons = FALSE
|
||||
check_access = FALSE
|
||||
check_anomalies = TRUE
|
||||
check_synth = TRUE
|
||||
ailock = TRUE
|
||||
var/area/syndicate_depot/core/depotarea
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/die()
|
||||
@@ -1018,7 +1027,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
|
||||
if(req_one_access && req_one_access.len)
|
||||
req_one_access.Cut()
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
one_access = 0
|
||||
one_access = FALSE
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/update_icon()
|
||||
if(stat & BROKEN)
|
||||
|
||||
@@ -11,51 +11,56 @@
|
||||
desc = "Used to control a room's automated defenses."
|
||||
icon = 'icons/obj/machines/turret_control.dmi'
|
||||
icon_state = "control_standby"
|
||||
anchored = 1
|
||||
density = 0
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/enabled = 0
|
||||
var/lethal = 0
|
||||
var/locked = 1
|
||||
var/enabled = FALSE
|
||||
var/lethal = FALSE
|
||||
var/lethal_is_configurable = TRUE
|
||||
var/locked = TRUE
|
||||
var/area/control_area //can be area name, path or nothing.
|
||||
|
||||
var/check_arrest = 1 //checks if the perp is set to arrest
|
||||
var/check_records = 1 //checks if a security record exists at all
|
||||
var/check_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
var/check_access = 1 //if this is active, the turret shoots everything that does not meet the access requirements
|
||||
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg
|
||||
var/ailock = 0 //Silicons cannot use this
|
||||
var/targetting_is_configurable = TRUE // if false, you cannot change who this turret attacks via its UI
|
||||
var/check_arrest = TRUE //checks if the perp is set to arrest
|
||||
var/check_records = TRUE //checks if a security record exists at all
|
||||
var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
var/check_access = TRUE //if this is active, the turret shoots everything that does not meet the access requirements
|
||||
var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg
|
||||
var/check_borgs = FALSE //if TRUE, target all cyborgs.
|
||||
var/ailock = FALSE //Silicons cannot use this
|
||||
|
||||
var/syndicate = 0
|
||||
var/syndicate = FALSE
|
||||
var/faction = "" // Turret controls can only access turrets that are in the same faction
|
||||
|
||||
req_access = list(ACCESS_AI_UPLOAD)
|
||||
|
||||
/obj/machinery/turretid/stun
|
||||
enabled = 1
|
||||
enabled = TRUE
|
||||
icon_state = "control_stun"
|
||||
|
||||
/obj/machinery/turretid/lethal
|
||||
enabled = 1
|
||||
lethal = 1
|
||||
enabled = TRUE
|
||||
lethal = TRUE
|
||||
icon_state = "control_kill"
|
||||
|
||||
/obj/machinery/turretid/syndicate
|
||||
enabled = 1
|
||||
lethal = 1
|
||||
enabled = TRUE
|
||||
lethal = TRUE
|
||||
lethal_is_configurable = FALSE
|
||||
targetting_is_configurable = FALSE
|
||||
icon_state = "control_kill"
|
||||
|
||||
lethal = 1
|
||||
check_arrest = 0
|
||||
check_records = 0
|
||||
check_weapons = 0
|
||||
check_access = 0
|
||||
check_anomalies = 1
|
||||
check_synth = 1
|
||||
ailock = 1
|
||||
check_arrest = FALSE
|
||||
check_records = FALSE
|
||||
check_weapons = FALSE
|
||||
check_access = FALSE
|
||||
check_anomalies = TRUE
|
||||
check_synth = TRUE
|
||||
check_borgs = FALSE
|
||||
ailock = TRUE
|
||||
|
||||
syndicate = 1
|
||||
syndicate = TRUE
|
||||
faction = "syndicate"
|
||||
req_access = list(ACCESS_SYNDICATE_LEADER)
|
||||
|
||||
@@ -87,21 +92,23 @@
|
||||
return
|
||||
|
||||
/obj/machinery/turretid/proc/isLocked(mob/user)
|
||||
if(ailock && (isrobot(user) || isAI(user)))
|
||||
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
|
||||
return 1
|
||||
if(isrobot(user) || isAI(user))
|
||||
if(ailock)
|
||||
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
if(locked && !(isrobot(user) || isAI(user) || isobserver(user)))
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
return 1
|
||||
if(isobserver(user))
|
||||
if(user.can_admin_interact())
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
return 0
|
||||
if(locked)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/turretid/CanUseTopic(mob/user)
|
||||
if(isLocked(user))
|
||||
return STATUS_CLOSE
|
||||
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/turretid/attackby(obj/item/W, mob/user)
|
||||
if(stat & BROKEN)
|
||||
@@ -120,89 +127,82 @@
|
||||
/obj/machinery/turretid/emag_act(user as mob)
|
||||
if(!emagged)
|
||||
to_chat(user, "<span class='danger'>You short out the turret controls' access analysis module.</span>")
|
||||
emagged = 1
|
||||
locked = 0
|
||||
ailock = 0
|
||||
emagged = TRUE
|
||||
locked = FALSE
|
||||
ailock = FALSE
|
||||
return
|
||||
|
||||
/obj/machinery/turretid/attack_ai(mob/user as mob)
|
||||
if(isLocked(user))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/turretid/attack_ghost(mob/user as mob)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/turretid/attack_hand(mob/user as mob)
|
||||
if(isLocked(user))
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/turretid/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/turretid/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 350)
|
||||
ui = new(user, src, ui_key, "PortableTurret", name, 500, 400)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/turretid/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
data["access"] = !isLocked(user)
|
||||
data["locked"] = locked
|
||||
data["enabled"] = enabled
|
||||
data["lethal_control"] = !syndicate ? 1 : 0
|
||||
data["lethal"] = lethal
|
||||
|
||||
if(data["access"] && !syndicate)
|
||||
var/settings[0]
|
||||
settings[++settings.len] = list("category" = "Neutralize All Non-Synthetics", "setting" = "check_synth", "value" = check_synth)
|
||||
settings[++settings.len] = list("category" = "Check Weapon Authorization", "setting" = "check_weapons", "value" = check_weapons)
|
||||
settings[++settings.len] = list("category" = "Check Security Records", "setting" = "check_records", "value" = check_records)
|
||||
settings[++settings.len] = list("category" = "Check Arrest Status", "setting" = "check_arrest", "value" = check_arrest)
|
||||
settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access)
|
||||
settings[++settings.len] = list("category" = "Check Misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies)
|
||||
data["settings"] = settings
|
||||
|
||||
/obj/machinery/turretid/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"locked" = isLocked(user), // does the current user have access?
|
||||
"on" = enabled,
|
||||
"targetting_is_configurable" = targetting_is_configurable, // If false, targetting settings don't show up
|
||||
"lethal" = lethal,
|
||||
"lethal_is_configurable" = lethal_is_configurable,
|
||||
"check_weapons" = check_weapons,
|
||||
"neutralize_noaccess" = check_access,
|
||||
"one_access" = FALSE,
|
||||
"selectedAccess" = list(),
|
||||
"access_is_configurable" = FALSE,
|
||||
"neutralize_norecord" = check_records,
|
||||
"neutralize_criminals" = check_arrest,
|
||||
"neutralize_all" = check_synth,
|
||||
"neutralize_unidentified" = check_anomalies,
|
||||
"neutralize_cyborgs" = check_borgs
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/turretid/Topic(href, href_list, var/nowindow = 0)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
/obj/machinery/turretid/tgui_act(action, params)
|
||||
if (..())
|
||||
return
|
||||
if(isLocked(usr))
|
||||
return 1
|
||||
|
||||
if(href_list["command"] && href_list["value"])
|
||||
var/value = text2num(href_list["value"])
|
||||
if(href_list["command"] == "enable")
|
||||
enabled = value
|
||||
else if(syndicate)
|
||||
return 1
|
||||
else if(href_list["command"] == "lethal")
|
||||
lethal = value
|
||||
else if(href_list["command"] == "check_synth")
|
||||
check_synth = value
|
||||
else if(href_list["command"] == "check_weapons")
|
||||
check_weapons = value
|
||||
else if(href_list["command"] == "check_records")
|
||||
check_records = value
|
||||
else if(href_list["command"] == "check_arrest")
|
||||
check_arrest = value
|
||||
else if(href_list["command"] == "check_access")
|
||||
check_access = value
|
||||
else if(href_list["command"] == "check_anomalies")
|
||||
check_anomalies = value
|
||||
|
||||
updateTurrets()
|
||||
return 1
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("power")
|
||||
enabled = !enabled
|
||||
if("lethal")
|
||||
if(lethal_is_configurable)
|
||||
lethal = !lethal
|
||||
if(targetting_is_configurable)
|
||||
switch(action)
|
||||
if("authweapon")
|
||||
check_weapons = !check_weapons
|
||||
if("authaccess")
|
||||
check_access = !check_access
|
||||
if("authnorecord")
|
||||
check_records = !check_records
|
||||
if("autharrest")
|
||||
check_arrest = !check_arrest
|
||||
if("authxeno")
|
||||
check_anomalies = !check_anomalies
|
||||
if("authsynth")
|
||||
check_synth = !check_synth
|
||||
if("authborgs")
|
||||
check_borgs = !check_borgs
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/turretid/proc/updateTurrets()
|
||||
var/datum/turret_checks/TC = new
|
||||
TC.enabled = enabled
|
||||
TC.lethal = lethal
|
||||
TC.check_synth = check_synth
|
||||
TC.check_borgs = check_borgs
|
||||
TC.check_access = check_access
|
||||
TC.check_records = check_records
|
||||
TC.check_arrest = check_arrest
|
||||
|
||||
+275
-249
@@ -11,9 +11,6 @@
|
||||
var/max_amount = 0
|
||||
var/price = 0 // Price to buy one
|
||||
|
||||
/**
|
||||
* A vending machine
|
||||
*/
|
||||
/obj/machinery/vending
|
||||
name = "\improper Vendomat"
|
||||
desc = "A generic vending machine."
|
||||
@@ -25,8 +22,10 @@
|
||||
max_integrity = 300
|
||||
integrity_failure = 100
|
||||
armor = list(melee = 20, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70)
|
||||
var/icon_vend //Icon_state when vending
|
||||
var/icon_deny //Icon_state when denying access
|
||||
/// Icon_state when vending
|
||||
var/icon_vend
|
||||
/// Icon_state when denying access
|
||||
var/icon_deny
|
||||
|
||||
// Power
|
||||
use_power = IDLE_POWER_USE
|
||||
@@ -34,12 +33,14 @@
|
||||
var/vend_power_usage = 150
|
||||
|
||||
// Vending-related
|
||||
var/active = 1 //No sales pitches if off!
|
||||
var/vend_ready = 1 //Are we ready to vend?? Is it time??
|
||||
var/vend_delay = 10 //How long does it take to vend?
|
||||
var/datum/data/vending_product/currently_vending = null // What we're requesting payment for right now
|
||||
var/status_message = "" // Status screen messages like "insufficient funds", displayed in NanoUI
|
||||
var/status_error = 0 // Set to 1 if status_message is an error
|
||||
/// No sales pitches if off
|
||||
var/active = 1
|
||||
/// If off, vendor is busy and unusable until current action finishes
|
||||
var/vend_ready = TRUE
|
||||
/// How long vendor takes to vend one item.
|
||||
var/vend_delay = 10
|
||||
/// Item currently being bought
|
||||
var/datum/data/vending_product/currently_vending = null
|
||||
|
||||
// To be filled out at compile time
|
||||
var/list/products = list() // For each, use the following pattern:
|
||||
@@ -51,16 +52,19 @@
|
||||
var/list/product_records = list()
|
||||
var/list/hidden_records = list()
|
||||
var/list/coin_records = list()
|
||||
var/list/imagelist = list()
|
||||
|
||||
|
||||
var/list/ads_list = list() //Small ad messages in the vending screen - random chance, TODO: implementation
|
||||
/// Unimplemented list of ads that are meant to show up somewhere, but don't.
|
||||
var/list/ads_list = list()
|
||||
|
||||
// Stuff relating vocalizations
|
||||
var/list/slogan_list = list() //List of slogans the vendor will say, optional
|
||||
/// List of slogans the vendor will say, optional
|
||||
var/list/slogan_list = list()
|
||||
var/vend_reply //Thank you for shopping!
|
||||
var/shut_up = 0 //Stop spouting those godawful pitches!
|
||||
/// If true, prevent saying sales pitches
|
||||
var/shut_up = FALSE
|
||||
///can we access the hidden inventory?
|
||||
var/extended_inventory = 0
|
||||
var/extended_inventory = FALSE
|
||||
var/last_reply = 0
|
||||
var/last_slogan = 0 //When did we last pitch?
|
||||
var/slogan_delay = 6000 //How long until we can pitch again?
|
||||
@@ -69,17 +73,26 @@
|
||||
var/obj/item/vending_refill/refill_canister = null
|
||||
|
||||
// Things that can go wrong
|
||||
emagged = 0 //Ignores if somebody doesn't have card access to that machine.
|
||||
var/seconds_electrified = 0 //Shock customers like an airlock.
|
||||
var/shoot_inventory = 0 //Fire items at customers! We're broken!
|
||||
var/shoot_speed = 3 //How hard are we firing the items?
|
||||
var/shoot_chance = 2 //How often are we firing the items?
|
||||
/// Allows people to access a vendor that's normally access restricted.
|
||||
emagged = 0
|
||||
/// Shocks people like an airlock
|
||||
var/seconds_electrified = 0
|
||||
/// Fire items at customers! We're broken!
|
||||
var/shoot_inventory = FALSE
|
||||
/// How hard are we firing the items?
|
||||
var/shoot_speed = 3
|
||||
/// How often are we firing the items? (prob(...))
|
||||
var/shoot_chance = 2
|
||||
|
||||
var/scan_id = 1
|
||||
/// If true, enforce access checks on customers. Disabled by messing with wires.
|
||||
var/scan_id = TRUE
|
||||
/// Holder for a coin inserted into the vendor
|
||||
var/obj/item/coin/coin
|
||||
var/datum/wires/vending/wires = null
|
||||
|
||||
/// boolean, whether this vending machine can accept people inserting items into it, used for coffee vendors
|
||||
var/item_slot = FALSE
|
||||
/// the actual item inserted
|
||||
var/obj/item/inserted_item = null
|
||||
|
||||
/obj/machinery/vending/Initialize(mapload)
|
||||
@@ -92,6 +105,10 @@
|
||||
build_inventory(products, product_records)
|
||||
build_inventory(contraband, hidden_records)
|
||||
build_inventory(premium, coin_records)
|
||||
for (var/datum/data/vending_product/R in (product_records + coin_records + hidden_records))
|
||||
var/obj/item/I = R.product_path
|
||||
var/pp = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-")
|
||||
imagelist[pp] = "[icon2base64(icon(initial(I.icon), initial(I.icon_state)))]"
|
||||
if(LAZYLEN(slogan_list))
|
||||
// So not all machines speak at the exact same time.
|
||||
// The first time this machine says something will be at slogantime + this random value,
|
||||
@@ -214,37 +231,16 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/vending/attackby(obj/item/I, mob/user, params)
|
||||
if(currently_vending && GLOB.vendor_account && !GLOB.vendor_account.suspended)
|
||||
var/paid = 0
|
||||
var/handled = 0
|
||||
if(istype(I, /obj/item/card/id))
|
||||
var/obj/item/card/id/C = I
|
||||
paid = pay_with_card(C)
|
||||
handled = 1
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/PDA = I
|
||||
if(PDA.id)
|
||||
paid = pay_with_card(PDA.id)
|
||||
handled = 1
|
||||
else if(istype(I, /obj/item/stack/spacecash))
|
||||
var/obj/item/stack/spacecash/C = I
|
||||
paid = pay_with_cash(C, user)
|
||||
handled = 1
|
||||
|
||||
if(paid)
|
||||
vend(currently_vending, usr)
|
||||
if(istype(I, /obj/item/coin))
|
||||
if(!premium.len)
|
||||
to_chat(user, "<span class='warning'>[src] does not accept coins.</span>")
|
||||
return
|
||||
else if(handled)
|
||||
SSnanoui.update_uis(src)
|
||||
return // don't smack that machine with your 2 thalers
|
||||
|
||||
if(istype(I, /obj/item/coin) && premium.len)
|
||||
if(!user.drop_item())
|
||||
return
|
||||
I.forceMove(src)
|
||||
coin = I
|
||||
to_chat(user, "<span class='notice'>You insert the [I] into the [src]</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
if(refill_canister && istype(I, refill_canister))
|
||||
if(!panel_open)
|
||||
@@ -295,7 +291,7 @@
|
||||
else
|
||||
SCREWDRIVER_CLOSE_PANEL_MESSAGE
|
||||
overlays.Cut()
|
||||
SSnanoui.update_uis(src) // Speaker switch is on the main UI, not wires UI
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/wirecutter_act(mob/user, obj/item/I)
|
||||
. = TRUE
|
||||
@@ -359,12 +355,10 @@
|
||||
if(!user.drop_item())
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to your hand, you can't seem to put it down!</span>")
|
||||
return
|
||||
|
||||
inserted_item = I
|
||||
I.forceMove(src)
|
||||
|
||||
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/proc/eject_item(mob/user)
|
||||
if(!item_slot || !inserted_item)
|
||||
@@ -377,23 +371,19 @@
|
||||
var/turf/T = get_turf(src)
|
||||
inserted_item.forceMove(T)
|
||||
inserted_item = null
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/emag_act(user as mob)
|
||||
emagged = TRUE
|
||||
to_chat(user, "You short out the product lock on [src]")
|
||||
|
||||
/**
|
||||
* Receive payment with cashmoney.
|
||||
*
|
||||
* usr is the mob who gets the change.
|
||||
*/
|
||||
|
||||
/obj/machinery/vending/proc/pay_with_cash(obj/item/stack/spacecash/cashmoney, mob/user)
|
||||
if(currently_vending.price > cashmoney.amount)
|
||||
// This is not a status display message, since it's something the character
|
||||
// themselves is meant to see BEFORE putting the money in
|
||||
to_chat(usr, "[bicon(cashmoney)] <span class='warning'>That is not enough money.</span>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
// Bills (banknotes) cannot really have worth different than face value,
|
||||
// so we have to eat the bill and spit out change in a bundle
|
||||
@@ -405,50 +395,36 @@
|
||||
|
||||
// Vending machines have no idea who paid with cash
|
||||
GLOB.vendor_account.credit(currently_vending.price, "Sale of [currently_vending.name]", name, "(cash)")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Scan a card and attempt to transfer payment from associated account.
|
||||
*
|
||||
* Takes payment for whatever is the currently_vending item. Returns 1 if
|
||||
* successful, 0 if failed
|
||||
*/
|
||||
/obj/machinery/vending/proc/pay_with_card(var/obj/item/card/id/I)
|
||||
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
|
||||
return pay_with_account(get_card_account(I))
|
||||
|
||||
/obj/machinery/vending/proc/pay_with_account(var/datum/money_account/customer_account)
|
||||
/obj/machinery/vending/proc/pay_with_card(obj/item/card/id/I, mob/M)
|
||||
visible_message("<span class='info'>[M] swipes a card through [src].</span>")
|
||||
return pay_with_account(get_card_account(I), M)
|
||||
|
||||
/obj/machinery/vending/proc/pay_with_account(datum/money_account/customer_account, mob/M)
|
||||
if(!customer_account)
|
||||
src.status_message = "Error: Unable to access account. Please contact technical support if problem persists."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
|
||||
to_chat(M, "<span class='warning'>Error: Unable to access account. Please contact technical support if problem persists.</span>")
|
||||
return FALSE
|
||||
if(customer_account.suspended)
|
||||
src.status_message = "Unable to access account: account suspended."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
|
||||
// Have the customer punch in the PIN before checking if there's enough money. Prevents people from figuring out acct is
|
||||
// empty at high security levels
|
||||
if(customer_account.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
|
||||
to_chat(M, "<span class='warning'>Unable to access account: account suspended.</span>")
|
||||
return FALSE
|
||||
// Have the customer punch in the PIN before checking if there's enough money.
|
||||
// Prevents people from figuring out acct is empty at high security levels
|
||||
if(customer_account.security_level != 0)
|
||||
// If card requires pin authentication (ie seclevel 1 or 2)
|
||||
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
|
||||
|
||||
if(!attempt_account_access(customer_account.account_number, attempt_pin, 2))
|
||||
src.status_message = "Unable to access account: incorrect credentials."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
|
||||
to_chat(M, "<span class='warning'>Unable to access account: incorrect credentials.</span>")
|
||||
return FALSE
|
||||
if(currently_vending.price > customer_account.money)
|
||||
src.status_message = "Insufficient funds in account."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
else
|
||||
// Okay to move the money at this point
|
||||
customer_account.charge(currently_vending.price, GLOB.vendor_account,
|
||||
"Purchase of [currently_vending.name]", name, GLOB.vendor_account.owner_name,
|
||||
"Sale of [currently_vending.name]", customer_account.owner_name)
|
||||
|
||||
return TRUE
|
||||
to_chat(M, "<span class='warning'>Your bank account has insufficient money to purchase this.</span>")
|
||||
return FALSE
|
||||
// Okay to move the money at this point
|
||||
customer_account.charge(currently_vending.price, GLOB.vendor_account,
|
||||
"Purchase of [currently_vending.name]", name, GLOB.vendor_account.owner_name,
|
||||
"Sale of [currently_vending.name]", customer_account.owner_name)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/vending/attack_ai(mob/user)
|
||||
@@ -465,174 +441,238 @@
|
||||
if(src.shock(user, 100))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
wires.Interact(user)
|
||||
|
||||
/**
|
||||
* Display the NanoUI window for the vending machine.
|
||||
*
|
||||
* See NanoUI documentation for details.
|
||||
*/
|
||||
/obj/machinery/vending/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/vending/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "vending_machine.tmpl", src.name, 440, 600)
|
||||
var/estimated_height = 100 + (length(product_records) * 34)
|
||||
if(length(prices) > 0)
|
||||
estimated_height += 100 // to account for the "current user" interface
|
||||
ui = new(user, src, ui_key, "Vending", name, 470, estimated_height, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/vending/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/vending/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
if(currently_vending)
|
||||
data["mode"] = 1
|
||||
data["product"] = sanitize(currently_vending.name)
|
||||
data["price"] = currently_vending.price
|
||||
data["message_err"] = 0
|
||||
data["message"] = src.status_message
|
||||
data["message_err"] = src.status_error
|
||||
else
|
||||
data["mode"] = 0
|
||||
var/list/listed_products = list()
|
||||
|
||||
var/list/display_records = product_records + coin_records
|
||||
if(extended_inventory)
|
||||
display_records = product_records + coin_records + hidden_records
|
||||
|
||||
for(var/key = 1 to display_records.len)
|
||||
var/datum/data/vending_product/I = display_records[key]
|
||||
|
||||
if(coin_records.Find(I) && !coin)
|
||||
continue
|
||||
|
||||
if(hidden_records.Find(I) && !extended_inventory)
|
||||
continue
|
||||
|
||||
listed_products.Add(list(list(
|
||||
"key" = key,
|
||||
"name" = sanitize(I.name),
|
||||
"price" = I.price,
|
||||
"amount" = I.amount)))
|
||||
|
||||
data["products"] = listed_products
|
||||
|
||||
if(coin)
|
||||
data["coin"] = coin.name
|
||||
|
||||
if(item_slot)
|
||||
data["item_slot"] = 1
|
||||
if(inserted_item)
|
||||
data["inserted_item"] = inserted_item
|
||||
else
|
||||
data["inserted_item"] = null
|
||||
else
|
||||
data["item_slot"] = 0
|
||||
|
||||
if(panel_open)
|
||||
data["panel"] = 1
|
||||
data["speaker"] = shut_up ? 0 : 1
|
||||
else
|
||||
data["panel"] = 0
|
||||
var/mob/living/carbon/human/H
|
||||
var/obj/item/card/id/C
|
||||
data["guestNotice"] = "No valid ID card detected. Wear your ID, or present cash.";
|
||||
data["userMoney"] = 0
|
||||
data["user"] = null
|
||||
if(ishuman(user))
|
||||
H = user
|
||||
C = H.get_idcard(TRUE)
|
||||
var/obj/item/stack/spacecash/S = H.get_active_hand()
|
||||
if(istype(S))
|
||||
data["userMoney"] = S.amount
|
||||
data["guestNotice"] = "Accepting Cash. You have: [S.amount] credits."
|
||||
else if(istype(C))
|
||||
var/datum/money_account/A = get_card_account(C)
|
||||
if(istype(A))
|
||||
data["user"] = list()
|
||||
data["user"]["name"] = A.owner_name
|
||||
data["userMoney"] = A.money
|
||||
data["user"]["job"] = (istype(C) && C.rank) ? C.rank : "No Job"
|
||||
else
|
||||
data["guestNotice"] = "Unlinked ID detected. Present cash to pay.";
|
||||
data["stock"] = list()
|
||||
for (var/datum/data/vending_product/R in product_records + coin_records + hidden_records)
|
||||
data["stock"][R.name] = R.amount
|
||||
data["extended_inventory"] = extended_inventory
|
||||
data["vend_ready"] = vend_ready
|
||||
data["coin_name"] = coin ? coin.name : FALSE
|
||||
data["panel_open"] = panel_open ? TRUE : FALSE
|
||||
data["speaker"] = shut_up ? FALSE : TRUE
|
||||
data["item_slot"] = item_slot // boolean
|
||||
data["inserted_item_name"] = inserted_item ? inserted_item.name : FALSE
|
||||
return data
|
||||
|
||||
/obj/machinery/vending/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon))
|
||||
if(!coin)
|
||||
to_chat(usr, "There is no coin in this machine.")
|
||||
return
|
||||
/obj/machinery/vending/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["chargesMoney"] = length(prices) > 0 ? TRUE : FALSE
|
||||
data["product_records"] = list()
|
||||
var/i = 1
|
||||
for (var/datum/data/vending_product/R in product_records)
|
||||
var/list/data_pr = list(
|
||||
path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"),
|
||||
name = R.name,
|
||||
price = (R.product_path in prices) ? prices[R.product_path] : 0,
|
||||
max_amount = R.max_amount,
|
||||
req_coin = FALSE,
|
||||
is_hidden = FALSE,
|
||||
inum = i
|
||||
)
|
||||
data["product_records"] += list(data_pr)
|
||||
i++
|
||||
data["coin_records"] = list()
|
||||
for (var/datum/data/vending_product/R in coin_records)
|
||||
var/list/data_cr = list(
|
||||
path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"),
|
||||
name = R.name,
|
||||
price = (R.product_path in prices) ? prices[R.product_path] : 0,
|
||||
max_amount = R.max_amount,
|
||||
req_coin = TRUE,
|
||||
is_hidden = FALSE,
|
||||
inum = i,
|
||||
premium = TRUE
|
||||
)
|
||||
data["coin_records"] += list(data_cr)
|
||||
i++
|
||||
data["hidden_records"] = list()
|
||||
for (var/datum/data/vending_product/R in hidden_records)
|
||||
var/list/data_hr = list(
|
||||
path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"),
|
||||
name = R.name,
|
||||
price = (R.product_path in prices) ? prices[R.product_path] : 0,
|
||||
max_amount = R.max_amount,
|
||||
req_coin = FALSE,
|
||||
is_hidden = TRUE,
|
||||
inum = i,
|
||||
premium = TRUE
|
||||
)
|
||||
data["hidden_records"] += list(data_hr)
|
||||
i++
|
||||
data["imagelist"] = imagelist
|
||||
return data
|
||||
|
||||
usr.put_in_hands(coin)
|
||||
coin = null
|
||||
to_chat(usr, "<span class='notice'>You remove [coin] from [src].</span>")
|
||||
/obj/machinery/vending/tgui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(issilicon(usr) && !isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>The vending machine refuses to interface with you, as you are not in its target demographic!</span>")
|
||||
return
|
||||
switch(action)
|
||||
if("toggle_voice")
|
||||
if(panel_open)
|
||||
shut_up = !shut_up
|
||||
. = TRUE
|
||||
if("eject_item")
|
||||
eject_item(usr)
|
||||
. = TRUE
|
||||
if("remove_coin")
|
||||
if(!coin)
|
||||
to_chat(usr, "<span class='warning'>There is no coin in this machine.</span>")
|
||||
return
|
||||
if(istype(usr, /mob/living/silicon))
|
||||
to_chat(usr, "<span class='warning'>You lack hands.</span>")
|
||||
return
|
||||
to_chat(usr, "<span class='notice'>You remove [coin] from [src].</span>")
|
||||
usr.put_in_hands(coin)
|
||||
coin = null
|
||||
. = TRUE
|
||||
if("vend")
|
||||
if(!vend_ready)
|
||||
to_chat(usr, "<span class='warning'>The vending machine is busy!</span>")
|
||||
return
|
||||
if(panel_open)
|
||||
to_chat(usr, "<span class='warning'>The vending machine cannot dispense products while its service panel is open!</span>")
|
||||
return
|
||||
var/key = text2num(params["inum"])
|
||||
var/list/display_records = product_records + coin_records
|
||||
if(extended_inventory)
|
||||
display_records = product_records + coin_records + hidden_records
|
||||
if(key < 1 || key > length(display_records))
|
||||
to_chat(usr, "<span class='warning'>ERROR: invalid inum passed to vendor. Report this bug.</span>")
|
||||
return
|
||||
var/datum/data/vending_product/R = display_records[key]
|
||||
if(!istype(R))
|
||||
to_chat(usr, "<span class='warning'>ERROR: unknown vending_product record. Report this bug.</span>")
|
||||
return
|
||||
var/list/record_to_check = product_records + coin_records
|
||||
if(extended_inventory)
|
||||
record_to_check = product_records + coin_records + hidden_records
|
||||
if(!R || !istype(R) || !R.product_path)
|
||||
to_chat(usr, "<span class='warning'>ERROR: unknown product record. Report this bug.</span>")
|
||||
return
|
||||
if(R in hidden_records)
|
||||
if(!extended_inventory)
|
||||
// Exploit prevention, stop the user purchasing hidden stuff if they haven't hacked the machine.
|
||||
to_chat(usr, "<span class='warning'>ERROR: machine does not allow extended_inventory in current state. Report this bug.</span>")
|
||||
return
|
||||
else if (!(R in record_to_check))
|
||||
// Exploit prevention, stop the user
|
||||
message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!")
|
||||
return
|
||||
if (R.amount <= 0)
|
||||
to_chat(usr, "Sold out of [R.name].")
|
||||
flick(icon_deny, src)
|
||||
return
|
||||
|
||||
if(href_list["remove_item"])
|
||||
eject_item(usr)
|
||||
vend_ready = FALSE // From this point onwards, vendor is locked to performing this transaction only, until it is resolved.
|
||||
|
||||
if(href_list["pay"])
|
||||
if(currently_vending && GLOB.vendor_account && !GLOB.vendor_account.suspended)
|
||||
var/paid = 0
|
||||
var/handled = 0
|
||||
var/datum/money_account/A = usr.get_worn_id_account()
|
||||
if(A)
|
||||
paid = pay_with_account(A)
|
||||
handled = 1
|
||||
else if(istype(usr.get_active_hand(), /obj/item/card))
|
||||
paid = pay_with_card(usr.get_active_hand())
|
||||
handled = 1
|
||||
else if(usr.can_admin_interact())
|
||||
paid = 1
|
||||
handled = 1
|
||||
if(!ishuman(usr) || R.price <= 0)
|
||||
// Either the purchaser is not human, or the item is free.
|
||||
// Skip all payment logic.
|
||||
vend(R, usr)
|
||||
add_fingerprint(usr)
|
||||
vend_ready = TRUE
|
||||
. = TRUE
|
||||
return
|
||||
|
||||
// --- THE REST OF THIS PROC IS JUST PAYMENT LOGIC ---
|
||||
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/obj/item/card/id/C = H.get_idcard(TRUE)
|
||||
|
||||
if(!GLOB.vendor_account || GLOB.vendor_account.suspended)
|
||||
to_chat(usr, "Vendor account offline. Unable to process transaction.")
|
||||
flick(icon_deny, src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
|
||||
currently_vending = R
|
||||
var/paid = FALSE
|
||||
|
||||
if(istype(usr.get_active_hand(), /obj/item/stack/spacecash))
|
||||
var/obj/item/stack/spacecash/S = usr.get_active_hand()
|
||||
paid = pay_with_cash(S)
|
||||
else if(istype(C, /obj/item/card))
|
||||
// Because this uses H.get_idcard(TRUE), it will attempt to use:
|
||||
// active hand, inactive hand, pda.id, and then wear_id ID in that order
|
||||
// this is important because it lets people buy stuff with someone else's ID by holding it while using the vendor
|
||||
paid = pay_with_card(C, usr)
|
||||
else if(usr.can_advanced_admin_interact())
|
||||
to_chat(usr, "<span class='notice'>Vending object due to admin interaction.</span>")
|
||||
paid = TRUE
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Payment failure: you have no ID or other method of payment.")
|
||||
vend_ready = TRUE
|
||||
flick(icon_deny, src)
|
||||
. = TRUE // we set this because they shouldn't even be able to get this far, and we want the UI to update.
|
||||
return
|
||||
if(paid)
|
||||
vend(currently_vending, usr)
|
||||
return
|
||||
else if(handled)
|
||||
SSnanoui.update_uis(src)
|
||||
return // don't smack that machine with your 2 credits
|
||||
|
||||
if((href_list["vend"]) && vend_ready && !currently_vending)
|
||||
|
||||
if(issilicon(usr) && !isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>The vending machine refuses to interface with you, as you are not in its target demographic!</span>")
|
||||
return
|
||||
|
||||
if(!allowed(usr) && !usr.can_admin_interact() && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>") //Unless emagged of course
|
||||
flick(icon_deny,src)
|
||||
return
|
||||
|
||||
var/key = text2num(href_list["vend"])
|
||||
var/list/display_records = product_records + coin_records
|
||||
if(extended_inventory)
|
||||
display_records = product_records + coin_records + hidden_records
|
||||
var/datum/data/vending_product/R = display_records[key]
|
||||
|
||||
// This should not happen unless the request from NanoUI was bad
|
||||
if(coin_records.Find(R) && !coin)
|
||||
return
|
||||
|
||||
if(hidden_records.Find(R) && !extended_inventory)
|
||||
return
|
||||
|
||||
if(R.price <= 0)
|
||||
vend(R, usr)
|
||||
else
|
||||
currently_vending = R
|
||||
if(!GLOB.vendor_account || GLOB.vendor_account.suspended)
|
||||
status_message = "This machine is currently unable to process payments due to problems with the associated account."
|
||||
status_error = 1
|
||||
. = TRUE
|
||||
else
|
||||
status_message = "Please swipe a card or insert cash to pay for the item."
|
||||
status_error = 0
|
||||
to_chat(usr, "<span class='warning'>Payment failure: unable to process payment.")
|
||||
vend_ready = TRUE
|
||||
if(.)
|
||||
add_fingerprint(usr)
|
||||
|
||||
else if(href_list["cancelpurchase"])
|
||||
currently_vending = null
|
||||
|
||||
else if(href_list["togglevoice"] && panel_open)
|
||||
shut_up = !src.shut_up
|
||||
|
||||
add_fingerprint(usr)
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user)
|
||||
if(!allowed(usr) && !usr.can_admin_interact() && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")//Unless emagged of course
|
||||
flick(icon_deny,src)
|
||||
if(!allowed(user) && !user.can_admin_interact() && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")//Unless emagged of course
|
||||
flick(icon_deny, src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
|
||||
if(!R.amount)
|
||||
to_chat(user, "<span class='warning'>The vending machine has ran out of that product.</span>")
|
||||
vend_ready = TRUE
|
||||
return
|
||||
|
||||
vend_ready = 0 //One thing at a time!!
|
||||
status_message = "Vending..."
|
||||
status_error = 0
|
||||
SSnanoui.update_uis(src)
|
||||
vend_ready = FALSE //One thing at a time!!
|
||||
|
||||
if(coin_records.Find(R))
|
||||
if(!coin)
|
||||
to_chat(user, "<span class='notice'>You need to insert a coin to get this item.</span>")
|
||||
vend_ready = TRUE
|
||||
return
|
||||
if(coin.string_attached)
|
||||
if(prob(50))
|
||||
@@ -652,15 +692,13 @@
|
||||
use_power(vend_power_usage) //actuators and stuff
|
||||
if(icon_vend) //Show the vending animation if needed
|
||||
flick(icon_vend, src)
|
||||
playsound(get_turf(src), 'sound/machines/machine_vend.ogg', 50, TRUE)
|
||||
addtimer(CALLBACK(src, .proc/delayed_vend, R, user), vend_delay)
|
||||
|
||||
/obj/machinery/vending/proc/delayed_vend(datum/data/vending_product/R, mob/user)
|
||||
do_vend(R, user)
|
||||
status_message = ""
|
||||
status_error = 0
|
||||
vend_ready = 1
|
||||
vend_ready = TRUE
|
||||
currently_vending = null
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
//override this proc to add handling for what to do with the vended product when you have a inserted item and remember to include a parent call for this generic handling
|
||||
/obj/machinery/vending/proc/do_vend(datum/data/vending_product/R, mob/user)
|
||||
@@ -796,17 +834,6 @@
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
/obj/machinery/vending/atmospherics //Commenting this out until someone ponies up some actual working, broken, and unpowered sprites - Quarxink
|
||||
name = "\improper Tank Vendor"
|
||||
desc = "A vendor with a wide variety of masks and gas tanks."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "dispenser"
|
||||
product_paths = "/obj/item/tank/oxygen;/obj/item/tank/plasma;/obj/item/tank/emergency_oxygen;/obj/item/tank/emergency_oxygen/engi;/obj/item/clothing/mask/breath"
|
||||
product_amounts = "10;10;10;5;25"
|
||||
vend_delay = 0
|
||||
*/
|
||||
|
||||
/obj/machinery/vending/assist
|
||||
products = list( /obj/item/assembly/prox_sensor = 5,/obj/item/assembly/igniter = 3,/obj/item/assembly/signaler = 4,
|
||||
/obj/item/wirecutters = 1, /obj/item/cartridge/signal = 4)
|
||||
@@ -1553,7 +1580,6 @@
|
||||
desc = "Tools for tools."
|
||||
icon_state = "tool"
|
||||
icon_deny = "tool-deny"
|
||||
//req_access_txt = "12" //Maintenance access
|
||||
products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/crowbar = 5,/obj/item/weldingtool = 3,/obj/item/wirecutters = 5,
|
||||
/obj/item/wrench = 5,/obj/item/analyzer = 5,/obj/item/t_scanner = 5,/obj/item/screwdriver = 5)
|
||||
contraband = list(/obj/item/weldingtool/hugetank = 2,/obj/item/clothing/gloves/color/fyellow = 2)
|
||||
|
||||
+20
-20
@@ -158,36 +158,36 @@
|
||||
/obj/machinery/computer/mech_bay_power_console/attack_hand(mob/user as mob)
|
||||
if(..())
|
||||
return
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/mech_bay_power_console/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "mech_bay_console.tmpl", "Mech Bay Control Console", 500, 325)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "MechBayConsole", name, 400, 150, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
/obj/machinery/computer/mech_bay_power_console/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("reconnect")
|
||||
reconnect()
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/tgui_data(mob/user)
|
||||
var/data = list()
|
||||
if(!recharge_port)
|
||||
reconnect()
|
||||
if(recharge_port && !QDELETED(recharge_port))
|
||||
data["recharge_port"] = list("mech" = null)
|
||||
if(recharge_port.recharging_mecha && !QDELETED(recharge_port.recharging_mecha))
|
||||
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mecha.obj_integrity, "maxhealth" = initial(recharge_port.recharging_mecha.max_integrity), "cell" = null)
|
||||
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mecha.obj_integrity, "maxhealth" = recharge_port.recharging_mecha.max_integrity, "cell" = null, "name" = recharge_port.recharging_mecha.name)
|
||||
if(recharge_port.recharging_mecha.cell && !QDELETED(recharge_port.recharging_mecha.cell))
|
||||
data["has_mech"] = 1
|
||||
data["mecha_name"] = recharge_port.recharging_mecha || "None"
|
||||
data["mecha_charge"] = isnull(recharge_port.recharging_mecha) ? 0 : recharge_port.recharging_mecha.cell.charge
|
||||
data["mecha_maxcharge"] = isnull(recharge_port.recharging_mecha) ? 0 : recharge_port.recharging_mecha.cell.maxcharge
|
||||
data["mecha_charge_percentage"] = isnull(recharge_port.recharging_mecha) ? 0 : round(recharge_port.recharging_mecha.cell.percent())
|
||||
else
|
||||
data["has_mech"] = 0
|
||||
|
||||
data["recharge_port"]["mech"]["cell"] = list(
|
||||
"charge" = recharge_port.recharging_mecha.cell.charge,
|
||||
"maxcharge" = recharge_port.recharging_mecha.cell.maxcharge
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/Initialize()
|
||||
|
||||
@@ -159,7 +159,6 @@
|
||||
radio.name = "[src] radio"
|
||||
radio.icon = icon
|
||||
radio.icon_state = icon_state
|
||||
radio.subspace_transmission = 1
|
||||
|
||||
/obj/mecha/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
materials = list(MAT_METAL=10000, MAT_GLASS=2500)
|
||||
var/code = 2
|
||||
|
||||
is_special = 1
|
||||
|
||||
/obj/item/radio/electropack/attack_hand(mob/user as mob)
|
||||
if(src == user.back)
|
||||
to_chat(user, "<span class='notice'>You need help taking this off!</span>")
|
||||
@@ -54,23 +52,6 @@
|
||||
if(src.flags & NODROP)
|
||||
A.flags |= NODROP
|
||||
|
||||
/obj/item/radio/electropack/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
|
||||
set_frequency(new_frequency)
|
||||
|
||||
else if(href_list["code"])
|
||||
code += text2num(href_list["code"])
|
||||
code = round(code)
|
||||
code = clamp(code, 1, 100)
|
||||
|
||||
else if(href_list["power"])
|
||||
on = !on
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/radio/electropack/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.encryption != code)
|
||||
@@ -96,18 +77,48 @@
|
||||
return
|
||||
|
||||
|
||||
/obj/item/radio/electropack/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/radio/electropack/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_inventory_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "radio_electro.tmpl", "[name]", 400, 500)
|
||||
ui = new(user, src, ui_key, "Electropack", name, 360, 150, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/item/radio/electropack/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
/obj/item/radio/electropack/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["power"] = on
|
||||
data["freq"] = format_frequency(frequency)
|
||||
data["frequency"] = frequency
|
||||
data["code"] = code
|
||||
|
||||
data["minFrequency"] = PUBLIC_LOW_FREQ
|
||||
data["maxFrequency"] = PUBLIC_HIGH_FREQ
|
||||
return data
|
||||
|
||||
/obj/item/radio/electropack/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
if("freq")
|
||||
var/value = params["freq"]
|
||||
if(value)
|
||||
frequency = sanitize_frequency(value)
|
||||
set_frequency(frequency)
|
||||
else
|
||||
. = FALSE
|
||||
if("code")
|
||||
var/value = text2num(params["code"])
|
||||
if(value)
|
||||
value = round(value)
|
||||
code = clamp(value, 1, 100)
|
||||
else
|
||||
. = FALSE
|
||||
if("reset")
|
||||
if(params["reset"] == "freq")
|
||||
frequency = initial(frequency)
|
||||
else if(params["reset"] == "code")
|
||||
code = initial(code)
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
add_fingerprint(usr)
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"Vox Armalis" = 'icons/mob/species/armalis/ears.dmi'
|
||||
) //We read you loud and skree-er.
|
||||
materials = list(MAT_METAL=75)
|
||||
subspace_transmission = TRUE
|
||||
canhear_range = 0 // can't hear headsets from very far away
|
||||
|
||||
slot_flags = SLOT_EARS
|
||||
@@ -91,6 +90,7 @@
|
||||
ks1type = /obj/item/encryptionkey/syndicate/nukeops
|
||||
requires_tcomms = FALSE
|
||||
instant = TRUE // Work instantly if there are no comms
|
||||
freqlock = TRUE
|
||||
|
||||
/obj/item/radio/headset/syndicate/alt //undisguised bowman with flash protection
|
||||
name = "syndicate headset"
|
||||
@@ -289,6 +289,7 @@
|
||||
icon_state = "com_headset"
|
||||
item_state = "headset"
|
||||
ks2type = /obj/item/encryptionkey/ert
|
||||
freqlock = TRUE
|
||||
|
||||
/obj/item/radio/headset/ert/alt
|
||||
name = "\proper emergency response team's bowman headset"
|
||||
@@ -367,7 +368,7 @@
|
||||
else
|
||||
to_chat(user, "This headset doesn't have any encryption keys! How useless...")
|
||||
|
||||
/obj/item/radio/headset/proc/recalculateChannels(var/setDescription = FALSE)
|
||||
/obj/item/radio/headset/recalculateChannels(setDescription = FALSE)
|
||||
channels = list()
|
||||
translate_binary = FALSE
|
||||
translate_hive = FALSE
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
name = "illicit intercom"
|
||||
desc = "Talk through this. Evilly"
|
||||
frequency = SYND_FREQ
|
||||
subspace_transmission = TRUE
|
||||
syndiekey = new /obj/item/encryptionkey/syndicate/nukeops
|
||||
|
||||
/obj/item/radio/intercom/syndicate/New()
|
||||
@@ -85,7 +84,6 @@
|
||||
/obj/item/radio/intercom/pirate
|
||||
name = "pirate radio intercom"
|
||||
desc = "You wouldn't steal a space shuttle. Piracy. It's a crime!"
|
||||
subspace_transmission = 1
|
||||
|
||||
/obj/item/radio/intercom/pirate/New()
|
||||
..()
|
||||
@@ -109,13 +107,13 @@
|
||||
GLOB.global_intercoms.Remove(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/intercom/attack_ai(mob/user as mob)
|
||||
/obj/item/radio/intercom/attack_ai(mob/user)
|
||||
add_hiddenprint(user)
|
||||
add_fingerprint(user)
|
||||
spawn(0)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/radio/intercom/attack_hand(mob/user as mob)
|
||||
/obj/item/radio/intercom/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
spawn(0)
|
||||
attack_self(user)
|
||||
|
||||
@@ -26,21 +26,37 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
suffix = "\[3\]"
|
||||
icon_state = "walkietalkie"
|
||||
item_state = "walkietalkie"
|
||||
var/on = 1 // 0 for off
|
||||
/// boolean for radio enabled or not
|
||||
var/on = TRUE
|
||||
var/last_transmission
|
||||
var/frequency = PUB_FREQ //common chat
|
||||
var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies
|
||||
var/canhear_range = 3 // the range which mobs can hear this radio from
|
||||
var/frequency = PUB_FREQ
|
||||
/// tune to frequency to unlock traitor supplies
|
||||
var/traitor_frequency = 0
|
||||
/// the range which mobs can hear this radio from
|
||||
var/canhear_range = 3
|
||||
var/datum/wires/radio/wires = null
|
||||
var/b_stat = 0
|
||||
var/broadcasting = 0
|
||||
var/listening = 1
|
||||
var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
|
||||
var/subspace_transmission = 0
|
||||
var/obj/item/encryptionkey/syndicate/syndiekey = null //Holder for the syndicate encryption key if present
|
||||
var/disable_timer = 0 //How many times this is disabled by EMPs
|
||||
|
||||
var/is_special = 0 //For electropacks mostly, skips Topic() checks
|
||||
/// Whether the radio will broadcast stuff it hears, out over the radio
|
||||
var/broadcasting = FALSE
|
||||
/// Whether the radio is currently receiving
|
||||
var/listening = TRUE
|
||||
/// Whether the radio can be re-tuned to restricted channels it has no key for
|
||||
var/freerange = FALSE
|
||||
/// Whether the radio is able to have its primary frequency changed. Used for radios with weird primary frequencies, like DS, syndi, etc
|
||||
var/freqlock = FALSE
|
||||
|
||||
/// Whether the radio broadcasts to everyone within a few tiles, or not
|
||||
var/loudspeaker = FALSE
|
||||
/// Whether loudspeaker can be toggled by the user
|
||||
var/has_loudspeaker = FALSE
|
||||
|
||||
/// see communications.dm for full list. First channes is a "default" for :h
|
||||
var/list/channels = list()
|
||||
/// Holder for the syndicate encryption key if present
|
||||
var/obj/item/encryptionkey/syndicate/syndiekey = null
|
||||
/// How many times this is disabled by EMPs
|
||||
var/disable_timer = 0
|
||||
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
@@ -100,47 +116,87 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
/obj/item/radio/attack_ghost(mob/user)
|
||||
return interact(user)
|
||||
|
||||
/obj/item/radio/attack_self(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
/obj/item/radio/attack_self(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/radio/interact(mob/user)
|
||||
if(!user)
|
||||
return 0
|
||||
|
||||
if(b_stat)
|
||||
wires.Interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
return ui_interact(user)
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/radio/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 550)
|
||||
ui = new(user, src, ui_key, "Radio", name, 360, 150 + (length(channels) * 20), master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/item/radio/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
/obj/item/radio/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["mic_status"] = broadcasting
|
||||
data["speaker"] = listening
|
||||
data["freq"] = format_frequency(frequency)
|
||||
data["rawfreq"] = num2text(frequency)
|
||||
|
||||
data["mic_cut"] = (wires.is_cut(WIRE_RADIO_TRANSMIT) || wires.is_cut(WIRE_RADIO_SIGNAL))
|
||||
data["spk_cut"] = (wires.is_cut(WIRE_RADIO_RECEIVER) || wires.is_cut(WIRE_RADIO_SIGNAL))
|
||||
|
||||
var/list/chanlist = list_channels(user)
|
||||
if(islist(chanlist) && chanlist.len)
|
||||
data["chan_list"] = chanlist
|
||||
data["chan_list_len"] = chanlist.len
|
||||
|
||||
if(syndiekey)
|
||||
data["useSyndMode"] = 1
|
||||
data["broadcasting"] = broadcasting
|
||||
data["listening"] = listening
|
||||
data["frequency"] = frequency
|
||||
data["minFrequency"] = freerange ? RADIO_LOW_FREQ : PUBLIC_LOW_FREQ
|
||||
data["maxFrequency"] = freerange ? RADIO_HIGH_FREQ : PUBLIC_HIGH_FREQ
|
||||
data["canReset"] = frequency == initial(frequency) ? FALSE : TRUE
|
||||
data["freqlock"] = freqlock
|
||||
data["channels"] = list()
|
||||
for(var/channel in channels)
|
||||
data["channels"][channel] = channels[channel] & FREQ_LISTENING
|
||||
|
||||
data["has_loudspeaker"] = has_loudspeaker
|
||||
data["loudspeaker"] = loudspeaker
|
||||
return data
|
||||
|
||||
/obj/item/radio/tgui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if(freqlock)
|
||||
return
|
||||
var/tune = params["tune"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(tune == "reset")
|
||||
tune = initial(frequency)
|
||||
else if(adjust)
|
||||
tune = frequency + adjust * 10
|
||||
else if(text2num(tune) != null)
|
||||
tune = tune * 10
|
||||
else
|
||||
. = FALSE
|
||||
if(hidden_uplink)
|
||||
if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
|
||||
usr << browse(null, "window=radio")
|
||||
if(.)
|
||||
set_frequency(sanitize_frequency(tune, freerange))
|
||||
if("listen")
|
||||
listening = !listening
|
||||
if("broadcast")
|
||||
broadcasting = !broadcasting
|
||||
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
|
||||
if("loudspeaker")
|
||||
// Toggle loudspeaker mode, AKA everyone around you hearing your radio.
|
||||
if(has_loudspeaker)
|
||||
loudspeaker = !loudspeaker
|
||||
if(loudspeaker)
|
||||
canhear_range = 3
|
||||
else
|
||||
canhear_range = 0
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/radio/proc/list_channels(var/mob/user)
|
||||
return list_internal_channels(user)
|
||||
@@ -190,53 +246,6 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
/obj/item/radio/proc/ToggleReception()
|
||||
listening = !listening && !(wires.is_cut(WIRE_RADIO_RECEIVER) || wires.is_cut(WIRE_RADIO_SIGNAL))
|
||||
|
||||
/obj/item/radio/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(is_special)
|
||||
return 0
|
||||
|
||||
if(href_list["track"])
|
||||
var/mob/target = locate(href_list["track"])
|
||||
var/mob/living/silicon/ai/A = locate(href_list["track2"])
|
||||
if(A && target)
|
||||
A.ai_actual_track(target)
|
||||
. = 1
|
||||
|
||||
else if(href_list["freq"])
|
||||
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
||||
if((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ))
|
||||
new_frequency = sanitize_frequency(new_frequency)
|
||||
set_frequency(new_frequency)
|
||||
if(hidden_uplink)
|
||||
if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
|
||||
usr << browse(null, "window=radio")
|
||||
. = 1
|
||||
else if(href_list["talk"])
|
||||
ToggleBroadcast()
|
||||
. = 1
|
||||
else if(href_list["listen"])
|
||||
var/chan_name = href_list["ch_name"]
|
||||
if(!chan_name)
|
||||
ToggleReception()
|
||||
else
|
||||
if(channels[chan_name] & FREQ_LISTENING)
|
||||
channels[chan_name] &= ~FREQ_LISTENING
|
||||
else
|
||||
channels[chan_name] |= FREQ_LISTENING
|
||||
. = 1
|
||||
else if(href_list["spec_freq"])
|
||||
var/freq = href_list["spec_freq"]
|
||||
if(has_channel_access(usr, freq))
|
||||
set_frequency(text2num(freq))
|
||||
. = 1
|
||||
|
||||
if(href_list["nowindow"]) // here for pAIs, maybe others will want it, idk
|
||||
return 1
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/radio/proc/autosay(message, from, channel, role = "Unknown") //BS12 EDIT
|
||||
var/datum/radio_frequency/connection = null
|
||||
if(channel && channels && channels.len > 0)
|
||||
@@ -582,19 +591,24 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
if(!disable_timer)
|
||||
on = 1
|
||||
|
||||
/obj/item/radio/proc/recalculateChannels()
|
||||
/// Exists so that borg radios and headsets can override it.
|
||||
stack_trace("recalculateChannels() called on a radio which does not implement the proc.")
|
||||
|
||||
///////////////////////////////
|
||||
//////////Borg Radios//////////
|
||||
///////////////////////////////
|
||||
//Giving borgs their own radio to have some more room to work with -Sieve
|
||||
|
||||
/obj/item/radio/borg
|
||||
name = "Cyborg Radio"
|
||||
var/mob/living/silicon/robot/myborg = null // Cyborg which owns this radio. Used for power checks
|
||||
var/obj/item/encryptionkey/keyslot = null//Borg radios can handle a single encryption key
|
||||
var/shut_up = 1
|
||||
icon = 'icons/obj/robot_component.dmi' // Cyborgs radio icons should look like the component.
|
||||
icon_state = "radio"
|
||||
has_loudspeaker = TRUE
|
||||
loudspeaker = FALSE
|
||||
canhear_range = 0
|
||||
subspace_transmission = 1
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/borg/syndicate
|
||||
@@ -616,12 +630,14 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
..()
|
||||
syndiekey = keyslot
|
||||
set_frequency(SYND_FREQ)
|
||||
freqlock = TRUE
|
||||
|
||||
/obj/item/radio/borg/deathsquad
|
||||
|
||||
/obj/item/radio/borg/deathsquad/New()
|
||||
..()
|
||||
set_frequency(DTH_FREQ)
|
||||
freqlock = TRUE
|
||||
|
||||
/obj/item/radio/borg/ert
|
||||
keyslot = new /obj/item/encryptionkey/ert
|
||||
@@ -629,6 +645,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
/obj/item/radio/borg/ert/New()
|
||||
..()
|
||||
set_frequency(ERT_FREQ)
|
||||
freqlock = TRUE
|
||||
|
||||
/obj/item/radio/borg/ert/specops
|
||||
keyslot = new /obj/item/encryptionkey/centcom
|
||||
@@ -673,7 +690,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
else
|
||||
to_chat(user, "This radio doesn't have any encryption keys!")
|
||||
|
||||
/obj/item/radio/borg/proc/recalculateChannels()
|
||||
/obj/item/radio/borg/recalculateChannels()
|
||||
channels = list()
|
||||
syndiekey = null
|
||||
|
||||
@@ -706,72 +723,12 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
||||
|
||||
return
|
||||
|
||||
/obj/item/radio/borg/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["mode"])
|
||||
var/enable_subspace_transmission = text2num(href_list["mode"])
|
||||
if(enable_subspace_transmission != subspace_transmission)
|
||||
subspace_transmission = !subspace_transmission
|
||||
if(subspace_transmission)
|
||||
to_chat(usr, "<span class='notice'>Subspace Transmission is enabled.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>Subspace Transmission is disabled.</span>")
|
||||
|
||||
if(subspace_transmission == 0)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled
|
||||
channels = list()
|
||||
else
|
||||
recalculateChannels()
|
||||
. = 1
|
||||
if(href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio.
|
||||
var/do_shut_up = text2num(href_list["shutup"])
|
||||
if(do_shut_up != shut_up)
|
||||
shut_up = !shut_up
|
||||
if(shut_up)
|
||||
canhear_range = 0
|
||||
to_chat(usr, "<span class='notice'>Loudspeaker disabled.</span>")
|
||||
else
|
||||
canhear_range = 3
|
||||
to_chat(usr, "<span class='notice'>Loudspeaker enabled.</span>")
|
||||
. = 1
|
||||
|
||||
|
||||
/obj/item/radio/borg/interact(mob/user as mob)
|
||||
/obj/item/radio/borg/interact(mob/user)
|
||||
if(!on)
|
||||
return
|
||||
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/borg/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 430, 500)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/item/radio/borg/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
data["mic_status"] = broadcasting
|
||||
data["speaker"] = listening
|
||||
data["freq"] = format_frequency(frequency)
|
||||
data["rawfreq"] = num2text(frequency)
|
||||
|
||||
var/list/chanlist = list_channels(user)
|
||||
if(islist(chanlist) && chanlist.len)
|
||||
data["chan_list"] = chanlist
|
||||
data["chan_list_len"] = chanlist.len
|
||||
|
||||
if(syndiekey)
|
||||
data["useSyndMode"] = 1
|
||||
|
||||
data["has_loudspeaker"] = 1
|
||||
data["loudspeaker"] = !shut_up
|
||||
data["has_subspace"] = 1
|
||||
data["subspace"] = subspace_transmission
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/radio/proc/config(op)
|
||||
if(SSradio)
|
||||
for(var/ch_name in channels)
|
||||
|
||||
@@ -86,64 +86,64 @@
|
||||
O.hear_message(M, msg)
|
||||
|
||||
/obj/item/transfer_valve/attack_self(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/transfer_valve/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_inventory_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "transfer_valve.tmpl", "Tank Transfer Valve", 460, 280)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "TransferValve", name, 460, 320, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
//ui.set_auto_update(1)
|
||||
|
||||
/obj/item/transfer_valve/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
data["attachmentOne"] = tank_one ? tank_one.name : null
|
||||
data["attachmentTwo"] = tank_two ? tank_two.name : null
|
||||
data["valveAttachment"] = attached_device ? attached_device.name : null
|
||||
data["valveOpen"] = valve_open ? 1 : 0
|
||||
|
||||
/obj/item/transfer_valve/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tank_one"] = tank_one ? tank_one.name : null
|
||||
data["tank_two"] = tank_two ? tank_two.name : null
|
||||
data["attached_device"] = attached_device ? attached_device.name : null
|
||||
data["valve"] = valve_open
|
||||
return data
|
||||
|
||||
/obj/item/transfer_valve/Topic(href, href_list)
|
||||
..()
|
||||
if(usr.incapacitated())
|
||||
return 0
|
||||
if(loc != usr)
|
||||
return 0
|
||||
if(tank_one && href_list["tankone"])
|
||||
split_gases()
|
||||
valve_open = 0
|
||||
tank_one.forceMove(get_turf(src))
|
||||
tank_one = null
|
||||
|
||||
|
||||
/obj/item/transfer_valve/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("tankone")
|
||||
if(tank_one)
|
||||
split_gases()
|
||||
valve_open = FALSE
|
||||
tank_one.forceMove(get_turf(src))
|
||||
tank_one = null
|
||||
update_icon()
|
||||
if((!tank_two || tank_two.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL))
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
if("tanktwo")
|
||||
if(tank_two)
|
||||
split_gases()
|
||||
valve_open = FALSE
|
||||
tank_two.forceMove(get_turf(src))
|
||||
tank_two = null
|
||||
update_icon()
|
||||
if((!tank_one || tank_one.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL))
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
if("toggle")
|
||||
toggle_valve()
|
||||
if("device")
|
||||
if(attached_device)
|
||||
attached_device.attack_self(usr)
|
||||
if("remove_device")
|
||||
if(attached_device)
|
||||
attached_device.forceMove(get_turf(src))
|
||||
attached_device.holder = null
|
||||
attached_device = null
|
||||
update_icon()
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
update_icon()
|
||||
if((!tank_two || tank_two.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL))
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
else if(tank_two && href_list["tanktwo"])
|
||||
split_gases()
|
||||
valve_open = 0
|
||||
tank_two.forceMove(get_turf(src))
|
||||
tank_two = null
|
||||
update_icon()
|
||||
if((!tank_one || tank_one.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL))
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
else if(href_list["open"])
|
||||
toggle_valve()
|
||||
else if(attached_device)
|
||||
if(href_list["rem_device"])
|
||||
attached_device.forceMove(get_turf(src))
|
||||
attached_device.holder = null
|
||||
attached_device = null
|
||||
update_icon()
|
||||
if(href_list["device"])
|
||||
attached_device.attack_self(usr)
|
||||
add_fingerprint(usr)
|
||||
return 1 // Returning 1 sends an update to attached UIs
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
/obj/item/transfer_valve/proc/process_activation(obj/item/D)
|
||||
if(toggle)
|
||||
|
||||
@@ -66,6 +66,10 @@ LIGHTERS ARE IN LIGHTERS.DM
|
||||
..()
|
||||
light()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/catch_fire()
|
||||
if(!lit)
|
||||
light("<span class='warning'>The [name] is lit by the flames!</span>")
|
||||
|
||||
/obj/item/clothing/mask/cigarette/welder_act(mob/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(I.tool_use_check(user, 0)) //Don't need to flash eyes because you are a badass
|
||||
|
||||
@@ -138,70 +138,55 @@
|
||||
if(!(air_contents))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/tank/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_inventory_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "tanks.tmpl", "Tank", 500, 300)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "Tank", name, 300, 150, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/item/tank/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/using_internal
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
if(C.internal == src)
|
||||
using_internal = 1
|
||||
|
||||
var/data[0]
|
||||
/obj/item/tank/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
|
||||
data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0)
|
||||
data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE)
|
||||
data["minReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE)
|
||||
data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE)
|
||||
data["valveOpen"] = using_internal ? 1 : 0
|
||||
|
||||
data["maskConnected"] = 0
|
||||
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
if(C.internal == src)
|
||||
data["maskConnected"] = 1
|
||||
else
|
||||
if(C.wear_mask && (C.wear_mask.flags & AIRTIGHT))
|
||||
data["maskConnected"] = 1
|
||||
else if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(H.head && (H.head.flags & AIRTIGHT))
|
||||
data["maskConnected"] = 1
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
if(!istype(C))
|
||||
C = loc.loc
|
||||
if(!istype(C))
|
||||
return data
|
||||
data["has_mask"] = C.wear_mask ? TRUE : FALSE
|
||||
data["connected"] = (C.internal && C.internal == src) ? TRUE : FALSE
|
||||
return data
|
||||
|
||||
/obj/item/tank/Topic(href, href_list)
|
||||
/obj/item/tank/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["dist_p"])
|
||||
if(href_list["dist_p"] == "reset")
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
else if(href_list["dist_p"] == "max")
|
||||
distribute_pressure = TANK_MAX_RELEASE_PRESSURE
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("pressure")
|
||||
var/pressure = params["pressure"]
|
||||
if(pressure == "reset")
|
||||
pressure = initial(distribute_pressure)
|
||||
else if(pressure == "min")
|
||||
pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
else if(pressure == "max")
|
||||
pressure = TANK_MAX_RELEASE_PRESSURE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
distribute_pressure = clamp(round(pressure), TANK_DEFAULT_RELEASE_PRESSURE, TANK_MAX_RELEASE_PRESSURE)
|
||||
if("internals")
|
||||
toggle_internals(usr)
|
||||
else
|
||||
var/cp = text2num(href_list["dist_p"])
|
||||
distribute_pressure += cp
|
||||
distribute_pressure = min(max(round(distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE)
|
||||
|
||||
if(href_list["stat"])
|
||||
toggle_internals(usr)
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1
|
||||
|
||||
. = FALSE
|
||||
if(.)
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/tank/remove_air(amount)
|
||||
return air_contents.remove(amount)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
anchored = TRUE
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
|
||||
var/gps = null
|
||||
var/obj/effect/light_emitter/tendril/emitted_light
|
||||
|
||||
/obj/structure/spawner/lavaland/goliath
|
||||
@@ -29,7 +28,6 @@ GLOBAL_LIST_INIT(tendrils, list())
|
||||
/obj/structure/spawner/lavaland/Initialize(mapload)
|
||||
. = ..()
|
||||
emitted_light = new(loc)
|
||||
gps = new /obj/item/gps/internal(src)
|
||||
GLOB.tendrils += src
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
@@ -59,7 +57,6 @@ GLOBAL_LIST_INIT(tendrils, list())
|
||||
SSmedals.SetScore(TENDRIL_CLEAR_SCORE, L.client, 1)
|
||||
GLOB.tendrils -= src
|
||||
QDEL_NULL(emitted_light)
|
||||
QDEL_NULL(gps)
|
||||
return ..()
|
||||
|
||||
/obj/effect/light_emitter/tendril
|
||||
|
||||
@@ -242,7 +242,7 @@ client/proc/one_click_antag()
|
||||
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
|
||||
var/obj/effect/landmark/closet_spawn = locate("landmark*Nuclear-Closet")
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
var/nuke_code = rand(10000, 99999)
|
||||
|
||||
if(nuke_spawn)
|
||||
var/obj/item/paper/P = new
|
||||
|
||||
@@ -624,11 +624,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
var/beepsound = input(usr, "What sound should the announcement make?", "Announcement Sound", "") as anything in MsgSound
|
||||
|
||||
GLOB.command_announcement.Announce(input, customname, MsgSound[beepsound], , , type)
|
||||
print_command_report(input, "[command_name()] Update")
|
||||
print_command_report(input, customname)
|
||||
if("No")
|
||||
//same thing as the blob stuff - it's not public, so it's classified, dammit
|
||||
GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.")
|
||||
print_command_report(input, "Classified [command_name()] Update")
|
||||
print_command_report(input, "Classified: [customname]")
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
R.set_frequency(DTH_FREQ)
|
||||
R.requires_tcomms = FALSE
|
||||
R.instant = TRUE
|
||||
R.freqlock = TRUE
|
||||
equip_to_slot_or_del(R, slot_l_ear)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform)
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
var/death = TRUE //Kill the mob
|
||||
var/roundstart = TRUE //fires on initialize
|
||||
var/instant = FALSE //fires on New
|
||||
var/flavour_text = "The mapper forgot to set this!"
|
||||
var/flavour_text = "" //flavour/fluff about the role, optional.
|
||||
var/description = "A description for this has not been set. This is either an oversight or an admin-spawned spawner not in normal use." //intended as OOC info about the role
|
||||
var/important_info = "" //important info such as rules that apply to you, etc. Optional.
|
||||
var/faction = null
|
||||
var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
|
||||
var/random = FALSE //Don't set a name or gender, just go random
|
||||
@@ -336,7 +338,7 @@
|
||||
name = "sleeper"
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper"
|
||||
flavour_text = "<span class='big bold'>You are a space doctor!</span>"
|
||||
flavour_text = "You are a space doctor!"
|
||||
assignedrole = "Space Doctor"
|
||||
|
||||
/obj/effect/mob_spawn/human/doctor/alive/equip(mob/living/carbon/human/H)
|
||||
@@ -470,11 +472,14 @@
|
||||
name = "bartender sleeper"
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper"
|
||||
flavour_text = "<span class='big bold'>You are a space bartender!</span><b> Time to mix drinks and change lives.</b>"
|
||||
description = "Stuck on Lavaland, you could try getting back to civilisation...or serve drinks to those that wander by."
|
||||
flavour_text = "You are a space bartender! Time to mix drinks and change lives. Wait, where did your bar just get transported to?"
|
||||
assignedrole = "Space Bartender"
|
||||
|
||||
/obj/effect/mob_spawn/human/beach/alive/lifeguard
|
||||
flavour_text = "<span class='big bold'>You're a spunky lifeguard!</span><b> It's up to you to make sure nobody drowns or gets eaten by sharks and stuff.</b>"
|
||||
flavour_text = "You're a spunky lifeguard! It's up to you to make sure nobody drowns or gets eaten by sharks and stuff. Then suddenly your entire beach was transported to this strange hell.\
|
||||
You aren't trained for this, but you'll still keep your guests alive!"
|
||||
description = "Try to survive on lavaland with the pitiful equipment of a lifeguard. Or hide in your biodome."
|
||||
mob_gender = "female"
|
||||
name = "lifeguard sleeper"
|
||||
id_job = "Lifeguard"
|
||||
@@ -502,7 +507,8 @@
|
||||
name = "beach bum sleeper"
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper"
|
||||
flavour_text = "You are a beach bum!"
|
||||
flavour_text = "You are a beach bum! You think something just happened to the beach but you don't really pay too much attention."
|
||||
description = "Try to survive on lavaland or just enjoy the beach, waiting for visitors."
|
||||
assignedrole = "Beach Bum"
|
||||
|
||||
/datum/outfit/beachbum
|
||||
@@ -523,6 +529,7 @@
|
||||
roundstart = FALSE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "remains"
|
||||
description = "Be a spooky scary skeleton." //not mapped in anywhere so admin spawner, who knows what they'll use this for.
|
||||
flavour_text = "By unknown powers, your skeletal remains have been reanimated! Walk this mortal plain and terrorize all living adventurers who dare cross your path."
|
||||
assignedrole = "Skeleton"
|
||||
|
||||
|
||||
@@ -64,9 +64,11 @@
|
||||
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 \
|
||||
important_info = "You are not an antag. Do not mess with the station or create AIs."
|
||||
description = "As a Free Golem on lavaland, you are unable to use most weapons, but you can mine, research and make more of your kind. Earn enough mining points and you can even move your shuttle out of there."
|
||||
flavour_text = "You are a Free Golem. Your family worships The Liberator. 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 ..()
|
||||
@@ -77,8 +79,10 @@
|
||||
if(!mapload && A)
|
||||
notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in [A.name].", source = src)
|
||||
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>"
|
||||
important_info = "Serve your creator, even if they are an antag."
|
||||
flavour_text = "You are a golem created to serve your creator."
|
||||
description = "You are a Golem. 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."
|
||||
owner = creator
|
||||
|
||||
/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn, name)
|
||||
|
||||
@@ -10,10 +10,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 \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are a security officer working for Nanotrasen, 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>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/security
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
id = /obj/item/card/id/away/old/sec
|
||||
@@ -35,10 +36,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are a medical working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are a medical doctor working for Nanotrasen, 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>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/medical
|
||||
shoes = /obj/item/clothing/shoes/black
|
||||
id = /obj/item/card/id/away/old/med
|
||||
@@ -60,10 +62,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 \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are an engineer working for Nanotrasen, 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>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/engineering
|
||||
shoes = /obj/item/clothing/shoes/workboots
|
||||
id = /obj/item/card/id/away/old/eng
|
||||
@@ -85,10 +88,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 \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are a scientist working for Nanotrasen, 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>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/science
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
id = /obj/item/card/id/away/old/sci
|
||||
|
||||
@@ -309,6 +309,20 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
/datum/asset/chem_master/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
//Cloning pod sprites for UIs
|
||||
/datum/asset/cloning
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/cloning/register()
|
||||
assets["pod_idle.gif"] = icon('icons/obj/cloning.dmi', "pod_idle")
|
||||
assets["pod_cloning.gif"] = icon('icons/obj/cloning.dmi', "pod_cloning")
|
||||
assets["pod_mess.gif"] = icon('icons/obj/cloning.dmi', "pod_mess")
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
|
||||
/datum/asset/cloning/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
//Pipe sprites for UIs
|
||||
/datum/asset/rpd
|
||||
|
||||
@@ -120,6 +120,12 @@
|
||||
else
|
||||
icon = initial(icon)
|
||||
|
||||
/**
|
||||
* Used for any clothing interactions when the user is on fire. (e.g. Cigarettes getting lit.)
|
||||
*/
|
||||
/obj/item/clothing/proc/catch_fire() //Called in handle_fire()
|
||||
return
|
||||
|
||||
//Ears: currently only used for headsets and earmuffs
|
||||
/obj/item/clothing/ears
|
||||
name = "ears"
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
SA.health = SA.maxHealth
|
||||
SA.del_on_death = FALSE
|
||||
greet_sentient(SA)
|
||||
print_command_report(sentience_report, "[command_name()] Update")
|
||||
print_command_report(sentience_report, "[command_name()] Update", FALSE)
|
||||
processing = TRUE // Let it naturally end, if it runs successfully
|
||||
|
||||
/datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M)
|
||||
|
||||
@@ -13,15 +13,3 @@
|
||||
possible_destinations = "laborcamp_away"
|
||||
circuit = /obj/item/circuitboard/labor_shuttle/one_way
|
||||
req_access = list( )
|
||||
|
||||
/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list)
|
||||
if(href_list["move"])
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp")
|
||||
if(!M)
|
||||
to_chat(usr, "<span class='warning'>Cannot locate shuttle!</span>")
|
||||
return 0
|
||||
var/obj/docking_port/stationary/S = M.get_docked()
|
||||
if(S && S.name == "laborcamp_away")
|
||||
to_chat(usr, "<span class='warning'>Shuttle is already at the outpost!</span>")
|
||||
return 0
|
||||
..()
|
||||
|
||||
@@ -780,4 +780,4 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set category = "Ghost"
|
||||
|
||||
var/datum/spawners_menu/menu = new /datum/spawners_menu(src)
|
||||
menu.ui_interact(src)
|
||||
menu.tgui_interact(src)
|
||||
|
||||
@@ -66,9 +66,7 @@
|
||||
if(!is_station_level(T.z))
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if(cryo_ssd(src))
|
||||
var/obj/effect/portal/P = new /obj/effect/portal(T, null, null, 40)
|
||||
P.name = "NT SSD Teleportation Portal"
|
||||
cryo_ssd(src)
|
||||
if(A.fast_despawn)
|
||||
force_cryo_human(src)
|
||||
|
||||
|
||||
@@ -186,6 +186,8 @@
|
||||
return 1
|
||||
if(fire_stacks > 0)
|
||||
adjust_fire_stacks(-0.1) //the fire is slowly consumed
|
||||
for(var/obj/item/clothing/C in contents)
|
||||
C.catch_fire()
|
||||
else
|
||||
ExtinguishMob()
|
||||
return
|
||||
|
||||
@@ -83,6 +83,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
var/lockcharge //Used when locking down a borg to preserve cell charge
|
||||
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
|
||||
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
|
||||
var/can_lock_cover = FALSE //Used to set if a borg can re-lock its cover.
|
||||
var/has_camera = TRUE
|
||||
var/pdahide = 0 //Used to hide the borg from the messenger list
|
||||
var/tracking_entities = 0 //The number of known entities currently accessing the internal camera
|
||||
@@ -752,6 +753,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
if(allowed(W))
|
||||
locked = !locked
|
||||
to_chat(user, "You [ locked ? "lock" : "unlock"] [src]'s interface.")
|
||||
to_chat(src, "<span class='notice'>[user] [ locked ? "locked" : "unlocked"] your interface.</span>")
|
||||
update_icons()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
@@ -768,7 +770,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
if(!user.drop_item())
|
||||
return
|
||||
if(U.action(src))
|
||||
to_chat(user, "<span class='notice'>You apply the upgrade to [src].</span>")
|
||||
user.visible_message("<span class = 'notice'>[user] applied [U] to [src].</span>", "<span class='notice'>You apply [U] to [src].</span>")
|
||||
U.forceMove(src)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Upgrade error.</span>")
|
||||
@@ -964,16 +966,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
update_icons()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/verb/unlock_own_cover()
|
||||
/mob/living/silicon/robot/verb/toggle_own_cover()
|
||||
set category = "Robot Commands"
|
||||
set name = "Unlock Cover"
|
||||
set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you."
|
||||
if(locked)
|
||||
switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No"))
|
||||
if("Yes")
|
||||
locked = 0
|
||||
update_icons()
|
||||
to_chat(usr, "You unlock your cover.")
|
||||
set name = "Toggle Cover"
|
||||
set desc = "Toggles the lock on your cover."
|
||||
|
||||
if(can_lock_cover)
|
||||
if(alert("Are you sure?", locked ? "Unlock Cover" : "Lock Cover", "Yes", "No") == "Yes")
|
||||
locked = !locked
|
||||
update_icons()
|
||||
to_chat(usr, "<span class='notice'>You [locked ? "lock" : "unlock"] your cover.</span>")
|
||||
return
|
||||
if(!locked)
|
||||
to_chat(usr, "<span class='warning'>You cannot lock your cover yourself. Find a robotocist.</span>")
|
||||
return
|
||||
if(alert("You cannnot lock your own cover again. Are you sure?\n You will need a robotocist to re-lock you.", "Unlock Own Cover", "Yes", "No") == "Yes")
|
||||
locked = !locked
|
||||
update_icons()
|
||||
to_chat(usr, "<span class='notice'>You unlock your cover.</span>")
|
||||
|
||||
/mob/living/silicon/robot/attack_ghost(mob/user)
|
||||
if(wiresexposed)
|
||||
@@ -1119,7 +1129,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/robot/proc/radio_menu()
|
||||
radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code
|
||||
radio.interact(src)
|
||||
|
||||
/mob/living/silicon/robot/proc/control_headlamp()
|
||||
if(stat || lamp_recharging || low_power_mode)
|
||||
@@ -1403,6 +1413,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
modtype = "Commando"
|
||||
faction = list("nanotrasen")
|
||||
is_emaggable = FALSE
|
||||
can_lock_cover = TRUE
|
||||
default_cell_type = /obj/item/stock_parts/cell/bluespace
|
||||
|
||||
/mob/living/silicon/robot/deathsquad/init(alien = FALSE, connect_to_AI = TRUE, mob/living/silicon/ai/ai_to_sync_to = null)
|
||||
@@ -1431,6 +1442,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
static_radio_channels = 1
|
||||
allow_rename = FALSE
|
||||
weapons_unlock = TRUE
|
||||
can_lock_cover = TRUE
|
||||
default_cell_type = /obj/item/stock_parts/cell/super
|
||||
var/eprefix = "Amber"
|
||||
|
||||
@@ -1487,6 +1499,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
ear_protection = 1 // Immunity to the audio part of flashbangs
|
||||
emp_protection = TRUE // Immunity to EMP, due to heavy shielding
|
||||
damage_protection = 20 // Reduce all incoming damage by this number. Very high in the case of /destroyer borgs, since it is an admin-only borg.
|
||||
can_lock_cover = TRUE
|
||||
default_cell_type = /obj/item/stock_parts/cell/bluespace
|
||||
|
||||
/mob/living/silicon/robot/destroyer/init(alien = FALSE, connect_to_AI = TRUE, mob/living/silicon/ai/ai_to_sync_to = null)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
modtype = "Syndicate"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
ionpulse = 1
|
||||
can_lock_cover = TRUE
|
||||
lawchannel = "State"
|
||||
var/playstyle_string = "<span class='userdanger'>You are a Syndicate assault cyborg!</span><br>\
|
||||
<b>You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
|
||||
|
||||
@@ -94,7 +94,6 @@
|
||||
hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_PATH_HUD = HUD_LIST_LIST)//Diagnostic HUD views
|
||||
|
||||
/obj/item/radio/headset/bot
|
||||
subspace_transmission = 1
|
||||
requires_tcomms = FALSE
|
||||
canhear_range = 0
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple/Life(seconds, times_fired)
|
||||
. = ..()
|
||||
if(.) // if mob is NOT dead
|
||||
if(stat != DEAD) // Can't use if(.) for this due to the fact it can sometimes return FALSE even when mob is alive.
|
||||
if(!degenerate && spider_myqueen)
|
||||
if(dcheck_counter >= 10)
|
||||
dcheck_counter = 0
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/Life(seconds, times_fired)
|
||||
. = ..()
|
||||
if(.) // if mob is NOT dead
|
||||
if(stat != DEAD) // Can't use if(.) for this due to the fact it can sometimes return FALSE even when mob is alive.
|
||||
if(ckey && canlay < 12 && hasnested) // max 12 eggs worth stored at any one time, realistically that's tons.
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
if(eggslaid >= 20)
|
||||
|
||||
@@ -298,7 +298,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Life(seconds, times_fired)
|
||||
. = ..()
|
||||
if(!.) // if mob is dead
|
||||
if(stat == DEAD) // Can't use if(.) for this due to the fact it can sometimes return FALSE even when mob is alive.
|
||||
if(prob(2))
|
||||
// 2% chance every cycle to decompose
|
||||
visible_message("<span class='notice'>\The dead body of the [src] decomposes!</span>")
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
|
||||
hard_drive.store_file(new/datum/computer_file/program/chatclient())
|
||||
hard_drive.store_file(new/datum/computer_file/program/card_mod())
|
||||
hard_drive.store_file(new/datum/computer_file/program/comm())
|
||||
|
||||
// ===== CIVILIAN CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/civilian
|
||||
|
||||
@@ -1,385 +0,0 @@
|
||||
/datum/computer_file/program/comm
|
||||
filename = "comm"
|
||||
filedesc = "Command and communications"
|
||||
program_icon_state = "comm"
|
||||
extended_desc = "Used to command and control the station. Can relay long-range communications. This program can not be run on tablet computers."
|
||||
required_access = ACCESS_HEADS
|
||||
requires_ntnet = 1
|
||||
size = 12
|
||||
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
|
||||
network_destination = "station long-range communication array"
|
||||
|
||||
var/authenticated = COMM_AUTHENTICATION_NONE
|
||||
var/list/messagetitle = list()
|
||||
var/list/messagetext = list()
|
||||
var/currmsg = 0
|
||||
var/aicurrmsg = 0
|
||||
var/menu_state = COMM_SCREEN_MAIN
|
||||
var/ai_menu_state = COMM_SCREEN_MAIN
|
||||
var/message_cooldown = 0
|
||||
var/centcomm_message_cooldown = 0
|
||||
var/tmp_alertlevel = 0
|
||||
|
||||
var/stat_msg1
|
||||
var/stat_msg2
|
||||
var/display_type="blank"
|
||||
|
||||
var/datum/announcement/priority/crew_announcement = new
|
||||
|
||||
/datum/computer_file/program/comm/New()
|
||||
GLOB.shuttle_caller_list += src
|
||||
..()
|
||||
crew_announcement.newscast = 0
|
||||
|
||||
/datum/computer_file/program/comm/Destroy()
|
||||
GLOB.shuttle_caller_list -= src
|
||||
SSshuttle.autoEvac()
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/comm/proc/is_authenticated(mob/user, loud = 1)
|
||||
if(authenticated == COMM_AUTHENTICATION_MAX)
|
||||
return COMM_AUTHENTICATION_MAX
|
||||
else if(user.can_admin_interact())
|
||||
return COMM_AUTHENTICATION_MAX
|
||||
else if(authenticated)
|
||||
return COMM_AUTHENTICATION_MIN
|
||||
else
|
||||
if(loud)
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return COMM_AUTHENTICATION_NONE
|
||||
|
||||
/datum/computer_file/program/comm/proc/change_security_level(mob/user, new_level)
|
||||
tmp_alertlevel = new_level
|
||||
var/old_level = GLOB.security_level
|
||||
if(!tmp_alertlevel)
|
||||
tmp_alertlevel = SEC_LEVEL_GREEN
|
||||
if(tmp_alertlevel < SEC_LEVEL_GREEN)
|
||||
tmp_alertlevel = SEC_LEVEL_GREEN
|
||||
if(tmp_alertlevel > SEC_LEVEL_BLUE)
|
||||
tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this
|
||||
set_security_level(tmp_alertlevel)
|
||||
if(GLOB.security_level != old_level)
|
||||
log_game("[key_name(user)] has changed the security level to [get_security_level()].")
|
||||
message_admins("[key_name_admin(user)] has changed the security level to [get_security_level()].")
|
||||
switch(GLOB.security_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
feedback_inc("alert_comms_green", 1)
|
||||
if(SEC_LEVEL_BLUE)
|
||||
feedback_inc("alert_comms_blue", 1)
|
||||
tmp_alertlevel = 0
|
||||
|
||||
/datum/computer_file/program/comm/proc/setCurrentMessage(mob/user, value)
|
||||
if(isAI(user) || isrobot(user))
|
||||
aicurrmsg = value
|
||||
else
|
||||
currmsg = value
|
||||
|
||||
/datum/computer_file/program/comm/proc/getCurrentMessage(mob/user)
|
||||
if(isAI(user) || isrobot(user))
|
||||
return aicurrmsg
|
||||
else
|
||||
return currmsg
|
||||
|
||||
/datum/computer_file/program/comm/proc/setMenuState(mob/user, value)
|
||||
if(isAI(user) || isrobot(user))
|
||||
ai_menu_state=value
|
||||
else
|
||||
menu_state=value
|
||||
|
||||
/datum/computer_file/program/comm/proc/getMenuState(mob/user)
|
||||
if(isAI(user) || isrobot(user))
|
||||
return ai_menu_state
|
||||
else
|
||||
return menu_state
|
||||
|
||||
/datum/computer_file/program/comm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui)
|
||||
if(!ui)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers)
|
||||
assets.send(user)
|
||||
ui = new(user, src, ui_key, "comm_program.tmpl", "Command and communications program", 575, 500)
|
||||
ui.set_layout_key("program")
|
||||
ui.open()
|
||||
|
||||
/datum/computer_file/program/comm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/list/data = get_header_data()
|
||||
data["is_ai"] = isAI(user) || isrobot(user)
|
||||
data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state
|
||||
data["emagged"] = computer ? computer.emagged : null
|
||||
data["authenticated"] = is_authenticated(user, 0)
|
||||
data["screen"] = getMenuState(usr)
|
||||
|
||||
data["stat_display"] = list(
|
||||
"type" = display_type,
|
||||
"line_1" = (stat_msg1 ? stat_msg1 : "-----"),
|
||||
"line_2" = (stat_msg2 ? stat_msg2 : "-----"),
|
||||
|
||||
"presets" = list(
|
||||
list("name" = "blank", "label" = "Clear", "desc" = "Blank slate"),
|
||||
list("name" = "shuttle", "label" = "Shuttle ETA", "desc" = "Display how much time is left."),
|
||||
list("name" = "message", "label" = "Message", "desc" = "A custom message.")
|
||||
),
|
||||
|
||||
"alerts"=list(
|
||||
list("alert" = "default", "label" = "Nanotrasen", "desc" = "Oh god."),
|
||||
list("alert" = "redalert", "label" = "Red Alert", "desc" = "Nothing to do with communists."),
|
||||
list("alert" = "lockdown", "label" = "Lockdown", "desc" = "Let everyone know they're on lockdown."),
|
||||
list("alert" = "biohazard", "label" = "Biohazard", "desc" = "Great for virus outbreaks and parties."),
|
||||
)
|
||||
)
|
||||
|
||||
data["security_level"] = GLOB.security_level
|
||||
data["str_security_level"] = capitalize(get_security_level())
|
||||
data["levels"] = list(
|
||||
list("id" = SEC_LEVEL_GREEN, "name" = "Green"),
|
||||
list("id" = SEC_LEVEL_BLUE, "name" = "Blue"),
|
||||
)
|
||||
|
||||
var/list/msg_data = list()
|
||||
for(var/i = 1; i <= messagetext.len; i++)
|
||||
msg_data.Add(list(list("title" = messagetitle[i], "body" = messagetext[i], "id" = i)))
|
||||
|
||||
data["messages"] = msg_data
|
||||
if((data["is_ai"] && aicurrmsg) || (!data["is_ai"] && currmsg))
|
||||
data["current_message"] = data["is_ai"] ? messagetext[aicurrmsg] : messagetext[currmsg]
|
||||
data["current_message_title"] = data["is_ai"] ? messagetitle[aicurrmsg] : messagetitle[currmsg]
|
||||
|
||||
data["lastCallLoc"] = SSshuttle.emergencyLastCallLoc ? format_text(SSshuttle.emergencyLastCallLoc.name) : null
|
||||
|
||||
var/shuttle[0]
|
||||
switch(SSshuttle.emergency.mode)
|
||||
if(SHUTTLE_IDLE, SHUTTLE_RECALL)
|
||||
shuttle["callStatus"] = 2 //#define
|
||||
else
|
||||
shuttle["callStatus"] = 1
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/timeleft = SSshuttle.emergency.timeLeft()
|
||||
shuttle["eta"] = "[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
|
||||
data["shuttle"] = shuttle
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/comm/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
var/turf/T = get_turf(computer)
|
||||
if(!is_secure_level(T.z))
|
||||
to_chat(usr, "<span class='warning'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||
return 1
|
||||
|
||||
if(href_list["PRG_login"])
|
||||
if(!ishuman(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
var/list/access = usr.get_access()
|
||||
if(ACCESS_HEADS in access)
|
||||
authenticated = COMM_AUTHENTICATION_MIN
|
||||
|
||||
if(ACCESS_CAPTAIN in access)
|
||||
authenticated = COMM_AUTHENTICATION_MAX
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/obj/item/card/id = H.get_idcard(TRUE)
|
||||
if(istype(id))
|
||||
crew_announcement.announcer = GetNameAndAssignmentFromId(id)
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
|
||||
if(href_list["PRG_logout"])
|
||||
authenticated = COMM_AUTHENTICATION_NONE
|
||||
crew_announcement.announcer = ""
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
|
||||
if(is_authenticated(usr))
|
||||
switch(href_list["PRG_operation"])
|
||||
if("main")
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("changeseclevel")
|
||||
setMenuState(usr,COMM_SCREEN_SECLEVEL)
|
||||
|
||||
if("newalertlevel")
|
||||
if(isAI(usr) || isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>Firewalls prevent you from changing the alert level.</span>")
|
||||
return 1
|
||||
else if(usr.can_admin_interact())
|
||||
change_security_level(usr, text2num(href_list["level"]))
|
||||
return 1
|
||||
else if(!ishuman(usr))
|
||||
to_chat(usr, "<span class='warning'>Security measures prevent you from changing the alert level.</span>")
|
||||
return 1
|
||||
|
||||
var/mob/living/carbon/human/L = usr
|
||||
var/obj/item/card = L.get_active_hand()
|
||||
var/obj/item/card/id/I = (card && card.GetID()) || L.wear_id || L.wear_pda
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/pda = I
|
||||
I = pda.id
|
||||
if(I && istype(I))
|
||||
if(ACCESS_CAPTAIN in I.access)
|
||||
change_security_level(usr, text2num(href_list["level"]))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You are not authorized to do this.</span>")
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You need to swipe your ID.</span>")
|
||||
|
||||
if("announce")
|
||||
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||
if(message_cooldown)
|
||||
to_chat(usr, "<span class='warning'>Please allow at least one minute to pass between announcements.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement")
|
||||
if(!input || message_cooldown || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
crew_announcement.Announce(input)
|
||||
message_cooldown = 1
|
||||
spawn(600)//One minute cooldown
|
||||
message_cooldown = 0
|
||||
|
||||
if("callshuttle")
|
||||
var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","")
|
||||
if(!input || ..() || !is_authenticated(usr))
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
|
||||
call_shuttle_proc(usr, input)
|
||||
if(SSshuttle.emergency.timer)
|
||||
post_status("shuttle")
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("cancelshuttle")
|
||||
if(isAI(usr) || isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>Firewalls prevent you from recalling the shuttle.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No")
|
||||
if(response == "Yes")
|
||||
cancel_call_proc(usr)
|
||||
if(SSshuttle.emergency.timer)
|
||||
post_status("shuttle")
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
|
||||
if("messagelist")
|
||||
currmsg = 0
|
||||
if(href_list["msgid"])
|
||||
setCurrentMessage(usr, text2num(href_list["msgid"]))
|
||||
setMenuState(usr,COMM_SCREEN_MESSAGES)
|
||||
|
||||
if("delmessage")
|
||||
if(href_list["msgid"])
|
||||
currmsg = text2num(href_list["msgid"])
|
||||
var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No")
|
||||
if(response == "Yes")
|
||||
if(currmsg)
|
||||
var/id = getCurrentMessage()
|
||||
var/title = messagetitle[id]
|
||||
var/text = messagetext[id]
|
||||
messagetitle.Remove(title)
|
||||
messagetext.Remove(text)
|
||||
if(currmsg == id)
|
||||
currmsg = 0
|
||||
if(aicurrmsg == id)
|
||||
aicurrmsg = 0
|
||||
setMenuState(usr,COMM_SCREEN_MESSAGES)
|
||||
|
||||
if("status")
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
|
||||
// Status display stuff
|
||||
if("setstat")
|
||||
display_type=href_list["statdisp"]
|
||||
switch(display_type)
|
||||
if("message")
|
||||
post_status("message", stat_msg1, stat_msg2, usr)
|
||||
if("alert")
|
||||
post_status("alert", href_list["alert"], user = usr)
|
||||
else
|
||||
post_status(href_list["statdisp"], user = usr)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg1")
|
||||
stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg2")
|
||||
stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
|
||||
if("nukerequest")
|
||||
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||
if(centcomm_message_cooldown)
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","")
|
||||
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
Nuke_request(input, usr)
|
||||
to_chat(usr, "<span class='notice'>Request sent.</span>")
|
||||
log_game("[key_name(usr)] has requested the nuclear codes from Centcomm")
|
||||
GLOB.priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg')
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(6000)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
|
||||
if("MessageCentcomm")
|
||||
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||
if(centcomm_message_cooldown)
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
Centcomm_announce(input, usr)
|
||||
to_chat(usr, "Message transmitted.")
|
||||
log_game("[key_name(usr)] has made a Centcomm announcement: [input]")
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(6000)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
|
||||
// OMG SYNDICATE ...LETTERHEAD
|
||||
if("MessageSyndicate")
|
||||
if((is_authenticated(usr) == COMM_AUTHENTICATION_MAX) && (computer && computer.emagged))
|
||||
if(centcomm_message_cooldown)
|
||||
to_chat(usr, "Arrays recycling. Please stand by.")
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
Syndicate_announce(input, usr)
|
||||
to_chat(usr, "Message transmitted.")
|
||||
log_game("[key_name(usr)] has made a Syndicate announcement: [input]")
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(6000)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
setMenuState(usr,COMM_SCREEN_MAIN)
|
||||
|
||||
if("RestartNanoMob")
|
||||
if(SSmob_hunt)
|
||||
if(SSmob_hunt.manual_reboot())
|
||||
var/loading_msg = pick("Respawning spawns", "Reticulating splines", "Flipping hat",
|
||||
"Capturing all of them", "Fixing minor text issues", "Being the very best",
|
||||
"Nerfing this", "Not communicating with playerbase", "Coding a ripoff in a 2D spaceman game")
|
||||
to_chat(usr, "<span class='notice'>Restarting Nano-Mob Hunter GO! game server. [loading_msg]...</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Nano-Mob Hunter GO! game server reboot failed due to recent restart. Please wait before re-attempting.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.</span>")
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
return 1
|
||||
@@ -1,105 +0,0 @@
|
||||
/datum/nano_module/ert_manager
|
||||
name = "ERT Manager"
|
||||
var/ert_type = "Code Red"
|
||||
var/commander_slots = 1
|
||||
var/security_slots = 3
|
||||
var/medical_slots = 3
|
||||
var/engineering_slots = 3
|
||||
var/janitor_slots = 0
|
||||
var/paranormal_slots = 0
|
||||
var/cyborg_slots = 0
|
||||
var/autoclose = 0
|
||||
|
||||
|
||||
/datum/nano_module/ert_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.admin_state)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(ui && autoclose)
|
||||
ui.close()
|
||||
return 0
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ert_config.tmpl", "ERT Panel", 600, 600, state = state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/datum/nano_module/ert_manager/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["set_code"])
|
||||
ert_type = href_list["set_code"]
|
||||
|
||||
if(href_list["set_com"])
|
||||
commander_slots = text2num(href_list["set_com"])
|
||||
|
||||
if(href_list["set_sec"])
|
||||
security_slots = text2num(href_list["set_sec"])
|
||||
|
||||
if(href_list["set_med"])
|
||||
medical_slots = text2num(href_list["set_med"])
|
||||
|
||||
if(href_list["set_eng"])
|
||||
engineering_slots = text2num(href_list["set_eng"])
|
||||
|
||||
if(href_list["set_jan"])
|
||||
janitor_slots = text2num(href_list["set_jan"])
|
||||
|
||||
if(href_list["set_par"])
|
||||
paranormal_slots = text2num(href_list["set_par"])
|
||||
|
||||
if(href_list["set_cyb"])
|
||||
cyborg_slots = text2num(href_list["set_cyb"])
|
||||
|
||||
if(href_list["dispatch_ert"])
|
||||
GLOB.ert_request_answered = TRUE
|
||||
var/slots_list = list()
|
||||
if(commander_slots > 0)
|
||||
slots_list += "commander: [commander_slots]"
|
||||
if(security_slots > 0)
|
||||
slots_list += "security: [security_slots]"
|
||||
if(medical_slots > 0)
|
||||
slots_list += "medical: [medical_slots]"
|
||||
if(engineering_slots > 0)
|
||||
slots_list += "engineering: [engineering_slots]"
|
||||
if(janitor_slots > 0)
|
||||
slots_list += "janitor: [janitor_slots]"
|
||||
if(paranormal_slots > 0)
|
||||
slots_list += "paranormal: [paranormal_slots]"
|
||||
if(cyborg_slots > 0)
|
||||
slots_list += "cyborg: [cyborg_slots]"
|
||||
var/slot_text = jointext(slots_list, ", ")
|
||||
notify_ghosts("An ERT is being dispatched. Open positions: [slot_text]")
|
||||
message_admins("[key_name_admin(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]", 1)
|
||||
log_admin("[key_name(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]")
|
||||
GLOB.event_announcement.Announce("Attention, [station_name()]. We are attempting to assemble an ERT. Standby.", "ERT Protocol Activated")
|
||||
autoclose = 1
|
||||
ui_interact(usr)
|
||||
trigger_armed_response_team(convert_ert_string(ert_type), commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
|
||||
return 0
|
||||
|
||||
ui_interact(usr)
|
||||
|
||||
|
||||
/proc/convert_ert_string(thestring)
|
||||
switch(thestring)
|
||||
if("Code Amber")
|
||||
return new /datum/response_team/amber
|
||||
if("Code Red")
|
||||
return new /datum/response_team/red
|
||||
if("Code Gamma")
|
||||
return new /datum/response_team/gamma
|
||||
|
||||
|
||||
/datum/nano_module/ert_manager/ui_data()
|
||||
var/data[0]
|
||||
data["alert_level"] = get_security_level()
|
||||
data["ert_type"] = ert_type
|
||||
data["com"] = commander_slots
|
||||
data["sec"] = security_slots
|
||||
data["med"] = medical_slots
|
||||
data["eng"] = engineering_slots
|
||||
data["jan"] = janitor_slots
|
||||
data["par"] = paranormal_slots
|
||||
data["cyb"] = cyborg_slots
|
||||
|
||||
return data
|
||||
|
||||
@@ -12,24 +12,32 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
insert_anim = "faxsend"
|
||||
pass_flags = PASSTABLE
|
||||
var/fax_network = "Local Fax Network"
|
||||
var/syndie_restricted = FALSE //is it a syndicate base fax restricted from contacting NT assets?
|
||||
/// If true, prevents fax machine from sending messages to NT machines
|
||||
var/syndie_restricted = FALSE
|
||||
|
||||
var/long_range_enabled = 0 // Can we send messages off the station?
|
||||
/// Can we send messages off-station?
|
||||
var/long_range_enabled = FALSE
|
||||
req_one_access = list(ACCESS_LAWYER, ACCESS_HEADS, ACCESS_ARMORY)
|
||||
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 30
|
||||
active_power_usage = 200
|
||||
|
||||
var/obj/item/card/id/scan = null // identification
|
||||
/// ID card inserted into the machine, used to log in with
|
||||
var/obj/item/card/id/scan = null
|
||||
|
||||
var/authenticated = 0
|
||||
var/sendcooldown = 0 // to avoid spamming fax messages
|
||||
/// Whether the machine is "logged in" or not
|
||||
var/authenticated = FALSE
|
||||
/// Next world.time at which this fax machine can send a message to CC/syndicate
|
||||
var/sendcooldown = 0
|
||||
/// After sending a message to CC/syndicate, cannot send another to them for this many deciseconds
|
||||
var/cooldown_time = 1800
|
||||
|
||||
var/department = "Unknown" // our department
|
||||
/// Our department, determines whether this machine gets faxes sent to a department
|
||||
var/department = "Unknown"
|
||||
|
||||
var/destination = "Not Selected" // the department we're sending to
|
||||
/// Target department to send outgoing faxes to
|
||||
var/destination
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/New()
|
||||
..()
|
||||
@@ -44,7 +52,7 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
/obj/machinery/photocopier/faxmachine/longrange
|
||||
name = "long range fax machine"
|
||||
fax_network = "Central Command Quantum Entanglement Network"
|
||||
long_range_enabled = 1
|
||||
long_range_enabled = TRUE
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/longrange/syndie
|
||||
name = "syndicate long range fax machine"
|
||||
@@ -58,17 +66,17 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
GLOB.hidden_departments |= department
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/attack_hand(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/attackby(obj/item/item, mob/user, params)
|
||||
if(istype(item,/obj/item/card/id) && !scan)
|
||||
scan(item)
|
||||
else if(istype(item, /obj/item/paper) || istype(item, /obj/item/photo) || istype(item, /obj/item/paper_bundle))
|
||||
..()
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -80,42 +88,6 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You swipe the card through [src], but nothing happens.</span>")
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "faxmachine.tmpl", "Fax Machine UI", 540, 450)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
var/is_authenticated = is_authenticated(user)
|
||||
|
||||
if(scan)
|
||||
data["scan_name"] = scan.name
|
||||
else
|
||||
data["scan_name"] = "-----"
|
||||
data["authenticated"] = is_authenticated
|
||||
if(!is_authenticated)
|
||||
data["network"] = "Disconnected"
|
||||
else if(!emagged)
|
||||
data["network"] = fax_network
|
||||
else
|
||||
data["network"] = "ERR*?*%!*"
|
||||
if(copyitem)
|
||||
data["paper"] = copyitem.name
|
||||
data["paperinserted"] = 1
|
||||
else
|
||||
data["paper"] = "-----"
|
||||
data["paperinserted"] = 0
|
||||
data["destination"] = destination
|
||||
data["cooldown"] = sendcooldown
|
||||
if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments))
|
||||
data["respectcooldown"] = 1
|
||||
else
|
||||
data["respectcooldown"] = 0
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/is_authenticated(mob/user)
|
||||
if(authenticated)
|
||||
return TRUE
|
||||
@@ -123,87 +95,134 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
/obj/machinery/photocopier/faxmachine/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "FaxMachine", name, 540, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["authenticated"] = is_authenticated(user)
|
||||
data["scan_name"] = scan ? scan.name : FALSE
|
||||
if(!data["authenticated"])
|
||||
data["network"] = "Disconnected"
|
||||
else if(!emagged)
|
||||
data["network"] = fax_network
|
||||
else
|
||||
data["network"] = "ERR*?*%!*"
|
||||
data["paper"] = copyitem ? copyitem.name : FALSE
|
||||
data["paperinserted"] = copyitem ? TRUE : FALSE
|
||||
data["destination"] = destination ? destination : FALSE
|
||||
data["sendError"] = FALSE
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
data["sendError"] = "No Power"
|
||||
else if(!data["authenticated"])
|
||||
data["sendError"] = "Not Logged In"
|
||||
else if(!data["paper"])
|
||||
data["sendError"] = "Nothing Inserted"
|
||||
else if(!data["destination"])
|
||||
data["sendError"] = "Destination Not Set"
|
||||
else if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments))
|
||||
var/cooldown_seconds = cooldown_seconds()
|
||||
if(cooldown_seconds)
|
||||
data["sendError"] = "Re-aligning in [cooldown_seconds] seconds..."
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
var/is_authenticated = is_authenticated(usr)
|
||||
if(href_list["send"])
|
||||
if(copyitem && is_authenticated)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("scan") // insert/remove your ID card
|
||||
scan()
|
||||
if("auth") // log in/out
|
||||
if(!is_authenticated && scan)
|
||||
if(scan.registered_name in GLOB.fax_blacklist)
|
||||
to_chat(usr, "<span class='warning'>Login rejected: individual is blacklisted from fax network.</span>")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
. = FALSE
|
||||
else if(check_access(scan))
|
||||
authenticated = TRUE
|
||||
else // ID doesn't have access to this machine
|
||||
to_chat(usr, "<span class='warning'>Login rejected: ID card does not have required access.</span>")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
. = FALSE
|
||||
else if(is_authenticated)
|
||||
authenticated = FALSE
|
||||
if("paper") // insert/eject paper/paperbundle/photo
|
||||
if(copyitem)
|
||||
copyitem.forceMove(get_turf(src))
|
||||
if(ishuman(usr))
|
||||
if(!usr.get_active_hand() && Adjacent(usr))
|
||||
usr.put_in_hands(copyitem)
|
||||
to_chat(usr, "<span class='notice'>You eject [copyitem] from [src].</span>")
|
||||
copyitem = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/paper) || istype(I, /obj/item/photo) || istype(I, /obj/item/paper_bundle))
|
||||
usr.drop_item()
|
||||
copyitem = I
|
||||
I.forceMove(src)
|
||||
to_chat(usr, "<span class='notice'>You insert [I] into [src].</span>")
|
||||
flick(insert_anim, src)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>[src] only accepts paper, paper bundles, and photos.</span>")
|
||||
. = FALSE
|
||||
if("rename") // rename the item that is currently in the fax machine
|
||||
if(copyitem)
|
||||
var/n_name = sanitize(copytext(input(usr, "What would you like to label the fax?", "Fax Labelling", copyitem.name) as text, 1, MAX_MESSAGE_LEN))
|
||||
if((copyitem && copyitem.loc == src && usr.stat == 0))
|
||||
if(istype(copyitem, /obj/item/paper))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : initial(copyitem.name))]"
|
||||
copyitem.desc = "This is a paper titled '" + copyitem.name + "'."
|
||||
else if(istype(copyitem, /obj/item/photo))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "photo")]"
|
||||
else if(istype(copyitem, /obj/item/paper_bundle))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "paper")]"
|
||||
else
|
||||
. = FALSE
|
||||
else
|
||||
. = FALSE
|
||||
else
|
||||
. = FALSE
|
||||
if("dept") // choose which department receives the fax
|
||||
if(is_authenticated)
|
||||
var/lastdestination = destination
|
||||
var/list/combineddepartments = GLOB.alldepartments.Copy()
|
||||
if(long_range_enabled)
|
||||
combineddepartments += GLOB.admin_departments.Copy()
|
||||
if(emagged)
|
||||
combineddepartments += GLOB.hidden_admin_departments.Copy()
|
||||
combineddepartments += GLOB.hidden_departments.Copy()
|
||||
if(syndie_restricted)
|
||||
combineddepartments = GLOB.hidden_admin_departments.Copy()
|
||||
combineddepartments += GLOB.hidden_departments.Copy()
|
||||
for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes)
|
||||
if(F.emagged)//we can contact emagged faxes on the station
|
||||
combineddepartments |= F.department
|
||||
destination = input(usr, "To which department?", "Choose a department", "") as null|anything in combineddepartments
|
||||
if(!destination)
|
||||
destination = lastdestination
|
||||
if("send") // actually send the fax
|
||||
if(!copyitem || !is_authenticated || !destination)
|
||||
return
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments))
|
||||
var/cooldown_seconds = cooldown_seconds()
|
||||
if(cooldown_seconds > 0)
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
to_chat(usr, "<span class='warning'>[src] is not ready for another [cooldown_seconds] seconds.</span>")
|
||||
return
|
||||
send_admin_fax(usr, destination)
|
||||
sendcooldown = world.time + cooldown_time
|
||||
else
|
||||
sendfax(destination, usr)
|
||||
|
||||
if(sendcooldown)
|
||||
spawn(sendcooldown) // cooldown time
|
||||
sendcooldown = 0
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
if(href_list["paper"])
|
||||
if(copyitem)
|
||||
copyitem.forceMove(get_turf(src))
|
||||
if(ishuman(usr))
|
||||
if(!usr.get_active_hand() && Adjacent(usr))
|
||||
usr.put_in_hands(copyitem)
|
||||
to_chat(usr, "<span class='notice'>You eject \the [copyitem] from \the [src].</span>")
|
||||
copyitem = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/paper) || istype(I, /obj/item/photo) || istype(I, /obj/item/paper_bundle))
|
||||
usr.drop_item()
|
||||
copyitem = I
|
||||
I.forceMove(src)
|
||||
to_chat(usr, "<span class='notice'>You insert \the [I] into \the [src].</span>")
|
||||
flick(insert_anim, src)
|
||||
|
||||
if(href_list["scan"])
|
||||
scan()
|
||||
|
||||
if(href_list["dept"])
|
||||
if(is_authenticated)
|
||||
var/lastdestination = destination
|
||||
var/list/combineddepartments = GLOB.alldepartments.Copy()
|
||||
if(long_range_enabled)
|
||||
combineddepartments += GLOB.admin_departments.Copy()
|
||||
|
||||
if(emagged)
|
||||
combineddepartments += GLOB.hidden_admin_departments.Copy()
|
||||
combineddepartments += GLOB.hidden_departments.Copy()
|
||||
|
||||
if(syndie_restricted)
|
||||
combineddepartments = GLOB.hidden_admin_departments.Copy()
|
||||
combineddepartments += GLOB.hidden_departments.Copy()
|
||||
for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes)
|
||||
if(F.emagged)//we can contact emagged faxes on the station
|
||||
combineddepartments |= F.department
|
||||
|
||||
destination = input(usr, "To which department?", "Choose a department", "") as null|anything in combineddepartments
|
||||
if(!destination)
|
||||
destination = lastdestination
|
||||
|
||||
if(href_list["auth"])
|
||||
if(!is_authenticated && scan)
|
||||
if(scan.registered_name in GLOB.fax_blacklist)
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
else if(check_access(scan))
|
||||
authenticated = 1
|
||||
else if(is_authenticated)
|
||||
authenticated = 0
|
||||
|
||||
if(href_list["rename"])
|
||||
if(copyitem)
|
||||
var/n_name = sanitize(copytext(input(usr, "What would you like to label the fax?", "Fax Labelling", copyitem.name) as text, 1, MAX_MESSAGE_LEN))
|
||||
if((copyitem && copyitem.loc == src && usr.stat == 0))
|
||||
if(istype(copyitem, /obj/item/paper))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : initial(copyitem.name))]"
|
||||
copyitem.desc = "This is a paper titled '" + copyitem.name + "'."
|
||||
else if(istype(copyitem, /obj/item/photo))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "photo")]"
|
||||
else if(istype(copyitem, /obj/item/paper_bundle))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "paper")]"
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
if(.)
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/scan(var/obj/item/card/id/card = null)
|
||||
if(scan) // Card is in machine
|
||||
@@ -226,7 +245,7 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
usr.drop_item()
|
||||
card.forceMove(src)
|
||||
scan = card
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/verb/eject_id()
|
||||
set category = null
|
||||
@@ -237,25 +256,20 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
return
|
||||
|
||||
if(scan)
|
||||
to_chat(usr, "You remove \the [scan] from \the [src].")
|
||||
to_chat(usr, "You remove [scan] from [src].")
|
||||
scan.forceMove(get_turf(src))
|
||||
if(!usr.get_active_hand() && Adjacent(usr))
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else
|
||||
to_chat(usr, "There is nothing to remove from \the [src].")
|
||||
to_chat(usr, "There is nothing to remove from [src].")
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/sendfax(var/destination,var/mob/sender)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
use_power(200)
|
||||
|
||||
use_power(active_power_usage)
|
||||
var/success = 0
|
||||
for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes)
|
||||
if(F.department == destination)
|
||||
success = F.receivefax(copyitem)
|
||||
|
||||
if(success)
|
||||
var/datum/fax/F = new /datum/fax()
|
||||
F.name = copyitem.name
|
||||
@@ -272,10 +286,10 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/receivefax(var/obj/item/incoming)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(department == "Unknown")
|
||||
return 0 //You can't send faxes to "Unknown"
|
||||
return FALSE //You can't send faxes to "Unknown"
|
||||
|
||||
flick("faxreceive", src)
|
||||
|
||||
@@ -291,19 +305,13 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
else if(istype(incoming, /obj/item/paper_bundle))
|
||||
bundlecopy(incoming)
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
use_power(active_power_usage)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/send_admin_fax(var/mob/sender, var/destination)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
if(sendcooldown)
|
||||
return
|
||||
|
||||
use_power(200)
|
||||
use_power(active_power_usage)
|
||||
|
||||
if(!(istype(copyitem, /obj/item/paper) || istype(copyitem, /obj/item/paper_bundle) || istype(copyitem, /obj/item/photo)))
|
||||
visible_message("[src] beeps, \"Error transmitting message.\"")
|
||||
@@ -327,10 +335,12 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
|
||||
for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes)
|
||||
if(F.department == destination)
|
||||
F.receivefax(copyitem)
|
||||
sendcooldown = cooldown_time
|
||||
spawn(50)
|
||||
visible_message("[src] beeps, \"Message transmitted successfully.\"")
|
||||
visible_message("[src] beeps, \"Message transmitted successfully.\"")
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/cooldown_seconds()
|
||||
if(sendcooldown < world.time)
|
||||
return 0
|
||||
return round((sendcooldown - world.time) / 10)
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/proc/message_admins(var/mob/sender, var/faxname, var/faxtype, var/obj/item/sent, font_colour="#9A04D1")
|
||||
var/msg = "<span class='boldnotice'><font color='[font_colour]'>[faxname]: </font> [key_name_admin(sender)] | REPLY: (<A HREF='?_src_=holder;[faxname == "SYNDICATE FAX" ? "SyndicateReply" : "CentcommReply"]=[sender.UID()]'>RADIO</A>) (<a href='?_src_=holder;AdminFaxCreate=\ref[sender];originfax=\ref[src];faxtype=[faxtype];replyto=\ref[sent]'>FAX</a>) ([ADMIN_SM(sender,"SM")]) | REJECT: (<A HREF='?_src_=holder;FaxReplyTemplate=[sender.UID()];originfax=\ref[src]'>TEMPLATE</A>) ([ADMIN_BSA(sender,"BSA")]) (<A HREF='?_src_=holder;EvilFax=[sender.UID()];originfax=\ref[src]'>EVILFAX</A>) </span>: Receiving '[sent.name]' via secure connection... <a href='?_src_=holder;AdminFaxView=\ref[sent]'>view message</a>"
|
||||
|
||||
+76
-72
@@ -227,8 +227,8 @@
|
||||
if(terminal)
|
||||
terminal.master = null
|
||||
terminal = null
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/power/smes/proc/make_terminal(user, tempDir, tempLoc)
|
||||
// create a terminal object at the same position as original turf loc
|
||||
@@ -339,89 +339,91 @@
|
||||
|
||||
/obj/machinery/power/smes/attack_ai(mob/user)
|
||||
add_hiddenprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/power/smes/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/power/smes/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
/obj/machinery/power/smes/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "smes.tmpl", "SMES Power Storage Unit", 540, 380)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "Smes", name, 340, 350, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/power/smes/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
data["nameTag"] = name_tag
|
||||
data["storedCapacity"] = round(100.0*charge/capacity, 0.1)
|
||||
data["charging"] = inputting
|
||||
data["chargeMode"] = input_attempt
|
||||
data["chargeLevel"] = input_level
|
||||
data["chargeMax"] = input_level_max
|
||||
data["outputOnline"] = output_attempt
|
||||
data["outputLevel"] = output_level
|
||||
data["outputMax"] = output_level_max
|
||||
data["outputLoad"] = round(output_used)
|
||||
|
||||
if(outputting)
|
||||
data["outputting"] = 2 // smes is outputting
|
||||
else if(!outputting && output_attempt)
|
||||
data["outputting"] = 1 // smes is online but not outputting because it's charge level is too low
|
||||
else
|
||||
data["outputting"] = 0 // smes is not outputting
|
||||
|
||||
/obj/machinery/power/smes/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"capacity" = capacity,
|
||||
"capacityPercent" = round(100*charge/capacity, 0.1),
|
||||
"charge" = charge,
|
||||
"inputAttempt" = input_attempt,
|
||||
"inputting" = inputting,
|
||||
"inputLevel" = input_level,
|
||||
"inputLevel_text" = DisplayPower(input_level),
|
||||
"inputLevelMax" = input_level_max,
|
||||
"inputAvailable" = input_available,
|
||||
"outputAttempt" = output_attempt,
|
||||
"outputting" = outputting,
|
||||
"outputLevel" = output_level,
|
||||
"outputLevel_text" = DisplayPower(output_level),
|
||||
"outputLevelMax" = output_level_max,
|
||||
"outputUsed" = round(output_used),
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/power/smes/Topic(href, href_list)
|
||||
/obj/machinery/power/smes/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("tryinput")
|
||||
inputting(!input_attempt)
|
||||
update_icon()
|
||||
if("tryoutput")
|
||||
outputting(!output_attempt)
|
||||
update_icon()
|
||||
if("input")
|
||||
var/target = params["target"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(target == "min")
|
||||
target = 0
|
||||
else if(target == "max")
|
||||
target = input_level_max
|
||||
else if(adjust)
|
||||
target = input_level + adjust
|
||||
else if(text2num(target) != null)
|
||||
target = text2num(target)
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
input_level = clamp(target, 0, input_level_max)
|
||||
if("output")
|
||||
var/target = params["target"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(target == "min")
|
||||
target = 0
|
||||
else if(target == "max")
|
||||
target = output_level_max
|
||||
else if(adjust)
|
||||
target = output_level + adjust
|
||||
else if(text2num(target) != null)
|
||||
target = text2num(target)
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
output_level = clamp(target, 0, output_level_max)
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
log_smes(usr)
|
||||
|
||||
if( href_list["cmode"] )
|
||||
inputting(!input_attempt)
|
||||
update_icon()
|
||||
|
||||
else if( href_list["online"] )
|
||||
outputting(!output_attempt)
|
||||
update_icon()
|
||||
|
||||
else if( href_list["input"] )
|
||||
switch( href_list["input"] )
|
||||
if("min")
|
||||
input_level = 0
|
||||
if("max")
|
||||
input_level = input_level_max
|
||||
if("set")
|
||||
input_level = input(usr, "Enter new input level (0-[input_level_max])", "SMES Input Power Control", input_level) as num
|
||||
input_level = max(0, min(input_level_max, input_level)) // clamp to range
|
||||
|
||||
else if( href_list["output"] )
|
||||
switch( href_list["output"] )
|
||||
if("min")
|
||||
output_level = 0
|
||||
if("max")
|
||||
output_level = output_level_max
|
||||
if("set")
|
||||
output_level = input(usr, "Enter new output level (0-[output_level_max])", "SMES Output Power Control", output_level) as num
|
||||
output_level = max(0, min(output_level_max, output_level)) // clamp to range
|
||||
|
||||
investigate_log("input/output; [input_level>output_level?"<font color='green'>":"<font color='red'>"][input_level]/[output_level]</font> | Output-mode: [output_attempt?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [input_attempt?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [usr.key]","singulo")
|
||||
|
||||
return 1
|
||||
/obj/machinery/power/smes/proc/log_smes(mob/user)
|
||||
investigate_log("input/output; [input_level>output_level?"<font color='green'>":"<font color='red'>"][input_level]/[output_level]</font> | Charge: [charge] | Output-mode: [output_attempt?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [input_attempt?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [user ? key_name(user) : "outside forces"]", "singulo")
|
||||
|
||||
/obj/machinery/power/smes/proc/ion_act()
|
||||
if(is_station_level(src.z))
|
||||
@@ -448,6 +450,7 @@
|
||||
smoke.attach(src)
|
||||
smoke.start()
|
||||
|
||||
|
||||
/obj/machinery/power/smes/proc/inputting(var/do_input)
|
||||
input_attempt = do_input
|
||||
if(!input_attempt)
|
||||
@@ -459,14 +462,15 @@
|
||||
outputting = 0
|
||||
|
||||
/obj/machinery/power/smes/emp_act(severity)
|
||||
inputting(rand(0,1))
|
||||
outputting(rand(0,1))
|
||||
inputting(rand(0, 1))
|
||||
outputting(rand(0, 1))
|
||||
output_level = rand(0, output_level_max)
|
||||
input_level = rand(0, input_level_max)
|
||||
charge -= 1e6/severity
|
||||
if(charge < 0)
|
||||
charge = 0
|
||||
update_icon()
|
||||
log_smes()
|
||||
..()
|
||||
|
||||
/obj/machinery/power/smes/engineering
|
||||
|
||||
+74
-81
@@ -254,13 +254,17 @@
|
||||
// Solar Control Computer
|
||||
//
|
||||
|
||||
#define TRACKER_OFF 0
|
||||
#define TRACKER_TIMED 1
|
||||
#define TRACKER_AUTO 2
|
||||
|
||||
/obj/machinery/power/solar_control
|
||||
name = "solar panel control"
|
||||
desc = "A controller for solar panel arrays."
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "computer"
|
||||
anchored = 1
|
||||
density = 1
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 250
|
||||
max_integrity = 200
|
||||
@@ -272,17 +276,17 @@
|
||||
var/targetdir = 0 // target angle in manual tracking (since it updates every game minute)
|
||||
var/gen = 0
|
||||
var/lastgen = 0
|
||||
var/track = 0 // 0= off 1=timed 2=auto (tracker)
|
||||
var/track = TRACKER_OFF
|
||||
var/trackrate = 600 // 300-900 seconds
|
||||
var/nexttime = 0 // time for a panel to rotate of 1? in manual tracking
|
||||
var/autostart = 0 // Automatically search for connected devices
|
||||
var/autostart = FALSE // Automatically search for connected devices
|
||||
var/obj/machinery/power/tracker/connected_tracker = null
|
||||
var/list/connected_panels = list()
|
||||
|
||||
// Used for mapping in solar array which automatically starts itself (telecomms, for example)
|
||||
/obj/machinery/power/solar_control/autostart
|
||||
track = 2 // Auto tracking mode
|
||||
autostart = 1 // Automatically start
|
||||
track = TRACKER_AUTO
|
||||
autostart = TRUE // Automatically search for connected devices
|
||||
|
||||
/obj/machinery/power/solar_control/Initialize()
|
||||
SSsun.solars |= src
|
||||
@@ -294,7 +298,7 @@
|
||||
set_panels(cdir)
|
||||
if(autostart)
|
||||
search_for_connected()
|
||||
if(connected_tracker && track == 2)
|
||||
if(connected_tracker && track == TRACKER_AUTO)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
set_panels(cdir)
|
||||
|
||||
@@ -334,15 +338,9 @@
|
||||
if(stat & (NOPOWER | BROKEN))
|
||||
return
|
||||
|
||||
switch(track)
|
||||
if(1)
|
||||
if(trackrate) //we're manual tracking. If we set a rotation speed...
|
||||
cdir = targetdir //...the current direction is the targetted one (and rotates panels to it)
|
||||
if(2) // auto-tracking
|
||||
if(connected_tracker)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
|
||||
set_panels(cdir)
|
||||
if(track == TRACKER_AUTO && connected_tracker) // auto-tracking
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
set_panels(cdir)
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/power/solar_control/update_icon()
|
||||
@@ -359,44 +357,73 @@
|
||||
overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir))
|
||||
|
||||
/obj/machinery/power/solar_control/attack_ai(mob/user as mob)
|
||||
src.add_hiddenprint(user)
|
||||
ui_interact(user)
|
||||
add_hiddenprint(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/power/solar_control/attack_ghost(mob/user as mob)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/power/solar_control/attack_hand(mob/user)
|
||||
if(..(user))
|
||||
return 1
|
||||
|
||||
return TRUE
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/solar_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/power/solar_control/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "solar_control.tmpl", name, 490, 420)
|
||||
ui = new(user, src, ui_key, "SolarControl", name, 490, 300)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/power/solar_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
data["generated"] = round(lastgen)
|
||||
data["angle"] = cdir
|
||||
data["direction"] = angle2text(cdir)
|
||||
|
||||
data["tracking_state"] = track
|
||||
data["tracking_rate"] = trackrate
|
||||
data["rotating_way"] = (trackrate<0 ? "CCW" : "CW")
|
||||
|
||||
/obj/machinery/power/solar_control/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["generated"] = round(lastgen) //generated power by all connected panels
|
||||
data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * SOLARGENRATE) //power generation ratio. Used for the power bar
|
||||
data["direction"] = angle2text(cdir) //current orientation of the panels
|
||||
data["cdir"] = cdir //current orientation of the of the panels in degrees
|
||||
data["tracking_state"] = track //tracker status: TRACKER_OFF, TRACKER_TIMED, TRACKER_AUTO
|
||||
data["tracking_rate"] = trackrate //rotation speed of tracker in degrees/h
|
||||
data["rotating_direction"] = (trackrate < 0 ? "Counter clockwise" : "Clockwise") //direction of tracker
|
||||
data["connected_panels"] = connected_panels.len
|
||||
data["connected_tracker"] = (connected_tracker ? 1 : 0)
|
||||
|
||||
data["connected_tracker"] = (connected_tracker ? TRUE : FALSE)
|
||||
return data
|
||||
|
||||
/obj/machinery/power/solar_control/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
switch(action)
|
||||
if("cdir") //change panel orientation
|
||||
var/newAngle = text2num(params["cdir"])
|
||||
if(!isnull(newAngle)) //0 is ok
|
||||
cdir = clamp(newAngle, 0, 359)
|
||||
targetdir = cdir
|
||||
set_panels(cdir)
|
||||
if("tdir") //change tracker rotation
|
||||
var/newTrackrate = text2num(params["tdir"])
|
||||
if(!newTrackrate)
|
||||
newTrackrate = 1
|
||||
trackrate = clamp(newTrackrate, -7200, 7200)
|
||||
nexttime = world.time + 36000 / abs(trackrate)
|
||||
if("track") //change tracker status
|
||||
track = text2num(params["track"])
|
||||
if(track == TRACKER_AUTO)
|
||||
if(connected_tracker)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
set_panels(cdir)
|
||||
else if(track == TRACKER_TIMED)
|
||||
targetdir = cdir
|
||||
if(trackrate)
|
||||
nexttime = world.time + 36000 / abs(trackrate)
|
||||
set_panels(targetdir)
|
||||
if("refresh")
|
||||
search_for_connected()
|
||||
if(connected_tracker && track == TRACKER_AUTO)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
set_panels(cdir)
|
||||
|
||||
/obj/machinery/power/solar_control/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
playsound(src.loc, I.usesound, 50, 1)
|
||||
@@ -450,50 +477,16 @@
|
||||
if(stat & (NOPOWER | BROKEN))
|
||||
return
|
||||
|
||||
if(connected_tracker) //NOTE : handled here so that we don't add trackers to the processing list
|
||||
if(connected_tracker.powernet != powernet)
|
||||
connected_tracker.unset_control()
|
||||
if(connected_tracker && connected_tracker.powernet != powernet) //NOTE : handled here so that we don't add trackers to the processing list
|
||||
connected_tracker.unset_control()
|
||||
|
||||
if(track==1 && trackrate) //manual tracking and set a rotation speed
|
||||
if(nexttime <= world.time) //every time we need to increase/decrease the angle by 1?...
|
||||
targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
|
||||
nexttime += 36000/abs(trackrate) //reset the counter for the next 1?
|
||||
|
||||
/obj/machinery/power/solar_control/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["rate_control"])
|
||||
if(href_list["cdir"])
|
||||
src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360)
|
||||
src.targetdir = src.cdir
|
||||
if(track == 2) //manual update, so losing auto-tracking
|
||||
track = 0
|
||||
spawn(1)
|
||||
set_panels(cdir)
|
||||
if(href_list["tdir"])
|
||||
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
|
||||
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
|
||||
|
||||
if(href_list["track"])
|
||||
track = text2num(href_list["track"])
|
||||
if(track == 2)
|
||||
if(connected_tracker)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
set_panels(cdir)
|
||||
else if(track == 1) //begin manual tracking
|
||||
src.targetdir = src.cdir
|
||||
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
|
||||
set_panels(targetdir)
|
||||
|
||||
if(href_list["search_connected"])
|
||||
search_for_connected()
|
||||
if(connected_tracker && track == 2)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
//manual tracking and set a rotation speed
|
||||
if(track == TRACKER_TIMED && trackrate && nexttime <= world.time) //every time we need to increase/decrease the angle by 1?...
|
||||
targetdir = (targetdir + trackrate / abs(trackrate) + 360) % 360 //... do it
|
||||
nexttime += 36000 / abs(trackrate) //reset the counter for the next 1?
|
||||
cdir = targetdir
|
||||
set_panels(cdir)
|
||||
|
||||
return
|
||||
|
||||
//rotates the panel to the passed angle
|
||||
/obj/machinery/power/solar_control/proc/set_panels(var/cdir)
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
var/ammo_type = /obj/item/ammo_casing
|
||||
var/max_ammo = 7
|
||||
var/multiple_sprites = 0
|
||||
var/icon_prefix // boxes with multiple sprites use this as their base
|
||||
var/caliber
|
||||
var/multiload = 1
|
||||
var/list/initial_mats //For calculating refund values.
|
||||
@@ -192,11 +193,12 @@
|
||||
update_icon()
|
||||
|
||||
/obj/item/ammo_box/update_icon()
|
||||
var/icon_base = initial(icon_prefix) ? initial(icon_prefix) : initial(icon_state)
|
||||
switch(multiple_sprites)
|
||||
if(1)
|
||||
icon_state = "[initial(icon_state)]-[stored_ammo.len]"
|
||||
icon_state = "[icon_base]-[stored_ammo.len]"
|
||||
if(2)
|
||||
icon_state = "[initial(icon_state)]-[stored_ammo.len ? "[max_ammo]" : "0"]"
|
||||
icon_state = "[icon_base]-[stored_ammo.len ? "[max_ammo]" : "0"]"
|
||||
desc = "[initial(desc)] There are [stored_ammo.len] shell\s left!"
|
||||
|
||||
/obj/item/ammo_box/proc/update_mat_value()
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/obj/item/ammo_box/a357
|
||||
name = "speed loader (.357)"
|
||||
desc = "Designed to quickly reload revolvers."
|
||||
icon_state = "357"
|
||||
ammo_type = /obj/item/ammo_casing/a357
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
icon_state = "357-7" // DEFAULT icon, composed of prefix + "-" + max_ammo for multiple_sprites == 1 boxes
|
||||
multiple_sprites = 1 // see: /obj/item/ammo_box/update_icon()
|
||||
icon_prefix = "357" // icon prefix, used in above formula to generate dynamic icons
|
||||
|
||||
/obj/item/ammo_box/c38
|
||||
name = "speed loader (.38)"
|
||||
@@ -12,7 +13,9 @@
|
||||
icon_state = "38"
|
||||
ammo_type = /obj/item/ammo_casing/c38
|
||||
max_ammo = 6
|
||||
icon_state = "38-6" // see previous entry for explanation of these vars
|
||||
multiple_sprites = 1
|
||||
icon_prefix = "38"
|
||||
|
||||
/obj/item/ammo_box/c9mm
|
||||
name = "ammo box (9mm)"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
var/list/hacked_reagents = list("toxin")
|
||||
var/hack_message = "You disable the safety safeguards, enabling the \"Mad Scientist\" mode."
|
||||
var/unhack_message = "You re-enable the safety safeguards, enabling the \"NT Standard\" mode."
|
||||
var/is_drink = FALSE
|
||||
|
||||
/obj/machinery/chem_dispenser/get_cell()
|
||||
return cell
|
||||
@@ -120,7 +121,6 @@
|
||||
var/usedpower = cell.give(recharge_amount)
|
||||
if(usedpower)
|
||||
use_power(15 * recharge_amount)
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
recharge_counter = 0
|
||||
return
|
||||
recharge_counter++
|
||||
@@ -131,7 +131,6 @@
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
stat |= NOPOWER
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
/obj/machinery/chem_dispenser/ex_act(severity)
|
||||
if(severity < 3)
|
||||
@@ -145,19 +144,17 @@
|
||||
beaker = null
|
||||
overlays.Cut()
|
||||
|
||||
/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
/obj/machinery/chem_dispenser/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "chem_dispenser.tmpl", ui_title, 390, 655)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "ChemDispenser", ui_title, 390, 655)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/chem_dispenser/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/chem_dispenser/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["glass"] = is_drink
|
||||
data["amount"] = amount
|
||||
data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI.
|
||||
data["maxEnergy"] = cell.maxcharge * powerefficiency
|
||||
@@ -187,63 +184,59 @@
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/chem_dispenser/Topic(href, href_list)
|
||||
/obj/machinery/chem_dispenser/tgui_act(actions, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(href_list["amount"])
|
||||
amount = round(text2num(href_list["amount"]), 1) // round to nearest 1
|
||||
if(amount < 0) // Since the user can actually type the commands himself, some sanity checking
|
||||
amount = 0
|
||||
if(amount > 100)
|
||||
amount = 100
|
||||
|
||||
if(href_list["dispense"])
|
||||
if(!is_operational() || QDELETED(cell))
|
||||
return
|
||||
if(beaker && dispensable_reagents.Find(href_list["dispense"]))
|
||||
. = TRUE
|
||||
switch(actions)
|
||||
if("amount")
|
||||
amount = clamp(round(text2num(params["amount"]), 1), 0, 50) // round to nearest 1 and clamp to 0 - 50
|
||||
if("dispense")
|
||||
if(!is_operational() || QDELETED(cell))
|
||||
return
|
||||
if(!beaker || !dispensable_reagents.Find(params["reagent"]))
|
||||
return
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/free = R.maximum_volume - R.total_volume
|
||||
var/actual = min(amount, (cell.charge * powerefficiency) * 10, free)
|
||||
|
||||
if(!cell.use(actual / powerefficiency))
|
||||
atom_say("Not enough energy to complete operation!")
|
||||
return
|
||||
|
||||
R.add_reagent(href_list["dispense"], actual)
|
||||
R.add_reagent(params["reagent"], actual)
|
||||
overlays.Cut()
|
||||
if(!icon_beaker)
|
||||
icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
|
||||
icon_beaker = mutable_appearance('icons/obj/chemical.dmi', "disp_beaker") //randomize beaker overlay position.
|
||||
icon_beaker.pixel_x = rand(-10, 5)
|
||||
overlays += icon_beaker
|
||||
|
||||
if(href_list["remove"])
|
||||
if(beaker)
|
||||
if(href_list["removeamount"])
|
||||
var/amount = text2num(href_list["removeamount"])
|
||||
if(isnum(amount) && (amount > 0))
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/id = href_list["remove"]
|
||||
R.remove_reagent(id, amount)
|
||||
else if(isnum(amount) && (amount == -1)) //Isolate instead
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/id = href_list["remove"]
|
||||
R.isolate_reagent(id)
|
||||
|
||||
if(href_list["ejectBeaker"])
|
||||
if(beaker)
|
||||
if("remove")
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!beaker || !amount)
|
||||
return
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/id = params["reagent"]
|
||||
if(amount > 0)
|
||||
R.remove_reagent(id, amount)
|
||||
else if(amount == -1) //Isolate instead
|
||||
R.isolate_reagent(id)
|
||||
if("ejectBeaker")
|
||||
if(!beaker)
|
||||
return
|
||||
beaker.forceMove(loc)
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
usr.put_in_hands(beaker)
|
||||
beaker = null
|
||||
overlays.Cut()
|
||||
else
|
||||
return FALSE
|
||||
|
||||
add_fingerprint(usr)
|
||||
return TRUE // update UIs attached to this object
|
||||
|
||||
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
|
||||
if(exchange_parts(user, I))
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
if(isrobot(user))
|
||||
@@ -263,9 +256,9 @@
|
||||
beaker = I
|
||||
I.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You set [I] on the machine.</span>")
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
SStgui.update_uis(src) // update all UIs attached to src
|
||||
if(!icon_beaker)
|
||||
icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
|
||||
icon_beaker = mutable_appearance('icons/obj/chemical.dmi', "disp_beaker") //randomize beaker overlay position.
|
||||
icon_beaker.pixel_x = rand(-10, 5)
|
||||
overlays += icon_beaker
|
||||
return
|
||||
@@ -299,8 +292,7 @@
|
||||
to_chat(user, unhack_message)
|
||||
dispensable_reagents -= hacked_reagents
|
||||
hackedcheck = FALSE
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/chem_dispenser/screwdriver_act(mob/user, obj/item/I)
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", "[initial(icon_state)]", I))
|
||||
@@ -321,14 +313,14 @@
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/chem_dispenser/attack_ghost(mob/user)
|
||||
if(user.can_admin_interact())
|
||||
return attack_hand(user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_dispenser/attack_hand(mob/user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_dispenser/soda
|
||||
icon_state = "soda_dispenser"
|
||||
@@ -342,6 +334,7 @@
|
||||
hacked_reagents = list("thirteenloko")
|
||||
hack_message = "You change the mode from 'McNano' to 'Pizza King'."
|
||||
unhack_message = "You change the mode from 'Pizza King' to 'McNano'."
|
||||
is_drink = TRUE
|
||||
|
||||
/obj/machinery/chem_dispenser/soda/New()
|
||||
..()
|
||||
@@ -377,6 +370,7 @@
|
||||
hacked_reagents = list("goldschlager", "patron", "absinthe", "ethanol", "nothing", "sake")
|
||||
hack_message = "You disable the 'nanotrasen-are-cheap-bastards' lock, enabling hidden and very expensive boozes."
|
||||
unhack_message = "You re-enable the 'nanotrasen-are-cheap-bastards' lock, disabling hidden and very expensive boozes."
|
||||
is_drink = TRUE
|
||||
|
||||
/obj/machinery/chem_dispenser/beer/New()
|
||||
..()
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
/obj/machinery/chem_heater
|
||||
name = "chemical heater"
|
||||
density = 1
|
||||
anchored = 1
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "mixer0b"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 40
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
resistance_flags = FIRE_PROOF|ACID_PROOF
|
||||
var/obj/item/reagent_containers/beaker = null
|
||||
var/desired_temp = T0C
|
||||
var/on = FALSE
|
||||
/// Whether this should auto-eject the beaker once done heating/cooling.
|
||||
var/auto_eject = FALSE
|
||||
/// The higher this number, the faster reagents will heat/cool.
|
||||
var/speed_increase = 0
|
||||
|
||||
/obj/machinery/chem_heater/New()
|
||||
..()
|
||||
@@ -19,35 +23,36 @@
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/chem_heater/RefreshParts()
|
||||
speed_increase = initial(speed_increase)
|
||||
for(var/obj/item/stock_parts/micro_laser/M in component_parts)
|
||||
speed_increase += 5 * (M.rating - 1)
|
||||
|
||||
/obj/machinery/chem_heater/process()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
var/state_change = FALSE
|
||||
if(on)
|
||||
if(beaker)
|
||||
if(!beaker.reagents.total_volume)
|
||||
on = FALSE
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
beaker.reagents.temperature_reagents(desired_temp)
|
||||
beaker.reagents.temperature_reagents(desired_temp)
|
||||
if(abs(beaker.reagents.chem_temp - desired_temp) <= 3)
|
||||
beaker.reagents.temperature_reagents(desired_temp, max(1, 35 - speed_increase))
|
||||
if(round(beaker.reagents.chem_temp) == round(desired_temp))
|
||||
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
|
||||
on = FALSE
|
||||
state_change = TRUE
|
||||
|
||||
if(state_change)
|
||||
SSnanoui.update_uis(src)
|
||||
if(auto_eject)
|
||||
eject_beaker()
|
||||
|
||||
/obj/machinery/chem_heater/proc/eject_beaker(mob/user)
|
||||
if(beaker)
|
||||
beaker.forceMove(get_turf(src))
|
||||
if(Adjacent(user) && !issilicon(user))
|
||||
if(user && Adjacent(user) && !issilicon(user))
|
||||
user.put_in_hands(beaker)
|
||||
beaker = null
|
||||
icon_state = "mixer0b"
|
||||
on = FALSE
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/chem_heater/power_change()
|
||||
if(powered())
|
||||
@@ -55,7 +60,6 @@
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
stat |= NOPOWER
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
/obj/machinery/chem_heater/attackby(obj/item/I, mob/user)
|
||||
if(isrobot(user))
|
||||
@@ -71,7 +75,7 @@
|
||||
I.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You add the beaker to the machine!</span>")
|
||||
icon_state = "mixer1b"
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
if(exchange_parts(user, I))
|
||||
@@ -95,62 +99,62 @@
|
||||
default_deconstruction_crowbar(user, I)
|
||||
|
||||
/obj/machinery/chem_heater/attack_hand(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_heater/attack_ghost(mob/user)
|
||||
if(user.can_admin_interact())
|
||||
return attack_hand(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_heater/attack_ai(mob/user)
|
||||
add_hiddenprint(user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/chem_heater/Topic(href, href_list)
|
||||
/obj/machinery/chem_heater/tgui_act(action, params)
|
||||
if(..())
|
||||
return FALSE
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(href_list["toggle_on"])
|
||||
if(!beaker.reagents.total_volume)
|
||||
return FALSE
|
||||
on = !on
|
||||
. = 1
|
||||
|
||||
if(href_list["adjust_temperature"])
|
||||
var/val = href_list["adjust_temperature"]
|
||||
if(isnum(val))
|
||||
desired_temp = clamp(desired_temp+val, 0, 1000)
|
||||
else if(val == "input")
|
||||
var/target = input("Please input the target temperature", name) as num
|
||||
desired_temp = clamp(target, 0, 1000)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("toggle_on")
|
||||
on = !on
|
||||
if("adjust_temperature")
|
||||
desired_temp = clamp(text2num(params["target"]), 0, 1000)
|
||||
if("eject_beaker")
|
||||
eject_beaker(usr)
|
||||
. = FALSE
|
||||
if("toggle_autoeject")
|
||||
auto_eject = !auto_eject
|
||||
else
|
||||
return FALSE
|
||||
. = 1
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["eject_beaker"])
|
||||
eject_beaker(usr)
|
||||
. = 0 //updated in eject_beaker() already
|
||||
|
||||
/obj/machinery/chem_heater/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null)
|
||||
/obj/machinery/chem_heater/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "chem_heater.tmpl", "ChemHeater", 350, 270)
|
||||
ui = new(user, src, ui_key, "ChemHeater", "Chemical Heater", 350, 270, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/chem_heater/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/chem_heater/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
var/cur_temp = beaker ? beaker.reagents.chem_temp : null
|
||||
|
||||
data["targetTemp"] = desired_temp
|
||||
data["targetTempReached"] = FALSE
|
||||
data["autoEject"] = auto_eject
|
||||
data["isActive"] = on
|
||||
data["isBeakerLoaded"] = beaker ? 1 : 0
|
||||
data["isBeakerLoaded"] = beaker ? TRUE : FALSE
|
||||
|
||||
data["currentTemp"] = beaker ? beaker.reagents.chem_temp : null
|
||||
data["currentTemp"] = cur_temp
|
||||
data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null
|
||||
data["beakerMaxVolume"] = beaker ? beaker.volume : null
|
||||
|
||||
if(cur_temp)
|
||||
data["targetTempReached"] = round(cur_temp) == round(desired_temp)
|
||||
|
||||
//copy-pasted from chem dispenser
|
||||
var/beakerContents[0]
|
||||
if(beaker)
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#define MAX_PILL_SPRITE 20 //max icon state of the pill sprites
|
||||
#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
|
||||
#define MAX_UNITS_PER_PILL 100 // Max amount of units in a pill
|
||||
#define MAX_UNITS_PER_PATCH 30 // Max amount of units in a patch
|
||||
#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
|
||||
|
||||
/obj/machinery/chem_master
|
||||
name = "\improper ChemMaster 3000"
|
||||
density = TRUE
|
||||
@@ -14,10 +20,12 @@
|
||||
var/useramount = 30 // Last used amount
|
||||
var/pillamount = 10
|
||||
var/patchamount = 10
|
||||
var/bottlesprite = "bottle"
|
||||
var/pillsprite = "1"
|
||||
var/bottlesprite = 1
|
||||
var/pillsprite = 1
|
||||
var/client/has_sprites = list()
|
||||
var/printing = FALSE
|
||||
var/static/list/pill_bottle_wrappers
|
||||
var/static/list/bottle_styles
|
||||
|
||||
/obj/machinery/chem_master/New()
|
||||
..()
|
||||
@@ -94,7 +102,7 @@
|
||||
beaker = I
|
||||
I.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You add the beaker to the machine!</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
update_icon()
|
||||
|
||||
else if(istype(I, /obj/item/storage/pill_bottle))
|
||||
@@ -109,14 +117,10 @@
|
||||
loaded_pill_bottle = I
|
||||
I.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You add [I] into the dispenser slot!</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/machinery/chem_master/crowbar_act(mob/user, obj/item/I)
|
||||
if(!panel_open)
|
||||
return
|
||||
@@ -142,319 +146,127 @@
|
||||
power_change()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/chem_master/Topic(href, href_list)
|
||||
/obj/machinery/chem_master/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(tgui_act_modal(action, params, ui, state))
|
||||
return TRUE
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
|
||||
if(href_list["ejectp"])
|
||||
if(loaded_pill_bottle)
|
||||
loaded_pill_bottle.forceMove(loc)
|
||||
loaded_pill_bottle = null
|
||||
else if(href_list["change_pillbottle"])
|
||||
if(loaded_pill_bottle)
|
||||
var/list/wrappers = list("Default wrapper", "Red wrapper", "Green wrapper", "Pale green wrapper", "Blue wrapper", "Light blue wrapper", "Teal wrapper", "Yellow wrapper", "Orange wrapper", "Pink wrapper", "Brown wrapper")
|
||||
var/chosen = input(usr, "Select a pillbottle wrapper", "Pillbottle wrapper", wrappers[1]) as null|anything in wrappers
|
||||
if(!chosen)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("toggle")
|
||||
mode = !mode
|
||||
if("ejectp")
|
||||
if(loaded_pill_bottle)
|
||||
loaded_pill_bottle.forceMove(loc)
|
||||
loaded_pill_bottle = null
|
||||
if("print")
|
||||
if(printing || condi)
|
||||
return
|
||||
var/color
|
||||
switch(chosen)
|
||||
if("Default wrapper")
|
||||
loaded_pill_bottle.cut_overlays()
|
||||
return
|
||||
if("Red wrapper")
|
||||
color = COLOR_RED
|
||||
if("Green wrapper")
|
||||
color = COLOR_GREEN
|
||||
if("Pink wrapper")
|
||||
color = COLOR_PINK
|
||||
if("Teal wrapper")
|
||||
color = COLOR_TEAL
|
||||
if("Blue wrapper")
|
||||
color = COLOR_BLUE
|
||||
if("Brown wrapper")
|
||||
color = COLOR_MAROON
|
||||
if("Light blue wrapper")
|
||||
color = COLOR_CYAN_BLUE
|
||||
if("Yellow wrapper")
|
||||
color = COLOR_YELLOW
|
||||
if("Pale green wrapper")
|
||||
color = COLOR_PALE_BTL_GREEN
|
||||
if("Orange wrapper")
|
||||
color = COLOR_ORANGE
|
||||
loaded_pill_bottle.wrapper_color = color
|
||||
loaded_pill_bottle.apply_wrap()
|
||||
else if(href_list["close"])
|
||||
usr << browse(null, "window=chem_master")
|
||||
onclose(usr, "chem_master")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
if(href_list["print_p"])
|
||||
if(!printing)
|
||||
var/idx = text2num(params["idx"]) || 0
|
||||
var/from_beaker = text2num(params["beaker"]) || FALSE
|
||||
var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
|
||||
if(idx < 1 || idx > length(reagent_list))
|
||||
return
|
||||
|
||||
var/datum/reagent/R = reagent_list[idx]
|
||||
|
||||
printing = TRUE
|
||||
visible_message("<span class='notice'>[src] rattles and prints out a sheet of paper.</span>")
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
|
||||
var/obj/item/paper/P = new /obj/item/paper(loc)
|
||||
P.info = "<CENTER><B>Chemical Analysis</B></CENTER><BR>"
|
||||
P.info = "<center><b>Chemical Analysis</b></center><br>"
|
||||
P.info += "<b>Time of analysis:</b> [station_time_timestamp()]<br><br>"
|
||||
P.info += "<b>Chemical name:</b> [href_list["name"]]<br>"
|
||||
if(href_list["name"] == "Blood")
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/datum/reagent/blood/G
|
||||
for(var/datum/reagent/F in R.reagent_list)
|
||||
if(F.name == href_list["name"])
|
||||
G = F
|
||||
break
|
||||
var/B = G.data["blood_type"]
|
||||
var/C = G.data["blood_DNA"]
|
||||
P.info += "<b>Description:</b><br>Blood Type: [B]<br>DNA: [C]"
|
||||
P.info += "<b>Chemical name:</b> [R.name]<br>"
|
||||
if(istype(R, /datum/reagent/blood))
|
||||
var/datum/reagent/blood/B = R
|
||||
P.info += "<b>Description:</b> N/A<br><b>Blood Type:</b> [B.data["blood_type"]]<br><b>DNA:</b> [B.data["blood_DNA"]]"
|
||||
else
|
||||
P.info += "<b>Description:</b> [href_list["desc"]]"
|
||||
P.info += "<b>Description:</b> [R.description]"
|
||||
P.info += "<br><br><b>Notes:</b><br>"
|
||||
P.name = "Chemical Analysis - [href_list["name"]]"
|
||||
printing = FALSE
|
||||
P.name = "Chemical Analysis - [R.name]"
|
||||
spawn(50)
|
||||
printing = FALSE
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
if(beaker)
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
if(href_list["analyze"])
|
||||
var/dat = ""
|
||||
if(!condi)
|
||||
if(href_list["name"] == "Blood")
|
||||
var/datum/reagent/blood/G
|
||||
for(var/datum/reagent/F in R.reagent_list)
|
||||
if(F.name == href_list["name"])
|
||||
G = F
|
||||
break
|
||||
var/A = G.name
|
||||
var/B = G.data["blood_type"]
|
||||
var/C = G.data["blood_DNA"]
|
||||
dat += "<TITLE>Chemmaster 3000</TITLE>Chemical infos:<BR><BR>Name:<BR>[A]<BR><BR>Description:<BR>Blood Type: [B]<br>DNA: [C]"
|
||||
else
|
||||
dat += "<TITLE>Chemmaster 3000</TITLE>Chemical infos:<BR><BR>Name:<BR>[href_list["name"]]<BR><BR>Description:<BR>[href_list["desc"]]"
|
||||
dat += "<BR><BR><A href='?src=[UID()];print_p=1;desc=[href_list["desc"]];name=[href_list["name"]]'>(Print Analysis)</A><BR>"
|
||||
dat += "<A href='?src=[UID()];main=1'>(Back)</A>"
|
||||
if(. || !beaker)
|
||||
return
|
||||
|
||||
. = TRUE
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
switch(action)
|
||||
if("add")
|
||||
var/id = params["id"]
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!id || !amount)
|
||||
return
|
||||
R.trans_id_to(src, id, amount)
|
||||
if("remove")
|
||||
var/id = params["id"]
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!id || !amount)
|
||||
return
|
||||
if(mode)
|
||||
reagents.trans_id_to(beaker, id, amount)
|
||||
else
|
||||
dat += "<TITLE>Condimaster 3000</TITLE>Condiment infos:<BR><BR>Name:<BR>[href_list["name"]]<BR><BR>Description:<BR>[href_list["desc"]]<BR><BR><BR><A href='?src=[UID()];main=1'>(Back)</A>"
|
||||
usr << browse(dat, "window=chem_master;size=575x500")
|
||||
return
|
||||
|
||||
else if(href_list["add"])
|
||||
|
||||
if(href_list["amount"])
|
||||
var/id = href_list["add"]
|
||||
var/amount = text2num(href_list["amount"])
|
||||
R.trans_id_to(src, id, amount)
|
||||
|
||||
else if(href_list["addcustom"])
|
||||
|
||||
var/id = href_list["addcustom"]
|
||||
useramount = input("Select the amount to transfer.", 30, useramount) as num
|
||||
useramount = isgoodnumber(useramount)
|
||||
Topic(null, list("amount" = "[useramount]", "add" = "[id]"))
|
||||
|
||||
else if(href_list["remove"])
|
||||
|
||||
if(href_list["amount"])
|
||||
var/id = href_list["remove"]
|
||||
var/amount = text2num(href_list["amount"])
|
||||
if(mode)
|
||||
reagents.trans_id_to(beaker, id, amount)
|
||||
else
|
||||
reagents.remove_reagent(id, amount)
|
||||
|
||||
|
||||
else if(href_list["removecustom"])
|
||||
|
||||
var/id = href_list["removecustom"]
|
||||
useramount = input("Select the amount to transfer.", 30, useramount) as num
|
||||
useramount = isgoodnumber(useramount)
|
||||
Topic(null, list("amount" = "[useramount]", "remove" = "[id]"))
|
||||
|
||||
else if(href_list["toggle"])
|
||||
mode = !mode
|
||||
|
||||
else if(href_list["main"])
|
||||
attack_hand(usr)
|
||||
return
|
||||
else if(href_list["eject"])
|
||||
if(beaker)
|
||||
beaker.forceMove(get_turf(src))
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
usr.put_in_hands(beaker)
|
||||
beaker = null
|
||||
reagents.clear_reagents()
|
||||
update_icon()
|
||||
else if(href_list["createpill"] || href_list["createpill_multiple"])
|
||||
if(!condi)
|
||||
var/count = 1
|
||||
if(href_list["createpill_multiple"])
|
||||
count = input("Select the number of pills to make.", 10, pillamount) as num|null
|
||||
if(count == null)
|
||||
return
|
||||
count = isgoodnumber(count)
|
||||
if(count > 20)
|
||||
count = 20 //Pevent people from creating huge stacks of pills easily. Maybe move the number to defines?
|
||||
if(count <= 0)
|
||||
return
|
||||
var/amount_per_pill = reagents.total_volume / count
|
||||
if(amount_per_pill > 100)
|
||||
amount_per_pill = 100
|
||||
var/name = clean_input("Name:","Name your pill!","[reagents.get_master_reagent_name()] ([amount_per_pill]u)")
|
||||
if(!name)
|
||||
return
|
||||
name = reject_bad_text(name)
|
||||
while(count--)
|
||||
if(reagents.total_volume <= 0)
|
||||
to_chat(usr, "<span class='notice'>Not enough reagents to create these pills!</span>")
|
||||
return
|
||||
var/obj/item/reagent_containers/food/pill/P = new/obj/item/reagent_containers/food/pill(loc)
|
||||
if(!name)
|
||||
name = reagents.get_master_reagent_name()
|
||||
P.name = "[name] pill"
|
||||
P.pixel_x = rand(-7, 7) //random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = "pill"+pillsprite
|
||||
reagents.trans_to(P, amount_per_pill)
|
||||
if(loaded_pill_bottle && loaded_pill_bottle.type == /obj/item/storage/pill_bottle)
|
||||
if(loaded_pill_bottle.contents.len < loaded_pill_bottle.storage_slots)
|
||||
P.forceMove(loaded_pill_bottle)
|
||||
updateUsrDialog()
|
||||
else
|
||||
var/name = clean_input("Name:", "Name your bag!", reagents.get_master_reagent_name())
|
||||
if(!name)
|
||||
return
|
||||
name = reject_bad_text(name)
|
||||
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(loc)
|
||||
if(!name) name = reagents.get_master_reagent_name()
|
||||
P.originalname = name
|
||||
P.name = "[name] pack"
|
||||
P.desc = "A small condiment pack. The label says it contains [name]."
|
||||
reagents.trans_to(P, 10)
|
||||
else if(href_list["createpatch"] || href_list["createpatch_multiple"])
|
||||
if(!condi)
|
||||
var/count = 1
|
||||
if(href_list["createpatch_multiple"])
|
||||
count = input("Select the number of patches to make.", 10, patchamount) as num|null
|
||||
if(count == null)
|
||||
return
|
||||
count = isgoodnumber(count)
|
||||
if(!count || count <= 0)
|
||||
return
|
||||
if(count > 20)
|
||||
count = 20 //Pevent people from creating huge stacks of patches easily. Maybe move the number to defines?
|
||||
var/amount_per_patch = reagents.total_volume/count
|
||||
if(amount_per_patch > 30)
|
||||
amount_per_patch = 30
|
||||
var/name = clean_input("Name:", "Name your patch!", "[reagents.get_master_reagent_name()] ([amount_per_patch]u)")
|
||||
if(!name)
|
||||
return
|
||||
name = reject_bad_text(name)
|
||||
var/is_medical_patch = chemical_safety_check(reagents)
|
||||
while(count--)
|
||||
var/obj/item/reagent_containers/food/pill/patch/P = new/obj/item/reagent_containers/food/pill/patch(loc)
|
||||
if(!name) name = reagents.get_master_reagent_name()
|
||||
P.name = "[name] patch"
|
||||
P.pixel_x = rand(-7, 7) //random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
reagents.trans_to(P,amount_per_patch)
|
||||
if(is_medical_patch)
|
||||
P.instant_application = TRUE
|
||||
P.icon_state = "bandaid_med"
|
||||
if(loaded_pill_bottle && loaded_pill_bottle.type == /obj/item/storage/pill_bottle/patch_pack)
|
||||
if(loaded_pill_bottle.contents.len < loaded_pill_bottle.storage_slots)
|
||||
P.forceMove(loaded_pill_bottle)
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["createbottle"])
|
||||
if(!condi)
|
||||
var/name = clean_input("Name:", "Name your bottle!", reagents.get_master_reagent_name())
|
||||
if(!name)
|
||||
return
|
||||
name = reject_bad_text(name)
|
||||
var/obj/item/reagent_containers/glass/bottle/reagent/P = new/obj/item/reagent_containers/glass/bottle/reagent(loc)
|
||||
if(!name)
|
||||
name = reagents.get_master_reagent_name()
|
||||
P.name = "[name] bottle"
|
||||
P.pixel_x = rand(-7, 7) //random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = bottlesprite
|
||||
reagents.trans_to(P, 50)
|
||||
else
|
||||
var/obj/item/reagent_containers/food/condiment/P = new/obj/item/reagent_containers/food/condiment(loc)
|
||||
reagents.trans_to(P, 50)
|
||||
else if(href_list["change_pill"])
|
||||
#define MAX_PILL_SPRITE 20 //max icon state of the pill sprites
|
||||
var/dat = "<table>"
|
||||
var/j = 0
|
||||
for(var/i = 1 to MAX_PILL_SPRITE)
|
||||
j++
|
||||
if(j == 1)
|
||||
dat += "<tr>"
|
||||
dat += "<td><a href=\"?src=[UID()]&pill_sprite=[i]\"><img src=\"pill[i].png\" /></a></td>"
|
||||
if(j == 5)
|
||||
dat += "</tr>"
|
||||
j = 0
|
||||
dat += "</table>"
|
||||
usr << browse(dat, "window=chem_master_iconsel;size=225x193")
|
||||
return
|
||||
else if(href_list["change_bottle"])
|
||||
var/dat = "<table>"
|
||||
var/j = 0
|
||||
for(var/i in list("bottle", "small_bottle", "wide_bottle", "round_bottle", "reagent_bottle"))
|
||||
j++
|
||||
if(j == 1)
|
||||
dat += "<tr>"
|
||||
dat += "<td><a href=\"?src=[UID()]&bottle_sprite=[i]\"><img src=\"[i].png\" /></a></td>"
|
||||
if(j == 5)
|
||||
dat += "</tr>"
|
||||
j = 0
|
||||
dat += "</table>"
|
||||
usr << browse(dat, "window=chem_master_iconsel;size=225x193")
|
||||
return
|
||||
else if(href_list["pill_sprite"])
|
||||
pillsprite = href_list["pill_sprite"]
|
||||
usr << browse(null, "window=chem_master_iconsel")
|
||||
else if(href_list["bottle_sprite"])
|
||||
bottlesprite = href_list["bottle_sprite"]
|
||||
usr << browse(null, "window=chem_master_iconsel")
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
reagents.remove_reagent(id, amount)
|
||||
if("eject")
|
||||
if(!beaker)
|
||||
return
|
||||
beaker.forceMove(get_turf(src))
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
usr.put_in_hands(beaker)
|
||||
beaker = null
|
||||
reagents.clear_reagents()
|
||||
update_icon()
|
||||
if("create_condi_bottle")
|
||||
if(!condi || !reagents.total_volume)
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/P = new(loc)
|
||||
reagents.trans_to(P, 50)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/chem_master/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/chem_master/attack_ghost(mob/user)
|
||||
if(user.can_admin_interact())
|
||||
return attack_hand(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_master/attack_hand(mob/user)
|
||||
if(..())
|
||||
return TRUE
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/chem_master/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = TRUE)
|
||||
/obj/machinery/chem_master/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
var/datum/asset/chem_master/assets = get_asset_datum(/datum/asset/chem_master)
|
||||
assets.send(user)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "chem_master.tmpl", name, 575, 500)
|
||||
ui = new(user, src, ui_key, "ChemMaster", name, 575, 500)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/chem_master/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/chem_master/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["condi"] = condi
|
||||
data["loaded_pill_bottle"] = (loaded_pill_bottle ? 1 : 0)
|
||||
data["loaded_pill_bottle"] = loaded_pill_bottle ? TRUE : FALSE
|
||||
if(loaded_pill_bottle)
|
||||
data["loaded_pill_bottle_name"] = loaded_pill_bottle.name
|
||||
data["loaded_pill_bottle_contents_len"] = loaded_pill_bottle.contents.len
|
||||
data["loaded_pill_bottle_storage_slots"] = loaded_pill_bottle.storage_slots
|
||||
|
||||
data["beaker"] = (beaker ? 1 : 0)
|
||||
data["beaker"] = beaker ? TRUE : FALSE
|
||||
if(beaker)
|
||||
var/list/beaker_reagents_list = list()
|
||||
data["beaker_reagents"] = beaker_reagents_list
|
||||
@@ -464,13 +276,255 @@
|
||||
data["buffer_reagents"] = buffer_reagents_list
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
buffer_reagents_list[++buffer_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "id" = R.id, "description" = R.description)
|
||||
else
|
||||
data["beaker_reagents"] = list()
|
||||
data["buffer_reagents"] = list()
|
||||
|
||||
data["pillsprite"] = pillsprite
|
||||
data["bottlesprite"] = bottlesprite
|
||||
data["mode"] = mode
|
||||
data["printing"] = printing
|
||||
|
||||
// Transfer modal information if there is one
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
|
||||
return data
|
||||
|
||||
/**
|
||||
* Called in tgui_act() to process modal actions
|
||||
*
|
||||
* Arguments:
|
||||
* * action - The action passed by tgui
|
||||
* * params - The params passed by tgui
|
||||
*/
|
||||
/obj/machinery/chem_master/proc/tgui_act_modal(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||
. = TRUE
|
||||
var/id = params["id"] // The modal's ID
|
||||
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
|
||||
switch(tgui_modal_act(src, action, params))
|
||||
if(TGUI_MODAL_OPEN)
|
||||
switch(id)
|
||||
if("analyze")
|
||||
var/idx = text2num(arguments["idx"]) || 0
|
||||
var/from_beaker = text2num(arguments["beaker"]) || FALSE
|
||||
var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
|
||||
if(idx < 1 || idx > length(reagent_list))
|
||||
return
|
||||
|
||||
var/datum/reagent/R = reagent_list[idx]
|
||||
var/list/result = list("idx" = idx, "name" = R.name, "desc" = R.description)
|
||||
if(!condi && istype(R, /datum/reagent/blood))
|
||||
var/datum/reagent/blood/B = R
|
||||
result["blood_type"] = B.data["blood_type"]
|
||||
result["blood_dna"] = B.data["blood_DNA"]
|
||||
|
||||
arguments["analysis"] = result
|
||||
tgui_modal_message(src, id, "", null, arguments)
|
||||
if("change_pill_bottle_style")
|
||||
if(!loaded_pill_bottle)
|
||||
return
|
||||
if(!pill_bottle_wrappers)
|
||||
pill_bottle_wrappers = list(
|
||||
"CLEAR" = "Default",
|
||||
COLOR_RED = "Red",
|
||||
COLOR_GREEN = "Green",
|
||||
COLOR_PALE_BTL_GREEN = "Pale green",
|
||||
COLOR_BLUE = "Blue",
|
||||
COLOR_CYAN_BLUE = "Light blue",
|
||||
COLOR_TEAL = "Teal",
|
||||
COLOR_YELLOW = "Yellow",
|
||||
COLOR_ORANGE = "Orange",
|
||||
COLOR_PINK = "Pink",
|
||||
COLOR_MAROON = "Brown"
|
||||
)
|
||||
var/current = pill_bottle_wrappers[loaded_pill_bottle.wrapper_color] || "Default"
|
||||
tgui_modal_choice(src, id, "Please select a pill bottle wrapper:", null, arguments, current, pill_bottle_wrappers)
|
||||
if("addcustom")
|
||||
if(!beaker || !beaker.reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount to transfer to buffer:", null, arguments, useramount)
|
||||
if("removecustom")
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount to transfer to [mode ? "beaker" : "disposal"]:", null, arguments, useramount)
|
||||
if("create_condi_pack")
|
||||
if(!condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please name your new condiment pack:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN)
|
||||
if("create_pill")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/num = round(text2num(arguments["num"] || 1))
|
||||
if(!num)
|
||||
return
|
||||
arguments["num"] = num
|
||||
var/amount_per_pill = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_PILL)
|
||||
var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_pill]u)"
|
||||
var/pills_text = num == 1 ? "new pill" : "[num] new pills"
|
||||
tgui_modal_input(src, id, "Please name your [pills_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
|
||||
if("create_pill_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount of pills to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
|
||||
if("change_pill_style")
|
||||
var/list/choices = list()
|
||||
for(var/i = 1 to MAX_PILL_SPRITE)
|
||||
choices += "pill[i].png"
|
||||
tgui_modal_bento(src, id, "Please select the new style for pills:", null, arguments, pillsprite, choices)
|
||||
if("create_patch")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/num = round(text2num(arguments["num"] || 1))
|
||||
if(!num)
|
||||
return
|
||||
arguments["num"] = num
|
||||
var/amount_per_patch = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_PATCH)
|
||||
var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_patch]u)"
|
||||
var/patches_text = num == 1 ? "new patch" : "[num] new patches"
|
||||
tgui_modal_input(src, id, "Please name your [patches_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
|
||||
if("create_patch_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please enter the amount of patches to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
|
||||
if("create_bottle")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_modal_input(src, id, "Please name your bottle:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN)
|
||||
if("change_bottle_style")
|
||||
if(!bottle_styles)
|
||||
bottle_styles = list("bottle", "small_bottle", "wide_bottle", "round_bottle", "reagent_bottle")
|
||||
var/list/bottle_styles_png = list()
|
||||
for(var/style in bottle_styles)
|
||||
bottle_styles_png += "[style].png"
|
||||
tgui_modal_bento(src, id, "Please select the new style for bottles:", null, arguments, bottlesprite, bottle_styles_png)
|
||||
else
|
||||
return FALSE
|
||||
if(TGUI_MODAL_ANSWER)
|
||||
var/answer = params["answer"]
|
||||
switch(id)
|
||||
if("change_pill_bottle_style")
|
||||
if(!pill_bottle_wrappers || !loaded_pill_bottle) // wat?
|
||||
return
|
||||
var/color = "CLEAR"
|
||||
for(var/col in pill_bottle_wrappers)
|
||||
var/col_name = pill_bottle_wrappers[col]
|
||||
if(col_name == answer)
|
||||
color = col
|
||||
break
|
||||
if(length(color) && color != "CLEAR")
|
||||
loaded_pill_bottle.wrapper_color = color
|
||||
loaded_pill_bottle.apply_wrap()
|
||||
else
|
||||
loaded_pill_bottle.wrapper_color = null
|
||||
loaded_pill_bottle.cut_overlays()
|
||||
if("addcustom")
|
||||
var/amount = isgoodnumber(text2num(answer))
|
||||
if(!amount || !arguments["id"])
|
||||
return
|
||||
tgui_act("add", list("id" = arguments["id"], "amount" = amount), ui, state)
|
||||
if("removecustom")
|
||||
var/amount = isgoodnumber(text2num(answer))
|
||||
if(!amount || !arguments["id"])
|
||||
return
|
||||
tgui_act("remove", list("id" = arguments["id"], "amount" = amount), ui, state)
|
||||
if("create_condi_pack")
|
||||
if(!condi || !reagents.total_volume)
|
||||
return
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/obj/item/reagent_containers/food/condiment/pack/P = new(loc)
|
||||
P.originalname = answer
|
||||
P.name = "[answer] pack"
|
||||
P.desc = "A small condiment pack. The label says it contains [answer]."
|
||||
reagents.trans_to(P, 10)
|
||||
if("create_pill")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
|
||||
if(!count)
|
||||
return
|
||||
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/amount_per_pill = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_PILL)
|
||||
while(count--)
|
||||
if(reagents.total_volume <= 0)
|
||||
to_chat(usr, "<span class='notice'>Not enough reagents to create these pills!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/food/pill/P = new(loc)
|
||||
P.name = "[answer] pill"
|
||||
P.pixel_x = rand(-7, 7) // Random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = "pill[pillsprite]"
|
||||
reagents.trans_to(P, amount_per_pill)
|
||||
// Load the pills in the bottle if there's one loaded
|
||||
if(istype(loaded_pill_bottle) && length(loaded_pill_bottle.contents) < loaded_pill_bottle.storage_slots)
|
||||
P.forceMove(loaded_pill_bottle)
|
||||
if("create_pill_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_act("modal_open", list("id" = "create_pill", "arguments" = list("num" = answer)), ui, state)
|
||||
if("change_pill_style")
|
||||
var/new_style = clamp(text2num(answer) || 0, 0, MAX_PILL_SPRITE)
|
||||
if(!new_style)
|
||||
return
|
||||
pillsprite = new_style
|
||||
if("create_patch")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
|
||||
if(!count)
|
||||
return
|
||||
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/amount_per_patch = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_PATCH)
|
||||
var/is_medical_patch = chemical_safety_check(reagents)
|
||||
while(count--)
|
||||
if(reagents.total_volume <= 0)
|
||||
to_chat(usr, "<span class='notice'>Not enough reagents to create these patches!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/food/pill/patch/P = new(loc)
|
||||
P.name = "[answer] patch"
|
||||
P.pixel_x = rand(-7, 7) // random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
reagents.trans_to(P, amount_per_patch)
|
||||
if(is_medical_patch)
|
||||
P.instant_application = TRUE
|
||||
P.icon_state = "bandaid_med"
|
||||
// Load the patches in the bottle if there's one loaded
|
||||
if(istype(loaded_pill_bottle, /obj/item/storage/pill_bottle/patch_pack) && length(loaded_pill_bottle.contents) < loaded_pill_bottle.storage_slots)
|
||||
P.forceMove(loaded_pill_bottle)
|
||||
if("create_patch_multiple")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
tgui_act("modal_open", list("id" = "create_patch", "arguments" = list("num" = answer)), ui, state)
|
||||
if("create_bottle")
|
||||
if(condi || !reagents.total_volume)
|
||||
return
|
||||
|
||||
if(!length(answer))
|
||||
answer = reagents.get_master_reagent_name()
|
||||
var/obj/item/reagent_containers/glass/bottle/reagent/P = new(loc)
|
||||
P.name = "[answer] bottle"
|
||||
P.pixel_x = rand(-7, 7) // random position
|
||||
P.pixel_y = rand(-7, 7)
|
||||
P.icon_state = length(bottle_styles) && bottle_styles[bottlesprite] || "bottle"
|
||||
reagents.trans_to(P, 50)
|
||||
if("change_bottle_style")
|
||||
if(!bottle_styles)
|
||||
return
|
||||
var/new_sprite = text2num(answer) || 1
|
||||
if(new_sprite < 1 || new_sprite > length(bottle_styles))
|
||||
return
|
||||
bottlesprite = new_sprite
|
||||
else
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/chem_master/proc/isgoodnumber(num)
|
||||
if(isnum(num))
|
||||
if(num > 200)
|
||||
@@ -481,7 +535,7 @@
|
||||
num = round(num)
|
||||
return num
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/chem_master/proc/chemical_safety_check(datum/reagents/R)
|
||||
var/all_safe = TRUE
|
||||
@@ -503,3 +557,9 @@
|
||||
component_parts += new /obj/item/reagent_containers/glass/beaker(null)
|
||||
component_parts += new /obj/item/reagent_containers/glass/beaker(null)
|
||||
RefreshParts()
|
||||
|
||||
#undef MAX_PILL_SPRITE
|
||||
#undef MAX_MULTI_AMOUNT
|
||||
#undef MAX_UNITS_PER_PILL
|
||||
#undef MAX_UNITS_PER_PATCH
|
||||
#undef MAX_CUSTOM_NAME_LEN
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
eyeobj = new /mob/camera/aiEye/remote/xenobio(get_turf(src))
|
||||
eyeobj.origin = src
|
||||
eyeobj.visible_icon = 1
|
||||
eyeobj.acceleration = FALSE
|
||||
eyeobj.icon = 'icons/obj/abductor.dmi'
|
||||
eyeobj.icon_state = "camera_target"
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ GLOBAL_VAR_INIT(ert_request_answered, FALSE)
|
||||
to_chat(usr, "<span class='warning'>Central Command has already dispatched an emergency response team!</span>")
|
||||
return
|
||||
|
||||
var/datum/nano_module/ert_manager/E = new()
|
||||
E.ui_interact(usr)
|
||||
var/datum/tgui_module/ert_manager/E = new()
|
||||
E.tgui_interact(usr)
|
||||
|
||||
|
||||
/mob/dead/observer/proc/JoinResponseTeam()
|
||||
@@ -209,7 +209,7 @@ GLOBAL_VAR_INIT(ert_request_answered, FALSE)
|
||||
var/paranormal_outfit
|
||||
var/borg_path = /mob/living/silicon/robot/ert
|
||||
|
||||
/datum/response_team/proc/setSlots(com=1, sec=3, med=3, eng=3, jan=0, par=0, cyb=0)
|
||||
/datum/response_team/proc/setSlots(com=1, sec=4, med=0, eng=0, jan=0, par=0, cyb=0)
|
||||
slots["Commander"] = com
|
||||
slots["Security"] = sec
|
||||
slots["Medic"] = med
|
||||
@@ -318,3 +318,4 @@ GLOBAL_VAR_INIT(ert_request_answered, FALSE)
|
||||
name = "centcomm bounced radio"
|
||||
frequency = ERT_FREQ
|
||||
icon_state = "radio"
|
||||
freqlock = TRUE
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
name = "broken rejuvenation pod"
|
||||
desc = "A small sleeper typically used to instantly restore minor wounds. This one seems broken, and its occupant is comatose."
|
||||
mob_name = "a translocated vet"
|
||||
flavour_text = "<span class='big bold'>What...?</span><b> Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \
|
||||
description = "You are an intern working in an animal hospital that suddenly got transported to lavaland. Good luck."
|
||||
flavour_text = "What...? Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \
|
||||
everyone's gone. One of the cats scratched you just a few minutes ago. That's why you were in the pod - to heal the scratch. The scabs are still fresh; you see them right now. So where is \
|
||||
everyone? Where did they go? What happened to the hospital? And is that <i>smoke</i> you smell? You need to find someone else. Maybe they can tell you what happened.</b>"
|
||||
everyone? Where did they go? What happened to the hospital? And is that smoke you smell? You need to find someone else. Maybe they can tell you what happened."
|
||||
assignedrole = "Translocated Vet"
|
||||
allow_species_pick = TRUE
|
||||
|
||||
|
||||
@@ -67,9 +67,10 @@
|
||||
anchored = FALSE
|
||||
move_resist = MOVE_FORCE_NORMAL
|
||||
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 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. \
|
||||
<br><i>You are free to attack miners and other outsiders. <font size=6>DO NOT</font> leave Lavaland without admin permission! <font size=6>DO NOT</font> attack the mining outpost without being provoked.</b></i>"
|
||||
important_info = "Do not leave Lavaland without admin permission. Do not attack the mining outpost without being provoked."
|
||||
description = "You are an ashwalker, a native inhabitant of Lavaland. Try to survive with nothing but spears and other tribal technology. Bring dead bodies back to your tendril to create more of your kind. You are free to attack miners and other outsiders."
|
||||
flavour_text = "Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. \
|
||||
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/carbon/human/new_spawn)
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
random = TRUE
|
||||
allow_species_pick = 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 \
|
||||
description = "You are a single survivor stranded on lavaland in a makeshift shelter. Try to survive with barely any equipment. For when miner is just too boring."
|
||||
flavour_text = "You've been stranded in this godless prison of a planet for longer than you can remember. 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"
|
||||
@@ -22,28 +23,28 @@
|
||||
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/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/color/orange
|
||||
outfit.shoes = /obj/item/clothing/shoes/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/storage/labcoat
|
||||
outfit.back = /obj/item/storage/backpack/medic
|
||||
outfit.shoes = /obj/item/clothing/shoes/black
|
||||
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 \
|
||||
flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so kindly 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/black
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
mob_species = /datum/species/diona/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 \
|
||||
description = "You are a diona on Lavaland with access to a full botany setup. Perfect to mess around with plants in peace."
|
||||
flavour_text = "You are a sentient ecosystem, 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>"
|
||||
for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago."
|
||||
assignedrole = "Lifebringer"
|
||||
|
||||
/obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn)
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
death = FALSE
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper_s"
|
||||
flavour_text = "<span class='big bold'>You are a syndicate agent,</span><b> employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. <b>Continue your research as best you can, and try to keep a low profile. The base is rigged with explosives, do not abandon it or let it fall into enemy hands!</b> \
|
||||
<br><i>You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. <font size=6>DO NOT</font> work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. <font size=6>DO NOT</font> leave your base without admin permission.</i>"
|
||||
important_info = "Do not work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. Do not leave your base without admin permission."
|
||||
description = "Experiment with deadly chems and viruses in peace or help any visiting Syndicate Agent."
|
||||
flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Continue your research as best you can, and try to keep a low profile. The base is rigged with explosives, do not abandon it or let it fall into enemy hands!\
|
||||
It's been made clear to you that the Syndicate will make you regret it if you disappoint them."
|
||||
outfit = /datum/outfit/lavaland_syndicate
|
||||
assignedrole = "Lavaland Syndicate"
|
||||
del_types = list() // Necessary to prevent del_types from removing radio!
|
||||
@@ -59,13 +61,13 @@
|
||||
/obj/effect/mob_spawn/human/lavaland_syndicate/comms
|
||||
name = "Syndicate Comms Agent sleeper"
|
||||
mob_name = "Syndicate Comms Agent"
|
||||
flavour_text = "<span class='big bold'>You are a syndicate agent,</span><b> employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. <b>Monitor enemy activity as best you can, and try to keep a low profile. Do not abandon the base.</b> Use the communication equipment to provide support to any field agents, and sow disinformation to throw Nanotrasen off your trail. Do not let the base fall into enemy hands!</b> \
|
||||
<br><i>You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. <font size=6>DO NOT</font> work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. <font size=6>DO NOT</font> leave your base without admin permission.</i>"
|
||||
important_info = "Do not work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. Do not leave your base without admin permission. Do not reveal the existence of yourself to NT."
|
||||
description = "Monitor comms and cameras and try to assist any agents on station while keeping your existence a secret."
|
||||
flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Monitor enemy activity as best you can, and try to keep a low profile."
|
||||
outfit = /datum/outfit/lavaland_syndicate/comms
|
||||
|
||||
/obj/effect/mob_spawn/human/lavaland_syndicate/comms/space
|
||||
flavour_text = "<span class='big bold'>You are a syndicate agent,</span><b> assigned to a small listening post station situated near your hated enemy's top secret research facility: Space Station 13. <b>Monitor enemy activity as best you can, and try to keep a low profile. Do not abandon the base.</b> Use the communication equipment to provide support to any field agents, and sow disinformation to throw Nanotrasen off your trail. Do not let the base fall into enemy hands!</b> \
|
||||
<br><i>You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. <font size=6>DO NOT</font> work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. <font size=6>DO NOT</font> leave your base without admin permission.</i>"
|
||||
flavour_text = "You are a syndicate agent, employed in a small listening outpost. You'd be bored to death if you couldn't listen in on those NT idiots mess up all the time."
|
||||
|
||||
/obj/effect/mob_spawn/human/lavaland_syndicate/comms/space/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "auth_off"
|
||||
|
||||
var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made.
|
||||
var/event = ""
|
||||
var/screen = 1
|
||||
var/active = FALSE // This gets set to TRUE on all devices except the one where the initial request was made.
|
||||
var/event
|
||||
var/swiping = FALSE // on swiping screen?
|
||||
var/list/ert_chosen = list()
|
||||
var/confirmed = 0 //This variable is set by the device that confirms the request.
|
||||
var/confirm_delay = 20 //(2 seconds)
|
||||
var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device.
|
||||
var/confirmed = FALSE // This variable is set by the device that confirms the request.
|
||||
var/confirm_delay = 5 SECONDS // time allowed for a second person to confirm a swipe.
|
||||
var/busy = FALSE // Busy when waiting for authentication or an event request has been sent from this device.
|
||||
var/obj/machinery/keycard_auth/event_source
|
||||
var/mob/event_triggered_by
|
||||
var/mob/event_confirmed_by
|
||||
var/ert_reason = "Reason for ERT"
|
||||
var/ert_reason
|
||||
|
||||
anchored = 1
|
||||
use_power = IDLE_POWER_USE
|
||||
@@ -35,16 +35,19 @@
|
||||
return
|
||||
if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))
|
||||
if(check_access(W))
|
||||
if(active == 1)
|
||||
if(active)
|
||||
//This is not the device that made the initial request. It is the device confirming the request.
|
||||
if(event_source)
|
||||
event_source.confirmed = 1
|
||||
event_source.confirmed = TRUE
|
||||
event_source.event_confirmed_by = usr
|
||||
else if(screen == 2)
|
||||
if(event == "Emergency Response Team" && ert_reason == "Reason for ERT")
|
||||
to_chat(user, "<span class='notice'>Supply a reason for calling the ERT first!</span>")
|
||||
SStgui.update_uis(event_source)
|
||||
SStgui.update_uis(src)
|
||||
else if(swiping)
|
||||
if(event == "Emergency Response Team" && !ert_reason)
|
||||
to_chat(user, "<span class='warning'>Supply a reason for calling the ERT first!</span>")
|
||||
return
|
||||
event_triggered_by = usr
|
||||
SStgui.update_uis(src)
|
||||
broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
@@ -59,57 +62,58 @@
|
||||
stat |= NOPOWER
|
||||
|
||||
/obj/machinery/keycard_auth/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/keycard_auth/attack_hand(mob/user as mob)
|
||||
/obj/machinery/keycard_auth/attack_hand(mob/user)
|
||||
if(..())
|
||||
return 1
|
||||
ui_interact(user)
|
||||
return TRUE
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(busy)
|
||||
to_chat(user, "This device is busy.")
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/keycard_auth/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 540, 320)
|
||||
ui = new(user, src, ui_key, "KeycardAuth", name, 540, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/keycard_auth/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
data["screen"] = screen
|
||||
data["event"] = event
|
||||
data["ertreason"] = ert_reason
|
||||
|
||||
/obj/machinery/keycard_auth/tgui_data()
|
||||
var/list/data = list()
|
||||
data["redAvailable"] = GLOB.security_level == SEC_LEVEL_RED ? FALSE : TRUE
|
||||
data["swiping"] = swiping
|
||||
data["busy"] = busy
|
||||
data["event"] = active && event_source && event_source.event ? event_source.event : event
|
||||
data["ertreason"] = active && event_source && event_source.ert_reason ? event_source.ert_reason : ert_reason
|
||||
data["isRemote"] = active ? TRUE : FALSE
|
||||
data["hasSwiped"] = event_triggered_by ? TRUE : FALSE
|
||||
data["hasConfirm"] = event_confirmed_by || (active && event_source && event_source.event_confirmed_by) ? TRUE : FALSE
|
||||
return data
|
||||
|
||||
/obj/machinery/keycard_auth/Topic(href, href_list)
|
||||
/obj/machinery/keycard_auth/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(busy)
|
||||
to_chat(usr, "This device is busy.")
|
||||
return
|
||||
if(busy)
|
||||
to_chat(usr, "<span class='warning'>This device is busy.</span>")
|
||||
return
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("ert")
|
||||
ert_reason = stripped_input(usr, "Reason for ERT Call:", "", "")
|
||||
if("reset")
|
||||
reset()
|
||||
if("triggerevent")
|
||||
event = params["triggerevent"]
|
||||
swiping = TRUE
|
||||
|
||||
if(href_list["triggerevent"])
|
||||
event = href_list["triggerevent"]
|
||||
screen = 2
|
||||
if(href_list["reset"])
|
||||
reset()
|
||||
if(href_list["ert"])
|
||||
ert_reason = stripped_input(usr, "Reason for ERT Call:", "", "")
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/keycard_auth/proc/reset()
|
||||
active = 0
|
||||
event = ""
|
||||
screen = 1
|
||||
confirmed = 0
|
||||
active = FALSE
|
||||
event = null
|
||||
swiping = FALSE
|
||||
confirmed = FALSE
|
||||
event_source = null
|
||||
icon_state = "auth_off"
|
||||
event_triggered_by = null
|
||||
@@ -125,7 +129,7 @@
|
||||
|
||||
sleep(confirm_delay)
|
||||
if(confirmed)
|
||||
confirmed = 0
|
||||
confirmed = FALSE
|
||||
trigger_event(event)
|
||||
log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]")
|
||||
message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1)
|
||||
@@ -135,16 +139,17 @@
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
event_source = source
|
||||
busy = 1
|
||||
active = 1
|
||||
busy = TRUE
|
||||
active = TRUE
|
||||
SStgui.update_uis(src)
|
||||
icon_state = "auth_on"
|
||||
|
||||
sleep(confirm_delay)
|
||||
|
||||
event_source = null
|
||||
icon_state = "auth_off"
|
||||
active = 0
|
||||
busy = 0
|
||||
active = FALSE
|
||||
busy = FALSE
|
||||
|
||||
/obj/machinery/keycard_auth/proc/trigger_event()
|
||||
switch(event)
|
||||
@@ -178,7 +183,7 @@
|
||||
if(fullmin_count)
|
||||
GLOB.ert_request_answered = TRUE
|
||||
ERT_Announce(ert_reason , event_triggered_by, 0)
|
||||
ert_reason = "Reason for ERT"
|
||||
ert_reason = null
|
||||
feedback_inc("alert_keycard_auth_ert",1)
|
||||
spawn(3000)
|
||||
if(!GLOB.ert_request_answered)
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
flags = NODECONSTRUCT
|
||||
|
||||
/obj/machinery/computer/shuttle/ert/Topic(href, href_list)
|
||||
if(href_list["move"])
|
||||
/obj/machinery/computer/shuttle/ert/can_call_shuttle(mob/user, action)
|
||||
if(action == "move")
|
||||
var/authorized_roles = list(SPECIAL_ROLE_ERT, SPECIAL_ROLE_DEATHSQUAD)
|
||||
if(!((usr.mind?.assigned_role in authorized_roles) || is_admin(usr)))
|
||||
message_admins("Potential ERT shuttle hijack, ERT shuttle moved by unauthorized user: [key_name_admin(usr)]")
|
||||
..()
|
||||
|
||||
if(!((user.mind?.assigned_role in authorized_roles) || is_admin(user)))
|
||||
message_admins("Potential ERT shuttle hijack, ERT shuttle moved by unauthorized user: [key_name_admin(user)]")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/ert
|
||||
name = "specops navigation computer"
|
||||
|
||||
@@ -727,13 +727,13 @@
|
||||
name = "Shuttle Console"
|
||||
icon_screen = "shuttle"
|
||||
icon_keyboard = "tech_key"
|
||||
req_access = list( )
|
||||
req_access = list()
|
||||
circuit = /obj/item/circuitboard/shuttle
|
||||
var/shuttleId
|
||||
var/possible_destinations = ""
|
||||
var/admin_controlled
|
||||
var/max_connect_range = 7
|
||||
var/docking_request = 0
|
||||
var/moved = FALSE //workaround for nukie shuttle, hope I find a better way to do this...
|
||||
|
||||
/obj/machinery/computer/shuttle/New(location, obj/item/circuitboard/shuttle/C)
|
||||
..()
|
||||
@@ -773,21 +773,20 @@
|
||||
return
|
||||
connect()
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/shuttle/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/shuttle/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "shuttle_console.tmpl", M ? M.name : "shuttle", 300, 200)
|
||||
ui = new(user, src, ui_key, "ShuttleConsole", name, 350, 150, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/shuttle/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
/obj/machinery/computer/shuttle/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
data["status"] = M ? M.getStatusText() : null
|
||||
if(M)
|
||||
data["shuttle"] = 1
|
||||
data["shuttle"] = TRUE //this should just be boolean, right?
|
||||
var/list/docking_ports = list()
|
||||
data["docking_ports"] = docking_ports
|
||||
var/list/options = params2list(possible_destinations)
|
||||
@@ -799,34 +798,35 @@
|
||||
docking_ports[++docking_ports.len] = list("name" = S.name, "id" = S.id)
|
||||
data["docking_ports_len"] = docking_ports.len
|
||||
data["admin_controlled"] = admin_controlled
|
||||
data["docking_request"] = docking_request
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/shuttle/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/shuttle/tgui_act(action, params)
|
||||
if(..()) //we can't actually interact, so no action
|
||||
return TRUE
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='danger'>Access denied.</span>")
|
||||
return
|
||||
|
||||
return TRUE
|
||||
if(!can_call_shuttle(usr, action))
|
||||
return TRUE
|
||||
var/list/options = params2list(possible_destinations)
|
||||
if(href_list["move"])
|
||||
if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING.
|
||||
// Seriously, though, NEVER trust a Topic with something like this. Ever.
|
||||
// Sidenote for whoever did this last. Why did you set it to echo whatever the user entered to admin chat? You solved one exploit and created another.
|
||||
if(action == "move")
|
||||
var/destination = params["move"]
|
||||
if(!options.Find(destination))//figure out if this translation works
|
||||
message_admins("<span class='boldannounce'>EXPLOIT:</span> [ADMIN_LOOKUPFLW(usr)] attempted to move [src] to an invalid location! [ADMIN_COORDJMP(src)]")
|
||||
return
|
||||
switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1, usr))
|
||||
switch(SSshuttle.moveShuttle(shuttleId, destination, TRUE, usr))
|
||||
if(0)
|
||||
atom_say("Shuttle departing! Please stand away from the doors.")
|
||||
usr.create_log(MISC_LOG, "used [src] to call the [shuttleId] shuttle")
|
||||
if(!moved)
|
||||
moved = TRUE
|
||||
add_fingerprint(usr)
|
||||
return TRUE
|
||||
if(1)
|
||||
to_chat(usr, "<span class='warning'>Invalid shuttle requested.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>Unable to comply.</span>")
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer/shuttle/emag_act(mob/user)
|
||||
if(!emagged)
|
||||
@@ -834,6 +834,10 @@
|
||||
emagged = 1
|
||||
to_chat(user, "<span class='notice'>You fried the consoles ID checking system.</span>")
|
||||
|
||||
//for restricting when the computer can be used, needed for some console subtypes.
|
||||
/obj/machinery/computer/shuttle/proc/can_call_shuttle(mob/user, action)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/shuttle/ferry
|
||||
name = "transport ferry console"
|
||||
circuit = /obj/item/circuitboard/ferry
|
||||
@@ -844,25 +848,23 @@
|
||||
/obj/machinery/computer/shuttle/ferry/request
|
||||
name = "ferry console"
|
||||
circuit = /obj/item/circuitboard/ferry/request
|
||||
var/cooldown //prevents spamming admins
|
||||
var/next_request //to prevent spamming admins
|
||||
possible_destinations = "ferry_home"
|
||||
admin_controlled = 1
|
||||
admin_controlled = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
|
||||
/obj/machinery/computer/shuttle/ferry/request/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["request"])
|
||||
if(cooldown)
|
||||
/obj/machinery/computer/shuttle/ferry/request/tgui_act(action, params)
|
||||
if(..()) // Note that the parent handels normal shuttle movement on top of security checks
|
||||
return
|
||||
if(action == "request")
|
||||
if(world.time < next_request)
|
||||
return
|
||||
cooldown = 1
|
||||
next_request = world.time + 60 SECONDS //1 minute cooldown
|
||||
to_chat(usr, "<span class='notice'>Your request has been recieved by Centcom.</span>")
|
||||
log_admin("[key_name(usr)] requested to move the transport ferry to Centcom.")
|
||||
message_admins("<b>FERRY: <font color='blue'>[key_name_admin(usr)] (<A HREF='?_src_=holder;secretsfun=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>")
|
||||
. = 1
|
||||
SSnanoui.update_uis(src)
|
||||
spawn(600) //One minute cooldown
|
||||
cooldown = 0
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/computer/shuttle/white_ship
|
||||
name = "White Ship Console"
|
||||
|
||||
@@ -11,20 +11,18 @@
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
flags = NODECONSTRUCT
|
||||
var/challenge = FALSE
|
||||
var/moved = FALSE
|
||||
|
||||
/obj/machinery/computer/shuttle/syndicate/recall
|
||||
name = "syndicate shuttle recall terminal"
|
||||
circuit = /obj/item/circuitboard/shuttle/syndicate/recall
|
||||
possible_destinations = "syndicate_away"
|
||||
|
||||
/obj/machinery/computer/shuttle/syndicate/Topic(href, href_list)
|
||||
if(href_list["move"])
|
||||
/obj/machinery/computer/shuttle/syndicate/can_call_shuttle(user, action)
|
||||
if(action == "move")
|
||||
if(challenge && world.time < SYNDICATE_CHALLENGE_TIMER)
|
||||
to_chat(usr, "<span class='warning'>You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare.</span>")
|
||||
return 0
|
||||
moved = TRUE
|
||||
..()
|
||||
to_chat(user, "<span class='warning'>You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/shuttle/syndicate/drop_pod
|
||||
name = "syndicate assault pod control"
|
||||
@@ -35,11 +33,11 @@
|
||||
shuttleId = "steel_rain"
|
||||
possible_destinations = null
|
||||
|
||||
/obj/machinery/computer/shuttle/syndicate/drop_pod/Topic(href, href_list)
|
||||
if(href_list["move"])
|
||||
/obj/machinery/computer/shuttle/syndicate/drop_pod/can_call_shuttle(user, action)
|
||||
if(action == "move")
|
||||
if(z != level_name_to_num(CENTCOMM))
|
||||
to_chat(usr, "<span class='warning'>Pods are one way!</span>")
|
||||
return 0
|
||||
to_chat(user, "<span class='warning'>Pods are one way!</span>")
|
||||
return FALSE
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/shuttle/sst
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user