Merge remote-tracking branch 'ParadiseSS13/master' into pr/Kyep/14200

This commit is contained in:
AffectedArc07
2020-09-15 21:00:07 +01:00
70 changed files with 2935 additions and 2507 deletions
@@ -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,
+1 -1
View File
@@ -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)
+7 -2
View File
@@ -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 ? 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
@@ -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)
+1 -1
View File
@@ -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
+15 -12
View File
@@ -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
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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()
+134 -154
View File
@@ -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,114 @@
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 +191,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 +293,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 +315,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 +351,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 +372,29 @@
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)]"
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)
+193 -204
View File
@@ -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
+104 -55
View File
@@ -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
+275 -249
View File
@@ -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
View File
@@ -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()
@@ -126,7 +126,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
wires.Interact(user)
tgui_interact(user)
/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_physical_state)
/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", name, 360, 150 + (length(channels) * 20), master_ui, state)
@@ -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)
+2 -2
View File
@@ -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
+12 -5
View File
@@ -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
+1 -1
View File
@@ -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
..()
+1 -1
View File
@@ -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)
@@ -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
-105
View File
@@ -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
+155 -145
View File
@@ -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
View File
@@ -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
+3 -3
View File
@@ -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
@@ -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)
+5 -6
View File
@@ -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"
+38 -36
View File
@@ -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"
+9 -11
View File
@@ -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
+1 -1
View File
@@ -13,7 +13,7 @@
/datum/station_goal/proc/send_report()
GLOB.priority_announcement.Announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", 'sound/AI/commandreport.ogg')
print_command_report(get_report(), "Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]")
print_command_report(get_report(), "Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]", FALSE)
on_report()
/datum/station_goal/proc/on_report()
+100
View File
@@ -0,0 +1,100 @@
/datum/tgui_module/ert_manager
name = "ERT Manager"
var/ert_type = "Red"
var/commander_slots = 1 // defaults for open slots
var/security_slots = 4
var/medical_slots = 0
var/engineering_slots = 0
var/janitor_slots = 0
var/paranormal_slots = 0
var/cyborg_slots = 0
/datum/tgui_module/ert_manager/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_admin_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ERTManager", name, 350, 430, master_ui, state)
ui.autoupdate = TRUE
ui.open()
/datum/tgui_module/ert_manager/tgui_data(mob/user)
var/list/data = list()
data["str_security_level"] = capitalize(get_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["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
data["total"] = commander_slots + security_slots + medical_slots + engineering_slots + janitor_slots + paranormal_slots + cyborg_slots
data["spawnpoints"] = GLOB.emergencyresponseteamspawn.len
return data
/datum/tgui_module/ert_manager/tgui_act(action, params)
if(..())
return
. = TRUE
switch(action)
if("ert_type")
ert_type = params["ert_type"]
if("toggle_com")
commander_slots = commander_slots ? 0 : 1
if("set_sec")
security_slots = text2num(params["set_sec"])
if("set_med")
medical_slots = text2num(params["set_med"])
if("set_eng")
engineering_slots = text2num(params["set_eng"])
if("set_jan")
janitor_slots = text2num(params["set_jan"])
if("set_par")
paranormal_slots = text2num(params["set_par"])
if("set_cyb")
cyborg_slots = text2num(params["set_cyb"])
if("dispatch_ert")
var/datum/response_team/D
switch(ert_type)
if("Amber")
D = new /datum/response_team/amber
if("Red")
D = new /datum/response_team/red
if("Gamma")
D = new /datum/response_team/gamma
else
to_chat(usr, "<span class='userdanger'>Invalid ERT type.</span>")
return
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 = english_list(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")
trigger_armed_response_team(D, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
else
return FALSE
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

-91
View File
@@ -1,91 +0,0 @@
<!--
Title: Brig Timer
Used In File(s): \code\game\machinery\doors\brigdoors.dm
-->
<div class="item">
<div class="itemLabel">
Cell:
</div>
<div class="itemContent">
{{:data.cell_id}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Occupant:
</div>
<div class="itemContent">
{{:data.occupant}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Crimes:
</div>
<div class="itemContent">
{{:data.crimes}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Brigged By:
</div>
<div class="itemContent">
{{:data.brigged_by}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Time Brigged For:
</div>
<div class="itemContent">
{{:data.time_set}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Time Left:
</div>
<div class="itemContent">
{{:data.time_left}}
</div>
</div>
{{if data.isAllowed}}
<div class="item">
<div class="itemLabel">
Actions:
</div>
<div class="itemContent">
{{:helper.link('Flash', 'flash', {'flash' : 1}, null, data.isAllowed ? '' : 'dsabled')}}
{{:helper.link('Release', null, {'release' : 1}, null, data.isAllowed ? '' : 'disabled')}}
</div>
</div>
{{if !data.timing}}
<h3>Inmate Information</h3>
<div class="item">
<div class="itemLabel">
Name:
</div>
<div class="itemContent">
{{:helper.link('Set', 'pencil', {'prisoner_name' : 'input'})}} {{:data.prisoner_name}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Charge:
</div>
<div class="itemContent">
{{:helper.link('Set', 'pencil', {'prisoner_charge' : 'input'})}} {{:data.prisoner_charge}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Time (in minutes):
</div>
<div class="itemContent">
{{:helper.link('Set', 'pencil', {'prisoner_time' : 'input'})}} {{:data.prisoner_time}}
</div>
</div>
{{:helper.link('Submit', null, {'set_timer' : 1}, null, data.isAllowed ? '' : 'disabled')}}
{{/if}}
{{/if}}
-142
View File
@@ -1,142 +0,0 @@
<!--
Title: Communications
Used In File(s): /code/game/machinery/computers/communications.dm
-->
<!--
#define COMM_SCREEN_MAIN 1
#define COMM_SCREEN_STAT 2
#define COMM_SCREEN_MESSAGES 3
#define COMM_SCREEN_SECLEVEL 4
-->
{{if !data.authenticated}}
<div class="notice">Please swipe your ID card. {{:helper.link('Log In','unlock',{'login':1},null,'fixed')}}</div>
{{else}}
{{if !data.is_ai}}
<div class="notice">Please remember to {{:helper.link('Log Out','lock',{'logout':1},null,'fixed')}}</div>
{{/if}}
{{if data.lastCallLoc}}
<div class="line">Most recent shuttle call/recall traced to: <b>{{:data.lastCallLoc}}</b></div>
{{else}}
<div class="line">Unable to trace most recent shuttle call/recall signal.</div>
{{/if}}
<div class="item">
<h3>Emergency Shuttle:</h3>
{{if data.shuttle.eta}}
<div class="itemLabel">ETA:</div>
<div class="itemContents">
{{>data.shuttle.eta}}
</div>
{{/if}}<!-- SHUTTLE ETA -->
<div class="itemLabel">Options:</div>
<div class="itemContents">
{{if data.shuttle.callStatus == 1 && !data.is_ai}}
{{:helper.link('Cancel Shuttle','arrow-left',{'operation':'cancelshuttle'})}}
{{else data.shuttle.callStatus == 2}}
{{:helper.link('Call Shuttle','arrow-circle-down',{'operation':'callshuttle'})}}
{{/if}}
</div>
</div>
{{if data.screen==1}}
<!-- MAIN SCREEN -->
<h3>Menu</h3>
<div class="item">
{{if data.authenticated==2}}
<div class="line">
{{:helper.link('Make an Announcement','info',{'operation':'announce'})}}
</div>
<div class="line">
{{if data.emagged}}
{{:helper.link('Message [UNKNOWN]','envelope',{'operation':'MessageSyndicate'})}}
</div>
<div class="line">
{{:helper.link('Reset Relays','refresh',{'operation':'RestoreBackup'})}}
{{else}}
{{:helper.link('Message CentComm','envelope',{'operation':'MessageCentcomm'})}}
{{/if}}
</div>
<div class="line">
{{:helper.link('Request Nuclear Authentication Codes','exclamation-triangle',{'operation':'nukerequest'})}}
</div>
{{/if}}
<div class="line">
{{:helper.link('Change Alert Level','signal',{'operation':'changeseclevel'})}}
</div>
<div class="line">
{{:helper.link('Change Status Displays','info',{'operation':'status'})}}
</div>
<div class="line">
{{:helper.link('Message List','comment',{'operation':'messagelist'})}}
</div>
<div class="line">
{{:helper.link('Restart Nano-Mob Hunter GO! Server','power-off',{'operation':'RestartNanoMob'})}}
</div>
</div>
{{else data.screen==2}}
<!-- STATUS DISPLAYS -->
<h2>Status Displays</h2>
{{:helper.link('Back','home',{'operation':'main'})}}
<h3>Presets</h3>
{{for data.stat_display.presets}}
<div class="line">
<div class="statusLabel">{{:helper.link(value.label,'info',{'operation':'setstat','statdisp':value.name},null,(name==data.stat_display.type?'linkOn':''))}}</div>
</div>
{{/for}}
<h3>Alerts</h3>
{{for data.stat_display.alerts}}
<div class="line">
<div class="statusLabel">{{:helper.link(value.label,'exclamation-triangle',{'operation':'setstat','statdisp':'alert','alert':value.alert},null,(value.alert==data.stat_display.type?'linkOn':''))}}</div>
</div>
{{/for}}
<h3>Messages</h3>
<div class="item">
{{if data.stat_display.type}}
<div class="line">
<div class="statusLabel">{{:helper.link('Line 1:','gear',{'operation':'setmsg1'})}}</div>
<div class="statusValue">{{>data.stat_display.line_1}}</div>
</div>
<div class="line">
<div class="statusLabel">{{:helper.link('Line 2:','gear',{'operation':'setmsg2'})}}</div>
<div class="statusValue">{{>data.stat_display.line_2}}</div>
</div>
{{/if}}
</div>
{{else data.screen==3}}
<!-- MESSAGES -->
<h3>Messages</h3>
{{if data.current_message}}
{{:helper.link('Messages','home',{'operation':'messagelist'})}}
<h3>{{:data.current_message_title}}</h3>
<div class="item">
{{:data.current_message}}
</div>
{{else}}
{{:helper.link('Back','home',{'operation':'main'})}}
{{for data.messages}}
<div class="line">
<b>{{:value.title}}</b><br>
{{:helper.link('Open','envelope-o',{'operation':'messagelist','msgid':value.id})}}
{{:helper.link('Delete','close',{'operation':'delmessage','msgid':value.id})}}
</div>
{{/for}}
{{/if}}
{{else data.screen==4}}
<!-- ALERT LEVEL -->
<h3>Security Level</h3>
{{:helper.link('Back','home',{'operation':'main'})}}
<div class="item">
<div class="line">
<div class="itemLabel">Security Level:</div>
<div class="itemContents">{{>data.str_security_level}}</div>
</div>
<div class="line">
<div class="itemLabel">Presets:</div>
<div class="itemContents">
{{for data.levels}}
{{:helper.link(value.name,'comment',{'operation':'newalertlevel','level':value.id},null,(value.id==data.security_level?'linkOn':''))}}
{{/for}}
</div>
</div>
</div>
{{/if}}<!-- SCREEN -->
{{/if}}<!-- AUTHENTICATED -->
-75
View File
@@ -1,75 +0,0 @@
<div class='item'>
<table style='width: 100%'>
<tr>
<td>Station Alert Level</td><td>{{:data.alert_level}}</td>
</tr><tr>
<td>ERT Type</td><TD>
{{if data.ert_type == 'Code Amber'}} <font color='#FF7E00'> AMBER </font> {{else}} {{:helper.link('Amber', null, {"set_code": 'Code Amber'})}} {{/if}}
{{if data.ert_type == 'Code Red'}} <font color='#DC143C'> RED </font> {{else}} {{:helper.link('Red', null, {"set_code": 'Code Red'})}} {{/if}}
{{if data.ert_type == 'Code Gamma'}} <font color='#DB7093'> GAMMA </font> {{else}} {{:helper.link('Gamma', null, {"set_code": 'Code Gamma'})}} {{/if}}
</td>
</tr>
</table>
</div>
<hr>
<div class='item'>
<table style='width: 100%'>
<tr><th>Department</th><th>Slots</th><th>Change Slots</th></tr>
<tr><td>Command</td><td>{{if data.com == 0}}-{{else}}{{:helper.smoothRound(data.com)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_com": 0})}}
{{:helper.link('1', null, {"set_com": 1})}}</td></tr>
<tr><td>Security</td><td>{{if data.sec == 0}}-{{else}}{{:helper.smoothRound(data.sec)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_sec": 0})}}
{{:helper.link('1', null, {"set_sec": 1})}}
{{:helper.link('2', null, {"set_sec": 2})}}
{{:helper.link('3', null, {"set_sec": 3})}}
{{:helper.link('4', null, {"set_sec": 4})}}
{{:helper.link('5', null, {"set_sec": 5})}}
</td>
<tr><td>Medical</td><td>{{if data.med == 0}}-{{else}}{{:helper.smoothRound(data.med)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_med": 0})}}
{{:helper.link('1', null, {"set_med": 1})}}
{{:helper.link('2', null, {"set_med": 2})}}
{{:helper.link('3', null, {"set_med": 3})}}
{{:helper.link('4', null, {"set_med": 4})}}
{{:helper.link('5', null, {"set_med": 5})}}
</td>
<tr><td>Engineering</td><td>{{if data.eng == 0}}-{{else}}{{:helper.smoothRound(data.eng)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_eng": 0})}}
{{:helper.link('1', null, {"set_eng": 1})}}
{{:helper.link('2', null, {"set_eng": 2})}}
{{:helper.link('3', null, {"set_eng": 3})}}
{{:helper.link('4', null, {"set_eng": 4})}}
{{:helper.link('5', null, {"set_eng": 5})}}
</td>
<tr><td>Paranormal</td><td>{{if data.par == 0}}-{{else}}{{:helper.smoothRound(data.par)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_par": 0})}}
{{:helper.link('1', null, {"set_par": 1})}}
{{:helper.link('2', null, {"set_par": 2})}}
{{:helper.link('3', null, {"set_par": 3})}}
{{:helper.link('4', null, {"set_par": 4})}}
{{:helper.link('5', null, {"set_par": 5})}}
</td>
<tr><td>Janitor</td><td>{{if data.jan == 0}}-{{else}}{{:helper.smoothRound(data.jan)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_jan": 0})}}
{{:helper.link('1', null, {"set_jan": 1})}}
{{:helper.link('2', null, {"set_jan": 2})}}
{{:helper.link('3', null, {"set_jan": 3})}}
{{:helper.link('4', null, {"set_jan": 4})}}
{{:helper.link('5', null, {"set_jan": 5})}}
</td>
<tr><td>{{if data.ert_type == 'Code Gamma'}}<font color='#DB7093'>GAMMA</font> {{/if}}Cyborg</td><td>{{if data.cyb == 0}}-{{else}}{{:helper.smoothRound(data.cyb)}}{{/if}}</td><td>
{{:helper.link('0', null, {"set_cyb": 0})}}
{{:helper.link('1', null, {"set_cyb": 1})}}
{{:helper.link('2', null, {"set_cyb": 2})}}
{{:helper.link('3', null, {"set_cyb": 3})}}
{{:helper.link('4', null, {"set_cyb": 4})}}
{{:helper.link('5', null, {"set_cyb": 5})}}
</td></tr>
</table>
<BR>
</div>
<div class='item'>
{{:helper.link('Dispatch', null, {"dispatch_ert": 1})}}
</div>
-67
View File
@@ -1,67 +0,0 @@
<!--
Title: Fax Machine UI
Used In File(s): \code\modules\paperwork\faxmachine.dm
-->
<div class='item'>
<h2>Authorization</h2>
</div>
<div class='item'>
<div class='itemLabel'>
Confirm identity:
</div>
<div class='itemContent'>
{{:helper.link(data.scan_name, 'eject', {'scan' : 1})}}
</div>
</div>
<div class='item'>
<div class='itemLabel'>
Authorize:
</div>
<div class='itemContent'>
{{:helper.link(data.authenticated ? 'Log Out' : 'Log In', data.authenticated ? 'unlock' : 'lock', {'auth' : 1})}}
</div>
</div>
<hr>
<div class='item'>
<h2>Fax Menu</h2>
</div>
<div class="item">
<div class='itemLabel'>
Network:
</div>
<div class='itemContent'>
{{:data.network}}
</div>
</div>
<div class="item">
<div class='itemLabel'>
Currently sending:
</div>
<div class='itemContent'>
{{:helper.link(data.paper, 'eject', {'paper' : 1})}}
{{if data.paperinserted}}
{{:helper.link('Rename', 'pencil', {'rename' : 1})}}
{{/if}}
</div>
</div>
<div class="item">
<div class='itemLabel'>
Sending to:
</div>
<div class='itemContent'>
{{:helper.link(data.destination, 'print', {'dept' : 1}, !data.authenticated ? 'disabled' : '')}}
</div>
</div>
<div class="item">
<div class='itemLabel'>
Action:
</div>
<div class="itemContent">
{{if data.authenticated}}
{{:helper.link(data.cooldown && data.respectcooldown ? "Realigning" : "Send", data.cooldown && data.respectcooldown ? 'clock-o' : "envelope-o", {'send' : 1}, data.cooldown && data.respectcooldown ? 'disabled' : "")}}
{{else}}
{{:helper.link(data.cooldown && data.respectcooldown ? "Realigning" : "Send", data.cooldown && data.respectcooldown ? 'clock-o' : "envelope-o", null, !data.authenticated ? 'disabled' : "")}}
{{/if}}
</div>
</div>
-39
View File
@@ -1,39 +0,0 @@
<!--
Title: Keycard Authentication Device UI
Used In File(s): \code\modules\security_levels\keycard_authentication.dm
-->
<style type="text/css">
.event {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
text-align: center;
}
</style>
<div class="item">
<h1>Keycard Authentication Device</h1>
This device is used to trigger certain high security events. It requires the simultaneous swipe of two high-level ID cards.
<div class="item">
{{if data.screen == 1}}
<h2>Trigger Event</h2>
{{:helper.link('Red Alert', 'exclamation-triangle', { 'triggerevent' : 'Red Alert' })}}
{{:helper.link('Emergency Response Team', 'exclamation-triangle', { 'triggerevent' : 'Emergency Response Team' })}}
{{:helper.link('Grant Emergency Maintenance Access', 'unlock', { 'triggerevent' : 'Grant Emergency Maintenance Access' })}}
{{:helper.link('Revoke Emergency Maintenance Access', 'lock', { 'triggerevent' : 'Revoke Emergency Maintenance Access' })}}
{{:helper.link('Activate Station-Wide Emergency Access', 'unlock', { 'triggerevent' : 'Activate Station-Wide Emergency Access' })}}
{{:helper.link('Deactivate Station-Wide Emergency Access', 'lock', { 'triggerevent' : 'Deactivate Station-Wide Emergency Access' })}}
{{else data.screen == 2}}
{{if data.event == 'Emergency Response Team'}}
<div class="item">
<div class="itemLabel">Reason for ERT Call:</div>
<div class="itemContent">
{{:helper.link(data.ertreason, 'exclamation-triangle', { 'ert' : 'callreason' })}}
</div>
</div>
{{/if}}
<h2 class="bad" style="text-align: center;">Please swipe your card to authorize the following event:</h2>
<div class="event">{{:data.event}}</div>
{{:helper.link('Back', 'close', { 'reset' : 1 })}}
{{/if}}
</div>
</div>
-55
View File
@@ -1,55 +0,0 @@
<h3>Subsystems</h3>
<div class="item">
<div class="itemLabel">
Power Port:
</div>
<div class="itemContent">
{{if data.recharge_port}}
<span class='good'>OK</span>
{{else}}
<span class='bad'>ERROR</span>
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Mecha:
</div>
<div class="itemContent">
{{if data.has_mech}}
<span class='good'>LOCATED ({{:data.mecha_name}})</span>
{{else}}
<span class='average'>NONE</span>
{{/if}}
</div>
</div>
{{if data.has_mech}}
<h3>Charging</h3>
<div class="item">
<div class="itemLabel">
Charge Level:
</div>
<div class="itemContent">
{{:helper.displayBar(data.mecha_charge_percentage, 0, 100)}}
<div class="statusValue">
{{:helper.smoothRound(data.mecha_charge_percentage)}}%<br>
</div>
</div>
</div>
<div class="item">
<div class="itemLabel">
Cell Rating:
</div>
<div class="itemContent">
{{:data.mecha_maxcharge}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Cell Charge:
</div>
<div class="itemContent">
{{:helper.smoothRound(data.mecha_charge)}}
</div>
</div>
{{/if}}
-100
View File
@@ -1,100 +0,0 @@
{{if data.robots}}
{{if !data.is_ai}}
<div class='notice'>
<div class="itemContentSmall" style="width: 180px">
Emergency Self-Destruct:
</div>
<div class="itemContentFull">
{{if data.safety}}
{{:helper.link('ARM', 'unlock', {'arm' : 1}, !data.allowed ? 'disabled' : null)}}
{{:helper.link('DETONATE', 'exclamation-circle', {'nuke' : 1}, 'disabled')}}
{{else}}
{{:helper.link('DISARM', 'lock', {'arm' : 1}, !data.allowed ? 'disabled' : null)}}
{{:helper.link('DETONATE', 'exclamation-circle', {'nuke' : 1}, !data.allowed ? 'disabled' : null, 'redButton')}}
{{/if}}
</div>
<div class="clearBoth"></div>
</div>
{{/if}}
{{for data.robots}}
<hr>
<div class='item'>
<h2>{{:value.name}}</h2>
<h3>Information</h3>
<span class="itemLabel">
Status:
</span>
<span class="itemContent">
{{:value.status}}
</span>
<span class="itemLabel">
System Integrity:
</span>
<span class="itemContent">
{{:helper.smoothRound(value.health)}}%
</span>
<span class="itemLabel">
Location:
</span>
<span class="itemContent">
({{:value.xpos}}, {{:value.ypos}}, {{:value.zpos}}): {{:value.area}}
</span>
<span class="itemLabel">
Master AI:
</span>
<span class="itemContent">
{{:value.master_ai}}
</span>
<span class="itemLabel">
Module:
</span>
<span class="itemContent">
{{:value.module}}
</span>
{{if value.hackable}}
<span class="itemLabel">
Safeties:
</span>
<span class="itemContent">
ENABLED
</span>
{{else value.hacked}}
<span class="itemLabel">
Safeties:
</span>
<span class="itemContent">
DISABLED
</span>
{{/if}}
<h3>Power Cell</h3>
{{if value.cell}}
<span class="itemLabel">
Rating:
</span>
<span class="itemContent">
{{:value.cell_capacity}}
</span>
{{:helper.displayBar(value.cell_percentage, 0, 100, (value.cell_percentage >= 50) ? 'good' : (value.cell_percentage >= 25) ? 'average' : 'bad')}}
<b> {{:helper.smoothRound(value.cell_percentage)}}%</b>
{{else}}
<b><i>Not Installed</i></b>
{{:helper.displayBar(100, 0, 100, 'bad')}}
{{/if}}
<h3>Actions</h3>
{{if value.status == "Operational"}}
{{:helper.link('Lockdown', 'lock', {'lockdown' : value.name}, !data.allowed ? 'disabled' : null)}}
{{else}}
{{:helper.link('Unlock', 'unlock', {'lockdown' : value.name}, !data.allowed ? 'disabled' : null)}}
{{/if}}
{{:helper.link('Self-Destruct', 'exclamation-circle', {'detonate' : value.name}, !data.allowed ? 'disabled' : null, 'redButton')}}
{{if value.hackable}}
{{:helper.link('Hack', 'calculator', {'hack' : value.name}, !data.allowed ? 'disabled' : null, 'redButton')}}
{{/if}}
</div>
{{/for}}
{{else}}
<div class='item'>
<h3>No robots were found.</h3>
</div>
{{/if}}
-37
View File
@@ -1,37 +0,0 @@
<!--
Title: Shuttle Console
Used In File(s): /code/modules/shuttle/shuttle.dm
-->
<div class='item'>
<div class='itemLabel'>Location:</div>
<div class='itemContent'>{{:data.status ? data.status : '<span class="bad">*Missing*</span>'}}</div>
</div>
{{if data.shuttle}}
{{if data.docking_ports_len}}
<hr>
<div class='item'>
{{for data.docking_ports}}
<div class='line'>{{:helper.link('Send to ' + value.name, 'sign-out', {'move' : value.id})}}</div>
{{/for}}
</div>
{{else}}
<div class='item'>
<div class='itemLabel'>Status:</div>
<div class='itemContent bad'>Shuttle locked
{{if data.admin_controlled}}
<span>, authorized personnel only</span>
</div></div>
<hr>
<div class='item'>{{:helper.link('Request authorization', 'share-square-o', {'request' : 1})}}</div>
{{else}}
</div>
</div>
<hr>
{{/if}}
{{/if}}
{{if data.docking_request}}
<div class='line'>{{:helper.link('Request docking at the station', 'share-square-o', {'request' : 1})}}</div>
{{/if}}
{{/if}}
-89
View File
@@ -1,89 +0,0 @@
<div class="item">
<div class="itemLabel">
Stored Capacity:
</div>
<div class="itemContent">
{{:helper.displayBar(data.storedCapacity, 0, 100, data.charging ? 'good' : 'average')}}
<div class="statusValue">
{{:helper.smoothRound(data.storedCapacity)}}%
</div>
</div>
</div>
<h3>Input Management</h3>
<div class="item">
<div class="itemLabel">
Charge Mode:
</div>
<div class="itemContent">
{{:helper.link('Auto', 'refresh', {'cmode' : 1}, data.chargeMode ? 'selected' : null)}}{{:helper.link('Off', 'close', {'cmode' : 1}, data.chargeMode ? null : 'selected')}}
&nbsp;
{{if data.charging == 2}}
[<span class='good'>Charging</span>]
{{else data.charging == 1}}
[<span class='average'>Partially Charging</span>]
{{else}}
[<span class='bad'>Not Charging</span>]
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Input Level:
</div>
<div class="itemContent">
{{:helper.displayBar(data.chargeLevel, 0, data.chargeMax)}}
<div style="clear: both; padding-top: 4px;">
{{:helper.link('MIN', null, {'input' : 'min'}, (data.chargeLevel > 0) ? null : 'disabled')}}
{{:helper.link('SET', null, {'input' : 'set'}, null)}}
{{:helper.link('MAX', null, {'input' : 'max'}, (data.chargeLevel < data.chargeMax) ? null : 'disabled')}}
<div style="float: left; width: 100px; text-align: center;">&nbsp;{{:data.chargeLevel}} W&nbsp;</div>
</div>
</div>
</div>
<h3>Output Management</h3>
<div class="item">
<div class="itemLabel">
Output Status:
</div>
<div class="itemContent">
{{:helper.link('Online', 'power-off', {'online' : 1}, data.outputOnline ? 'selected' : null)}}{{:helper.link('Offline', 'close', {'online' : 1}, data.outputOnline ? null : 'selected')}}
&nbsp;
{{if data.outputting == 2}}
[<span class='good'>Outputting</span>]
{{else data.outputting == 1}}
[<span class='average'>Stored energy too low</span>]
{{else}}
[<span class='bad'>Not Outputting</span>]
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Output Level:
</div>
<div class="itemContent">
{{:helper.displayBar(data.outputLevel, 0, data.outputMax)}}
<div style="clear: both; padding-top: 4px;">
{{:helper.link('MIN', null, {'output' : 'min'}, (data.outputLevel > 0) ? null : 'disabled')}}
{{:helper.link('SET', null, {'output' : 'set'}, null)}}
{{:helper.link('MAX', null, {'output' : 'max'}, (data.outputLevel < data.outputMax) ? null : 'disabled')}}
<div style="float: left; width: 100px; text-align: center;">&nbsp;{{:data.outputLevel}} W&nbsp;</div>
</div>
</div>
</div>
<div class="item">
<div class="itemLabel">
Output Load:
</div>
<div class="itemContent">
{{:helper.displayBar(data.outputLoad, 0, data.outputMax, (data.outputLoad < data.outputLevel) ? 'good' : 'average')}}
<div class="statusValue">
{{:helper.smoothRound(data.outputLoad)}} W
</div>
</div>
</div>
-20
View File
@@ -1,20 +0,0 @@
<div class='statusDisplay'>
<h1>Mob Spawners</h1>
<table style='width:100%;'>
{{for data.spawners}}
<div class='item'>
<div class='itemLabel'>
<h3>{{:value.name}}</h3>
<p>{{:value.amount_left}} spawners left.</p>
</div>
<div class='itemContent'>
{{:value.desc}}
</div>
<div class='floatRight'>
{{:helper.link('Jump', null, {'action': 'jump', 'uid': value.uids}, null)}}
{{:helper.link('Spawn', null, {'action': 'spawn', 'uid': value.uids}, value.amount_left > 0 ? null : 'disabled')}}
</div>
</div>
{{/for}}
</table>
</div>
-56
View File
@@ -1,56 +0,0 @@
<div class="item">
<div class="itemLabel">
Attachment One:
</div>
<div class="itemContent">
{{if data.attachmentOne}}
{{:data.attachmentOne}}
{{else}}
<i>None</i>
{{/if}}
{{:helper.link('Remove', 'eject', {'tankone' : 1}, data.attachmentOne ? null : 'disabled')}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Attachment Two:
</div>
<div class="itemContent">
{{if data.attachmentTwo}}
{{:data.attachmentTwo}}
{{else}}
<i>None</i>
{{/if}}
{{:helper.link('Remove', 'eject', {'tanktwo' : 1}, data.attachmentTwo ? null : 'disabled')}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Valve Attachment:
</div>
<div class="itemContent">
{{if data.valveAttachment}}
{{:data.valveAttachment}}
{{else}}
<i>None</i>
{{/if}}
{{:helper.link('Remove', 'eject', {'rem_device' : 1}, data.valveAttachment ? null : 'disabled')}}
{{if data.valveAttachment}}
{{:helper.link('View', 'wrench', {'device' : 1})}}
{{/if}}
</div>
</div>
<div class="item">&nbsp;</div>
<div class="item">
<div class="itemLabel">
Valve Status:
</div>
<div class="itemContent">
{{:helper.link('Open', 'unlock', {'open' : 1}, (!data.attachmentOne || !data.attachmentTwo) ? 'disabled' : (data.valveOpen ? 'selected' : null))}}{{:helper.link('Close', 'lock', {'open' : 1}, (!data.attachmentOne || !data.attachmentTwo) ? 'disabled' : (data.valveOpen ? null : 'selected'))}}
</div>
</div>
-68
View File
@@ -1,68 +0,0 @@
<!--
Interface for vending machines
See: code/game/machinery/vending.dm
-->
{{if data.mode == 0}} <!-- Listing -->
<h2>Items available</h2>
<div class='item'>
{{for data.products}}
<div class='item'>
<div style='float'>
{{if value.price > 0}}
{{:helper.link('Buy (' + value.price + ')', 'shopping-cart', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}}
{{else}}
{{:helper.link('Vend', 'arrow-circle-down', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}}
{{/if}}
</div>
<div class='itemContent'>
{{if value.color}}<span style='color:{{:value.color}}'>{{:value.name}}</span>
{{else}}{{:value.name}}
{{/if}}
({{:value.amount ? value.amount : "NONE LEFT"}})
</div>
</div>
{{empty}}
No items available!
{{/for}}
</div>
{{if data.coin}}
<h2>Coin</h2>
<div class='item'>
<div class='itemLabel'>Coin deposited:</div>
<div class='itemContent'>{{:helper.link(data.coin, 'eject', {'remove_coin' : 1})}}</div>
</div>
{{/if}}
{{if data.item_slot == 1}}
<h2>Item Slot</h2>
<div class='item'>
<div class='itemLabel'>Item Slot:</div>
{{if data.inserted_item}}
<div class='itemContent'>{{:helper.link(data.inserted_item, 'eject', {'remove_item' : 1})}}</div>
{{else}}
<div class='itemContent'>Empty</div>
{{/if}}
</div>
{{/if}}
{{else data.mode == 1}} <!-- Payment screen -->
<h2>Item selected</h2>
<div class='item'>
<div class='item'>
<div class='itemLabel'>Item selected:</div> <div class='itemContent'>{{:data.product}}</div>
<div class='itemLabel'>Charge:</div> <div class='itemContent'>{{:data.price}}</div>
</div>
<div class='statusDisplay' style='overflow: auto;'>
{{if data.message_err}} <span class='uiIcon16 icon-alert' ></span>{{/if}} {{:data.message}}
</div>
<div class='item'>
{{:helper.link('Pay', 'shopping-cart', {'pay' : 1})}}
{{:helper.link('Cancel', 'arrow-left', {'cancelpurchase' : 1})}}
</div>
</div>
{{/if}}
{{if data.panel}}
<h2>Maintenance panel</h2>
<div class='item'>
<div class='itemLabel'>Speaker</div><div class='item'>{{:helper.link(data.speaker ? 'Enabled' : 'Disabled', 'gear', {'togglevoice' : 1})}}</div>
</div>
{{/if}}
+1 -2
View File
@@ -2082,7 +2082,6 @@
#include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm"
#include "code\modules\modular_computers\file_system\programs\antagonist\revelation.dm"
#include "code\modules\modular_computers\file_system\programs\command\card.dm"
#include "code\modules\modular_computers\file_system\programs\command\comms.dm"
#include "code\modules\modular_computers\file_system\programs\engineering\power_monitor.dm"
#include "code\modules\modular_computers\file_system\programs\engineering\sm_monitor.dm"
#include "code\modules\modular_computers\file_system\programs\generic\configurator.dm"
@@ -2121,7 +2120,6 @@
#include "code\modules\nano\interaction\self.dm"
#include "code\modules\nano\interaction\zlevel.dm"
#include "code\modules\nano\modules\atmos_control.dm"
#include "code\modules\nano\modules\ert_manager.dm"
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\law_manager.dm"
#include "code\modules\nano\modules\nano_module.dm"
@@ -2461,6 +2459,7 @@
#include "code\modules\tgui\tgui.dm"
#include "code\modules\tgui\modules\_base.dm"
#include "code\modules\tgui\modules\crew_monitor.dm"
#include "code\modules\tgui\modules\ert_manager.dm"
#include "code\modules\tgui\states\admin.dm"
#include "code\modules\tgui\states\always.dm"
#include "code\modules\tgui\states\conscious.dm"
Binary file not shown.
+123
View File
@@ -0,0 +1,123 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Button, LabeledList, Dropdown, Box, Section } from '../components';
import { Window } from '../layouts';
export const BrigTimer = (props, context) => {
const { act, data } = useBackend(context);
data.nameText = data.occupant;
if (data.timing) {
if (data.prisoner_hasrec) {
data.nameText = (<Box color="green">{data.occupant}</Box>);
} else {
data.nameText = (<Box color="red">{data.occupant}</Box>);
}
}
let nameIcon = "pencil-alt";
if (data.prisoner_name) {
if (!data.prisoner_hasrec) {
nameIcon = "exclamation-triangle";
}
}
let nameOptions = [];
let i = 0;
for (i = 0; i < data.spns.length; i++) {
nameOptions.push(data.spns[i]);
}
return (
<Window resizable>
<Window.Content>
<Section title="Cell Information">
<LabeledList>
<LabeledList.Item label="Cell ID">
{data.cell_id}
</LabeledList.Item>
<LabeledList.Item label="Occupant">
{data.nameText}
</LabeledList.Item>
<LabeledList.Item label="Crimes">
{data.crimes}
</LabeledList.Item>
<LabeledList.Item label="Brigged By">
{data.brigged_by}
</LabeledList.Item>
<LabeledList.Item label="Time Brigged For">
{data.time_set}
</LabeledList.Item>
<LabeledList.Item label="Time Left">
{data.time_left}
</LabeledList.Item>
<LabeledList.Item label="Actions">
<Fragment>
<Button
icon="lightbulb-o"
content="Flash"
disabled={!data.isAllowed}
onClick={() => act('flash')} />
<Button
icon="sync"
content="Reset Timer"
disabled={!data.timing || !data.isAllowed}
onClick={() => act('restart_timer')} />
<Button
icon="eject"
content="Release Prisoner"
disabled={!data.timing || !data.isAllowed}
onClick={() => act('stop')} />
</Fragment>
</LabeledList.Item>
</LabeledList>
</Section>
{!data.timing && (
<Section title="New Prisoner">
<LabeledList>
<LabeledList.Item label="Prisoner Name">
<Button
icon={nameIcon}
content={data.prisoner_name ? data.prisoner_name : "-----"}
disabled={!data.isAllowed}
onClick={() => act('prisoner_name')} />
{!!data.spns.length && (
<Dropdown
disabled={!data.isAllowed || !data.spns.length}
options={data.spns}
width="250px"
onSelected={value => act('prisoner_name',
{
prisoner_name: value,
})} />
)}
</LabeledList.Item>
<LabeledList.Item label="Prisoner Crimes">
<Button
icon="pencil-alt"
content={data.prisoner_charge
? data.prisoner_charge
: "-----"}
disabled={!data.isAllowed}
onClick={() => act('prisoner_charge')} />
</LabeledList.Item>
<LabeledList.Item label="Prisoner Time">
<Button
icon="pencil-alt"
content={data.prisoner_time ? data.prisoner_time : "-----"}
disabled={!data.isAllowed}
onClick={() => act('prisoner_time')} />
</LabeledList.Item>
<LabeledList.Item label="Start">
<Button
icon="gavel"
content="Start Sentence"
disabled={!data.prisoner_name
|| !data.prisoner_charge
|| !data.prisoner_time
|| !data.isAllowed}
onClick={() => act('start')} />
</LabeledList.Item>
</LabeledList>
</Section>
)}
</Window.Content>
</Window>
);
};
@@ -0,0 +1,315 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Button, LabeledList, Box, Section } from '../components';
import { Window } from '../layouts';
export const CommunicationsComputer = (props, context) => {
const { act, data } = useBackend(context);
let authReadable;
if (!data.authenticated) {
authReadable = "Not Logged In";
} else if (data.is_ai) {
authReadable = "AI";
} else if (data.authenticated === 1) {
authReadable = "Command";
} else if (data.authenticated === 2) {
authReadable = "Captain";
} else {
authReadable = "ERROR: Report This Bug!";
}
let reportText = "View (" + data.messages.length + ")";
let authBlock = (
<Fragment>
<Section title="Authentication">
<LabeledList>
{data.is_ai && (
<LabeledList.Item label="Access Level">
AI
</LabeledList.Item>
) || (
<LabeledList.Item label="Actions">
<Button
icon={data.authenticated ? 'sign-out-alt' : 'id-card'}
selected={data.authenticated}
content={data.authenticated
? "Log Out (" + authReadable + ")"
: 'Log In'}
onClick={() => act("auth")} />
</LabeledList.Item>
)}
</LabeledList>
</Section>
<Section title="Escape Shuttle">
<LabeledList>
{!!data.esc_status && (
<LabeledList.Item label="Status">
{data.esc_status}
</LabeledList.Item>
)}
{!!data.esc_callable && (
<LabeledList.Item label="Options">
<Button
icon="rocket"
content="Call Shuttle"
disabled={!data.authenticated}
onClick={() => act('callshuttle')} />
</LabeledList.Item>
)}
{!!data.esc_recallable && (
<LabeledList.Item label="Options">
<Button
icon="times"
content="Recall Shuttle"
disabled={!data.authenticated || data.is_ai}
onClick={() => act('cancelshuttle')} />
</LabeledList.Item>
)}
{!!data.lastCallLoc && (
<LabeledList.Item label="Last Call/Recall From">
{data.lastCallLoc}
</LabeledList.Item>
)}
</LabeledList>
</Section>
</Fragment>
);
let announceText = "Make Priority Announcement";
if (data.msg_cooldown > 0) {
announceText += " (" + data.msg_cooldown + "s)";
}
let ccMessageText = data.emagged ? "Message [UNKNOWN]" : "Message CentComm";
let nukeRequestText = "Request Authentication Codes";
if (data.cc_cooldown > 0) {
ccMessageText += " (" + data.cc_cooldown + "s)";
nukeRequestText += " (" + data.cc_cooldown + "s)";
}
let alertLevelText = data.str_security_level;
let alertLevelButtons = data.levels.map(slevel => {
return (
<Button
key={slevel.name}
icon={slevel.icon}
content={slevel.name}
disabled={!data.authmax
|| slevel.id === data.security_level}
onClick={() => act('newalertlevel', { level: slevel.id })} />
);
});
let presetButtons = data.stat_display["presets"].map(pb => {
return (
<Button
key={pb.name}
content={pb.label}
selected={pb.name === data.stat_display.type}
disabled={!data.authenticated}
onClick={() => act('setstat', { statdisp: pb.name })} />
);
});
let iconButtons = data.stat_display["alerts"].map(ib => {
return (
<Button
key={ib.alert}
content={ib.label}
selected={ib.alert === data.stat_display.icon}
disabled={!data.authenticated}
onClick={() => act('setstat',
{ statdisp: "alert", alert: ib.alert })} />
);
});
let messageView;
if (data.current_message_title) {
messageView = (
<Section title={data.current_message_title} buttons={
<Button
icon="times"
content="Return To Message List"
disabled={!data.authenticated}
onClick={() => act('messagelist')} />
}>
<Box>
{data.current_message}
</Box>
</Section>
);
} else {
let messageRows = data.messages.map(m => {
return (
<LabeledList.Item key={m.id} label={m.title}>
<Button
icon="eye"
content="View"
disabled={!data.authenticated
|| data.current_message_title === m.title}
onClick={() => act('messagelist', { msgid: m.id })} />
<Button
icon="times"
content="Delete"
disabled={!data.authenticated}
onClick={() => act('delmessage', { msgid: m.id })} />
</LabeledList.Item>
);
});
messageView = (
<Section title="Messages Received" buttons={
<Button
icon="arrow-circle-left"
content="Back To Main Menu"
onClick={() => act('main')} />
}>
<LabeledList>
{messageRows}
</LabeledList>
</Section>
);
}
switch (data.menu_state) {
// 1 = main screen
case 1:
return (
<Window resizable>
<Window.Content scrollable>
{authBlock}
<Section title="Captain-Only Actions">
<LabeledList>
<LabeledList.Item label="Current Alert"
color={data.security_level_color}>
{alertLevelText}
</LabeledList.Item>
<LabeledList.Item label="Change Alert">
{alertLevelButtons}
</LabeledList.Item>
<LabeledList.Item label="Announcement">
<Button
icon="bullhorn"
content={announceText}
disabled={!data.authmax || data.msg_cooldown > 0}
onClick={() => act('announce')} />
</LabeledList.Item>
{!!data.emagged && (
<LabeledList.Item label="Transmit">
<Button
icon="broadcast-tower"
color="red"
content={ccMessageText}
disabled={!data.authmax || data.cc_cooldown > 0}
onClick={() => act('MessageSyndicate')} />
<Button
icon="sync-alt"
content="Reset Relays"
disabled={!data.authmax}
onClick={() => act('RestoreBackup')} />
</LabeledList.Item>
) || (
<LabeledList.Item label="Transmit">
<Button
icon="broadcast-tower"
content={ccMessageText}
disabled={!data.authmax || data.cc_cooldown > 0}
onClick={() => act('MessageCentcomm')} />
</LabeledList.Item>
)}
<LabeledList.Item label="Nuclear Device">
<Button
icon="bomb"
content={nukeRequestText}
disabled={!data.authmax || data.cc_cooldown > 0}
onClick={() => act('nukerequest')} />
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Command Staff Actions">
<LabeledList>
<LabeledList.Item label="Displays">
<Button
icon="tv"
content="Change Status Displays"
disabled={!data.authenticated}
onClick={() => act('status')} />
</LabeledList.Item>
<LabeledList.Item label="Incoming Messages">
<Button
icon="folder-open"
content={reportText}
disabled={!data.authenticated}
onClick={() => act('messagelist')} />
</LabeledList.Item>
<LabeledList.Item label="Misc">
<Button
icon="sync-alt"
content="Restart Nano-Mob Hunter GO! Server"
disabled={!data.authenticated}
onClick={() => act('RestartNanoMob')} />
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
// 2 = status screen
case 2:
return (
<Window>
<Window.Content>
{authBlock}
<Section title="Modify Status Screens" buttons={
<Button
icon="arrow-circle-left"
content="Back To Main Menu"
onClick={() => act('main')} />
}>
<LabeledList>
<LabeledList.Item label="Presets">
{presetButtons}
</LabeledList.Item>
<LabeledList.Item label="Alerts">
{iconButtons}
</LabeledList.Item>
<LabeledList.Item label="Message Line 1">
<Button
icon="pencil-alt"
content={data.stat_display.line_1}
disabled={!data.authenticated}
onClick={() => act('setmsg1')} />
</LabeledList.Item>
<LabeledList.Item label="Message Line 2">
<Button
icon="pencil-alt"
content={data.stat_display.line_2}
disabled={!data.authenticated}
onClick={() => act('setmsg2')} />
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
// 3 = messages screen
case 3:
return (
<Window>
<Window.Content>
{authBlock}
{messageView}
</Window.Content>
</Window>
);
default:
return (
<Window>
<Window.Content>
{authBlock}
ERRROR. Unknown menu_state: {data.menu_state}
Please report this to NT Technical Support.
</Window.Content>
</Window>
);
}
};
+137
View File
@@ -0,0 +1,137 @@
import { useBackend } from '../backend';
import { Button, LabeledList, Box, Section } from '../components';
import { Window } from '../layouts';
export const ERTManager = (props, context) => {
const { act, data } = useBackend(context);
let slotOptions = [0, 1, 2, 3, 4, 5];
return (
<Window>
<Window.Content>
<Section title="Overview">
<LabeledList>
<LabeledList.Item label="Current Alert"
color={data.security_level_color}>
{data.str_security_level}
</LabeledList.Item>
<LabeledList.Item label="ERT Type">
<Button
content="Amber"
color={data.ert_type === "Amber"
? "orange"
: ""}
onClick={() => act('ert_type', { ert_type: "Amber" })} />
<Button
content="Red"
color={data.ert_type === "Red"
? "red"
: ""}
onClick={() => act('ert_type', { ert_type: "Red" })} />
<Button
content="Gamma"
color={data.ert_type === "Gamma"
? "purple"
: ""}
onClick={() => act('ert_type', { ert_type: "Gamma" })} />
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Slots">
<LabeledList>
<LabeledList.Item label="Commander">
<Button
content={data.com > 0 ? "Yes" : "No"}
selected={data.com > 0}
onClick={() => act('toggle_com')} />
</LabeledList.Item>
<LabeledList.Item label="Security">
{slotOptions.map((a, i) => (
<Button
key={"sec" + a}
selected={data.sec === a}
content={a}
onClick={() => act('set_sec', {
set_sec: a,
})}
/>
))}
</LabeledList.Item>
<LabeledList.Item label="Medical">
{slotOptions.map((a, i) => (
<Button
key={"med" + a}
selected={data.med === a}
content={a}
onClick={() => act('set_med', {
set_med: a,
})}
/>
))}
</LabeledList.Item>
<LabeledList.Item label="Engineering">
{slotOptions.map((a, i) => (
<Button
key={"eng" + a}
selected={data.eng === a}
content={a}
onClick={() => act('set_eng', {
set_eng: a,
})}
/>
))}
</LabeledList.Item>
<LabeledList.Item label="Paranormal">
{slotOptions.map((a, i) => (
<Button
key={"par" + a}
selected={data.par === a}
content={a}
onClick={() => act('set_par', {
set_par: a,
})}
/>
))}
</LabeledList.Item>
<LabeledList.Item label="Janitor">
{slotOptions.map((a, i) => (
<Button
key={"jan" + a}
selected={data.jan === a}
content={a}
onClick={() => act('set_jan', {
set_jan: a,
})}
/>
))}
</LabeledList.Item>
<LabeledList.Item label="Cyborg">
{slotOptions.map((a, i) => (
<Button
key={"cyb" + a}
selected={data.cyb === a}
content={a}
onClick={() => act('set_cyb', {
set_cyb: a,
})}
/>
))}
</LabeledList.Item>
<LabeledList.Item label="Total Slots">
<Box color={data.total > data.spawnpoints
? "red"
: "green"}>
{data.total} total, versus {data.spawnpoints} spawnpoints
</Box>
</LabeledList.Item>
<LabeledList.Item label="Dispatch">
<Button
icon="ambulance"
content="Send ERT"
onClick={() => act('dispatch_ert')} />
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,68 @@
import { useBackend } from "../backend";
import { Button, LabeledList, Section } from "../components";
import { Window } from "../layouts";
export const FaxMachine = (props, context) => {
const { act, data } = useBackend(context);
return (
<Window>
<Window.Content>
<Section title="Authorization">
<LabeledList>
<LabeledList.Item label="ID Card">
<Button
icon={data.scan_name ? 'eject' : 'id-card'}
selected={data.scan_name}
content={data.scan_name ? data.scan_name : '-----'}
tooltip={data.scan_name ? "Eject ID" : "Insert ID"}
onClick={() => act("scan")} />
</LabeledList.Item>
<LabeledList.Item label="Authorize">
<Button
icon={data.authenticated ? 'sign-out-alt' : 'id-card'}
selected={data.authenticated}
disabled={!data.scan_name && !data.authenticated}
content={data.authenticated ? 'Log Out' : 'Log In'}
onClick={() => act("auth")} />
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Fax Menu">
<LabeledList>
<LabeledList.Item label="Network">
{data.network}
</LabeledList.Item>
<LabeledList.Item label="Document">
<Button
icon={data.paper ? 'eject' : 'paperclip'}
disabled={!data.authenticated && !data.paper}
content={data.paper ? data.paper : '-----'}
onClick={() => act("paper")} />
{!!data.paper && (
<Button
icon="pencil-alt"
content="Rename"
onClick={() => act("rename")} />
)}
</LabeledList.Item>
<LabeledList.Item label="Sending To">
<Button
icon="print"
content={data.destination ? data.destination : "-----"}
disabled={!data.authenticated}
onClick={() => act("dept")} />
</LabeledList.Item>
<LabeledList.Item label="Action">
<Button
icon="envelope"
content={data.sendError ? data.sendError : "Send"}
disabled={!data.paper || !data.destination
|| !data.authenticated || data.sendError}
onClick={() => act("send")} />
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,141 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, Section, LabeledList } from '../components';
import { Window } from '../layouts';
export const KeycardAuth = (props, context) => {
const { act, data } = useBackend(context);
let infoBox = (
<Section title="Keycard Authentication Device">
<Box>
This device is used to trigger certain high security events.
It requires the simultaneous swipe of two high-level ID cards.
</Box>
</Section>
);
if (!data.swiping && !data.busy) {
return (
<Window>
<Window.Content>
{infoBox}
<Section title="Choose Action">
<LabeledList>
<LabeledList.Item
label="Red Alert">
<Button
icon="exclamation-triangle"
disabled={!data.redAvailable}
onClick={() => act('triggerevent',
{ 'triggerevent': 'Red Alert' })}
content="Red Alert" />
</LabeledList.Item>
<LabeledList.Item label="ERT">
<Button
icon="broadcast-tower"
onClick={() => act('triggerevent',
{ 'triggerevent': 'Emergency Response Team' })}
content="Call ERT" />
</LabeledList.Item>
<LabeledList.Item label="Emergency Maint Access">
<Button
icon="door-open"
onClick={() => act('triggerevent',
{ 'triggerevent':
'Grant Emergency Maintenance Access' })}
content="Grant" />
<Button
icon="door-closed"
onClick={() => act('triggerevent',
{ 'triggerevent':
'Revoke Emergency Maintenance Access' })}
content="Revoke" />
</LabeledList.Item>
<LabeledList.Item label="Emergency Station-Wide Access">
<Button
icon="door-open"
onClick={() => act('triggerevent',
{ 'triggerevent':
'Activate Station-Wide Emergency Access' })}
content="Grant" />
<Button
icon="door-closed"
onClick={() => act('triggerevent',
{ 'triggerevent':
'Deactivate Station-Wide Emergency Access' })}
content="Revoke" />
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
} else {
let swipeInfo = (
<Box color="red">
Waiting for YOU to swipe your ID...
</Box>
);
if (!data.hasSwiped && !data.ertreason
&& data.event === "Emergency Response Team") {
swipeInfo = (
<Box color="red">
Fill out the reason for your ERT request.
</Box>
);
} else if (data.hasConfirm) {
swipeInfo = (
<Box color="green">
Request Confirmed!
</Box>
);
} else if (data.isRemote) {
swipeInfo = (
<Box color="orange">
Swipe your card to CONFIRM the remote request.
</Box>
);
} else if (data.hasSwiped) {
swipeInfo = (
<Box color="orange">
Waiting for second person to confirm...
</Box>
);
}
return (
<Window>
<Window.Content>
{infoBox}
{data.event === 'Emergency Response Team' && (
<Section title="Reason for ERT Call">
<Box>
<Button
color={data.ertreason
? ""
: "red"}
icon={data.ertreason
? "check"
: "pencil-alt"}
content={data.ertreason
? data.ertreason
: "-----"}
disabled={data.busy}
onClick={() => act('ert')}
/>
</Box>
</Section>
)}
<Section title={data.event} buttons={
<Button
icon="arrow-circle-left"
content="Back"
disabled={data.busy || data.hasConfirm}
onClick={() => act('reset')} />
}>
{swipeInfo}
</Section>
</Window.Content>
</Window>
);
}
};
@@ -0,0 +1,74 @@
import { useBackend } from '../backend';
import { AnimatedNumber, Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components';
import { Window } from '../layouts';
export const MechBayConsole = (props, context) => {
const { act, data } = useBackend(context);
const { recharge_port } = data;
const mech = recharge_port && recharge_port.mech;
const cell = mech && mech.cell;
const name = mech && mech.name;
return (
<Window resizable>
<Window.Content>
<Section
title={!name ? "Mech status" : "Mech status: " + name}
textAlign="center"
buttons={(
<Button
icon="sync"
content="Sync"
onClick={() => act('reconnect')} />
)}>
<LabeledList>
<LabeledList.Item label="Integrity">
{!recharge_port && (
<NoticeBox>
No power port detected. Please re-sync.
</NoticeBox>
) || !mech && (
<NoticeBox>
No mech detected.
</NoticeBox>
) || (
<ProgressBar
value={mech.health / mech.maxhealth}
ranges={{
good: [0.7, Infinity],
average: [0.3, 0.7],
bad: [-Infinity, 0.3],
}} />
)}
</LabeledList.Item>
<LabeledList.Item label="Power">
{!recharge_port && (
<NoticeBox>
No power port detected. Please re-sync.
</NoticeBox>
) || !mech && (
<NoticeBox>
No mech detected.
</NoticeBox>
) || !cell && (
<NoticeBox>
No cell is installed.
</NoticeBox>
) || (
<ProgressBar
value={cell.charge / cell.maxcharge}
ranges={{
good: [0.7, Infinity],
average: [0.3, 0.7],
bad: [-Infinity, 0.3],
}}>
<AnimatedNumber value={cell.charge} />
{' / ' + cell.maxcharge}
</ProgressBar>
)}
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,143 @@
import { Fragment } from 'inferno';
import { useBackend, useSharedState } from '../backend';
import { Box, Button, LabeledList, ProgressBar, NoticeBox, Section, Tabs } from '../components';
import { Window } from '../layouts';
export const RoboticsControlConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
can_hack,
safety,
show_detonate_all,
cyborgs = [],
} = data;
return (
<Window resizable>
<Window.Content scrollable>
{!!show_detonate_all && (
<Section title="Emergency Self Destruct">
<Button
icon={safety ? 'lock' : 'unlock'}
content={safety ? 'Disable Safety' : 'Enable Safety'}
selected={safety}
onClick={() => act('arm', {})} />
<Button
icon="bomb"
disabled={safety}
content="Destroy ALL Cyborgs"
color="bad"
onClick={() => act('nuke', {})} />
</Section>
)}
<Cyborgs cyborgs={cyborgs} can_hack={can_hack} />
</Window.Content>
</Window>
);
};
const Cyborgs = (props, context) => {
const { cyborgs, can_hack } = props;
const { act, data } = useBackend(context);
if (!cyborgs.length) {
return (
<NoticeBox>
No cyborg units detected within access parameters.
</NoticeBox>
);
}
return cyborgs.map(cyborg => {
return (
<Section
key={cyborg.uid}
title={cyborg.name}
buttons={(
<Fragment>
{!!cyborg.hackable && !cyborg.emagged && (
<Button
icon="terminal"
content="Hack"
color="bad"
onClick={() => act('hackbot', {
uid: cyborg.uid,
})} />
)}
<Button.Confirm
icon={cyborg.locked_down ? 'unlock' : 'lock'}
color={cyborg.locked_down ? 'good' : 'default'}
content={cyborg.locked_down ? "Release" : "Lockdown"}
disabled={!data.auth}
onClick={() => act('stopbot', {
uid: cyborg.uid,
})} />
<Button.Confirm
icon="bomb"
content="Detonate"
disabled={!data.auth}
color="bad"
onClick={() => act('killbot', {
uid: cyborg.uid,
})} />
</Fragment>
)}>
<LabeledList>
<LabeledList.Item label="Status">
<Box color={cyborg.status
? 'bad'
: cyborg.locked_down
? 'average'
: 'good'}>
{cyborg.status
? "Not Responding"
: cyborg.locked_down
? "Locked Down"
: "Nominal"}
</Box>
</LabeledList.Item>
<LabeledList.Item label="Location">
<Box>
{cyborg.locstring}
</Box>
</LabeledList.Item>
<LabeledList.Item label="Integrity">
<ProgressBar
color={cyborg.health > 50 ? "good" : "bad"}
value={cyborg.health / 100} />
</LabeledList.Item>
{(typeof cyborg.charge === 'number') && (
<Fragment>
<LabeledList.Item label="Cell Charge">
<ProgressBar
color={cyborg.charge > 30 ? "good" : "bad"}
value={cyborg.charge / 100} />
</LabeledList.Item>
<LabeledList.Item label="Cell Capacity">
<Box color={cyborg.cell_capacity < 30000 ? "average" : "good"}>
{cyborg.cell_capacity}
</Box>
</LabeledList.Item>
</Fragment>
) || (
<LabeledList.Item label="Cell">
<Box color="bad">
No Power Cell
</Box>
</LabeledList.Item>
)}
{!!cyborg.is_hacked && (
<LabeledList.Item label="Safeties">
<Box color="bad">DISABLED</Box>
</LabeledList.Item>
)}
<LabeledList.Item label="Module">
{cyborg.module}
</LabeledList.Item>
<LabeledList.Item label="Master AI">
<Box color={cyborg.synchronization ? 'default' : 'average'}>
{cyborg.synchronization || "None"}
</Box>
</LabeledList.Item>
</LabeledList>
</Section>
);
});
};
@@ -0,0 +1,60 @@
import { useBackend } from '../backend';
import { Button, LabeledList, Box, Fragment, Section, NoticeBox } from '../components';
import { Window } from '../layouts';
import { LabeledListItem } from '../components/LabeledList';
export const ShuttleConsole = (props, context) => {
const { act, data } = useBackend(context);
return (
<Window resizable>
<Window.Content>
<Section>
<LabeledList>
<LabeledList.Item label="Location">
{data.status ? (
data.status
) : (
<NoticeBox color="red">
Shuttle Missing
</NoticeBox>
)}
</LabeledList.Item>
{!!data.shuttle && (// only show this stuff if there's a shuttle
!!data.docking_ports_len && (
<LabeledList.Item label={"Send to "}>
{data.docking_ports.map(port => (
<Button
icon="chevron-right"
key={port.name}
content={port.name}
onClick={() => act('move', {
move: port.id,
})} />
)
)}
</LabeledList.Item>
) || (// ELSE, if there's no docking ports.
<Fragment>
<LabeledListItem label="Status" color="red">
<NoticeBox color="red">
Shuttle Locked
</NoticeBox>
</LabeledListItem>
{!!data.admin_controlled && (
<LabeledListItem label="Authorization">
<Button
icon="exclamation-circle"
content="Request Authorization"
disabled={!data.status}
onClick={() => act('request')} />
</LabeledListItem>
)}
</Fragment>
)
)}
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
+188
View File
@@ -0,0 +1,188 @@
import { useBackend } from '../backend';
import { Box, Button, Flex, LabeledList, ProgressBar, Section, Slider } from '../components';
import { formatPower } from '../format';
import { Window } from '../layouts';
// Common power multiplier
const POWER_MUL = 1e3;
export const Smes = (props, context) => {
const { act, data } = useBackend(context);
const {
capacityPercent,
capacity,
charge,
inputAttempt,
inputting,
inputLevel,
inputLevelMax,
inputAvailable,
outputAttempt,
outputting,
outputLevel,
outputLevelMax,
outputUsed,
} = data;
const inputState = (
capacityPercent >= 100 && 'good'
|| inputting && 'average'
|| 'bad'
);
const outputState = (
outputting && 'good'
|| charge > 0 && 'average'
|| 'bad'
);
return (
<Window>
<Window.Content>
<Section title="Stored Energy">
<ProgressBar
value={capacityPercent * 0.01}
ranges={{
good: [0.5, Infinity],
average: [0.15, 0.5],
bad: [-Infinity, 0.15],
}} />
</Section>
<Section title="Input">
<LabeledList>
<LabeledList.Item
label="Charge Mode"
buttons={
<Button
icon={inputAttempt ? 'sync-alt' : 'times'}
selected={inputAttempt}
onClick={() => act('tryinput')}>
{inputAttempt ? 'Auto' : 'Off'}
</Button>
}>
<Box color={inputState}>
{capacityPercent >= 100 && 'Fully Charged'
|| inputting && 'Charging'
|| 'Not Charging'}
</Box>
</LabeledList.Item>
<LabeledList.Item label="Target Input">
<Flex inline width="100%">
<Flex.Item>
<Button
icon="fast-backward"
disabled={inputLevel === 0}
onClick={() => act('input', {
target: 'min',
})} />
<Button
icon="backward"
disabled={inputLevel === 0}
onClick={() => act('input', {
adjust: -10000,
})} />
</Flex.Item>
<Flex.Item grow={1} mx={1}>
<Slider
value={inputLevel / POWER_MUL}
fillValue={inputAvailable / POWER_MUL}
minValue={0}
maxValue={inputLevelMax / POWER_MUL}
step={5}
stepPixelSize={4}
format={value => formatPower(value * POWER_MUL, 1)}
onChange={(e, value) => act('input', {
target: value * POWER_MUL,
})} />
</Flex.Item>
<Flex.Item>
<Button
icon="forward"
disabled={inputLevel === inputLevelMax}
onClick={() => act('input', {
adjust: 10000,
})} />
<Button
icon="fast-forward"
disabled={inputLevel === inputLevelMax}
onClick={() => act('input', {
target: 'max',
})} />
</Flex.Item>
</Flex>
</LabeledList.Item>
<LabeledList.Item label="Available">
{formatPower(inputAvailable)}
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Output">
<LabeledList>
<LabeledList.Item
label="Output Mode"
buttons={
<Button
icon={outputAttempt ? 'power-off' : 'times'}
selected={outputAttempt}
onClick={() => act('tryoutput')}>
{outputAttempt ? 'On' : 'Off'}
</Button>
}>
<Box color={outputState}>
{outputting
? 'Sending'
: charge > 0
? 'Not Sending'
: 'No Charge'}
</Box>
</LabeledList.Item>
<LabeledList.Item label="Target Output">
<Flex inline width="100%">
<Flex.Item>
<Button
icon="fast-backward"
disabled={outputLevel === 0}
onClick={() => act('output', {
target: 'min',
})} />
<Button
icon="backward"
disabled={outputLevel === 0}
onClick={() => act('output', {
adjust: -10000,
})} />
</Flex.Item>
<Flex.Item grow={1} mx={1}>
<Slider
value={outputLevel / POWER_MUL}
minValue={0}
maxValue={outputLevelMax / POWER_MUL}
step={5}
stepPixelSize={4}
format={value => formatPower(value * POWER_MUL, 1)}
onChange={(e, value) => act('output', {
target: value * POWER_MUL,
})} />
</Flex.Item>
<Flex.Item>
<Button
icon="forward"
disabled={outputLevel === outputLevelMax}
onClick={() => act('output', {
adjust: 10000,
})} />
<Button
icon="fast-forward"
disabled={outputLevel === outputLevelMax}
onClick={() => act('output', {
target: 'max',
})} />
</Flex.Item>
</Flex>
</LabeledList.Item>
<LabeledList.Item label="Outputting">
{formatPower(outputUsed)}
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,66 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, Section } from '../components';
import { Window } from '../layouts';
export const SpawnersMenu = (props, context) => {
const { act, data } = useBackend(context);
const spawners = data.spawners || [];
return (
<Window
resizable>
<Window.Content scrollable>
<Section>
{spawners.map(spawner => (
<Section
mb={0.5}
key={spawner.name}
title={spawner.name + ' (' + spawner.amount_left + ' left)'}
level={2}
buttons={(
<Fragment>
<Button
icon="chevron-circle-right"
content="Jump"
onClick={() => act('jump', {
ID: spawner.uids,
})} />
<Button
icon="chevron-circle-right"
content="Spawn"
onClick={() => act('spawn', {
ID: spawner.uids,
})} />
</Fragment>
)}>
<Box
style={{ "white-space": "pre-wrap" }} // preserve newline
mb={1}
fontSize="16px">
{spawner.desc}
</Box>
{!!spawner.fluff && (
<Box // lighter grey than default grey for better contrast.
style={{ "white-space": "pre-wrap" }}
textColor="#878787"
fontSize="14px">
{spawner.fluff}
</Box>
)}
{!!spawner.important_info && (
<Box
style={{ "white-space": "pre-wrap" }}
mt={1}
bold
color="red"
fontSize="18px">
{spawner.important_info}
</Box>
)}
</Section>
))}
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,91 @@
import { useBackend } from '../backend';
import { Button, LabeledList, NoticeBox, Section } from '../components';
import { Window } from '../layouts';
export const TransferValve = (props, context) => {
const { act, data } = useBackend(context);
const {
tank_one,
tank_two,
attached_device,
valve,
} = data;
return (
<Window>
<Window.Content>
<Section>
<LabeledList>
<LabeledList.Item label="Valve Status">
<Button
icon={valve ? "unlock" : "lock"}
content={valve ? "Open" : "Closed"}
disabled={!tank_one || !tank_two}
onClick={() => act('toggle')} />
</LabeledList.Item>
</LabeledList>
</Section>
<Section
title="Assembly"
buttons={(
<Button
textAlign="center"
width="150px"
icon="cog"
content="Configure Assembly"
disabled={(!attached_device)}
onClick={() => act('device')} />
)}>
<LabeledList>
{attached_device ? (
<LabeledList.Item label="Attachment">
<Button
icon="eject"
content={attached_device}
disabled={!attached_device}
onClick={() => act('remove_device')} />
</LabeledList.Item>
) : (
<NoticeBox textAlign="center">
Attach Assembly
</NoticeBox>
)}
</LabeledList>
</Section>
<Section title="Attachment One">
<LabeledList>
{tank_one ? (
<LabeledList.Item label="Attachment">
<Button
icon="eject"
content={tank_one}
disabled={!tank_one}
onClick={() => act('tankone')} />
</LabeledList.Item>
) : (
<NoticeBox textAlign="center">
Attach Tank
</NoticeBox>
)}
</LabeledList>
</Section>
<Section title="Attachment Two">
<LabeledList>
{tank_two ? (
<LabeledList.Item label="Attachment">
<Button
icon="eject"
content={tank_two}
disabled={!tank_two}
onClick={() => act('tanktwo')} />
</LabeledList.Item>
) : (
<NoticeBox textAlign="center">
Attach Tank
</NoticeBox>
)}
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
+191
View File
@@ -0,0 +1,191 @@
import { classes } from 'common/react';
import { useBackend } from '../backend';
import { Box, Button, Section, Table } from '../components';
import { Window } from '../layouts';
const VendingRow = (props, context) => {
const { act, data } = useBackend(context);
const {
product,
productStock,
productImage,
} = props;
const {
chargesMoney,
user,
userMoney,
vend_ready,
coin_name,
inserted_item_name,
} = data;
const free = (
!chargesMoney
|| product.price === 0
);
let buttonText = "ERROR!";
let rowIcon = "";
if (product.req_coin) {
buttonText = "COIN";
rowIcon = "circle";
} else if (free) {
buttonText = "FREE";
rowIcon = "arrow-circle-down";
} else {
buttonText = product.price;
rowIcon = "shopping-cart";
}
let buttonDisabled = (
!vend_ready
|| (!coin_name && product.req_coin)
|| productStock === 0
|| (!free && product.price > userMoney)
);
return (
<Table.Row>
<Table.Cell collapsing>
<img
src={`data:image/jpeg;base64,${productImage}`}
style={{
'vertical-align': 'middle',
width: '32px',
margin: '0px',
'margin-left': '0px',
}} />
</Table.Cell>
<Table.Cell bold>
{product.name}
</Table.Cell>
<Table.Cell collapsing textAlign="center">
<Box
color={(
productStock <= 0 && 'bad'
|| productStock <= (product.max_amount / 2) && 'average'
|| 'good'
)}>
{productStock} in stock
</Box>
</Table.Cell>
<Table.Cell collapsing textAlign="center">
<Button
fluid
disabled={buttonDisabled}
icon={rowIcon}
content={buttonText}
textAlign="left"
onClick={() => act('vend', {
'inum': product.inum,
})} />
</Table.Cell>
</Table.Row>
);
};
export const Vending = (props, context) => {
const { act, data } = useBackend(context);
const {
user,
guestNotice,
userMoney,
chargesMoney,
product_records = [],
coin_records = [],
hidden_records = [],
stock,
vend_ready,
coin_name,
inserted_item_name,
panel_open,
speaker,
imagelist,
} = data;
let inventory;
inventory = [
...product_records,
...coin_records,
];
if (data.extended_inventory) {
inventory = [
...inventory,
...hidden_records,
];
}
// Just in case we still have undefined values in the list
inventory = inventory.filter(item => !!item);
return (
<Window
title="Vending Machine"
resizable>
<Window.Content scrollable>
{!!chargesMoney && (
<Section title="User">
{user && (
<Box>
Welcome, <b>{user.name}</b>,
{' '}
<b>{user.job || 'Unemployed'}</b>!
<br />
Your balance is <b>{userMoney} credits</b>.
</Box>
) || (
<Box color="light-grey">
{guestNotice}
</Box>
)}
</Section>
)}
{!!coin_name && (
<Section
title="Coin"
buttons={(
<Button
fluid
icon="eject"
content="Remove Coin"
onClick={() => act('remove_coin', {})} />
)}>
<Box>
{coin_name}
</Box>
</Section>
)}
{!!inserted_item_name && (
<Section
title="Item"
buttons={(
<Button
fluid
icon="eject"
content="Eject Item"
onClick={() => act('eject_item', {})} />
)}>
<Box>
{inserted_item_name}
</Box>
</Section>
)}
{!!panel_open && (
<Section title="Maintenance">
<Button
icon={speaker ? "check" : "volume-mute"}
selected={speaker}
content="Speaker"
textAlign="left"
onClick={() => act('toggle_voice', {})} />
</Section>
)}
<Section title="Products">
<Table>
{inventory.map(product => (
<VendingRow
key={product.name}
product={product}
productStock={stock[product.name]}
productImage={imagelist[product.path]} />
))}
</Table>
</Section>
</Window.Content>
</Window>
);
};
File diff suppressed because one or more lines are too long