Merge pull request #8720 from ShadowLarkens/tgui_cargo

TGUI Cargo
This commit is contained in:
Novacat
2020-08-18 09:48:13 -04:00
committed by GitHub
45 changed files with 3694 additions and 2150 deletions

View File

@@ -2,4 +2,7 @@ GLOBAL_LIST_INIT(speech_toppings, list("|" = "i", "+" = "b", "_" = "u"))
GLOBAL_LIST_EMPTY(meteor_list)
/// List of wire colors for each object type of that round. One for airlocks, one for vendors, etc.
GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the `holder_type` as the key, and a list of colors as the value.
GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the `holder_type` as the key, and a list of colors as the value.
// Reference list for disposal sort junctions. Filled up by sorting junction's New()
GLOBAL_LIST_EMPTY(tagger_locations)

View File

@@ -453,4 +453,22 @@ proc/TextPreview(var/string,var/len=40)
. += .(rest)
#define gender2text(gender) capitalize(gender)
#define gender2text(gender) capitalize(gender)
/// Used to get a properly sanitized input, of max_length
/// no_trim is self explanatory but it prevents the input from being trimed if you intend to parse newlines or whitespace.
/proc/stripped_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
var/name = input(user, message, title, default) as text|null
if(no_trim)
return copytext(html_encode(name), 1, max_length)
else
return trim(html_encode(name), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into &lt;)
// Used to get a properly sanitized multiline input, of max_length
/proc/stripped_multiline_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
var/name = input(user, message, title, default) as message|null
if(no_trim)
return copytext(html_encode(name), 1, max_length)
else
return trim(html_encode(name), max_length)

View File

@@ -36,7 +36,7 @@
if(!allowed(user))
return
user.set_machine(src)
ui_interact(user)
tgui_interact(user)
return
/obj/machinery/computer/supplycomp/emag_act(var/remaining_charges, var/mob/user)
@@ -44,24 +44,27 @@
to_chat(user, "<span class='notice'>Special supplies unlocked.</span>")
authorization |= SUP_CONTRABAND
req_access = list()
can_order_contraband = TRUE
return 1
// TGUI
/obj/machinery/computer/supplycomp/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SupplyConsole", name)
ui.open()
/obj/machinery/computer/supplycomp/ui_interact(mob/user, ui_key = "supply_records", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null)
var/data[0]
var/shuttle_status[0] // Supply shuttle status
var/pack_list[0] // List of supply packs within the active_category
var/orders[0]
var/receipts[0]
/obj/machinery/computer/supplycomp/tgui_data(mob/user)
var/list/data = ..()
var/list/shuttle_status = list()
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
shuttle_status["mode"] = SUP_SHUTTLE_TRANSIT
shuttle_status["time"] = shuttle.eta_minutes()
shuttle_status["time"] = shuttle.eta_seconds()
else
shuttle_status["time"] = 0
@@ -107,149 +110,192 @@
shuttle_status["engine"] = "Engaged"
else
shuttle["mode"] = SUP_SHUTTLE_ERROR
for(var/pack_name in SSsupply.supply_pack)
var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
if(P.group == active_category)
var/list/pack = list(
"name" = P.name,
"cost" = P.cost,
"contraband" = P.contraband,
"manifest" = uniquelist(P.manifest),
"random" = P.num_contained,
"expand" = 0,
"ref" = "\ref[P]"
)
if(P in expanded_packs)
pack["expand"] = 1
pack_list[++pack_list.len] = pack
shuttle_status["mode"] = SUP_SHUTTLE_ERROR
// Compile user-side orders
// Status determines which menus the entry will display in
// Organized in field-entry list for iterative display
// List is nested so both the list of orders, and the list of elements in each order, can be iterated over
var/list/orders = list()
for(var/datum/supply_order/S in SSsupply.order_history)
orders[++orders.len] = list(
"ref" = "\ref[S]",
"status" = S.status,
"entries" = list(
list("field" = "Supply Pack", "entry" = S.name),
list("field" = "Cost", "entry" = S.cost),
list("field" = "Index", "entry" = S.index),
list("field" = "Reason", "entry" = S.comment),
list("field" = "Ordered by", "entry" = S.ordered_by),
list("field" = "Ordered at", "entry" = S.ordered_at),
list("field" = "Approved by", "entry" = S.approved_by),
list("field" = "Approved at", "entry" = S.approved_at)
)
)
orders.Add(list(list(
"ref" = "\ref[S]",
"status" = S.status,
"cost" = S.cost,
"entries" = list(
list("field" = "Supply Pack", "entry" = S.name),
list("field" = "Cost", "entry" = S.cost),
list("field" = "Index", "entry" = S.index),
list("field" = "Reason", "entry" = S.comment),
list("field" = "Ordered by", "entry" = S.ordered_by),
list("field" = "Ordered at", "entry" = S.ordered_at),
list("field" = "Approved by", "entry" = S.approved_by),
list("field" = "Approved at", "entry" = S.approved_at)
)
)))
// Compile exported crates
var/list/receipts = list()
for(var/datum/exported_crate/E in SSsupply.exported_crates)
receipts[++receipts.len] = list(
"ref" = "\ref[E]",
"contents" = E.contents,
"error" = E.contents["error"],
"title" = list(
list("field" = "Name", "entry" = E.name),
list("field" = "Value", "entry" = E.value)
)
receipts.Add(list(list(
"ref" = "\ref[E]",
"contents" = E.contents,
"error" = E.contents["error"],
"title" = list(
list("field" = "Name", "entry" = E.name),
list("field" = "Value", "entry" = E.value)
)
)))
data["user"] = "\ref[user]"
data["currentTab"] = menu_tab // Communicator compatibility, controls which menu is in use
data["shuttle_auth"] = (authorization & SUP_SEND_SHUTTLE) // Whether this ui is permitted to control the supply shuttle
data["order_auth"] = (authorization & SUP_ACCEPT_ORDERS) // Whether this ui is permitted to accept/deny requested orders
data["shuttle"] = shuttle_status
data["supply_points"] = SSsupply.points
data["categories"] = all_supply_groups
data["active_category"] = active_category
data["supply_packs"] = pack_list
data["orders"] = orders
data["receipts"] = receipts
data["contraband"] = can_order_contraband || (authorization & SUP_CONTRABAND)
data["modal"] = tgui_modal_data(src)
return data
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, 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, "supply_records.tmpl", "Supply Console", 475, 700, state = key_state)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every 20 Master Controller tick
ui.set_auto_update(20) // Longer term to reduce the rate of data collection and processing
/obj/machinery/computer/supplycomp/tgui_static_data(mob/user)
var/list/data = ..()
var/list/pack_list = list()
for(var/pack_name in SSsupply.supply_pack)
var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
var/list/pack = list(
"name" = P.name,
"cost" = P.cost,
"group" = P.group,
"contraband" = P.contraband,
"manifest" = uniquelist(P.manifest),
"random" = P.num_contained,
"ref" = "\ref[P]"
)
pack_list.Add(list(pack))
data["supply_packs"] = pack_list
data["categories"] = all_supply_groups
return data
/obj/machinery/computer/supplycomp/Topic(href, href_list)
if(!SSsupply)
to_world_log("## ERROR: The SSsupply datum is missing.")
return
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (!shuttle)
to_world_log("## ERROR: The supply shuttle datum is missing.")
return
/obj/machinery/computer/supplycomp/tgui_act(action, params)
if(..())
return 1
return TRUE
if(!SSsupply)
log_runtime(EXCEPTION("## ERROR: The SSsupply datum is missing."))
return TRUE
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(!shuttle)
log_runtime(EXCEPTION("## ERROR: The supply shuttle datum is missing."))
return TRUE
if(isturf(loc) && ( in_range(src, usr) || istype(usr, /mob/living/silicon) ) )
usr.set_machine(src)
if(tgui_modal_act(src, action, params))
return TRUE
// NEW TOPIC
switch(action)
if("view_crate")
var/datum/supply_pack/P = locate(params["crate"])
if(!istype(P))
return FALSE
var/list/payload = list(
"name" = P.name,
"cost" = P.cost,
"manifest" = uniquelist(P.manifest),
"ref" = "\ref[P]",
"random" = P.num_contained,
)
tgui_modal_message(src, action, "", null, payload)
. = TRUE
if("request_crate_multi")
var/datum/supply_pack/S = locate(params["ref"])
// Switch menu
if(href_list["switch_tab"])
menu_tab = href_list["switch_tab"]
// Invalid ref
if(!istype(S))
return FALSE
if(href_list["active_category"])
active_category = href_list["active_category"]
if(href_list["pack_ref"])
var/datum/supply_pack/S = locate(href_list["pack_ref"])
// Invalid ref
if(!istype(S))
return
// Expand the supply pack's contents
if(href_list["expand"])
expanded_packs ^= S
// Make a request for the pack
if(href_list["request"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(S.contraband && !(authorization & SUP_CONTRABAND || can_order_contraband))
return FALSE
if(world.time < reqtime)
visible_message("<span class='warning'>[src]'s monitor flashes, \"[reqtime - world.time] seconds remaining until another requisition form may be printed.\"</span>")
return
return FALSE
var/amount = clamp(input(usr, "How many crates? (0 to 20)") as num|null, 0, 20)
if(!amount)
return FALSE
var/timeout = world.time + 600
var/reason = sanitize(input(user, "Reason:","Why do you require this item?","") as null|text)
var/reason = sanitize(input(usr, "Reason:","Why do you require this item?","") as null|text)
if(world.time > timeout)
to_chat(user, "<span class='warning'>Error. Request timed out.</span>")
return
to_chat(usr, "<span class='warning'>Error. Request timed out.</span>")
return FALSE
if(!reason)
return
return FALSE
SSsupply.create_order(S, user, reason)
for(var/i in 1 to amount)
SSsupply.create_order(S, usr, reason)
var/idname = "*None Provided*"
var/idrank = "*None Provided*"
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
idname = H.get_authentification_name()
idrank = H.get_assignment()
else if(issilicon(user))
idname = user.real_name
else if(issilicon(usr))
idname = usr.real_name
idrank = "Stationbound synthetic"
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc)
reqform.name = "Requisition Form - [S.name]"
reqform.info += "<h3>[station_name()] Supply Requisition Form</h3><hr>"
reqform.info += "INDEX: #[SSsupply.ordernum]<br>"
reqform.info += "REQUESTED BY: [idname]<br>"
reqform.info += "RANK: [idrank]<br>"
reqform.info += "REASON: [reason]<br>"
reqform.info += "SUPPLY CRATE TYPE: [S.name]<br>"
reqform.info += "ACCESS RESTRICTION: [get_access_desc(S.access)]<br>"
reqform.info += "AMOUNT: [amount]<br>"
reqform.info += "CONTENTS:<br>"
reqform.info += S.get_html_manifest()
reqform.info += "<hr>"
reqform.info += "STAMP BELOW TO APPROVE THIS REQUISITION:<br>"
reqform.update_icon() //Fix for appearing blank when printed.
reqtime = (world.time + 5) % 1e5
. = TRUE
if("request_crate")
var/datum/supply_pack/S = locate(params["ref"])
// Invalid ref
if(!istype(S))
return FALSE
if(S.contraband && !(authorization & SUP_CONTRABAND || can_order_contraband))
return FALSE
if(world.time < reqtime)
visible_message("<span class='warning'>[src]'s monitor flashes, \"[reqtime - world.time] seconds remaining until another requisition form may be printed.\"</span>")
return FALSE
var/timeout = world.time + 600
var/reason = sanitize(input(usr, "Reason:","Why do you require this item?","") as null|text)
if(world.time > timeout)
to_chat(usr, "<span class='warning'>Error. Request timed out.</span>")
return FALSE
if(!reason)
return FALSE
SSsupply.create_order(S, usr, reason)
var/idname = "*None Provided*"
var/idrank = "*None Provided*"
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
idname = H.get_authentification_name()
idrank = H.get_assignment()
else if(issilicon(usr))
idname = usr.real_name
idrank = "Stationbound synthetic"
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc)
@@ -268,24 +314,19 @@
reqform.update_icon() //Fix for appearing blank when printed.
reqtime = (world.time + 5) % 1e5
if(href_list["order_ref"])
var/datum/supply_order/O = locate(href_list["order_ref"])
// Invalid ref
if(!istype(O))
return
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(href_list["edit"])
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
. = TRUE
// Approving Orders
if("edit_order_value")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
var/new_val = sanitize(input(usr, params["edit"], "Enter the new value for this field:", params["default"]) as null|text)
if(!new_val)
return
return FALSE
switch(href_list["edit"])
switch(params["edit"])
if("Supply Pack")
O.name = new_val
@@ -313,68 +354,95 @@
if("Approved at")
O.approved_at = new_val
. = TRUE
if("approve_order")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.approve_order(O, usr)
. = TRUE
if("deny_order")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.deny_order(O, usr)
. = TRUE
if("delete_order")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.delete_order(O, usr)
. = TRUE
if("clear_all_requests")
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.deny_all_pending(usr)
. = TRUE
// Exports
if("export_edit_field")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
var/list/L = E.contents[params["index"]]
var/field = alert(usr, "Select which field to edit", , "Name", "Quantity", "Value")
if(href_list["approve"])
SSsupply.approve_order(O, user)
if(href_list["deny"])
SSsupply.deny_order(O, user)
if(href_list["delete"])
SSsupply.delete_order(O, user)
if(href_list["clear_all_requests"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
SSsupply.deny_all_pending(user)
if(href_list["export_ref"])
var/datum/exported_crate/E = locate(href_list["export_ref"])
// Invalid ref
if(!istype(E))
return
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(href_list["index"])
var/list/L = E.contents[href_list["index"]]
if(href_list["edit"])
var/field = alert(user, "Select which field to edit", , "Name", "Quantity", "Value")
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
if(!new_val)
return
switch(field)
if("Name")
L["object"] = new_val
if("Quantity")
var/num = text2num(new_val)
if(num)
L["quantity"] = num
if("Value")
var/num = text2num(new_val)
if(num)
L["value"] = num
if(href_list["delete"])
E.contents.Cut(href_list["index"], href_list["index"] + 1)
// Else clause means they're editing/deleting the whole export report, rather than a specific item in it
else if(href_list["edit"])
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
var/new_val = sanitize(input(usr, field, "Enter the new value for this field:", L[lowertext(field)]) as null|text)
if(!new_val)
return
switch(href_list["edit"])
switch(field)
if("Name")
L["object"] = new_val
if("Quantity")
var/num = text2num(new_val)
if(num)
L["quantity"] = num
if("Value")
var/num = text2num(new_val)
if(num)
L["value"] = num
. = TRUE
if("export_delete_field")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
E.contents.Cut(params["index"], params["index"] + 1)
. = TRUE
if("export_add_field")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.add_export_item(E, usr)
. = TRUE
if("export_edit")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
var/new_val = sanitize(input(usr, params["edit"], "Enter the new value for this field:", params["default"]) as null|text)
if(!new_val)
return
switch(params["edit"])
if("Name")
E.name = new_val
@@ -382,39 +450,39 @@
var/num = text2num(new_val)
if(num)
E.value = num
. = TRUE
if("export_delete")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.delete_export(E, usr)
. = TRUE
if("send_shuttle")
switch(params["mode"])
if("send_away")
if (shuttle.forbidden_atoms_check())
to_chat(usr, "<span class='warning'>For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.</span>")
else
shuttle.launch(src)
to_chat(usr, "<span class='notice'>Initiating launch sequence.</span>")
else if(href_list["delete"])
SSsupply.delete_export(E, user)
if("send_to_station")
shuttle.launch(src)
to_chat(usr, "<span class='notice'>The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.</span>")
else if(href_list["add_item"])
SSsupply.add_export_item(E, user)
if("cancel_shuttle")
shuttle.cancel_launch(src)
switch(href_list["send_shuttle"])
if("send_away")
if (shuttle.forbidden_atoms_check())
to_chat(usr, "<span class='warning'>For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.</span>")
else
shuttle.launch(src)
to_chat(usr, "<span class='notice'>Initiating launch sequence.</span>")
if("send_to_station")
shuttle.launch(src)
to_chat(usr, "<span class='notice'>The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.</span>")
if("cancel_shuttle")
shuttle.cancel_launch(src)
if("force_shuttle")
shuttle.force_launch(src)
if("force_shuttle")
shuttle.force_launch(src)
. = TRUE
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/supplycomp/proc/post_signal(var/command)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
if(!frequency) return

View File

@@ -38,7 +38,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
// 0 = no new message
// 1 = normal priority
// 2 = high priority
var/screen = RCS_MAINMENU
var/screen = RCS_VIEWMSGS
var/silent = 0 // set to 1 for it not to beep all the time
// var/hackState = 0
// 0 = not hacked
@@ -105,10 +105,16 @@ var/list/obj/machinery/requests_console/allConsoles = list()
if(..(user))
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/requests_console/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/requests_console/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "RequestConsole", "[department] Request Console")
ui.open()
/obj/machinery/requests_console/tgui_data(mob/user)
var/list/data = ..()
data["department"] = department
data["screen"] = screen
data["message_log"] = message_log
@@ -122,93 +128,103 @@ var/list/obj/machinery/requests_console/allConsoles = list()
data["message"] = message
data["recipient"] = recipient
data["priortiy"] = priority
data["priority"] = priority
data["msgStamped"] = msgStamped
data["msgVerified"] = msgVerified
data["announceAuth"] = announceAuth
return data
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "request_console.tmpl", "[department] Request Console", 520, 410)
ui.set_initial_data(data)
ui.open()
/obj/machinery/requests_console/Topic(href, href_list)
if(..()) return
usr.set_machine(src)
/obj/machinery/requests_console/tgui_act(action, list/params)
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if("write")
if(reject_bad_text(params["write"]))
recipient = params["write"] //write contains the string of the receiving department's name
if(reject_bad_text(href_list["write"]))
recipient = href_list["write"] //write contains the string of the receiving department's name
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
screen = RCS_MESSAUTH
switch(params["priority"])
if(1)
priority = 1
if(2)
priority = 2
else
priority = 0
else
reset_message(1)
. = TRUE
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
screen = RCS_MESSAUTH
switch(href_list["priority"])
if("1") priority = 1
if("2") priority = 2
else priority = 0
else
if("writeAnnouncement")
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
else
reset_message(1)
. = TRUE
if("sendAnnouncement")
if(!announcementConsole)
return FALSE
announcement.Announce(message, msg_sanitized = 1)
reset_message(1)
. = TRUE
if(href_list["writeAnnouncement"])
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
else
reset_message(1)
if("department")
if(!message)
return FALSE
var/log_msg = message
var/pass = 0
screen = RCS_SENTFAIL
for(var/obj/machinery/message_server/MS in machines)
if(!MS.active)
continue
MS.send_rc_message(ckey(params["department"]), department, log_msg, msgStamped, msgVerified, priority)
pass = 1
if(pass)
screen = RCS_SENTPASS
message_log += list(list("Message sent to [recipient]", "[message]"))
else
audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
. = TRUE
if(href_list["sendAnnouncement"])
if(!announcementConsole) return
announcement.Announce(message, msg_sanitized = 1)
reset_message(1)
//Handle printing
if("print")
var/msg = message_log[text2num(params["print"])];
if(msg)
msg = "<b>[msg[1]]:</b><br>[msg[2]]"
msg = replacetext(msg, "<BR>", "\n")
msg = strip_html_properly(msg)
var/obj/item/weapon/paper/R = new(src.loc)
R.name = "[department] Message"
R.info = "<H3>[department] Requests Console</H3><div>[msg]</div>"
. = TRUE
if(href_list["department"] && message)
var/log_msg = message
var/pass = 0
screen = RCS_SENTFAIL
for (var/obj/machinery/message_server/MS in machines)
if(!MS.active) continue
MS.send_rc_message(ckey(href_list["department"]),department,log_msg,msgStamped,msgVerified,priority)
pass = 1
if(pass)
screen = RCS_SENTPASS
message_log += "<B>Message sent to [recipient]</B><BR>[message]"
else
audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
//Handle screen switching
if("setScreen")
var/tempScreen = text2num(params["setScreen"])
if(tempScreen == RCS_ANNOUNCE && !announcementConsole)
return
if(tempScreen == RCS_VIEWMSGS)
for (var/obj/machinery/requests_console/Console in allConsoles)
if(Console.department == department)
Console.newmessagepriority = 0
Console.icon_state = "req_comp0"
Console.set_light(1)
if(tempScreen == RCS_MAINMENU)
reset_message()
screen = tempScreen
. = TRUE
//Handle printing
if (href_list["print"])
var/msg = message_log[text2num(href_list["print"])];
if(msg)
msg = replacetext(msg, "<BR>", "\n")
msg = strip_html_properly(msg)
var/obj/item/weapon/paper/R = new(src.loc)
R.name = "[department] Message"
R.info = "<H3>[department] Requests Console</H3><div>[msg]</div>"
//Handle screen switching
if(href_list["setScreen"])
var/tempScreen = text2num(href_list["setScreen"])
if(tempScreen == RCS_ANNOUNCE && !announcementConsole)
return
if(tempScreen == RCS_VIEWMSGS)
for (var/obj/machinery/requests_console/Console in allConsoles)
if(Console.department == department)
Console.newmessagepriority = 0
Console.icon_state = "req_comp0"
Console.set_light(1)
if(tempScreen == RCS_MAINMENU)
reset_message()
screen = tempScreen
//Handle silencing the console
if(href_list["toggleSilent"])
silent = !silent
updateUsrDialog()
return
//Handle silencing the console
if("toggleSilent")
silent = !silent
. = TRUE
//err... hacking code, which has no reason for existing... but anyway... it was once supposed to unlock priority 3 messaging on that console (EXTREME priority...), but the code for that was removed.
/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob)
@@ -238,7 +254,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
if(screen == RCS_MESSAUTH)
var/obj/item/weapon/card/id/T = O
msgVerified = text("<font color='green'><b>Verified by [T.registered_name] ([T.assignment])</b></font>")
updateUsrDialog()
SStgui.update_uis(src)
if(screen == RCS_ANNOUNCE)
var/obj/item/weapon/card/id/ID = O
if(access_RC_announce in ID.GetAccess())
@@ -247,13 +263,13 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else
reset_message()
to_chat(user, "<span class='warning'>You are not authorized to send announcements.</span>")
updateUsrDialog()
SStgui.update_uis(src)
if(istype(O, /obj/item/weapon/stamp))
if(inoperable(MAINT)) return
if(screen == RCS_MESSAUTH)
var/obj/item/weapon/stamp/T = O
msgStamped = text("<font color='blue'><b>Stamped with the [T.name]</b></font>")
updateUsrDialog()
SStgui.update_uis(src)
return
/obj/machinery/requests_console/proc/reset_message(var/mainmenu = 0)

View File

@@ -11,6 +11,7 @@ var/list/GPS_list = list()
matter = list(DEFAULT_WALL_MATERIAL = 500)
var/gps_tag = "GEN0"
var/emped = FALSE
var/updating = TRUE // Lets users lock the UI so they don't have to deal with constantly shifting signals
var/tracking = FALSE // Will not show other signals or emit its own signal if false.
var/long_range = FALSE // If true, can see farther, depending on get_map_levels().
var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown.
@@ -66,7 +67,11 @@ var/list/GPS_list = list()
add_overlay("working")
/obj/item/device/gps/attack_self(mob/user)
display(user)
tgui_interact(user)
/obj/item/device/gps/examine(mob/user)
. = ..()
. += display()
// Compiles all the data not available directly from the GPS
// Like the positions and directions to all other GPS units
@@ -117,12 +122,12 @@ var/list/GPS_list = list()
return dat
/obj/item/device/gps/proc/display(mob/user)
/obj/item/device/gps/proc/display()
if(!tracking)
to_chat(user, "The device is off. Alt-click it to turn it on.")
. = "The device is off. Alt-click it to turn it on."
return
if(emped)
to_chat(user, "It's busted!")
. = "It's busted!"
return
var/list/dat = list()
@@ -143,8 +148,7 @@ var/list/GPS_list = list()
else
dat += "No other signals detected."
var/result = dat.Join("<br>")
to_chat(user, result)
. = dat
/obj/item/device/gps/Topic(var/href, var/list/href_list)
if(..())
@@ -168,6 +172,85 @@ var/list/GPS_list = list()
hide_signal = !hide_signal
to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.")
/obj/item/device/gps/tgui_interact(mob/user, datum/tgui/ui)
if(emped)
to_chat(user, "<span class='hear'>[src] fizzles weakly.</span>")
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Gps", name)
ui.open()
ui.set_autoupdate(updating)
/obj/item/device/gps/tgui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gps_tag
data["updating"] = updating
data["globalmode"] = !local_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = list(curr.x, curr.y, curr.z)
data["currentCoordsText"] = "[curr.x], [curr.y], [using_map.get_zlevel_name(curr.z)]"
data["zLevelDetection"] = using_map.get_map_levels(curr.z, long_range)
var/list/signals = list()
data["signals"] = list()
for(var/obj/item/device/gps/G in GPS_list - src)
if(!G.tracking || G.emped || G.hide_signal)
continue
var/turf/T = get_turf(G)
if(!T)
continue
if(local_mode && curr.z != T.z)
continue
if(!(T.z in data["zLevelDetection"]))
continue
var/list/signal = list()
signal["entrytag"] = G.gps_tag //Name or 'tag' of the GPS
signal["coords"] = list(T.x, T.y, T.z)
signal["coordsText"] = "[T.x], [T.y], [using_map.get_zlevel_name(T.z)]"
if(T.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, T), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, T)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/device/gps/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("rename")
var/a = stripped_input(usr, "Please enter desired tag.", name, gps_tag, 20)
if(!a)
return
gps_tag = a
name = "global positioning system ([gps_tag])"
. = TRUE
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
local_mode = !local_mode
. = TRUE
/obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these.
tracking = TRUE
@@ -291,10 +374,10 @@ var/list/GPS_list = list()
/obj/item/device/gps/syndie/display(mob/user)
if(!tracking)
to_chat(user, "The device is off. Alt-click it to turn it on.")
. = "The device is off. Alt-click it to turn it on."
return
if(emped)
to_chat(user, "It's busted!")
. = "It's busted!"
return
var/list/dat = list()
@@ -312,5 +395,4 @@ var/list/GPS_list = list()
else
dat += "No other signals detected."
var/result = dat.Join("<br>")
to_chat(user, result)
. = dat

View File

@@ -130,9 +130,6 @@ var/custom_event_msg = null
var/DBConnection/dbcon = new() // Feedback database (New database)
var/DBConnection/dbcon_old = new() // /tg/station database (Old database) -- see the files in the SQL folder for information on what goes where.
// Reference list for disposal sort junctions. Filled up by sorting junction's New()
/var/list/tagger_locations = list()
// Added for Xenoarchaeology, might be useful for other stuff.
var/global/list/alphabet_uppercase = list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")

View File

@@ -33,7 +33,10 @@
/obj/machinery/mineral/processing_unit_console/attack_hand(mob/user)
if(..())
return
interact(user)
if(!allowed(user))
to_chat(user, "<span class='warning'>Access denied.</span>")
return
tgui_interact(user)
/obj/machinery/mineral/processing_unit_console/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/card/id))
@@ -42,97 +45,89 @@
if(!inserted_id && user.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(user)
SStgui.update_uis(src)
return
..()
/obj/machinery/mineral/processing_unit_console/interact(mob/user)
if(..())
return
/obj/machinery/mineral/processing_unit_console/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MiningOreProcessingConsole", name)
ui.open()
if(!allowed(user))
to_chat(user, "<span class='warning'>Access denied.</span>")
return
/obj/machinery/mineral/processing_unit_console/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["unclaimedPoints"] = machine.points
user.set_machine(src)
var/dat = "<h1>Ore processor console</h1>"
dat += "Current unclaimed points: [machine.points]<br>"
if(istype(inserted_id))
dat += "You have [inserted_id.mining_points] mining points collected. <A href='?src=\ref[src];choice=eject'>Eject ID.</A><br>"
dat += "<A href='?src=\ref[src];choice=claim'>Claim points.</A><br>"
if(inserted_id)
data["has_id"] = TRUE
data["id"] = list(
"name" = inserted_id.registered_name,
"points" = inserted_id.mining_points,
)
else
dat += "No ID inserted. <A href='?src=\ref[src];choice=insert'>Insert ID.</A><br>"
dat += "<hr><table>"
data["has_id"] = FALSE
data["ores"] = list()
for(var/ore in machine.ores_processing)
if(!machine.ores_stored[ore] && !show_all_ores) continue
if(!machine.ores_stored[ore] && !show_all_ores)
continue
var/ore/O = ore_data[ore]
if(!O) continue
dat += "<tr><td width = 40><b>[capitalize(O.display_name)]</b></td><td width = 30>[machine.ores_stored[ore]]</td><td width = 100>"
if(machine.ores_processing[ore])
switch(machine.ores_processing[ore])
if(PROCESS_NONE)
dat += "<font color='red'>not processing</font>"
if(PROCESS_SMELT)
dat += "<font color='orange'>smelting</font>"
if(PROCESS_COMPRESS)
dat += "<font color='blue'>compressing</font>"
if(PROCESS_ALLOY)
dat += "<font color='gray'>alloying</font>"
else
dat += "<font color='red'>not processing</font>"
dat += ".</td><td width = 30><a href='?src=\ref[src];toggle_smelting=[ore]'>\[change\]</a></td></tr>"
if(!O)
continue
data["ores"].Add(list(list(
"ore" = ore,
"name" = O.display_name,
"amount" = machine.ores_stored[ore],
"processing" = machine.ores_processing[ore] ? machine.ores_processing[ore] : 0,
)))
dat += "</table><hr>"
dat += "Currently displaying [show_all_ores ? "all ore types" : "only available ore types"]. <A href='?src=\ref[src];toggle_ores=1'>\[[show_all_ores ? "show less" : "show more"]\]</a></br>"
dat += "The ore processor is currently <A href='?src=\ref[src];toggle_power=1'>[(machine.active ? "<font color='green'>processing</font>" : "<font color='red'>disabled</font>")]</a>."
user << browse(dat, "window=processor_console;size=400x500")
onclose(user, "processor_console")
return
data["showAllOres"] = show_all_ores
data["power"] = machine.active
/obj/machinery/mineral/processing_unit_console/Topic(href, href_list)
return data
/obj/machinery/mineral/processing_unit_console/tgui_act(action, list/params)
if(..())
return 1
usr.set_machine(src)
src.add_fingerprint(usr)
return TRUE
if(href_list["toggle_smelting"])
var/choice = input("What setting do you wish to use for processing [href_list["toggle_smelting"]]?") as null|anything in list("Smelting","Compressing","Alloying","Nothing")
if(!choice) return
switch(choice)
if("Nothing") choice = PROCESS_NONE
if("Smelting") choice = PROCESS_SMELT
if("Compressing") choice = PROCESS_COMPRESS
if("Alloying") choice = PROCESS_ALLOY
machine.ores_processing[href_list["toggle_smelting"]] = choice
if(href_list["toggle_power"])
machine.active = !machine.active
if(href_list["toggle_ores"])
show_all_ores = !show_all_ores
if(href_list["choice"])
if(istype(inserted_id))
if(href_list["choice"] == "eject")
usr.put_in_hands(inserted_id)
inserted_id = null
if(href_list["choice"] == "claim")
add_fingerprint(usr)
switch(action)
if("toggleSmelting")
var/ore = params["ore"]
var/new_setting = params["set"]
if(new_setting == null)
new_setting = input("What setting do you wish to use for processing [ore]]?") as null|anything in list("Smelting","Compressing","Alloying","Nothing")
if(!new_setting)
return
switch(new_setting)
if("Nothing") new_setting = PROCESS_NONE
if("Smelting") new_setting = PROCESS_SMELT
if("Compressing") new_setting = PROCESS_COMPRESS
if("Alloying") new_setting = PROCESS_ALLOY
machine.ores_processing[ore] = new_setting
. = TRUE
if("power")
machine.active = !machine.active
. = TRUE
if("showAllOres")
show_all_ores = !show_all_ores
. = TRUE
if("logoff")
if(!inserted_id)
return
usr.put_in_hands(inserted_id)
inserted_id = null
. = TRUE
if("claim")
if(istype(inserted_id))
if(access_mining_station in inserted_id.access)
inserted_id.mining_points += machine.points
machine.points = 0
else
to_chat(usr, "<span class='warning'>Required access not found.</span>")
else if(href_list["choice"] == "insert")
. = TRUE
if("insert")
var/obj/item/weapon/card/id/I = usr.get_active_hand()
if(istype(I))
usr.drop_item()
@@ -140,9 +135,9 @@
inserted_id = I
else
to_chat(usr, "<span class='warning'>No valid ID.</span>")
src.updateUsrDialog()
return
. = TRUE
else
return FALSE
/**********************Mineral processing unit**************************/

View File

@@ -25,46 +25,47 @@
/obj/machinery/mineral/stacking_unit_console/attack_hand(mob/user)
add_fingerprint(user)
interact(user)
tgui_interact(user)
/obj/machinery/mineral/stacking_unit_console/interact(mob/user)
user.set_machine(src)
/obj/machinery/mineral/stacking_unit_console/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MiningStackingConsole", name)
ui.open()
var/dat
dat += text("<h1>Stacking unit console</h1><hr><table>")
/obj/machinery/mineral/stacking_unit_console/tgui_data(mob/user)
var/list/data = ..()
data["stacktypes"] = list()
for(var/stacktype in machine.stack_storage)
if(machine.stack_storage[stacktype] > 0)
dat += "<tr><td width = 150><b>[capitalize(stacktype)]:</b></td><td width = 30>[machine.stack_storage[stacktype]]</td><td width = 50><A href='?src=\ref[src];release_stack=[stacktype]'>\[release\]</a></td></tr>"
dat += "</table><hr>"
dat += text("<br>Stacking: [machine.stack_amt] <A href='?src=\ref[src];change_stack=1'>\[change\]</a><br><br>")
data["stacktypes"].Add(list(list(
"type" = stacktype,
"amt" = machine.stack_storage[stacktype],
)))
data["stackingAmt"] = machine.stack_amt
return data
user << browse("[dat]", "window=console_stacking_machine")
onclose(user, "console_stacking_machine")
/obj/machinery/mineral/stacking_unit_console/Topic(href, href_list)
/obj/machinery/mineral/stacking_unit_console/tgui_act(action, list/params)
if(..())
return 1
return TRUE
if(href_list["change_stack"])
var/choice = input("What would you like to set the stack amount to?") as null|anything in list(1,5,10,20,50)
if(!choice) return
machine.stack_amt = choice
switch(action)
if("change_stack")
machine.stack_amt = clamp(text2num(params["amt"]), 1, 50)
. = TRUE
if(href_list["release_stack"])
if(machine.stack_storage[href_list["release_stack"]] > 0)
var/stacktype = machine.stack_paths[href_list["release_stack"]]
var/obj/item/stack/material/S = new stacktype (get_turf(machine.output))
S.amount = machine.stack_storage[href_list["release_stack"]]
machine.stack_storage[href_list["release_stack"]] = 0
S.update_icon()
if("release_stack")
var/stack = params["stack"]
if(machine.stack_storage[stack] > 0)
var/stacktype = machine.stack_paths[stack]
var/obj/item/stack/material/S = new stacktype(get_turf(machine.output))
S.amount = machine.stack_storage[stack]
machine.stack_storage[stack] = 0
S.update_icon()
. = TRUE
src.add_fingerprint(usr)
src.updateUsrDialog()
return
add_fingerprint(usr)
/**********************Mineral stacking unit**************************/

View File

@@ -1,3 +1,9 @@
// Use this define to register something as a purchasable!
// * n — The proper name of the purchasable
// * o — The object type path of the purchasable to spawn
// * p — The price of the purchasable in mining points
#define EQUIPMENT(n, o, p) n = new /datum/data/mining_equipment(n, o, p)
/**********************Mining Equipment Locker**************************/
/obj/machinery/mineral/equipment_vendor
@@ -11,81 +17,8 @@
var/icon_vend = "adh-tool-vend"
circuit = /obj/item/weapon/circuitboard/mining_equipment_vendor
var/obj/item/weapon/card/id/inserted_id
//VOREStation Edit Start - Heavily modified list
var/list/prize_list = list(
new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
new /datum/data/mining_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 125),
new /datum/data/mining_equipment("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 125),
new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 150),
new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 200),
new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 900),
new /datum/data/mining_equipment("Geiger Counter", /obj/item/device/geiger, 750),
new /datum/data/mining_equipment("Plush Toy", /obj/random/plushie, 300),
new /datum/data/mining_equipment("GPS Device", /obj/item/device/gps/mining, 100),
// TODO new /datum/data/mining_equipment("Advanced Scanner", /obj/item/device/t_scanner/adv_mining_scanner, 800),
new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 500),
new /datum/data/mining_equipment("Shelter Capsule", /obj/item/device/survivalcapsule, 500),
// TODO new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500),
new /datum/data/mining_equipment("Umbrella", /obj/item/weapon/melee/umbrella/random, 200),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
new /datum/data/mining_equipment("Trauma Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/trauma, 250),
new /datum/data/mining_equipment("Burn Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/burn, 250),
new /datum/data/mining_equipment("Oxy Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/oxy, 250),
new /datum/data/mining_equipment("Detox Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/detox, 250),
new /datum/data/mining_equipment("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 1200),
// new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/required/kinetic_crusher, 750),
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator, 900),
new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 900),
new /datum/data/mining_equipment("Fulton Pack", /obj/item/extraction_pack, 1200),
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/weapon/pickaxe/silver, 1200),
// new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000),
new /datum/data/mining_equipment("Thalers - 100", /obj/item/weapon/spacecash/c100, 1000),
new /datum/data/mining_equipment("Hardsuit - Control Module", /obj/item/weapon/rig/industrial/vendor, 2000),
new /datum/data/mining_equipment("Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800),
new /datum/data/mining_equipment("Hardsuit - Drill", /obj/item/rig_module/device/drill, 5000),
new /datum/data/mining_equipment("Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000),
new /datum/data/mining_equipment("Hardsuit - Material Scanner", /obj/item/rig_module/vision/material, 500),
new /datum/data/mining_equipment("Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250),
new /datum/data/mining_equipment("Hardsuit - Intelligence Storage", /obj/item/rig_module/ai_container, 2500),
new /datum/data/mining_equipment("Hardsuit - Smoke Bomb Deployer", /obj/item/rig_module/grenade_launcher/smoke, 2000),
new /datum/data/mining_equipment("Industrial Equipment - Phoron Bore", /obj/item/weapon/gun/magnetic/matfed, 3000),
new /datum/data/mining_equipment("Industrial Equipment - Sheet-Snatcher",/obj/item/weapon/storage/bag/sheetsnatcher, 500),
new /datum/data/mining_equipment("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 500),
new /datum/data/mining_equipment("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 1000),
// new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500),
new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500),
new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 3100),
new /datum/data/mining_equipment("Bar Shelter Capsule", /obj/item/device/survivalcapsule/luxurybar, 10000),
new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 125),
new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 175),
new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
new /datum/data/mining_equipment("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
new /datum/data/mining_equipment("KA Efficiency Increase", /obj/item/borg/upgrade/modkit/efficiency, 1200),
new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
new /datum/data/mining_equipment("KA Holster", /obj/item/clothing/accessory/holster/waist/kinetic_accelerator, 350),
new /datum/data/mining_equipment("Fine Excavation Kit - Chisels",/obj/item/weapon/storage/excavation, 500),
new /datum/data/mining_equipment("Fine Excavation Kit - Measuring Tape",/obj/item/device/measuring_tape, 125),
new /datum/data/mining_equipment("Fine Excavation Kit - Hand Pick",/obj/item/weapon/pickaxe/hand, 375),
new /datum/data/mining_equipment("Explosive Excavation Kit - Plastic Charge",/obj/item/weapon/plastique/seismic/locked, 1500),
new /datum/data/mining_equipment("Injector (L) - Glucose",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose, 500),
new /datum/data/mining_equipment("Injector (L) - Panacea",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity, 500),
new /datum/data/mining_equipment("Injector (L) - Trauma",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute, 500),
new /datum/data/mining_equipment("Nanopaste Tube", /obj/item/stack/nanopaste, 1000),
new /datum/data/mining_equipment("Defense Equipment - Smoke Bomb",/obj/item/weapon/grenade/smokebomb, 100),
new /datum/data/mining_equipment("Defense Equipment - Razor Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked, 1000),
new /datum/data/mining_equipment("Defense Equipment - Sentry Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/ward, 1500),
new /datum/data/mining_equipment("Defense Equipment - Plasteel Machete", /obj/item/weapon/material/knife/machete, 500),
new /datum/data/mining_equipment("Fishing Net", /obj/item/weapon/material/fishing_net, 500),
new /datum/data/mining_equipment("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 1000),
new /datum/data/mining_equipment("Durasteel Fishing Rod", /obj/item/weapon/material/fishing_rod/modern/strong, 7500),
new /datum/data/mining_equipment("Survival Equipment - Insulated Poncho", /obj/random/thermalponcho, 750)
)
//VOREStation Edit End
var/list/prize_list // Initialized just below! (if you're wondering why - check CONTRIBUTING.md, look for: "hidden" init proc)
var/dirty_items = FALSE // Used to refresh the static/redundant data in case the machine gets VV'd
/datum/data/mining_equipment
var/equipment_name = "generic"
@@ -97,9 +30,96 @@
src.equipment_path = path
src.cost = cost
/obj/machinery/power/quantumpad/Initialize()
/obj/machinery/mineral/equipment_vendor/Initialize(mapload)
. = ..()
default_apply_parts()
//VOREStation Edit Start - Heavily modified list
prize_list = list()
prize_list["Gear"] = list(
// TODO EQUIPMENT("Advanced Scanner", /obj/item/device/t_scanner/adv_mining_scanner, 800),
// TODO EQUIPMENT("Explorer's Webbing", /obj/item/storage/belt/mining, 500),
EQUIPMENT("Defense Equipment - Plasteel Machete", /obj/item/weapon/material/knife/machete, 500),
EQUIPMENT("Defense Equipment - Razor Drone Deployer", /obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked, 1000),
EQUIPMENT("Defense Equipment - Sentry Drone Deployer", /obj/item/weapon/grenade/spawnergrenade/ward, 1500),
EQUIPMENT("Defense Equipment - Smoke Bomb", /obj/item/weapon/grenade/smokebomb, 100),
EQUIPMENT("Durasteel Fishing Rod", /obj/item/weapon/material/fishing_rod/modern/strong, 7500),
EQUIPMENT("Fishing Net", /obj/item/weapon/material/fishing_net, 500),
EQUIPMENT("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 1000),
EQUIPMENT("Fulton Beacon", /obj/item/fulton_core, 500),
EQUIPMENT("Geiger Counter", /obj/item/device/geiger, 750),
EQUIPMENT("GPS Device", /obj/item/device/gps/mining, 100),
// EQUIPMENT("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000),
EQUIPMENT("Jump Boots", /obj/item/clothing/shoes/bhop, 2500),
EQUIPMENT("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 1200),
EQUIPMENT("Survival Equipment - Insulated Poncho", /obj/random/thermalponcho, 750),
)
prize_list["Consumables"] = list(
EQUIPMENT("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
EQUIPMENT("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
EQUIPMENT("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
EQUIPMENT("Fulton Pack", /obj/item/extraction_pack, 1200),
EQUIPMENT("Injector (L) - Glucose", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose, 500),
EQUIPMENT("Injector (L) - Panacea", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity, 500),
EQUIPMENT("Injector (L) - Trauma", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute, 500),
EQUIPMENT("Nanopaste Tube", /obj/item/stack/nanopaste, 1000),
EQUIPMENT("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
EQUIPMENT("Shelter Capsule", /obj/item/device/survivalcapsule, 500),
EQUIPMENT("Burn Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/burn, 250),
EQUIPMENT("Detox Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/detox, 250),
EQUIPMENT("Oxy Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/oxy, 250),
EQUIPMENT("Trauma Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/trauma, 250),
)
prize_list["Kinetic Accelerator"] = list(
EQUIPMENT("Kinetic Accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator, 900),
EQUIPMENT("KA Adjustable Tracer Rounds",/obj/item/borg/upgrade/modkit/tracer/adjustable, 175),
EQUIPMENT("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
EQUIPMENT("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
EQUIPMENT("KA Efficiency Increase", /obj/item/borg/upgrade/modkit/efficiency, 1200),
EQUIPMENT("KA Holster", /obj/item/clothing/accessory/holster/waist/kinetic_accelerator, 350),
EQUIPMENT("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
EQUIPMENT("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
EQUIPMENT("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
EQUIPMENT("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 125),
)
prize_list["Digging Tools"] = list(
// EQUIPMENT("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
// EQUIPMENT("Kinetic Crusher", /obj/item/twohanded/required/kinetic_crusher, 750),
EQUIPMENT("Resonator", /obj/item/resonator, 900),
EQUIPMENT("Silver Pickaxe", /obj/item/weapon/pickaxe/silver, 1200),
EQUIPMENT("Super Resonator", /obj/item/resonator/upgraded, 2500),
EQUIPMENT("Fine Excavation Kit - Chisels", /obj/item/weapon/storage/excavation, 500),
EQUIPMENT("Fine Excavation Kit - Measuring Tape", /obj/item/device/measuring_tape, 125),
EQUIPMENT("Fine Excavation Kit - Hand Pick", /obj/item/weapon/pickaxe/hand, 375),
EQUIPMENT("Explosive Excavation Kit - Plastic Charge",/obj/item/weapon/plastique/seismic/locked, 1500),
)
prize_list["Hardsuit"] = list(
EQUIPMENT("Hardsuit - Control Module", /obj/item/weapon/rig/industrial/vendor, 2000),
EQUIPMENT("Hardsuit - Drill", /obj/item/rig_module/device/drill, 5000),
EQUIPMENT("Hardsuit - Intelligence Storage",/obj/item/rig_module/ai_container, 2500),
EQUIPMENT("Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250),
EQUIPMENT("Hardsuit - Material Scanner", /obj/item/rig_module/vision/material, 500),
EQUIPMENT("Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000),
EQUIPMENT("Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800),
EQUIPMENT("Hardsuit - Smoke Bomb Deployer", /obj/item/rig_module/grenade_launcher/smoke,2000),
)
prize_list["Miscellaneous"] = list(
EQUIPMENT("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 125),
EQUIPMENT("Bar Shelter Capsule", /obj/item/device/survivalcapsule/luxurybar, 10000),
EQUIPMENT("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 150),
EQUIPMENT("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 1000),
EQUIPMENT("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 500),
EQUIPMENT("Industrial Equipment - Phoron Bore", /obj/item/weapon/gun/magnetic/matfed, 3000),
EQUIPMENT("Industrial Equipment - Sheet-Snatcher",/obj/item/weapon/storage/bag/sheetsnatcher, 500),
EQUIPMENT("Laser Pointer", /obj/item/device/laser_pointer, 900),
EQUIPMENT("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 3100),
EQUIPMENT("Plush Toy", /obj/random/plushie, 300),
EQUIPMENT("Soap", /obj/item/weapon/soap/nanotrasen, 200),
EQUIPMENT("Thalers - 100", /obj/item/weapon/spacecash/c100, 1000),
EQUIPMENT("Umbrella", /obj/item/weapon/melee/umbrella/random, 200),
EQUIPMENT("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 125),
)
prize_list["Extra"] = list() // Used in child vendors
//VOREStation Edit End
/obj/machinery/mineral/equipment_vendor/power_change()
var/old_stat = stat
@@ -126,73 +146,104 @@
/obj/machinery/mineral/equipment_vendor/attack_hand(mob/user)
if(..())
return
interact(user)
tgui_interact(user)
/obj/machinery/mineral/equipment_vendor/attack_ghost(mob/user)
interact(user)
tgui_interact(user)
/obj/machinery/mineral/equipment_vendor/interact(mob/user)
user.set_machine(src)
/obj/machinery/mineral/equipment_vendor/tgui_data(mob/user)
var/list/data = ..()
var/dat
dat +="<div class='statusDisplay'>"
if(istype(inserted_id))
dat += "You have [inserted_id.mining_points] mining points collected. <A href='?src=\ref[src];choice=eject'>Eject ID.</A><br>"
// ID
if(inserted_id)
data["has_id"] = TRUE
data["id"] = list()
data["id"]["name"] = inserted_id.registered_name
data["id"]["points"] = get_points(inserted_id)
else
dat += "No ID inserted. <A href='?src=\ref[src];choice=insert'>Insert ID.</A><br>"
dat += "</div>"
dat += "<br><b>Equipment point cost list:</b><BR><table border='0' width='100%'>"
for(var/datum/data/mining_equipment/prize in prize_list)
dat += "<tr><td>[prize.equipment_name]</td><td>[prize.cost]</td><td><A href='?src=\ref[src];purchase=\ref[prize]'>Purchase</A></td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 600)
popup.set_content(dat)
popup.open()
data["has_id"] = FALSE
/obj/machinery/mineral/equipment_vendor/Topic(href, href_list)
return data
/obj/machinery/mineral/equipment_vendor/proc/get_points(obj/item/weapon/card/id/target)
if(!istype(target))
return 0
return target.mining_points
/obj/machinery/mineral/equipment_vendor/proc/remove_points(obj/item/weapon/card/id/target, amt)
target.mining_points -= amt
/obj/machinery/mineral/equipment_vendor/tgui_static_data(mob/user)
var/list/static_data[0]
// Available items - in static data because we don't wanna compute this list every time! It hardly changes.
static_data["items"] = list()
for(var/cat in prize_list)
var/list/cat_items = list()
for(var/prize_name in prize_list[cat])
var/datum/data/mining_equipment/prize = prize_list[cat][prize_name]
cat_items[prize_name] = list("name" = prize_name, "price" = prize.cost)
static_data["items"][cat] = cat_items
return static_data
/obj/machinery/mineral/equipment_vendor/vv_edit_var(var_name, var_value)
// Gotta update the static data in case an admin VV's the items for some reason..!
if(var_name == "prize_list")
dirty_items = TRUE
return ..()
/obj/machinery/mineral/equipment_vendor/tgui_interact(mob/user, datum/tgui/ui = null)
// Update static data if need be
if(dirty_items)
update_tgui_static_data(user, ui)
dirty_items = FALSE
// Open the window
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MiningVendor", name)
ui.open()
ui.set_autoupdate(FALSE)
/obj/machinery/mineral/equipment_vendor/tgui_act(action, params)
if(..())
return 1
return
if(href_list["choice"])
if(istype(inserted_id))
if(href_list["choice"] == "eject")
to_chat(usr, "<span class='notice'>You eject the ID from [src]'s card slot.</span>")
usr.put_in_hands(inserted_id)
inserted_id = null
else if(href_list["choice"] == "insert")
var/obj/item/weapon/card/id/I = usr.get_active_hand()
if(istype(I) && !inserted_id && usr.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(usr)
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
else
to_chat(usr, "<span class='warning'>No valid ID.</span>")
flick(icon_deny, src)
if(href_list["purchase"])
if(istype(inserted_id))
var/datum/data/mining_equipment/prize = locate(href_list["purchase"])
if (!prize || !(prize in prize_list))
to_chat(usr, "<span class='warning'>Error: Invalid choice!</span>")
flick(icon_deny, src)
. = TRUE
switch(action)
if("logoff")
if(!inserted_id)
return
if(prize.cost > inserted_id.mining_points)
to_chat(usr, "<span class='warning'>Error: Insufficent points for [prize.equipment_name]!</span>")
flick(icon_deny, src)
else
inserted_id.mining_points -= prize.cost
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
new prize.equipment_path(drop_location())
flick(icon_vend, src)
usr.put_in_hands(inserted_id)
inserted_id = null
if("purchase")
if(!inserted_id)
flick(icon_deny, src) //VOREStation Add
return
var/category = params["cat"] // meow
var/name = params["name"]
if(!(category in prize_list) || !(name in prize_list[category])) // Not trying something that's not in the list, are you?
flick(icon_deny, src) //VOREStation Add
return
var/datum/data/mining_equipment/prize = prize_list[category][name]
if(prize.cost > get_points(inserted_id)) // shouldn't be able to access this since the button is greyed out, but..
to_chat(usr, "<span class='danger'>You have insufficient points.</span>")
flick(icon_deny, src) //VOREStation Add
return
remove_points(inserted_id, prize.cost)
new prize.equipment_path(loc)
flick(icon_vend, src) //VOREStation Add
else
to_chat(usr, "<span class='warning'>Error: Please insert a valid ID!</span>")
flick(icon_deny, src)
updateUsrDialog()
flick(icon_deny, src) //VOREStation Add
return FALSE
add_fingerprint()
/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params)
if(default_deconstruction_screwdriver(user, I))
updateUsrDialog()
return
if(default_part_replacement(user, I))
return
@@ -201,7 +252,7 @@
if(istype(I, /obj/item/mining_voucher))
if(!powered())
return
RedeemVoucher(I, user)
redeem_voucher(I, user)
return
if(istype(I,/obj/item/weapon/card/id))
if(!powered())
@@ -209,16 +260,23 @@
else if(!inserted_id && user.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(user)
tgui_interact(user)
return
..()
return ..()
/obj/machinery/mineral/equipment_vendor/dismantle()
if(inserted_id)
inserted_id.forceMove(loc) //Prevents deconstructing the ORM from deleting whatever ID was inside it.
. = ..()
/obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/mining_voucher/voucher, mob/redeemer)
/**
* Called when someone slaps the machine with a mining voucher
*
* Arguments:
* * voucher - The voucher card item
* * redeemer - The person holding it
*/
/obj/machinery/mineral/equipment_vendor/proc/redeem_voucher(obj/item/mining_voucher/voucher, mob/redeemer)
var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in list("Kinetic Accelerator", "Resonator", "Mining Drone", "Advanced Scanner", "Crusher")
if(!selection || !Adjacent(redeemer) || voucher.loc != redeemer)
return

View File

@@ -8,109 +8,68 @@
circuit = /obj/item/weapon/circuitboard/exploration_equipment_vendor
icon_deny = "exploration-deny" //VOREStation Edit
icon_vend = "exploration-vend" //VOREStation Add
/obj/machinery/mineral/equipment_vendor/survey/Initialize(mapload)
. = ..()
//VOREStation Edit Start - Heavily modified list
prize_list = list(
new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 1),
new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 10),
new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 30),
new /datum/data/mining_equipment("GPS Device", /obj/item/device/gps/explorer, 10),
new /datum/data/mining_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 10),
new /datum/data/mining_equipment("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 10),
new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 15),
new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 20),
new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 90),
new /datum/data/mining_equipment("Geiger Counter", /obj/item/device/geiger, 75),
new /datum/data/mining_equipment("Plush Toy", /obj/random/plushie, 30),
new /datum/data/mining_equipment("Extraction Equipment - Fulton Beacon",/obj/item/fulton_core, 300),
new /datum/data/mining_equipment("Extraction Equipment - Fulton Pack",/obj/item/extraction_pack, 125),
new /datum/data/mining_equipment("Umbrella", /obj/item/weapon/melee/umbrella/random, 20),
new /datum/data/mining_equipment("Shelter Capsule", /obj/item/device/survivalcapsule, 50),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card/survey, 50),
new /datum/data/mining_equipment("Trauma Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/trauma, 25),
new /datum/data/mining_equipment("Burn Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/burn, 25),
new /datum/data/mining_equipment("Oxy Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/oxy, 25),
new /datum/data/mining_equipment("Detox Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/detox, 25),
new /datum/data/mining_equipment("Injector (L) - Glucose", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose,50),
new /datum/data/mining_equipment("Injector (L) - Panacea", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity,50),
new /datum/data/mining_equipment("Injector (L) - Trauma", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute,50),
new /datum/data/mining_equipment("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 50),
new /datum/data/mining_equipment("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 100),
new /datum/data/mining_equipment("Nanopaste Tube", /obj/item/stack/nanopaste, 100),
new /datum/data/mining_equipment("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 120),
new /datum/data/mining_equipment("UAV - Recon Skimmer", /obj/item/device/uav, 400),
new /datum/data/mining_equipment("Thalers - 100", /obj/item/weapon/spacecash/c100, 100),
new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 250),
new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 310),
new /datum/data/mining_equipment("Bar Shelter Capsule", /obj/item/device/survivalcapsule/luxurybar, 1000),
new /datum/data/mining_equipment("Industrial Equipment - Phoron Bore",/obj/item/weapon/gun/magnetic/matfed, 300),
new /datum/data/mining_equipment("Survey Tools - Shovel", /obj/item/weapon/shovel, 40),
new /datum/data/mining_equipment("Survey Tools - Mechanical Trap", /obj/item/weapon/beartrap, 50),
new /datum/data/mining_equipment("Defense Equipment - Smoke Bomb",/obj/item/weapon/grenade/smokebomb, 10),
new /datum/data/mining_equipment("Defense Equipment - Razor Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked, 100),
new /datum/data/mining_equipment("Defense Equipment - Sentry Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/ward, 150),
new /datum/data/mining_equipment("Defense Equipment - Steel Machete", /obj/item/weapon/material/knife/machete, 75),
new /datum/data/mining_equipment("Fishing Net", /obj/item/weapon/material/fishing_net, 50),
new /datum/data/mining_equipment("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 100),
new /datum/data/mining_equipment("Durasteel Fishing Rod", /obj/item/weapon/material/fishing_rod/modern/strong, 750),
new /datum/data/mining_equipment("Survival Equipment - Insulated Poncho", /obj/random/thermalponcho, 75)
)
//VOREStation Edit End
prize_list = list()
prize_list["Gear"] = list(
EQUIPMENT("Defense Equipment - Plasteel Machete", /obj/item/weapon/material/knife/machete, 500),
EQUIPMENT("Defense Equipment - Razor Drone Deployer", /obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked, 1000),
EQUIPMENT("Defense Equipment - Sentry Drone Deployer", /obj/item/weapon/grenade/spawnergrenade/ward, 1500),
EQUIPMENT("Defense Equipment - Smoke Bomb", /obj/item/weapon/grenade/smokebomb, 100),
EQUIPMENT("Durasteel Fishing Rod", /obj/item/weapon/material/fishing_rod/modern/strong, 7500),
EQUIPMENT("Fishing Net", /obj/item/weapon/material/fishing_net, 500),
EQUIPMENT("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 1000),
EQUIPMENT("Fulton Beacon", /obj/item/fulton_core, 500),
EQUIPMENT("Geiger Counter", /obj/item/device/geiger, 750),
EQUIPMENT("GPS Device", /obj/item/device/gps/mining, 100),
EQUIPMENT("Jump Boots", /obj/item/clothing/shoes/bhop, 2500),
EQUIPMENT("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 1200),
EQUIPMENT("Survival Equipment - Insulated Poncho", /obj/random/thermalponcho, 750),
)
prize_list["Consumables"] = list(
EQUIPMENT("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
EQUIPMENT("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
EQUIPMENT("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
EQUIPMENT("Fulton Pack", /obj/item/extraction_pack, 1200),
EQUIPMENT("Injector (L) - Glucose", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose, 500),
EQUIPMENT("Injector (L) - Panacea", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity, 500),
EQUIPMENT("Injector (L) - Trauma", /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute, 500),
EQUIPMENT("Nanopaste Tube", /obj/item/stack/nanopaste, 1000),
EQUIPMENT("Point Transfer Card", /obj/item/weapon/card/mining_point_card/survey, 500),
EQUIPMENT("Shelter Capsule", /obj/item/device/survivalcapsule, 500),
EQUIPMENT("Burn Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/burn, 250),
EQUIPMENT("Detox Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/detox, 250),
EQUIPMENT("Oxy Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/oxy, 250),
EQUIPMENT("Trauma Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/trauma, 250),
)
prize_list["Digging Tools"] = list(
EQUIPMENT("Survey Tools - Shovel", /obj/item/weapon/shovel, 40),
EQUIPMENT("Survey Tools - Mechanical Trap", /obj/item/weapon/beartrap, 50),
)
prize_list["Miscellaneous"] = list(
EQUIPMENT("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 125),
EQUIPMENT("Bar Shelter Capsule", /obj/item/device/survivalcapsule/luxurybar, 10000),
EQUIPMENT("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 150),
EQUIPMENT("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 1000),
EQUIPMENT("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 500),
EQUIPMENT("Industrial Equipment - Phoron Bore", /obj/item/weapon/gun/magnetic/matfed, 3000),
EQUIPMENT("Laser Pointer", /obj/item/device/laser_pointer, 900),
EQUIPMENT("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 3100),
EQUIPMENT("Plush Toy", /obj/random/plushie, 300),
EQUIPMENT("Soap", /obj/item/weapon/soap/nanotrasen, 200),
EQUIPMENT("Thalers - 100", /obj/item/weapon/spacecash/c100, 1000),
EQUIPMENT("Umbrella", /obj/item/weapon/melee/umbrella/random, 200),
EQUIPMENT("UAV - Recon Skimmer", /obj/item/device/uav, 400),
EQUIPMENT("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 125),
)
//VOREStation Edit End
/obj/machinery/mineral/equipment_vendor/survey/interact(mob/user)
user.set_machine(src)
/obj/machinery/mineral/equipment_vendor/survey/get_points(obj/item/weapon/card/id/target)
if(!istype(target))
return 0
return target.survey_points
var/dat
dat +="<div class='statusDisplay'>"
if(istype(inserted_id))
dat += "You have [inserted_id.survey_points] survey points collected. <A href='?src=\ref[src];choice=eject'>Eject ID.</A><br>"
else
dat += "No ID inserted. <A href='?src=\ref[src];choice=insert'>Insert ID.</A><br>"
dat += "</div>"
dat += "<br><b>Equipment point cost list:</b><BR><table border='0' width='100%'>"
for(var/datum/data/mining_equipment/prize in prize_list)
dat += "<tr><td>[prize.equipment_name]</td><td>[prize.cost]</td><td><A href='?src=\ref[src];purchase=\ref[prize]'>Purchase</A></td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "miningvendor", "Survey Equipment Vendor", 400, 600)
popup.set_content(dat)
popup.open()
/obj/machinery/mineral/equipment_vendor/survey/Topic(href, href_list)
if(..())
return 1
if(href_list["choice"])
if(istype(inserted_id))
if(href_list["choice"] == "eject")
to_chat(usr, "<span class='notice'>You eject the ID from [src]'s card slot.</span>")
usr.put_in_hands(inserted_id)
inserted_id = null
else if(href_list["choice"] == "insert")
var/obj/item/weapon/card/id/I = usr.get_active_hand()
if(istype(I) && !inserted_id && usr.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(usr)
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
else
to_chat(usr, "<span class='warning'>No valid ID.</span>")
flick(icon_deny, src)
if(href_list["purchase"])
if(istype(inserted_id))
var/datum/data/mining_equipment/prize = locate(href_list["purchase"])
if (!prize || !(prize in prize_list))
to_chat(usr, "<span class='warning'>Error: Invalid choice!</span>")
flick(icon_deny, src)
return
if(prize.cost > inserted_id.survey_points)
to_chat(usr, "<span class='warning'>Error: Insufficent points for [prize.equipment_name]!</span>")
flick(icon_deny, src)
else
inserted_id.survey_points -= prize.cost
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
flick(icon_vend, src) //VOREStation Add
new prize.equipment_path(drop_location())
else
to_chat(usr, "<span class='warning'>Error: Please insert a valid ID!</span>")
flick(icon_deny, src)
updateUsrDialog()
/obj/machinery/mineral/equipment_vendor/survey/remove_points(obj/item/weapon/card/id/target, amt)
target.survey_points -= amt

View File

@@ -61,72 +61,57 @@
load(C)
/mob/living/bot/mulebot/attack_hand(var/mob/user)
interact(user)
tgui_interact(user)
/mob/living/bot/mulebot/proc/interact(var/mob/user)
var/dat
dat += "<TT><B>Multiple Utility Load Effector Mk. III</B></TT><BR><BR>"
dat += "ID: [suffix]<BR>"
dat += "Power: [on ? "On" : "Off"]<BR>"
/mob/living/bot/mulebot/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MuleBot", "Mulebot [suffix ? "([suffix])" : ""]")
ui.open()
if(!open)
dat += "<BR>Current Load: [load ? load.name : "<i>none</i>"]<BR>"
/mob/living/bot/mulebot/tgui_data(mob/user)
var/list/data = list(
"suffix" = suffix,
"power" = on,
"issilicon" = issilicon(user),
"load" = load,
"locked" = locked,
"auto_return" = auto_return,
"crates_only" = crates_only,
"hatch" = open,
"safety" = safety,
)
return data
if(locked)
dat += "<HR>Controls are locked"
else
dat += "<HR>Controls are unlocked<BR><BR>"
if(!locked || issilicon(user))
dat += "<A href='byond://?src=\ref[src];op=power'>Toggle power</A><BR>"
dat += "<A href='byond://?src=\ref[src];op=stop'>Stop</A><BR>"
dat += "<A href='byond://?src=\ref[src];op=go'>Proceed</A><BR>"
dat += "<A href='byond://?src=\ref[src];op=home'>Return to home</A><BR>"
dat += "<A href='byond://?src=\ref[src];op=destination'>Set destination</A><BR>"
dat += "<A href='byond://?src=\ref[src];op=sethome'>Set home</A><BR>"
dat += "<A href='byond://?src=\ref[src];op=autoret'>Toggle auto return home</A> ([auto_return ? "On" : "Off"])<BR>"
dat += "<A href='byond://?src=\ref[src];op=cargotypes'>Toggle non-standard cargo</A> ([crates_only ? "Off" : "On"])<BR>"
if(load)
dat += "<A href='byond://?src=\ref[src];op=unload'>Unload now</A><BR>"
dat += "<HR>The maintenance hatch is closed.<BR>"
else
if(!issilicon(user))
dat += "The maintenance hatch is open.<BR><BR>"
dat += "<A href='byond://?src=\ref[src];op=safety'>Toggle safety</A> ([safety ? "On" : "Off - DANGER"])<BR>"
else
dat += "The bot is in maintenance mode and cannot be controlled.<BR>"
user << browse("<HEAD><TITLE>Mulebot [suffix ? "([suffix])" : ""]</TITLE></HEAD>[dat]", "window=mulebot;size=350x500")
onclose(user, "mulebot")
return
/mob/living/bot/mulebot/Topic(href, href_list)
/mob/living/bot/mulebot/tgui_act(action, params)
if(..())
return
usr.set_machine(src)
return TRUE
add_fingerprint(usr)
switch(href_list["op"])
switch(action)
if("power")
if(on)
turn_off()
else
turn_on()
visible_message("[usr] switches [on ? "on" : "off"] [src].")
. = TRUE
if("stop")
obeyCommand("Stop")
. = TRUE
if("go")
obeyCommand("GoTD")
. = TRUE
if("home")
obeyCommand("Home")
. = TRUE
if("destination")
obeyCommand("SetD")
. = TRUE
if("sethome")
var/new_dest
@@ -138,20 +123,23 @@
if(new_dest)
home = get_turf(beaconlist[new_dest])
homeName = new_dest
. = TRUE
if("unload")
unload()
. = TRUE
if("autoret")
auto_return = !auto_return
. = TRUE
if("cargotypes")
crates_only = !crates_only
. = TRUE
if("safety")
safety = !safety
interact(usr)
. = TRUE
/mob/living/bot/mulebot/attackby(var/obj/item/O, var/mob/user)
..()

View File

@@ -4,7 +4,7 @@
set desc = "Tag yourself for delivery through the disposals system."
set category = "Robot Commands"
var/new_tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in tagger_locations
var/new_tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in GLOB.tagger_locations
if(!new_tag)
mail_destination = ""

View File

@@ -53,7 +53,7 @@
data["fabricator"] = dronefab
data["fabPower"] = dronefab?.produce_drones
data["areas"] = tagger_locations
data["areas"] = GLOB.tagger_locations
data["selected_area"] = "[drone_call_area]"
return data
@@ -65,7 +65,7 @@
switch(action)
if("set_dcall_area")
var/t_area = params["area"]
if(!t_area || !(t_area in tagger_locations))
if(!t_area || !(t_area in GLOB.tagger_locations))
return
drone_call_area = t_area

View File

@@ -2,9 +2,9 @@
/obj/machinery/computer/shuttle_control/explore
name = "general shuttle control console"
circuit = /obj/item/weapon/circuitboard/shuttle_console/explore
ui_template = "shuttle_control_console_exploration.tmpl"
tgui_subtemplate = "ShuttleControlConsoleExploration"
/obj/machinery/computer/shuttle_control/explore/get_ui_data(var/datum/shuttle/autodock/overmap/shuttle)
/obj/machinery/computer/shuttle_control/explore/shuttlerich_tgui_data(var/datum/shuttle/autodock/overmap/shuttle)
. = ..()
if(istype(shuttle))
var/total_gas = 0
@@ -25,22 +25,28 @@
"fuel_span" = fuel_span
)
/obj/machinery/computer/shuttle_control/explore/handle_topic_href(var/datum/shuttle/autodock/overmap/shuttle, var/list/href_list)
/obj/machinery/computer/shuttle_control/explore/tgui_act(action, list/params)
if(..())
return TRUE
var/datum/shuttle/autodock/overmap/shuttle = SSshuttles.shuttles[shuttle_tag]
if(!istype(shuttle))
to_chat(usr, "<span class='warning'>Unable to establish link with the shuttle.</span>")
return TRUE
if(ismob(usr))
var/mob/user = usr
shuttle.operator_skill = user.get_skill_value(/datum/skill/pilot)
if((. = ..()) != null)
return
if(href_list["pick"])
var/list/possible_d = shuttle.get_possible_destinations()
var/D
if(possible_d.len)
D = input("Choose shuttle destination", "Shuttle Destination") as null|anything in possible_d
else
to_chat(usr,"<span class='warning'>No valid landing sites in range.</span>")
possible_d = shuttle.get_possible_destinations()
if(CanInteract(usr, global.default_state) && (D in possible_d))
shuttle.set_destination(possible_d[D])
return TOPIC_REFRESH
switch(action)
if("pick")
var/list/possible_d = shuttle.get_possible_destinations()
var/D
if(possible_d.len)
D = input("Choose shuttle destination", "Shuttle Destination") as null|anything in possible_d
else
to_chat(usr,"<span class='warning'>No valid landing sites in range.</span>")
possible_d = shuttle.get_possible_destinations()
if(CanInteract(usr, global.default_state) && (D in possible_d))
shuttle.set_destination(possible_d[D])
return TRUE

View File

@@ -444,8 +444,12 @@
// if paper is not in usr, then it must be near them, or in a clipboard or folder, which must be in or near usr
if(src.loc != usr && !src.Adjacent(usr) && !((istype(src.loc, /obj/item/weapon/clipboard) || istype(src.loc, /obj/item/weapon/folder)) && (src.loc.loc == usr || src.loc.Adjacent(usr)) ) )
if(istype(loc, /obj/item/weapon/clipboard) || istype(loc, /obj/structure/noticeboard) || istype(loc, /obj/item/weapon/folder))
if(loc.loc != usr && !in_range(loc, usr))
return
else if(loc != usr && !Adjacent(usr))
return
/*
t = checkhtml(t)

View File

@@ -20,36 +20,6 @@
if(LAZYLEN(notices) >= max_notices)
break
// Automatically place noticeboards that aren't mapped to specific positions.
if(pixel_x == 0 && pixel_y == 0)
var/turf/here = get_turf(src)
var/placing = 0
for(var/checkdir in GLOB.cardinal)
var/turf/T = get_step(here, checkdir)
if(T.density)
placing = checkdir
break
for(var/thing in T)
var/atom/A = thing
if(A.simulated && !A.CanPass(src, T))
placing = checkdir
break
switch(placing)
if(NORTH)
pixel_x = 0
pixel_y = 32
if(SOUTH)
pixel_x = 0
pixel_y = -32
if(EAST)
pixel_x = 32
pixel_y = 0
if(WEST)
pixel_x = -32
pixel_y = 0
update_icon()
/obj/structure/noticeboard/proc/add_paper(var/atom/movable/paper, var/skip_icon_update)
@@ -77,16 +47,16 @@
QDEL_NULL_LIST(notices)
. = ..()
/obj/structure/noticeboard/ex_act(var/severity)
/obj/structure/noticeboard/ex_act(severity)
dismantle()
/obj/structure/noticeboard/update_icon()
icon_state = "[base_icon_state][LAZYLEN(notices)]"
/obj/structure/noticeboard/attackby(var/obj/item/weapon/thing, var/mob/user)
if(thing.is_screwdriver())
var/choice = input("Which direction do you wish to place the noticeboard?", "Noticeboard Offset") as null|anything in list("North", "South", "East", "West")
if(choice && Adjacent(user) && thing.loc == user && !user.incapacitated())
/obj/structure/noticeboard/attackby(obj/item/I, mob/user)
if(I.is_screwdriver())
var/choice = input("Which direction do you wish to place the noticeboard?", "Noticeboard Offset") as null|anything in list("North", "South", "East", "West", "No Offset")
if(choice && Adjacent(user) && I.loc == user && !user.incapacitated())
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
switch(choice)
if("North")
@@ -101,27 +71,29 @@
if("West")
pixel_x = -32
pixel_y = 0
if("No Offset")
return
return
else if(thing.is_wrench())
visible_message(SPAN_WARNING("\The [user] begins dismantling \the [src]."))
else if(I.is_wrench())
visible_message("<span class='warning'>[user] begins dismantling [src].</span>")
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, 50, src))
visible_message(SPAN_DANGER("\The [user] has dismantled \the [src]!"))
visible_message("<span class='danger'>[user] has dismantled [src]!</span>")
dismantle()
return
else if(istype(thing, /obj/item/weapon/paper) || istype(thing, /obj/item/weapon/photo))
else if(istype(I, /obj/item/weapon/paper) || istype(I, /obj/item/weapon/photo))
if(jobban_isbanned(user, "Graffiti"))
to_chat(user, SPAN_WARNING("You are banned from leaving persistent information across rounds."))
to_chat(user, "<span class='warning'>You are banned from leaving persistent information across rounds.</span>")
else
if(LAZYLEN(notices) < max_notices && user.unEquip(thing, src))
if(LAZYLEN(notices) < max_notices && user.unEquip(I, src))
add_fingerprint(user)
add_paper(thing)
to_chat(user, SPAN_NOTICE("You pin \the [thing] to \the [src]."))
SSpersistence.track_value(thing, /datum/persistent/paper)
add_paper(I)
to_chat(user, "<span class='notice'>You pin [I] to [src].</span>")
SSpersistence.track_value(I, /datum/persistent/paper)
else
to_chat(user, SPAN_WARNING("You hesitate, certain \the [thing] will not be seen among the many others already attached to \the [src]."))
to_chat(user, "<span class='warning'>You hesitate, certain [I] will not be seen among the many others already attached to \the [src].</span>")
return
..()
return ..()
/obj/structure/noticeboard/attack_ai(var/mob/user)
examine(user)
@@ -129,56 +101,71 @@
/obj/structure/noticeboard/attack_hand(var/mob/user)
examine(user)
/obj/structure/noticeboard/examine(var/mob/user)
. = ..()
if(.)
var/list/dat = list("<table>")
for(var/thing in notices)
LAZYADD(dat, "<tr><td>[thing]</td><td>")
if(istype(thing, /obj/item/weapon/paper))
LAZYADD(dat, "<a href='?src=\ref[src];read=\ref[thing]'>Read</a><a href='?src=\ref[src];write=\ref[thing]'>Write</a>")
else if(istype(thing, /obj/item/weapon/photo))
LAZYADD(dat, "<a href='?src=\ref[src];look=\ref[thing]'>Look</a>")
LAZYADD(dat, "<a href='?src=\ref[src];remove=\ref[thing]'>Remove</a></td></tr>")
var/datum/browser/popup = new(user, "noticeboard-\ref[src]", "Noticeboard")
popup.set_content(jointext(dat, null))
popup.open()
/obj/structure/noticeboard/examine(mob/user)
tgui_interact(user)
return list()
/obj/structure/noticeboard/Topic(var/mob/user, var/list/href_list)
if(href_list["read"])
var/obj/item/weapon/paper/P = locate(href_list["read"])
if(P && P.loc == src)
P.show_content(user)
. = TOPIC_HANDLED
/obj/structure/noticeboard/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "NoticeBoard", name)
ui.open()
if(href_list["look"])
var/obj/item/weapon/photo/P = locate(href_list["look"])
if(P && P.loc == src)
P.show(user)
. = TOPIC_HANDLED
/obj/structure/noticeboard/tgui_data(mob/user)
var/list/data = ..()
data["notices"] = list()
for(var/obj/item/I in notices)
data["notices"].Add(list(list(
"ispaper" = istype(I, /obj/item/weapon/paper),
"isphoto" = istype(I, /obj/item/weapon/photo),
"name" = I.name,
"ref" = "\ref[I]",
)))
if(href_list["remove"])
remove_paper(locate(href_list["remove"]))
add_fingerprint(user)
. = TOPIC_REFRESH
return data
if(href_list["write"])
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
return
var/obj/item/P = locate(href_list["write"])
if((P && P.loc == src)) //ifthe paper's on the board
var/mob/living/M = usr
if(istype(M))
var/obj/item/weapon/pen/E = M.get_type_in_hands(/obj/item/weapon/pen)
if(E)
add_fingerprint(M)
P.attackby(E, usr)
else
to_chat(M, "<span class='notice'>You'll need something to write with!</span>")
. = TOPIC_REFRESH
/obj/structure/noticeboard/tgui_act(action, params)
if(..())
return TRUE
if(. == TOPIC_REFRESH)
interact(user)
switch(action)
if("read")
var/obj/item/weapon/paper/P = locate(params["ref"])
if(P && P.loc == src)
P.show_content(usr)
. = TRUE
if("look")
var/obj/item/weapon/photo/P = locate(params["ref"])
if(P && P.loc == src)
P.show(usr)
. = TRUE
if("remove")
if(!in_range(src, usr))
return FALSE
var/obj/item/I = locate(params["ref"])
remove_paper(I)
if(istype(I))
usr.put_in_hands(I)
add_fingerprint(usr)
. = TRUE
if("write")
if(!in_range(src, usr))
return FALSE
var/obj/item/P = locate(params["ref"])
if((P && P.loc == src)) //if the paper's on the board
var/mob/living/M = usr
if(istype(M))
var/obj/item/weapon/pen/E = M.get_type_in_hands(/obj/item/weapon/pen)
if(E)
add_fingerprint(M)
P.attackby(E, usr)
else
to_chat(M, "<span class='notice'>You'll need something to write with!</span>")
. = TRUE
/obj/structure/noticeboard/anomaly
notices = 5
@@ -190,32 +177,32 @@
P.info = "<br>We keep test dummies in pens here for a reason, so standard procedure should be to activate newfound alien artifacts and place the two in close proximity. Promising items I might even approve monkey testing on."
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
contents += P
P = new()
P.name = "Memo RE: materials gathering"
P.info = "Corasang,<br>the hands-on approach to gathering our samples may very well be slow at times, but it's safer than allowing the blundering miners to roll willy-nilly over our dig sites in their mechs, destroying everything in the process. And don't forget the escavation tools on your way out there!<br>- R.W"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
contents += P
P = new()
P.name = "Memo RE: ethical quandaries"
P.info = "Darion-<br><br>I don't care what his rank is, our business is that of science and knowledge - questions of moral application do not come into this. Sure, so there are those who would employ the energy-wave particles my modified device has managed to abscond for their own personal gain, but I can hardly see the practical benefits of some of these artifacts our benefactors left behind. Ward--"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
contents += P
P = new()
P.name = "READ ME! Before you people destroy any more samples"
P.info = "how many times do i have to tell you people, these xeno-arch samples are del-i-cate, and should be handled so! careful application of a focussed, concentrated heat or some corrosive liquids should clear away the extraneous carbon matter, while application of an energy beam will most decidedly destroy it entirely - like someone did to the chemical dispenser! W, <b>the one who signs your paychecks</b>"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
contents += P
P = new()
P.name = "Reminder regarding the anomalous material suits"
P.info = "Do you people think the anomaly suits are cheap to come by? I'm about a hair trigger away from instituting a log book for the damn things. Only wear them if you're going out for a dig, and for god's sake don't go tramping around in them unless you're field testing something, R"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
contents += P

View File

@@ -1210,7 +1210,7 @@
New()
. = ..()
dpdir = dir | turn(dir, 180)
if(sort_tag) tagger_locations |= sort_tag
if(sort_tag) GLOB.tagger_locations |= sort_tag
updatename()
updatedesc()
update()
@@ -1276,7 +1276,7 @@
New()
. = ..()
if(sortType) tagger_locations |= sortType
if(sortType) GLOB.tagger_locations |= sortType
updatedir()
updatename()

View File

@@ -14,100 +14,100 @@
var/label_x
var/tag_x
attack_hand(mob/user as mob)
unwrap()
/obj/structure/bigDelivery/attack_hand(mob/user as mob)
unwrap()
proc/unwrap()
playsound(src, 'sound/items/package_unwrap.ogg', 50, 1)
// Destroy will drop our wrapped object on the turf, so let it.
qdel(src)
/obj/structure/bigDelivery/proc/unwrap()
playsound(src, 'sound/items/package_unwrap.ogg', 50, 1)
// Destroy will drop our wrapped object on the turf, so let it.
qdel(src)
attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/destTagger))
var/obj/item/device/destTagger/O = W
if(O.currTag)
if(src.sortTag != O.currTag)
to_chat(user, "<span class='notice'>You have labeled the destination as [O.currTag].</span>")
if(!src.sortTag)
src.sortTag = O.currTag
update_icon()
else
src.sortTag = O.currTag
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
/obj/structure/bigDelivery/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/destTagger))
var/obj/item/device/destTagger/O = W
if(O.currTag)
if(src.sortTag != O.currTag)
to_chat(user, "<span class='notice'>You have labeled the destination as [O.currTag].</span>")
if(!src.sortTag)
src.sortTag = O.currTag
update_icon()
else
to_chat(user, "<span class='warning'>The package is already labeled for [O.currTag].</span>")
src.sortTag = O.currTag
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
else
to_chat(user, "<span class='warning'>You need to set a destination first!</span>")
to_chat(user, "<span class='warning'>The package is already labeled for [O.currTag].</span>")
else
to_chat(user, "<span class='warning'>You need to set a destination first!</span>")
else if(istype(W, /obj/item/weapon/pen))
switch(alert("What would you like to alter?",,"Title","Description", "Cancel"))
if("Title")
var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN)
if(!str || !length(str))
to_chat(user, "<span class='warning'> Invalid text.</span>")
return
user.visible_message("\The [user] titles \the [src] with \a [W], marking down: \"[str]\"",\
"<span class='notice'>You title \the [src]: \"[str]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
name = "[name] ([str])"
if(!examtext && !nameset)
nameset = 1
update_icon()
else
nameset = 1
if("Description")
var/str = sanitize(input(usr,"Label text?","Set label",""))
if(!str || !length(str))
to_chat(user, "<font color='red'>Invalid text.</font>")
return
if(!examtext && !nameset)
examtext = str
update_icon()
else
examtext = str
user.visible_message("\The [user] labels \the [src] with \a [W], scribbling down: \"[examtext]\"",\
"<span class='notice'>You label \the [src]: \"[examtext]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
return
else if(istype(W, /obj/item/weapon/pen))
switch(alert("What would you like to alter?",,"Title","Description", "Cancel"))
if("Title")
var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN)
if(!str || !length(str))
to_chat(user, "<span class='warning'> Invalid text.</span>")
return
user.visible_message("\The [user] titles \the [src] with \a [W], marking down: \"[str]\"",\
"<span class='notice'>You title \the [src]: \"[str]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
name = "[name] ([str])"
if(!examtext && !nameset)
nameset = 1
update_icon()
else
nameset = 1
if("Description")
var/str = sanitize(input(usr,"Label text?","Set label",""))
if(!str || !length(str))
to_chat(user, "<font color='red'>Invalid text.</font>")
return
if(!examtext && !nameset)
examtext = str
update_icon()
else
examtext = str
user.visible_message("\The [user] labels \the [src] with \a [W], scribbling down: \"[examtext]\"",\
"<span class='notice'>You label \the [src]: \"[examtext]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
return
update_icon()
overlays = new()
if(nameset || examtext)
var/image/I = new/image('icons/obj/storage.dmi',"delivery_label")
if(icon_state == "deliverycloset")
I.pixel_x = 2
if(label_y == null)
label_y = rand(-6, 11)
I.pixel_y = label_y
else if(icon_state == "deliverycrate")
if(label_x == null)
label_x = rand(-8, 6)
I.pixel_x = label_x
I.pixel_y = -3
overlays += I
if(src.sortTag)
var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag")
if(icon_state == "deliverycloset")
if(tag_x == null)
tag_x = rand(-2, 3)
I.pixel_x = tag_x
I.pixel_y = 9
else if(icon_state == "deliverycrate")
if(tag_x == null)
tag_x = rand(-8, 6)
I.pixel_x = tag_x
I.pixel_y = -3
overlays += I
/obj/structure/bigDelivery/update_icon()
overlays = new()
if(nameset || examtext)
var/image/I = new/image('icons/obj/storage.dmi',"delivery_label")
if(icon_state == "deliverycloset")
I.pixel_x = 2
if(label_y == null)
label_y = rand(-6, 11)
I.pixel_y = label_y
else if(icon_state == "deliverycrate")
if(label_x == null)
label_x = rand(-8, 6)
I.pixel_x = label_x
I.pixel_y = -3
overlays += I
if(src.sortTag)
var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag")
if(icon_state == "deliverycloset")
if(tag_x == null)
tag_x = rand(-2, 3)
I.pixel_x = tag_x
I.pixel_y = 9
else if(icon_state == "deliverycrate")
if(tag_x == null)
tag_x = rand(-8, 6)
I.pixel_x = tag_x
I.pixel_y = -3
overlays += I
examine(mob/user)
. = ..()
if(get_dist(user, src) <= 4)
if(sortTag)
. += "<span class='notice'>It is labeled \"[sortTag]\"</span>"
if(examtext)
. += "<span class='notice'>It has a note attached which reads, \"[examtext]\"</span>"
/obj/structure/bigDelivery/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 4)
if(sortTag)
. += "<span class='notice'>It is labeled \"[sortTag]\"</span>"
if(examtext)
. += "<span class='notice'>It has a note attached which reads, \"[examtext]\"</span>"
/obj/item/smallDelivery
desc = "A small wrapped package."
@@ -121,100 +121,100 @@
var/nameset = 0
var/tag_x
attack_self(mob/user as mob)
if (src.wrapped) //sometimes items can disappear. For example, bombs. --rastaf0
wrapped.loc = user.loc
if(ishuman(user))
user.put_in_hands(wrapped)
else
wrapped.loc = get_turf(src)
/obj/item/smallDelivery/attack_self(mob/user as mob)
if (src.wrapped) //sometimes items can disappear. For example, bombs. --rastaf0
wrapped.loc = user.loc
if(ishuman(user))
user.put_in_hands(wrapped)
else
wrapped.loc = get_turf(src)
qdel(src)
return
qdel(src)
return
attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/destTagger))
var/obj/item/device/destTagger/O = W
if(O.currTag)
if(src.sortTag != O.currTag)
to_chat(user, "<span class='notice'>You have labeled the destination as [O.currTag].</span>")
if(!src.sortTag)
src.sortTag = O.currTag
update_icon()
else
src.sortTag = O.currTag
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
/obj/item/smallDelivery/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/destTagger))
var/obj/item/device/destTagger/O = W
if(O.currTag)
if(src.sortTag != O.currTag)
to_chat(user, "<span class='notice'>You have labeled the destination as [O.currTag].</span>")
if(!src.sortTag)
src.sortTag = O.currTag
update_icon()
else
to_chat(user, "<span class='warning'>The package is already labeled for [O.currTag].</span>")
src.sortTag = O.currTag
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
else
to_chat(user, "<span class='warning'>You need to set a destination first!</span>")
to_chat(user, "<span class='warning'>The package is already labeled for [O.currTag].</span>")
else
to_chat(user, "<span class='warning'>You need to set a destination first!</span>")
else if(istype(W, /obj/item/weapon/pen))
switch(alert("What would you like to alter?",,"Title","Description", "Cancel"))
if("Title")
var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN)
if(!str || !length(str))
to_chat(user, "<span class='warning'> Invalid text.</span>")
return
user.visible_message("\The [user] titles \the [src] with \a [W], marking down: \"[str]\"",\
"<span class='notice'>You title \the [src]: \"[str]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
name = "[name] ([str])"
if(!examtext && !nameset)
nameset = 1
update_icon()
else
nameset = 1
else if(istype(W, /obj/item/weapon/pen))
switch(alert("What would you like to alter?",,"Title","Description", "Cancel"))
if("Title")
var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN)
if(!str || !length(str))
to_chat(user, "<span class='warning'> Invalid text.</span>")
return
user.visible_message("\The [user] titles \the [src] with \a [W], marking down: \"[str]\"",\
"<span class='notice'>You title \the [src]: \"[str]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
name = "[name] ([str])"
if(!examtext && !nameset)
nameset = 1
update_icon()
else
nameset = 1
if("Description")
var/str = sanitize(input(usr,"Label text?","Set label",""))
if(!str || !length(str))
to_chat(user, "<font color='red'>Invalid text.</font>")
return
if(!examtext && !nameset)
examtext = str
update_icon()
else
examtext = str
user.visible_message("\The [user] labels \the [src] with \a [W], scribbling down: \"[examtext]\"",\
"<span class='notice'>You label \the [src]: \"[examtext]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
return
if("Description")
var/str = sanitize(input(usr,"Label text?","Set label",""))
if(!str || !length(str))
to_chat(user, "<font color='red'>Invalid text.</font>")
return
if(!examtext && !nameset)
examtext = str
update_icon()
else
examtext = str
user.visible_message("\The [user] labels \the [src] with \a [W], scribbling down: \"[examtext]\"",\
"<span class='notice'>You label \the [src]: \"[examtext]\"</span>",\
"You hear someone scribbling a note.")
playsound(src, pick('sound/bureaucracy/pen1.ogg','sound/bureaucracy/pen2.ogg'), 20)
return
update_icon()
overlays = new()
if((nameset || examtext) && icon_state != "deliverycrate1")
var/image/I = new/image('icons/obj/storage.dmi',"delivery_label")
if(icon_state == "deliverycrate5")
I.pixel_y = -1
overlays += I
if(src.sortTag)
var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag")
switch(icon_state)
if("deliverycrate1")
I.pixel_y = -5
if("deliverycrate2")
I.pixel_y = -2
if("deliverycrate3")
I.pixel_y = 0
if("deliverycrate4")
if(tag_x == null)
tag_x = rand(0,5)
I.pixel_x = tag_x
I.pixel_y = 3
if("deliverycrate5")
I.pixel_y = -3
overlays += I
/obj/item/smallDelivery/update_icon()
overlays = new()
if((nameset || examtext) && icon_state != "deliverycrate1")
var/image/I = new/image('icons/obj/storage.dmi',"delivery_label")
if(icon_state == "deliverycrate5")
I.pixel_y = -1
overlays += I
if(src.sortTag)
var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag")
switch(icon_state)
if("deliverycrate1")
I.pixel_y = -5
if("deliverycrate2")
I.pixel_y = -2
if("deliverycrate3")
I.pixel_y = 0
if("deliverycrate4")
if(tag_x == null)
tag_x = rand(0,5)
I.pixel_x = tag_x
I.pixel_y = 3
if("deliverycrate5")
I.pixel_y = -3
overlays += I
examine(mob/user)
. = ..()
if(get_dist(user, src) <= 4)
if(sortTag)
. += "<span class='notice'>It is labeled \"[sortTag]\"</span>"
if(examtext)
. += "<span class='notice'>It has a note attached which reads, \"[examtext]\"</span>"
/obj/item/smallDelivery/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 4)
if(sortTag)
. += "<span class='notice'>It is labeled \"[sortTag]\"</span>"
if(examtext)
. += "<span class='notice'>It has a note attached which reads, \"[examtext]\"</span>"
/obj/item/weapon/packageWrap
name = "package wrapper"
@@ -226,95 +226,95 @@
drop_sound = 'sound/items/drop/wrapper.ogg'
afterattack(var/obj/target as obj, mob/user as mob, proximity)
if(!proximity) return
if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete
return
if(istype(target, /obj/item/smallDelivery) || istype(target,/obj/structure/bigDelivery) \
|| istype(target, /obj/item/weapon/gift) || istype(target, /obj/item/weapon/evidencebag))
return
if(target.anchored)
return
if(target in user)
return
if(user in target) //no wrapping closets that you are inside - it's not physically possible
return
user.attack_log += text("\[[time_stamp()]\] <font color='blue'>Has used [src.name] on \ref[target]</font>")
if (istype(target, /obj/item) && !(istype(target, /obj/item/weapon/storage) && !istype(target,/obj/item/weapon/storage/box)))
var/obj/item/O = target
if (src.amount > 1)
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(O.loc)) //Aaannd wrap it up!
if(!istype(O.loc, /turf))
if(user.client)
user.client.screen -= O
P.wrapped = O
O.forceMove(P)
P.w_class = O.w_class
var/i = round(O.w_class)
if(i in list(1,2,3,4,5))
P.icon_state = "deliverycrate[i]"
switch(i)
if(1) P.name = "tiny parcel"
if(3) P.name = "normal-sized parcel"
if(4) P.name = "large parcel"
if(5) P.name = "huge parcel"
if(i < 1)
P.icon_state = "deliverycrate1"
P.name = "tiny parcel"
if(i > 5)
P.icon_state = "deliverycrate5"
P.name = "huge parcel"
P.add_fingerprint(usr)
O.add_fingerprint(usr)
src.add_fingerprint(usr)
src.amount -= 1
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
"You hear someone taping paper around a small object.")
playsound(src, 'sound/items/package_wrap.ogg', 50, 1)
else if (istype(target, /obj/structure/closet/crate))
var/obj/structure/closet/crate/O = target
if (src.amount > 3 && !O.opened)
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
P.icon_state = "deliverycrate"
P.wrapped = O
O.loc = P
src.amount -= 3
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
"You hear someone taping paper around a large object.")
playsound(src, 'sound/items/package_wrap.ogg', 50, 1)
else if(src.amount < 3)
to_chat(user, "<span class='warning'>You need more paper.</span>")
else if (istype (target, /obj/structure/closet))
var/obj/structure/closet/O = target
if (src.amount > 3 && !O.opened)
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
P.wrapped = O
O.sealed = 1
O.loc = P
src.amount -= 3
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
"You hear someone taping paper around a large object.")
playsound(src, 'sound/items/package_wrap.ogg', 50, 1)
else if(src.amount < 3)
to_chat(user, "<span class='warning'>You need more paper.</span>")
else
to_chat(user, "<font color='blue'>The object you are trying to wrap is unsuitable for the sorting machinery!</font>")
if (src.amount <= 0)
new /obj/item/weapon/c_tube( src.loc )
qdel(src)
return
/obj/item/weapon/packageWrap/afterattack(var/obj/target as obj, mob/user as mob, proximity)
if(!proximity) return
if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete
return
if(istype(target, /obj/item/smallDelivery) || istype(target,/obj/structure/bigDelivery) \
|| istype(target, /obj/item/weapon/gift) || istype(target, /obj/item/weapon/evidencebag))
return
if(target.anchored)
return
if(target in user)
return
if(user in target) //no wrapping closets that you are inside - it's not physically possible
return
examine(mob/user)
. = ..()
if(get_dist(user, src) <= 0)
. += "<font color='blue'>There are [amount] units of package wrap left!</font>"
user.attack_log += text("\[[time_stamp()]\] <font color='blue'>Has used [src.name] on \ref[target]</font>")
if (istype(target, /obj/item) && !(istype(target, /obj/item/weapon/storage) && !istype(target,/obj/item/weapon/storage/box)))
var/obj/item/O = target
if (src.amount > 1)
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(O.loc)) //Aaannd wrap it up!
if(!istype(O.loc, /turf))
if(user.client)
user.client.screen -= O
P.wrapped = O
O.forceMove(P)
P.w_class = O.w_class
var/i = round(O.w_class)
if(i in list(1,2,3,4,5))
P.icon_state = "deliverycrate[i]"
switch(i)
if(1) P.name = "tiny parcel"
if(3) P.name = "normal-sized parcel"
if(4) P.name = "large parcel"
if(5) P.name = "huge parcel"
if(i < 1)
P.icon_state = "deliverycrate1"
P.name = "tiny parcel"
if(i > 5)
P.icon_state = "deliverycrate5"
P.name = "huge parcel"
P.add_fingerprint(usr)
O.add_fingerprint(usr)
src.add_fingerprint(usr)
src.amount -= 1
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
"You hear someone taping paper around a small object.")
playsound(src, 'sound/items/package_wrap.ogg', 50, 1)
else if (istype(target, /obj/structure/closet/crate))
var/obj/structure/closet/crate/O = target
if (src.amount > 3 && !O.opened)
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
P.icon_state = "deliverycrate"
P.wrapped = O
O.loc = P
src.amount -= 3
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
"You hear someone taping paper around a large object.")
playsound(src, 'sound/items/package_wrap.ogg', 50, 1)
else if(src.amount < 3)
to_chat(user, "<span class='warning'>You need more paper.</span>")
else if (istype (target, /obj/structure/closet))
var/obj/structure/closet/O = target
if (src.amount > 3 && !O.opened)
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
P.wrapped = O
O.sealed = 1
O.loc = P
src.amount -= 3
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
"You hear someone taping paper around a large object.")
playsound(src, 'sound/items/package_wrap.ogg', 50, 1)
else if(src.amount < 3)
to_chat(user, "<span class='warning'>You need more paper.</span>")
else
to_chat(user, "<font color='blue'>The object you are trying to wrap is unsuitable for the sorting machinery!</font>")
if (src.amount <= 0)
new /obj/item/weapon/c_tube( src.loc )
qdel(src)
return
return
/obj/item/weapon/packageWrap/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 0)
. += "<font color='blue'>There are [amount] units of package wrap left!</font>"
/obj/structure/bigDelivery/Destroy()
if(wrapped) //sometimes items can disappear. For example, bombs. --rastaf0
@@ -338,30 +338,34 @@
item_state = "electronic"
slot_flags = SLOT_BELT
proc/openwindow(mob/user as mob)
var/dat = "<tt><center><h1><b>TagMaster 2.3</b></h1></center>"
/obj/item/device/destTagger/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "DestinationTagger", name)
ui.open()
dat += "<table style='width:100%; padding:4px;'><tr>"
for(var/i = 1, i <= tagger_locations.len, i++)
dat += "<td><a href='?src=\ref[src];nextTag=[tagger_locations[i]]'>[tagger_locations[i]]</a></td>"
/obj/item/device/destTagger/tgui_data(mob/user, datum/tgui/ui)
var/list/data = ..()
if (i%4==0)
dat += "</tr><tr>"
data["currTag"] = currTag
data["taggerLocs"] = GLOB.tagger_locations
dat += "</tr></table><br>Current Selection: [currTag ? currTag : "None"]</tt>"
return data
user << browse(dat, "window=destTagScreen;size=450x350")
onclose(user, "destTagScreen")
/obj/item/device/destTagger/attack_self(mob/user as mob)
tgui_interact(user)
attack_self(mob/user as mob)
openwindow(user)
return
Topic(href, href_list)
src.add_fingerprint(usr)
if(href_list["nextTag"] && href_list["nextTag"] in tagger_locations)
src.currTag = href_list["nextTag"]
openwindow(usr)
/obj/item/device/destTagger/tgui_act(action, params)
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if("set_tag")
var/new_tag = params["tag"]
if(!(new_tag in GLOB.tagger_locations))
return FALSE
currTag = new_tag
. = TRUE
/obj/machinery/disposal/deliveryChute
name = "Delivery chute"
@@ -371,94 +375,94 @@
var/c_mode = 0
New()
..()
spawn(5)
trunk = locate() in src.loc
if(trunk)
trunk.linked = src // link the pipe trunk to self
/obj/machinery/disposal/deliveryChute/New()
..()
spawn(5)
trunk = locate() in src.loc
if(trunk)
trunk.linked = src // link the pipe trunk to self
interact()
return
/obj/machinery/disposal/deliveryChute/interact()
return
/obj/machinery/disposal/deliveryChute/update()
return
/obj/machinery/disposal/deliveryChute/Bumped(var/atom/movable/AM) //Go straight into the chute
if(istype(AM, /obj/item/projectile) || istype(AM, /obj/effect) || istype(AM, /obj/mecha)) return
switch(dir)
if(NORTH)
if(AM.loc.y != src.loc.y+1) return
if(EAST)
if(AM.loc.x != src.loc.x+1) return
if(SOUTH)
if(AM.loc.y != src.loc.y-1) return
if(WEST)
if(AM.loc.x != src.loc.x-1) return
if(istype(AM, /obj))
var/obj/O = AM
O.loc = src
else if(istype(AM, /mob))
var/mob/M = AM
M.loc = src
src.flush()
/obj/machinery/disposal/deliveryChute/flush()
flushing = 1
flick("intake-closing", src)
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
// travels through the pipes.
air_contents = new() // new empty gas resv.
sleep(10)
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
sleep(5) // wait for animation to finish
H.init(src) // copy the contents of disposer to holder
H.start(src) // start the holder processing movement
flushing = 0
// now reset disposal state
flush = 0
if(mode == 2) // if was ready,
mode = 1 // switch to charging
update()
return
/obj/machinery/disposal/deliveryChute/attackby(var/obj/item/I, var/mob/user)
if(!I || !user)
return
Bumped(var/atom/movable/AM) //Go straight into the chute
if(istype(AM, /obj/item/projectile) || istype(AM, /obj/effect) || istype(AM, /obj/mecha)) return
switch(dir)
if(NORTH)
if(AM.loc.y != src.loc.y+1) return
if(EAST)
if(AM.loc.x != src.loc.x+1) return
if(SOUTH)
if(AM.loc.y != src.loc.y-1) return
if(WEST)
if(AM.loc.x != src.loc.x-1) return
if(istype(AM, /obj))
var/obj/O = AM
O.loc = src
else if(istype(AM, /mob))
var/mob/M = AM
M.loc = src
src.flush()
flush()
flushing = 1
flick("intake-closing", src)
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
// travels through the pipes.
air_contents = new() // new empty gas resv.
sleep(10)
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
sleep(5) // wait for animation to finish
H.init(src) // copy the contents of disposer to holder
H.start(src) // start the holder processing movement
flushing = 0
// now reset disposal state
flush = 0
if(mode == 2) // if was ready,
mode = 1 // switch to charging
update()
return
attackby(var/obj/item/I, var/mob/user)
if(!I || !user)
if(I.is_screwdriver())
if(c_mode==0)
c_mode=1
playsound(src, I.usesound, 50, 1)
to_chat(user, "You remove the screws around the power connection.")
return
else if(c_mode==1)
c_mode=0
playsound(src, I.usesound, 50, 1)
to_chat(user, "You attach the screws around the power connection.")
return
else if(istype(I, /obj/item/weapon/weldingtool) && c_mode==1)
var/obj/item/weapon/weldingtool/W = I
if(W.remove_fuel(0,user))
playsound(src, W.usesound, 50, 1)
to_chat(user, "You start slicing the floorweld off the delivery chute.")
if(do_after(user,20 * W.toolspeed))
if(!src || !W.isOn()) return
to_chat(user, "You sliced the floorweld off the delivery chute.")
var/obj/structure/disposalconstruct/C = new (src.loc)
C.ptype = 8 // 8 = Delivery chute
C.update()
C.anchored = 1
C.density = 1
qdel(src)
return
else
to_chat(user, "You need more welding fuel to complete this task.")
return
if(I.is_screwdriver())
if(c_mode==0)
c_mode=1
playsound(src, I.usesound, 50, 1)
to_chat(user, "You remove the screws around the power connection.")
return
else if(c_mode==1)
c_mode=0
playsound(src, I.usesound, 50, 1)
to_chat(user, "You attach the screws around the power connection.")
return
else if(istype(I, /obj/item/weapon/weldingtool) && c_mode==1)
var/obj/item/weapon/weldingtool/W = I
if(W.remove_fuel(0,user))
playsound(src, W.usesound, 50, 1)
to_chat(user, "You start slicing the floorweld off the delivery chute.")
if(do_after(user,20 * W.toolspeed))
if(!src || !W.isOn()) return
to_chat(user, "You sliced the floorweld off the delivery chute.")
var/obj/structure/disposalconstruct/C = new (src.loc)
C.ptype = 8 // 8 = Delivery chute
C.update()
C.anchored = 1
C.density = 1
qdel(src)
return
else
to_chat(user, "You need more welding fuel to complete this task.")
return
/obj/machinery/disposal/deliveryChute/Destroy()
if(trunk)

View File

@@ -113,15 +113,15 @@ var/global/list/obj/machinery/message_server/message_servers = list()
/obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1)
rc_msgs += new/datum/data_rc_msg(recipient,sender,message,stamp,id_auth)
var/authmsg = "[message]<br>"
var/authmsg = "[message]\n"
if (id_auth)
authmsg += "[id_auth]<br>"
authmsg += "([id_auth])\n"
if (stamp)
authmsg += "[stamp]<br>"
authmsg += "([stamp])\n"
for (var/obj/machinery/requests_console/Console in allConsoles)
if (ckey(Console.department) == ckey(recipient))
if(Console.inoperable())
Console.message_log += "<B>Message lost due to console failure.</B><BR>Please contact [station_name()] system adminsitrator or AI for technical assistance.<BR>"
Console.message_log += list(list("Message lost due to console failure.","Please contact [station_name()] system adminsitrator or AI for technical assistance."))
continue
if(Console.newmessagepriority < priority)
Console.newmessagepriority = priority
@@ -131,12 +131,12 @@ var/global/list/obj/machinery/message_server/message_servers = list()
if(!Console.silent)
playsound(Console, 'sound/machines/twobeep.ogg', 50, 1)
Console.audible_message(text("[bicon(Console)] *The Requests Console beeps: 'PRIORITY Alert in [sender]'"),,5)
Console.message_log += "<B><FONT color='red'>High Priority message from <A href='?src=\ref[Console];write=[sender]'>[sender]</A></FONT></B><BR>[authmsg]"
Console.message_log += list(list("High Priority message from [sender]", "[authmsg]"))
else
if(!Console.silent)
playsound(Console, 'sound/machines/twobeep.ogg', 50, 1)
Console.audible_message(text("[bicon(Console)] *The Requests Console beeps: 'Message from [sender]'"),,4)
Console.message_log += "<B>Message from <A href='?src=\ref[Console];write=[sender]'>[sender]</A></B><BR>[authmsg]"
Console.message_log += list(list("Message from [sender]", "[authmsg]"))
Console.set_light(2)

View File

@@ -36,17 +36,19 @@
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
ui_interact(user)
/obj/machinery/computer/roguezones/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
tgui_interact(user)
/obj/machinery/computer/roguezones/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "RogueZones", name)
ui.open()
/obj/machinery/computer/roguezones/tgui_data(mob/user)
var/chargePercent = min(100, ((((world.time - rm_controller.last_scan) / 10) / 60) / rm_controller.scan_wait) * 100)
var/curZoneOccupied = rm_controller.current_zone ? rm_controller.current_zone.is_occupied() : 0
var/list/data = list()
var/list/data = ..()
data["timeout_percent"] = chargePercent
data["diffstep"] = rm_controller.diffstep
data["difficulty"] = rm_controller.diffstep_strs[rm_controller.diffstep]
@@ -80,32 +82,24 @@
// Permit emergency recall of the shuttle if its stranded in a zone with just dead people.
data["can_recall_shuttle"] = (shuttle_control && (shuttle_control.z in using_map.belter_belt_z) && !curZoneOccupied)
return data
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "zone_console.tmpl", src.name, 600, 400)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(5)
/obj/machinery/computer/roguezones/Topic(href, href_list)
/obj/machinery/computer/roguezones/tgui_act(action, list/params)
if(..())
return 1
usr.set_machine(src)
if (href_list["action"])
switch(href_list["action"])
if ("scan_for_new")
scan_for_new_zone()
if ("point_at_old")
point_at_old_zone()
if ("recall_shuttle")
failsafe_shuttle_recall()
return TRUE
switch(action)
if("scan_for_new")
scan_for_new_zone()
. = TRUE
if("recall_shuttle")
failsafe_shuttle_recall()
. = TRUE
src.add_fingerprint(usr)
SSnanoui.update_uis(src)
add_fingerprint(usr)
/obj/machinery/computer/roguezones/proc/scan_for_new_zone()
if(scanning) return
if(scanning)
return
//Set some kinda scanning var to pause UI input on console
rm_controller.last_scan = world.time
@@ -137,9 +131,6 @@
return
/obj/machinery/computer/roguezones/proc/point_at_old_zone()
return
/obj/machinery/computer/roguezones/proc/failsafe_shuttle_recall()
if(!shuttle_control)

View File

@@ -8,8 +8,8 @@
var/shuttle_tag // Used to coordinate data in shuttle controller.
var/hacked = 0 // Has been emagged, no access restrictions.
var/ui_template = "shuttle_control_console.tmpl"
var/skip_act = FALSE
var/tgui_subtemplate = "ShuttleControlConsoleDefault"
/obj/machinery/computer/shuttle_control/attack_hand(user as mob)
if(..(user))
@@ -19,9 +19,9 @@
to_chat(user, "<span class='warning'>Access Denied.</span>")
return 1
ui_interact(user)
tgui_interact(user)
/obj/machinery/computer/shuttle_control/proc/get_ui_data(var/datum/shuttle/autodock/shuttle)
/obj/machinery/computer/shuttle_control/proc/shuttlerich_tgui_data(var/datum/shuttle/autodock/shuttle)
var/shuttle_state
switch(shuttle.moving_status)
if(SHUTTLE_IDLE) shuttle_state = "idle"
@@ -29,7 +29,7 @@
if(SHUTTLE_INTRANSIT) shuttle_state = "in_transit"
var/shuttle_status
switch (shuttle.process_state)
switch(shuttle.process_state)
if(IDLE_STATE)
var/cannot_depart = shuttle.current_location.cannot_depart(shuttle)
if (shuttle.in_use)
@@ -55,7 +55,8 @@
"can_launch" = shuttle.can_launch(),
"can_cancel" = shuttle.can_cancel(),
"can_force" = shuttle.can_force(),
"docking_codes" = shuttle.docking_codes
"docking_codes" = shuttle.docking_codes,
"subtemplate" = tgui_subtemplate,
)
// This is a subset of the actual checks; contains those that give messages to the user.
@@ -74,59 +75,54 @@
return FALSE
return TRUE
/obj/machinery/computer/shuttle_control/Topic(href, href_list)
if((. = ..()))
/obj/machinery/computer/shuttle_control/tgui_act(action, list/params)
if(..())
return TRUE
if(skip_act)
return
usr.set_machine(src)
src.add_fingerprint(usr)
add_fingerprint(usr)
var/datum/shuttle/autodock/shuttle = SSshuttles.shuttles[shuttle_tag]
if(!shuttle)
to_chat(usr, "<span class='warning'>Unable to establish link with the shuttle.</span>")
return handle_topic_href(shuttle, href_list, usr)
/obj/machinery/computer/shuttle_control/proc/handle_topic_href(var/datum/shuttle/autodock/shuttle, var/list/href_list, var/user)
if(!istype(shuttle))
return TOPIC_NOACTION
to_chat(usr, "<span class='warning'>Unable to establish link with the shuttle.</span>")
return TRUE
if(href_list["move"])
if(can_move(shuttle, user))
shuttle.launch(src)
return TOPIC_REFRESH
return TOPIC_HANDLED
switch(action)
if("move")
if(can_move(shuttle, usr))
shuttle.launch(src)
return TRUE
if(href_list["force"])
if(can_move(shuttle, user))
shuttle.force_launch(src)
return TOPIC_REFRESH
return TOPIC_HANDLED
if("force")
if(can_move(shuttle, usr))
shuttle.force_launch(src)
return TRUE
if(href_list["cancel"])
shuttle.cancel_launch(src)
return TOPIC_REFRESH
if("cancel")
shuttle.cancel_launch(src)
return TRUE
if(href_list["set_codes"])
var/newcode = input("Input new docking codes", "Docking codes", shuttle.docking_codes) as text|null
if (newcode && CanInteract(usr, global.default_state))
shuttle.set_docking_codes(uppertext(newcode))
return TOPIC_REFRESH
if("set_codes")
var/newcode = input("Input new docking codes", "Docking codes", shuttle.docking_codes) as text|null
if(newcode && !..())
shuttle.set_docking_codes(uppertext(newcode))
return TRUE
/obj/machinery/computer/shuttle_control/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ShuttleControl", "[shuttle_tag] Shuttle Control") // 470, 360
ui.open()
// We delegate populating data to another proc to make it easier for overriding types to add their data.
/obj/machinery/computer/shuttle_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/computer/shuttle_control/tgui_data(mob/user)
var/datum/shuttle/autodock/shuttle = SSshuttles.shuttles[shuttle_tag]
if (!istype(shuttle))
if(!istype(shuttle))
to_chat(user, "<span class='warning'>Unable to establish link with the shuttle.</span>")
return
var/list/data = get_ui_data(shuttle)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, ui_template, "[shuttle_tag] Shuttle Control", 470, 360)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return shuttlerich_tgui_data(shuttle)
// Call to set the linked shuttle tag; override to add behaviour to shuttle tag changes
/obj/machinery/computer/shuttle_control/proc/set_shuttle_tag(var/new_shuttle_tag)

View File

@@ -1,8 +1,8 @@
/obj/machinery/computer/shuttle_control/multi
circuit = /obj/item/weapon/circuitboard/shuttle_console/multi
ui_template = "shuttle_control_console_multi.tmpl"
tgui_subtemplate = "ShuttleControlConsoleMulti"
/obj/machinery/computer/shuttle_control/multi/get_ui_data(var/datum/shuttle/autodock/multi/shuttle)
/obj/machinery/computer/shuttle_control/multi/shuttlerich_tgui_data(var/datum/shuttle/autodock/multi/shuttle)
. = ..()
if(istype(shuttle))
. += list(
@@ -14,22 +14,28 @@
// "engines_charging" = ((shuttle.last_move + (shuttle.cooldown SECONDS)) > world.time), // Replaced by longer warmup_time
)
/obj/machinery/computer/shuttle_control/multi/handle_topic_href(var/datum/shuttle/autodock/multi/shuttle, var/list/href_list)
if((. = ..()) != null)
return
/obj/machinery/computer/shuttle_control/multi/tgui_act(action, list/params)
if(..())
return TRUE
if(href_list["pick"])
var/dest_key = input("Choose shuttle destination", "Shuttle Destination") as null|anything in shuttle.get_destinations()
if(dest_key && CanInteract(usr, global.default_state))
shuttle.set_destination(dest_key, usr)
return TOPIC_REFRESH
var/datum/shuttle/autodock/multi/shuttle = SSshuttles.shuttles[shuttle_tag]
if(!istype(shuttle))
to_chat(usr, "<span class='warning'>Unable to establish link with the shuttle.</span>")
return TRUE
if(href_list["toggle_cloaked"])
if(!shuttle.can_cloak)
return TOPIC_HANDLED
shuttle.cloaked = !shuttle.cloaked
if(shuttle.legit)
to_chat(usr, "<span class='notice'>Ship ATC inhibitor systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be notified of our arrival.</span>")
else
to_chat(usr, "<span class='warning'>Ship stealth systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.</span>")
return TOPIC_REFRESH
switch(action)
if("pick")
var/dest_key = input("Choose shuttle destination", "Shuttle Destination") as null|anything in shuttle.get_destinations()
if(dest_key && CanInteract(usr, global.default_state))
shuttle.set_destination(dest_key, usr)
return TRUE
if("toggle_cloaked")
if(!shuttle.can_cloak)
return TRUE
shuttle.cloaked = !shuttle.cloaked
if(shuttle.legit)
to_chat(usr, "<span class='notice'>Ship ATC inhibitor systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be notified of our arrival.</span>")
else
to_chat(usr, "<span class='warning'>Ship stealth systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.</span>")
return TRUE

View File

@@ -167,6 +167,8 @@
icon_screen = "flight_center"
var/list/my_doors //Should be list("id_tag" = "Pretty Door Name", ...)
var/list/my_sensors //Should be list("id_tag" = "Pretty Sensor Name", ...)
tgui_subtemplate = "ShuttleControlConsoleWeb"
skip_act = TRUE
// Note - Searching own area for doors/sensors is fine for legacy web shuttles as they are single-area.
// However if this code is copied to future multi-area shuttles, should search in all shuttle areas
@@ -205,80 +207,9 @@
return ..()
// Fairly copypasta-y.
/obj/machinery/computer/shuttle_control/web/attack_hand(mob/user)
if(..(user))
return
src.add_fingerprint(user)
ui_interact(user)
/*
// If nanoUI falls over and you want a non-nanoUI UI, feel free to uncomment this section.
var/datum/shuttle/autodock/web_shuttle/WS = shuttle_controller.shuttles[shuttle_tag]
if(!istype(WS))
message_admins("ERROR: Shuttle computer ([src]) ([shuttle_tag]) could not find their shuttle in the shuttles list.")
return
var/list/dat = list()
dat += "<center>[shuttle_tag] Ship Control<hr>"
if(WS.moving_status != SHUTTLE_IDLE)
dat += "Location: <font color='red'>Moving</font> <br>"
else
var/area/areacheck = get_area(src)
dat += "Location: [areacheck.name]<br>"
if((WS.last_move + WS.cooldown) > world.time)
dat += "<font color='red'>Engines charging.</font><br>"
else
dat += "<font color='green'>Engines ready.</font><br>"
if(WS.can_cloak)
dat += "<br><b><A href='?src=\ref[src];toggle_cloak=[1]'>Toggle cloaking field</A></b><br>"
for(var/datum/shuttle_route/route in WS.current_destination.routes)
dat += "<b><a href='?src=\ref[src];traverse=\ref[route]'>[route.display_route(WS.current_destination)]</a></b><br>"
//Docking
dat += "<br><br>"
if(WS.skip_docking_checks())
dat += "Docking Status: <font color='grey'>Not in use.</font>"
else
var/override_en = WS.docking_controller.override_enabled
var/docking_status = WS.docking_controller.get_docking_status()
dat += "Docking Status: "
switch(docking_status)
if("undocked")
dat += "<font color='[override_en? "red" : "grey"]'>Undocked</font>"
if("docking")
dat += "<font color='[override_en? "red" : "yellow"]'>Docking</font>"
if("undocking")
dat += "<font color='[override_en? "red" : "yellow"]'>Undocking</font>"
if("docked")
dat += "<font color='[override_en? "red" : "green"]'>Docked</font>"
if(override_en)
dat += " <font color='red'>(Override Enabled)</font>"
dat += ". <A href='?src=\ref[src];refresh=[1]'>\[Refresh\]</A><br><br>"
switch(docking_status)
if("undocked")
dat += "<b><A href='?src=\ref[src];dock_command=[1]'>Dock</A></b>"
if("docked")
dat += "<b><A href='?src=\ref[src];undock_command=[1]'>Undock</A></b>"
dat += "</center>"
user << browse(dat.Join(), "window=[shuttle_tag]shuttlecontrol;size=300x300")
*/
/obj/machinery/computer/shuttle_control/web/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/computer/shuttle_control/web/tgui_data(mob/user)
var/list/data = list()
var/list/routes[0]
var/datum/shuttle/autodock/web_shuttle/shuttle = SSshuttles.shuttles[shuttle_tag]
if(!istype(shuttle))
@@ -286,7 +217,7 @@
return
var/list/R = shuttle.web_master.get_available_routes()
for (var/i = 1 to length(R))
for(var/i = 1 to length(R))
var/datum/shuttle_route/route = R[i]
var/travel_time = null
var/travel_modifier = shuttle.flight_time_modifier
@@ -313,7 +244,6 @@
if(SHUTTLE_INTRANSIT)
shuttle_state = "in_transit"
// For the progress bar.
var/elapsed_time = world.time - shuttle.depart_time
var/total_time = shuttle.arrive_time - shuttle.depart_time
@@ -322,7 +252,6 @@
if(total_time) // Need to check or we might divide by zero.
percent_finished = (elapsed_time / total_time) * 100
var/list/doors = list()
if(my_doors)
for(var/doorname in my_doors)
@@ -356,111 +285,90 @@
"autopilot" = shuttle.autopilot ? 1 : 0,
"can_rename" = shuttle.can_rename ? 1 : 0,
"doors" = doors,
"sensors" = sensors
"sensors" = sensors,
"subtemplate" = tgui_subtemplate,
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
return data
if(!ui)
ui = new(user, src, ui_key, "flight.tmpl", "[shuttle.visible_name] Flight Computer", 500, 500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/shuttle_control/web/Topic(href, href_list)
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
/obj/machinery/computer/shuttle_control/web/tgui_act(action, list/params)
if(..())
return TRUE
var/datum/shuttle/autodock/web_shuttle/WS = SSshuttles.shuttles[shuttle_tag]
if(!istype(WS))
message_admins("ERROR: Shuttle computer ([src]) ([shuttle_tag]) could not find their shuttle in the shuttles list.")
return
if(href_list["refresh"])
ui_interact(usr)
if (WS.moving_status != SHUTTLE_IDLE)
if(WS.moving_status != SHUTTLE_IDLE)
to_chat(usr, "<font color='blue'>[WS.visible_name] is busy moving.</font>")
return
if(href_list["rename_command"])
WS.rename_shuttle(usr)
switch(action)
if("rename_command")
WS.rename_shuttle(usr)
if(href_list["dock_command"])
if(WS.autopilot)
to_chat(usr, "<span class='warning'>The autopilot must be disabled before you can control the vessel manually.</span>")
return
WS.dock()
if("dock_command")
if(WS.autopilot)
to_chat(usr, "<span class='warning'>The autopilot must be disabled before you can control the vessel manually.</span>")
return
WS.dock()
if(href_list["undock_command"])
if(WS.autopilot)
to_chat(usr, "<span class='warning'>The autopilot must be disabled before you can control the vessel manually.</span>")
return
WS.undock()
if("undock_command")
if(WS.autopilot)
to_chat(usr, "<span class='warning'>The autopilot must be disabled before you can control the vessel manually.</span>")
return
WS.undock()
if(href_list["cloak_command"])
if(!WS.can_cloak)
return
WS.cloaked = TRUE
to_chat(usr, "<span class='danger'>Ship stealth systems have been activated. The station will not be warned of our arrival.</span>")
if("toggle_cloaking")
if(!WS.can_cloak)
return
WS.cloaked = !WS.cloaked
if(WS.cloaked)
to_chat(usr, "<span class='danger'>Ship stealth systems have been activated. The station will not be warned of our arrival.</span>")
else
to_chat(usr, "<span class='danger'>Ship stealth systems have been deactivated. The station will be warned of our arrival.</span>")
if(href_list["uncloak_command"])
if(!WS.can_cloak)
return
WS.cloaked = FALSE
to_chat(usr, "<span class='danger'>Ship stealth systems have been deactivated. The station will be warned of our arrival.</span>")
if("toggle_autopilot")
WS.adjust_autopilot(!WS.autopilot)
if(href_list["autopilot_on_command"])
WS.adjust_autopilot(TRUE)
if("traverse")
if(WS.autopilot)
to_chat(usr, "<span class='warning'>The autopilot must be disabled before you can control the vessel manually.</span>")
return
if(href_list["autopilot_off_command"])
WS.adjust_autopilot(FALSE)
if((WS.last_move + WS.cooldown) > world.time)
to_chat(usr, "<font color='red'>The ship's drive is inoperable while the engines are charging.</font>")
return
if(href_list["traverse"])
if(WS.autopilot)
to_chat(usr, "<span class='warning'>The autopilot must be disabled before you can control the vessel manually.</span>")
return
var/index = text2num(params["traverse"])
var/datum/shuttle_route/new_route = WS.web_master.current_destination.routes[index]
if(!istype(new_route))
message_admins("ERROR: Shuttle computer was asked to traverse a nonexistant route.")
return
if((WS.last_move + WS.cooldown) > world.time)
to_chat(usr, "<font color='red'>The ship's drive is inoperable while the engines are charging.</font>")
return
if(!check_docking(WS))
return TRUE
var/index = text2num(href_list["traverse"])
var/datum/shuttle_route/new_route = WS.web_master.current_destination.routes[index]
if(!istype(new_route))
message_admins("ERROR: Shuttle computer was asked to traverse a nonexistant route.")
return
var/datum/shuttle_destination/target_destination = new_route.get_other_side(WS.web_master.current_destination)
if(!istype(target_destination))
message_admins("ERROR: Shuttle computer was asked to travel to a nonexistant destination.")
return
if(!check_docking(WS))
// updateUsrDialog()
ui_interact(usr)
return
WS.next_location = target_destination.my_landmark
if(!can_move(WS, usr))
return
var/datum/shuttle_destination/target_destination = new_route.get_other_side(WS.web_master.current_destination)
if(!istype(target_destination))
message_admins("ERROR: Shuttle computer was asked to travel to a nonexistant destination.")
return
WS.web_master.future_destination = target_destination
to_chat(usr, "<span class='notice'>[WS.visible_name] flight computer received command.</span>")
WS.web_master.reset_autopath() // Deviating from the path will almost certainly confuse the autopilot, so lets just reset its memory.
WS.next_location = target_destination.my_landmark
if(!can_move(WS, usr))
return
WS.web_master.future_destination = target_destination
to_chat(usr, "<span class='notice'>[WS.visible_name] flight computer received command.</span>")
WS.web_master.reset_autopath() // Deviating from the path will almost certainly confuse the autopilot, so lets just reset its memory.
var/travel_time = new_route.travel_time * WS.flight_time_modifier
// TODO - Leshana - Change this to use proccess stuff of autodock!
if(new_route.interim && new_route.travel_time)
WS.long_jump(target_destination.my_landmark, new_route.interim, travel_time / 10)
else
WS.short_jump(target_destination.my_landmark)
ui_interact(usr)
var/travel_time = new_route.travel_time * WS.flight_time_modifier
// TODO - Leshana - Change this to use proccess stuff of autodock!
if(new_route.interim && new_route.travel_time)
WS.long_jump(target_destination.my_landmark, new_route.interim, travel_time / 10)
else
WS.short_jump(target_destination.my_landmark)
//check if we're undocked, give option to force launch
/obj/machinery/computer/shuttle_control/web/proc/check_docking(datum/shuttle/autodock/MS)

View File

@@ -141,6 +141,26 @@
*/
/datum/proc/tgui_close(mob/user)
/**
* verb
*
* Used by a client to fix broken TGUI windows caused by opening a UI window before assets load.
* Probably not very performant and forcibly destroys a bunch of windows, so it has some warnings attached.
* Conveniently, also allows devs to force a dev server reattach without relogging, since it yeets windows.
*/
/client/verb/tgui_fix_white()
set desc = "Only use this if you have a broken TGUI window occupying your screen!"
set name = "Fix TGUI"
set category = "OOC"
if(alert(src, "Only use this verb if you have a white TGUI window stuck on your screen.", "Fix TGUI", "Continue", "Nevermind") != "Continue")
return
SStgui.close_user_uis(mob)
if(alert(src, "Did that fix the problem?", "Fix TGUI", "Yes", "No") == "No")
SStgui.force_close_all_windows(mob)
alert(src, "UIs should be fixed now. If not, please cry to your nearest coder.", "Fix TGUI")
/**
* verb
*

View File

@@ -1,241 +0,0 @@
{{if data.autopilot == 1}}
<div class='notice'>
<b><h3>AI PILOT (CLASS D) ACTIVE</h3></b>
<i>This vessel will start and stop automatically.<br>
Ensure that all non-cycling capable hatches and doors are closed, as the automated system may not be able to control them.<br>
Docking and flight controls are locked. To unlock, disable the automated flight system.</i><br>
</div>
{{/if}}
{{if data.can_rename == 1}}
<div class='item'>
<div class="itemContent">
<div style="float: left; width: 100%;">
{{:helper.link('Rename', 'pencil', {"rename_command" : 1})}}
</div>
</div>
</div>
{{/if}}
<h3>Shuttle Status</h3>
{{if data.is_moving == 0}}
<div class="item">
<div class="itemLabel">
Current Location:
</div>
<div class="itemContent">
{{:data.shuttle_location}}
</div>
</div>
{{/if}}
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Engines:
</div>
<div class="itemContent">
{{if data.shuttle_state == "idle"}}
<span class="idle">IDLE</span>
{{else data.shuttle_state == "warmup"}}
<span style="font-weight: bold;color: #336699">SPINNING UP</span>
{{else data.shuttle_state == "in_transit"}}
<span style="font-weight: bold;color: #336699">ENGAGED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
</div>
</div>
{{if data.is_moving == 0}}
{{if data.skip_docking == 0}}
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Docking Status:
</div>
<div class="itemContent">
{{if data.docking_status == "docked"}}
<span class="good">DOCKED</span>
{{else data.docking_status == "docking"}}
{{if !data.docking_override}}
<span class="average">DOCKING</span>
{{else}}
<span class="average">DOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocking"}}
{{if !data.docking_override}}
<span class="average">UNDOCKING</span>
{{else}}
<span class="average">UNDOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocked"}}
<span class="idle">UNDOCKED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
<span style="float:right">
{{:helper.link('Dock', 'arrowthickstop-1-e', {'dock_command' : 1}, (data.docking_status != "undocked")? 'selected' : null)}}
{{:helper.link('Undock', 'arrowthickstop-1-e', {'undock_command' : 1}, (data.docking_status != "docked")? 'selected' : null)}}
</div>
</div>
</div>
</div>
{{/if}}
{{if data.can_cloak == 1}}
<div class="item">
<div class="itemLabel">
Shuttle Stealth System:
</div>
<span style="float:right">
{{:helper.link('Cloak', 'radio-off', {'cloak_command' : 1}, (data.cloaked == 1)? 'selected' : null)}}
{{:helper.link('Uncloak', 'radio-on', {'uncloak_command' : 1}, (data.cloaked == 0)? 'selected' : null)}}
</div>
</div>
{{/if}}
{{if data.can_autopilot == 1}}
<div class="item">
<div class="itemLabel">
Automated Flight Control:
</div>
<span style="float:right">
{{:helper.link('On', 'circle-check', {'autopilot_on_command' : 1}, (data.autopilot == 1)? 'selected' : null)}}
{{:helper.link('Off', 'circle-close ', {'autopilot_off_command' : 1}, (data.autopilot == 0)? 'selected' : null)}}
</div>
</div>
{{/if}}
{{/if}}
{{if data.is_moving == 0}}
<h3>Available Destinations</h3>
<HR>
<div class="itemContent" style="width: 100%;"></div><BR>
{{for data.routes}}
<div class='item'>
<div class="itemLabel">
{{:value.name}}
</div>
<div class="itemContent">
<div style="float: left; width: 100%;">
{{:helper.link(value.travel_time, 'clock', {"traverse" : value.index})}}
</div>
</div>
</div>
{{/for}}
</div>
{{/if}}
{{if data.is_in_transit == 1}}
<h3>Destination ETA</h3>
<div class="item">
<div class="itemLabel">
Distance from target:
</div>
<div class="itemContent">
{{:helper.displayBar(data.travel_progress, 0, 100, "good")}}
<div class="statusValue">
<span class="good">{{:data.time_left}}s</span>
</div>
</div>
</div>
{{/if}}
{{if data.doors}}
<h3>Hatch Status</h3>
<HR>
<div class="item">
{{props data.doors}}
<div class="item">
<div class="itemLabel">{{:key}}</div>
<div class="itemContent">
{{if value.open}}
<span class="bad">OPN</span>
{{else}}
<span class="good">CLS</span>
{{/if}}
-
{{if value.bolted}}
<span class="good">BLT</span>
{{else}}
<span class="bad">UBLT</span>
{{/if}}
</div>
</div>
{{/props}}
</div>
{{/if}}
{{if data.sensors}}
<h3>Air Readout</h3>
<hr>
{{props data.sensors}}
<div class="item" style="position: relative; overflow: hidden;">
<div class="itemLabel" style="padding-right: 2px; height: 100%; position:absolute;">
<span style="position: relative;display: inline-block; top: 50%;left: 50%;transform: translate(-50%, -50%);">{{:key}}</span>
</div>
<div class="itemContentMedium statusDisplay floatRight" style="overflow: hidden;">
{{if value.reading == 1}}
<div class="itemLabelWide">
Pressure:
</div>
<div class = "itemContentSmall">
{{:helper.string('<span class="{0}">{1} kPa</span>', value.pressure < 80 || value.pressure > 120 ? 'bad' : value.pressure < 95 || value.pressure > 110 ? 'average' : 'good' , value.pressure)}}
</div>
<div class="itemLabelWide">
Temperature:
</div>
<div class = "itemContentSmall">
{{:helper.string('<span class="{0}">{1} &deg;C</span>', value.temp < 5 || value.temp > 35 ? 'bad' : value.temp < 15 || value.temp > 25 ? 'average' : 'good' , value.temp)}}
</div>
<br>
<div class="itemLabelWide">
Oxygen:
</div>
<div class = "itemContentSmall">
{{:helper.string('<span class="{0}">{1}%</span>', value.oxygen < 17 ? 'bad' : value.oxygen < 19 ? 'average' : 'good' , value.oxygen)}}
</div>
<div class="itemLabelWide">
Nitrogen:
</div>
<div class = "itemContentSmall">
{{:helper.string('<span class="{0}">{1}%</span>', value.nitrogen > 82 ? 'bad' : value.nitrogen > 80 ? 'average' : 'good' , value.nitrogen)}}
</div>
<div class="itemLabelWide">
Carbon&nbsp;Dioxide:
</div>
<div class = "itemContentSmall">
{{:helper.string('<span class="{0}">{1}%</span>', value.carbon_dioxide > 5 ? 'bad' : 'good' , value.carbon_dioxide)}}
</div>
<div class="itemLabelWide">
Phoron:
</div>
<div class = "itemContentSmall">
{{:helper.string('<span class="{0}">{1}%</span>', value.phoron > 0 ? 'bad' : 'good' , value.phoron)}}
</div>
{{if value.other > 0}}
<div class="itemLabelWide">
Unknown:
</div>
<div class = "itemContentSmall">
<span class="bad">{{:value.other}}%</span>
</div>
{{/if}}
{{else}}
<div class="itemContent" style="width: 100%;">
<span class="average"><b>Unable to get air reading</b></span>
</div>
{{/if}}
</div>
</div>
{{/props}}
{{/if}}

View File

@@ -1,123 +0,0 @@
<!--
Title: Request Console
Used In File(s): \code\game\machinery\requests_console.dm
#define RCS_MAINMENU 0 // Main men
#define RCS_RQASSIST 1 // Request supplies
#define RCS_RQSUPPLY 2 // Request assistance
#define RCS_SENDINFO 3 // Relay information
#define RCS_SENTPASS 4 // Message sent successfully
#define RCS_SENTFAIL 5 // Message sent unsuccessfully
#define RCS_VIEWMSGS 6 // View messages
#define RCS_MESSAUTH 7 // Authentication before sending
#define RCS_ANNOUNCE 8 // Send announcementu
-->
{{if data.screen == 1}}
<div class="item"><h3>Request assistance from another department.</h3></div>
<table class="block">
{{for data.assist_dept}}
{{if value != data.department}}
<tr>
<td><div class="itemLabelWidest" align="right">{{:value}} -</div></td>
<td><div class="item">{{:helper.link('Message', null, { 'write' : value , 'priority' : 1 })}}</div></td>
<td><div class="item">{{:helper.link('High Priority', null, { 'write' : value , 'priority' : 2 })}}</div></td>
</tr>
{{/if}}
{{empty}}
<tr><td><div class="itemLabel">There are no available departments to request assistance from.</div></td></tr>
{{/for}}
</table><br>
<div class="item">{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}</div>
{{else data.screen == 2}}
<div class="item"><h3>Request supplies from another department.</h3></div>
<table class="block">
{{for data.supply_dept}}
{{if value != data.department}}
<tr>
<td><div class="itemLabelWidest" align="right">{{:value}} - </div></td>
<td><div class="item">{{:helper.link('Message', null, { 'write' : value , 'priority' : 1 })}}</div></td>
<td><div class="item">{{:helper.link('High Priority', null, { 'write' : value , 'priority' : 2 })}}</div></td>
</tr>
{{/if}}
{{empty}}
<tr><td><div class="itemLabel">There are no available departments to request supplies from.</div></td></tr>
{{/for}}
</table><br>
<div class="item">{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}</div>
{{else data.screen == 3}}
<div class="item"><h3>Relay info to another department.</h3></div>
<table class="block">
{{for data.info_dept}}
{{if value != data.department}}
<tr>
<td><div class="itemLabelWidest" align="right">{{:value}} -</div></td>
<td width=70px><div class="item">{{:helper.link('Message', null, { 'write' : value , 'priority' : 1 })}}</div></td>
<td width=90px><div class="item">{{:helper.link('High Priority', null, { 'write' : value , 'priority' : 2 })}}</div></td>
</tr>
{{/if}}
{{empty}}
<tr><td><div class="itemLabel">There are no available departments to relay information to.</div></td></tr>
{{/for}}
</table><br>
<div class="item">{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}</div>
{{else data.screen == 4}}
<div class="item"><b>Message sent successfully.</b></div>
<div class="item">{{:helper.link('Continue', 'arrowthick-1-e', { 'setScreen' : 0 })}}</div>
{{else data.screen == 5}}
<div class="item"><b>An Error occured. Message not sent.</b></div>
<div class="item">{{:helper.link('Continue', 'arrowthick-1-e', { 'setScreen' : 0 })}}</div>
{{else data.screen == 6}}
<div class="statusDisplay" style="overflow: auto;">
{{for data.message_log}}
<div class="item">{{:value}}</div>
<div class="item">{{:helper.link('Print', null, { 'print' : index + 1 })}}</div>
{{empty}}
<div class="item">No messages have been received.</div>
{{/for}}
</div>
<div class="item">{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}</div>
{{else data.screen == 7}}
<div class="item"><h2>Message Authentication</h2></div><br>
<div class="statusDisplay" style="overflow: auto;">
<div class="item"><b>Message for {{:data.recipient}}:</b> {{:data.message}}</div>
<div class="item"><b>Validated by:</b> {{:data.msgVerified}}</div>
<div class="item"><b>Stamped by:</b> {{:data.msgStamped}}</div>
</div>
<div class="item">
{{:helper.link('Send Message', 'arrowthick-1-e', { 'department' : data.recipient })}}
{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}
</div>
{{else data.screen == 8}}
<div class="item"><h2>Station wide announcement</h2></div>
<div class="item"><b>Message:</b> {{:data.message}} {{:helper.link('Write Message', 'pencil', { 'writeAnnouncement' : 1 })}}</div>
<br>
{{if data.announceAuth}}
<div class="item"><b>ID verified. Authentication accepted.</b></div>
{{else}}
<div class="item">Swipe your ID card to authenticate yourself.</div>
{{/if}}
<br>
<div class="item">
{{:helper.link('Announce', 'signal-diag', { 'sendAnnouncement' : 1 }, (data.announceAuth && data.message) ? null : 'disabled' )}}
{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}
</div>
{{else}}
{{if data.newmessagepriority == 1}}
<div class="item"><font color='red'>There are new messages</font></div>
{{else data.newmessagepriority == 2}}
<div class="item"><font color='red'><b>NEW PRIORITY MESSAGES</b></font></div>
{{/if}}
<div class="item">{{:helper.link('View Messages', data.newmessagepriority ? 'mail-closed' : 'mail-open', { 'setScreen' : 6 })}}</div>
<br>
<div class="item">{{:helper.link('Request Assistance', 'gear', { 'setScreen' : 1 })}}</div>
<div class="item">{{:helper.link('Request Supplies', 'gear', { 'setScreen' : 2 })}}</div>
<div class="item">{{:helper.link('Relay Anonymous Information', 'gear', { 'setScreen' : 3})}}</div>
<br>
{{if data.announcementConsole}}
<div class="item">{{:helper.link('Send Station-wide Announcement', 'signal-diag', { 'setScreen' : 8})}}</div>
<br>
{{/if}}
<div class="item">{{:helper.link(data.silent ? 'Speaker OFF' : 'Speaker ON', data.silent ? 'volume-off' : 'volume-on', { 'toggleSilent' : 1})}}</div>
{{/if}}

View File

@@ -1,72 +0,0 @@
<h3>Shuttle Status</h3>
<div class="item" style="padding-top: 10px">
<div class="item">
{{:data.shuttle_status}}
</div>
</div>
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Bluespace Drive:
</div>
<div class="itemContent">
{{if data.shuttle_state == "idle"}}
<span class="idle">IDLE</span>
{{else data.shuttle_state == "warmup"}}
<span style="font-weight: bold;color: #336699">SPINNING UP</span>
{{else data.shuttle_state == "in_transit"}}
<span style="font-weight: bold;color: #336699">ENGAGED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
</div>
</div>
{{if data.has_docking}}
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Docking Status:
</div>
<div class="itemContent">
{{if data.docking_status == "docked"}}
<span class="good">DOCKED</span>
{{else data.docking_status == "docking"}}
{{if !data.docking_override}}
<span class="average">DOCKING</span>
{{else}}
<span class="average">DOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocking"}}
{{if !data.docking_override}}
<span class="average">UNDOCKING</span>
{{else}}
<span class="average">UNDOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocked"}}
<span class="idle">UNDOCKED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
<div class="itemLabel">
Docking Codes:
</div>
<div class="itemContent">
{{:helper.link(data.docking_codes ? data.docking_codes : 'Not set', null, {'set_codes' : '1'}, null , null)}}
</div>
</div>
</div>
{{/if}}
<h3>Shuttle Control</h3>
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemContent" style="padding-top: 2px; width: 100%">
{{:helper.link('Launch Shuttle', 'arrowthickstop-1-e', {'move' : '1'}, data.can_launch? null : 'disabled' , null)}}
{{:helper.link('Cancel Launch', 'cancel', {'cancel' : '1'}, data.can_cancel ? null : 'disabled' , null)}}
{{:helper.link('Force Launch', 'alert', {'force' : '1'}, data.can_force? null : 'disabled' , data.can_force ? 'redButton' : null)}}
</div>
</div>
</div>

View File

@@ -1,95 +0,0 @@
<h3>Shuttle Status</h3>
<div class="item" style="padding-top: 10px">
<div class="item">
{{:data.shuttle_status}}
</div>
</div>
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Engines:
</div>
<div class="itemContent">
{{if data.shuttle_state == "idle"}}
<span class="idle">IDLE</span>
{{else data.shuttle_state == "warmup"}}
<span style="font-weight: bold;color: #336699">SPINNING UP</span>
{{else data.shuttle_state == "in_transit"}}
<span style="font-weight: bold;color: #336699">ENGAGED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
</div>
</div>
{{if data.has_docking}}
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Docking Status:
</div>
<div class="itemContent">
{{if data.docking_status == "docked"}}
<span class="good">DOCKED</span>
{{else data.docking_status == "docking"}}
{{if !data.docking_override}}
<span class="average">DOCKING</span>
{{else}}
<span class="average">DOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocking"}}
{{if !data.docking_override}}
<span class="average">UNDOCKING</span>
{{else}}
<span class="average">UNDOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocked"}}
<span class="idle">UNDOCKED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
<div class="itemLabel">
Docking Codes:
</div>
<div class="itemContent">
{{:helper.link(data.docking_codes ? data.docking_codes : 'Not set', null, {'set_codes' : '1'}, null , null)}}
</div>
</div>
</div>
{{/if}}
<div class="item" style="padding-top: 10px">
<div class="itemLabel">
Current Destination:
</div>
<span class="average">{{:data.destination_name}}</span>
<div class="item">
{{:helper.link('Choose Destination', 'arrowreturn-1-s', {'pick' : '1'}, data.can_pick ? null : 'disabled' , null)}}
</div>
</div>
{{if data.fuel_usage}}
<div class="item" style="padding-top: 10px">
<div class="itemLabel">
Est. Delta-V Budget:
</div>
<div class="itemContent">
<span class='{{:data.fuel_span}}'>{{:data.remaining_fuel}} m/s</span>
</div>
<div class="itemLabel">
Avg. Delta-V Per Maneuver:
</div>
<div class="itemContent">
{{:data.fuel_usage}} m/s
</div>
</div>
{{/if}}
<h3>Shuttle Control</h3>
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemContent" style="padding-top: 2px; width: 100%">
{{:helper.link('Launch Shuttle', 'arrowthickstop-1-e', {'move' : '1'}, data.can_launch ? null : 'disabled' , null)}}
{{:helper.link('Cancel Launch', 'cancel', {'cancel' : '1'}, data.can_cancel ? null : 'disabled' , null)}}
{{:helper.link('Force Launch', 'alert', {'force' : '1'}, data.can_force ? null : 'disabled' , data.can_force ? 'redButton' : null)}}
</div>
</div>
</div>

View File

@@ -1,84 +0,0 @@
<h3>Shuttle Status</h3>
<div class="item" style="padding-top: 10px">
<div class="item">
{{:data.shuttle_status}}
</div>
{{if data.can_cloak}}
<div class="item">
{{:data.legit ? "ATC Inhibitor" : "Cloaking Field"}} is {{:data.cloaked ? "enabled" : "disabled"}}. {{:helper.link('Toggle', 'arrowreturn-1-s', {'toggle_cloaked' : '1'}) }}
</div>
{{/if}}
</div>
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Bluespace Drive:
</div>
<div class="itemContent">
{{if data.shuttle_state == "idle"}}
<span class="idle">IDLE</span>
{{else data.shuttle_state == "warmup"}}
<span style="font-weight: bold;color: #336699">SPINNING UP</span>
{{else data.shuttle_state == "in_transit"}}
<span style="font-weight: bold;color: #336699">ENGAGED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
</div>
</div>
{{if data.has_docking}}
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Docking Status:
</div>
<div class="itemContent">
{{if data.docking_status == "docked"}}
<span class="good">DOCKED</span>
{{else data.docking_status == "docking"}}
{{if !data.docking_override}}
<span class="average">DOCKING</span>
{{else}}
<span class="average">DOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocking"}}
{{if !data.docking_override}}
<span class="average">UNDOCKING</span>
{{else}}
<span class="average">UNDOCKING-MANUAL</span>
{{/if}}
{{else data.docking_status == "undocked"}}
<span class="idle">UNDOCKED</span>
{{else}}
<span class="bad">ERROR</span>
{{/if}}
</div>
<div class="itemLabel">
Docking Codes:
</div>
<div class="itemContent">
{{:helper.link(data.docking_codes ? data.docking_codes : 'Not set', null, {'set_codes' : '1'}, null , null)}}
</div>
</div>
</div>
{{/if}}
<div class="item" style="padding-top: 10px">
<div class="itemLabel">
Current Destination:
</div>
<span class="average">{{:data.destination_name}}</span>
<div class="item">
{{:helper.link('Choose Destination', 'arrowreturn-1-s', {'pick' : '1'}, data.can_pick ? null : 'disabled' , null)}}
</div>
</div>
<h3>Shuttle Control</h3>
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemContent" style="padding-top: 2px; width: 100%">
{{:helper.link('Launch Shuttle', 'arrowthickstop-1-e', {'move' : '1'}, data.can_launch ? null : 'disabled' , null)}}
{{:helper.link('Cancel Launch', 'cancel', {'cancel' : '1'}, data.can_cancel ? null : 'disabled' , null)}}
{{:helper.link('Force Launch', 'alert', {'force' : '1'}, data.can_force ? null : 'disabled' , data.can_force ? 'redButton' : null)}}
</div>
</div>
</div>

View File

@@ -1,83 +0,0 @@
<div class="item" style="padding-top: 10px">
<div class="item">
<div class="itemLabel">
Scn. Ramestat Core:
</div>
<div class="itemContent">
{{:helper.displayBar(data.timeout_percent, 0, 100, (data.timeout_percent < 75) ? 'bad' : (data.timeout_percent < 100) ? 'average' : 'good')}}
</div>
</div>
</div>
<div class="item">
<div class="itemLabel">
Mineral Content:
</div>
<div class="itemContent">
{{:data.difficulty}}
</div>
</div>
</div>
<div class="item">
<div class="itemLabel">
Shuttle Location:
</div>
<div class="itemContent">
{{:data.shuttle_location}}
</div>
{{if data.can_recall_shuttle > 0}}
<div class="itemContent">
{{:helper.link('Recall Shuttle', 'alert-red', {'action' : 'recall_shuttle'}, null)}}
</div>
{{/if}}
</div>
{{if data.occupied > 0}}
<div class="item">
<div class="itemLabel">
WARNING:
</div>
<div class="itemContent">
Area Occupied by {{:data.occupied}} personnel!
</div>
</div>
{{/if}}
<h3>Scanner Operation</h3>
<div class="item">
<div class="itemLabel">
Scanner Activation:
</div>
<div class="itemContent">
{{:helper.link('Scan For Asteroids', 'power', {'action' : 'scan_for_new'}, data.scan_ready ? null : 'disabled')}}
</div>
</div>
{{if data.scanning > 0}}
<div class="item">
<div class="itemLabel">
Scanning:
</div>
<div class="itemContent">
In Progress...
</div>
</div>
{{/if}}
{{if data.updated > 0 && data.scanning == 0}}
<div class="item">
<div class="itemLabel">
Info:
</div>
<div class="itemContent">
Updated shuttle destination!
</div>
</div>
{{/if}}
{{if data.debug > 0}}
<div class="item">
<div class="itemLabel">
DEBUG:
</div>
<div class="itemContent">
TP:{{:data.timeout_percent}},DS:{{:data.diffstep}},D:{{:data.difficulty}},O:{{:data.occupied}},DBG:{{:data.debug}},SL:{{:data.shuttle_location}},SAS:{{:data.shuttle_at_station}},SR:{{:data.scan_ready}}
</div>
</div>
{{/if}}

View File

@@ -103,4 +103,14 @@ export const formatCommaNumber = value => {
let parts = value.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
};
};
// Function from https://stackoverflow.com/a/34841026. CC BY-SA 4.0.
export const formatTime = seconds => {
let hours = Math.floor(seconds / 3600);
let minutes = Math.floor(seconds / 60) % 60;
return [hours, minutes, seconds % 60]
.map(v => v < 10 ? "0" + v : v)
.filter((v, i) => v !== "00" || i > 0)
.join(":");
};

View File

@@ -0,0 +1,34 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table } from "../components";
import { Window } from "../layouts";
export const DestinationTagger = (props, context) => {
const { act, data } = useBackend(context);
const {
currTag,
taggerLocs,
} = data;
return (
<Window width={450} height={310} resizable>
<Window.Content>
<Section title="Tagger Locations">
<Flex wrap="wrap" spacing={1} justify="center">
{taggerLocs.sort().map(tag => (
<Flex.Item key={tag}>
<Button
icon={(currTag === tag) ? "check-square-o" : "square-o"}
selected={currTag === tag}
content={tag}
onClick={() => act("set_tag", { tag: tag })} />
</Flex.Item>
))}
</Flex>
</Section>
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,133 @@
import { map, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { clamp } from 'common/math';
import { vecLength, vecSubtract } from 'common/vector';
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, Icon, LabeledList, Section, Table } from '../components';
import { Window } from '../layouts';
import { createLogger } from '../logging';
const logger = createLogger('lol what');
const coordsToVec = coords => map(parseFloat)(coords.split(', '));
export const Gps = (props, context) => {
const { act, data } = useBackend(context);
const {
currentArea,
currentCoords,
currentCoordsText,
globalmode,
power,
tag,
updating,
} = data;
const signals = flow([
map((signal, index) => {
// Calculate distance to the target. BYOND distance is capped to 127,
// that's why we roll our own calculations here.
const dist = signal.dist && (
Math.round(vecLength(vecSubtract(
currentCoords,
signal.coords)))
);
return { ...signal, dist, index };
}),
sortBy(
// Signals with distance metric go first
signal => signal.dist === undefined,
// Sort alphabetically
signal => signal.entrytag),
])(data.signals || []);
return (
<Window
title="Global Positioning System"
width={470}
height={700}
resizable>
<Window.Content scrollable>
<Section
title="Control"
buttons={(
<Button
icon="power-off"
content={power ? "On" : "Off"}
selected={power}
onClick={() => act('power')} />
)}>
<LabeledList>
<LabeledList.Item label="Tag">
<Button
icon="pencil-alt"
content={tag}
onClick={() => act('rename')} />
</LabeledList.Item>
<LabeledList.Item label="Scan Mode">
<Button
icon={updating ? "unlock" : "lock"}
content={updating ? "AUTO" : "MANUAL"}
color={!updating && "bad"}
onClick={() => act('updating')} />
</LabeledList.Item>
<LabeledList.Item label="Range">
<Button
icon="sync"
content={globalmode ? "MAXIMUM" : "LOCAL"}
selected={!globalmode}
onClick={() => act('globalmode')} />
</LabeledList.Item>
</LabeledList>
</Section>
{!!power && (
<Fragment>
<Section title="Current Location">
<Box fontSize="18px">
{currentArea} ({currentCoordsText})
</Box>
</Section>
<Section title="Detected Signals">
<Table>
<Table.Row bold>
<Table.Cell content="Name" />
<Table.Cell collapsing content="Direction" />
<Table.Cell collapsing content="Coordinates" />
</Table.Row>
{signals.map(signal => (
<Table.Row
key={signal.entrytag + signal.coords + signal.index}
className="candystripe">
<Table.Cell bold color="label">
{signal.entrytag}
</Table.Cell>
<Table.Cell
collapsing
opacity={signal.dist !== undefined && (
clamp(
1.2 / Math.log(Math.E + signal.dist / 20),
0.4, 1)
)}>
{signal.degrees !== undefined && (
<Icon
mr={1}
size={1.2}
name="arrow-up"
rotation={signal.degrees} />
)}
{signal.dist !== undefined && (
signal.dist + 'm'
)}
</Table.Cell>
<Table.Cell collapsing>
{signal.coordsText}
</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
</Fragment>
)}
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,145 @@
import { toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Collapsible, Dropdown, Flex, Input, NoticeBox, Section, LabeledList, AnimatedNumber } from '../components';
import { Window } from "../layouts";
import { refocusLayout } from '../layouts';
import { sortBy } from 'common/collections';
import { MiningUser } from './common/Mining';
export const MiningOreProcessingConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
unclaimedPoints,
ores,
showAllOres,
power,
} = data;
return (
<Window width={400} height={500} resizable>
<Window.Content>
<MiningUser insertIdText={(
<Box>
<Button
icon="arrow-right"
mr={1}
onClick={() => act("insert")}>
Insert ID
</Button>
in order to claim points.
</Box>
)} />
<Section title="Status" buttons={
<Button
icon="power-off"
selected={power}
onClick={() => act("power")}>
{power ? "Smelting" : "Not Smelting"}
</Button>
}>
<LabeledList>
<LabeledList.Item label="Current unclaimed points" buttons={
<Button
disabled={unclaimedPoints < 1}
icon="download"
onClick={() => act("claim")}>
Claim
</Button>
}>
<AnimatedNumber value={unclaimedPoints} />
</LabeledList.Item>
</LabeledList>
</Section>
<MOPCOres />
</Window.Content>
</Window>
);
};
// ORDER IS IMPORTANT HERE.
const processingOptions = [
"Not Processing",
"Smelting",
"Compressing",
"Alloying",
];
// Higher in the list == closer to top
// This is just kind of an arbitrary list to sort by because the machine has no predictable ore order in it's list
// and alphabetizing them doesn't really make sense
const oreOrder = [
"verdantium",
"mhydrogen",
"diamond",
"platinum",
"uranium",
"gold",
"silver",
"rutile",
"phoron",
"marble",
"lead",
"sand",
"carbon",
"hematite",
];
const oreSorter = (a, b) => {
if (oreOrder.indexOf(a.ore) === -1) {
return a.ore - b.ore;
}
if (oreOrder.indexOf(b.ore) === -1) {
return a.ore - b.ore;
}
return oreOrder.indexOf(b.ore) - oreOrder.indexOf(a.ore);
};
const MOPCOres = (props, context) => {
const { act, data } = useBackend(context);
const {
ores,
showAllOres,
power,
} = data;
return (
<Section title="Ore Processing Controls" buttons={
<Button
icon={showAllOres ? "toggle-on" : "toggle-off"}
selected={showAllOres}
onClick={() => act("showAllOres")}>
{showAllOres ? "All Ores" : "Ores in Machine"}
</Button>
}>
<LabeledList>
{ores.length && ores.sort(oreSorter).map(ore => (
<LabeledList.Item key={ore.ore} label={toTitleCase(ore.name)} buttons={
<Dropdown
width="120px"
color={
ore.processing === 0 && 'red'
|| ore.processing === 1 && 'green'
|| ore.processing === 2 && 'blue'
|| ore.processing === 3 && 'yellow'
}
options={processingOptions}
selected={processingOptions[ore.processing]}
onSelected={val => act("toggleSmelting", {
ore: ore.ore,
set: processingOptions.indexOf(val),
})} />
}>
<Box inline>
<AnimatedNumber value={ore.amount} />
</Box>
</LabeledList.Item>
)) || (
<Box color="bad" textAlign="center">
No ores in machine.
</Box>
)}
</LabeledList>
</Section>
);
};

View File

@@ -0,0 +1,51 @@
import { toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Collapsible, Dropdown, Flex, Input, NoticeBox, Section, LabeledList, AnimatedNumber, NumberInput } from '../components';
import { Window } from "../layouts";
import { sortBy } from 'common/collections';
export const MiningStackingConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
stacktypes,
stackingAmt,
} = data;
return (
<Window width={400} height={500} resizable>
<Window.Content>
<Section title="Stacker Controls">
<LabeledList>
<LabeledList.Item label="Stacking">
<NumberInput
fluid
value={stackingAmt}
minValue={1}
maxValue={50}
stepPixelSize={5}
onChange={(e, val) => act("change_stack", { amt: val })} />
</LabeledList.Item>
<LabeledList.Divider />
{stacktypes.length && stacktypes.sort().map(stack => (
<LabeledList.Item key={stack.type} label={toTitleCase(stack.type)} buttons={
<Button
icon="eject"
onClick={() => act("release_stack", { stack: stack.type })}>
Eject
</Button>
}>
<AnimatedNumber value={stack.amt} />
</LabeledList.Item>
)) || (
<LabeledList.Item label="Empty" color="average">
No stacks in machine.
</LabeledList.Item>
)}
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,179 @@
import { createSearch } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Collapsible, Dropdown, Flex, Input, NoticeBox, Section } from '../components';
import { Window } from "../layouts";
import { refocusLayout } from '../layouts';
import { MiningUser } from './common/Mining';
const sortTypes = {
'Alphabetical': (a, b) => a - b,
'By availability': (a, b) => -(a.affordable - b.affordable),
'By price': (a, b) => a.price - b.price,
};
export const MiningVendor = (props, context) => {
return (
<Window width={400} height={450} resizable>
<Window.Content className="Layout__content--flexColumn" scrollable>
<MiningUser insertIdText="Please insert an ID in order to make purchases." />
<MiningVendorSearch />
<MiningVendorItems />
</Window.Content>
</Window>
);
};
const MiningVendorItems = (props, context) => {
const { act, data } = useBackend(context);
const {
has_id,
id,
items,
} = data;
// Search thingies
const [
searchText,
_setSearchText,
] = useLocalState(context, 'search', '');
const [
sortOrder,
_setSortOrder,
] = useLocalState(context, 'sort', 'Alphabetical');
const [
descending,
_setDescending,
] = useLocalState(context, 'descending', false);
const searcher = createSearch(searchText, item => {
return item[0];
});
let has_contents = false;
let contents = Object.entries(items).map((kv, _i) => {
let items_in_cat = Object.entries(kv[1])
.filter(searcher)
.map(kv2 => {
kv2[1].affordable = has_id && id.points >= kv2[1].price;
return kv2[1];
})
.sort(sortTypes[sortOrder]);
if (items_in_cat.length === 0) {
return;
}
if (descending) {
items_in_cat = items_in_cat.reverse();
}
has_contents = true;
return (
<MiningVendorItemsCategory
key={kv[0]}
title={kv[0]}
items={items_in_cat}
/>
);
});
return (
<Flex.Item grow="1" overflow="auto">
<Section onClick={e => refocusLayout()}>
{has_contents
? contents : (
<Box color="label">
No items matching your criteria was found!
</Box>
)}
</Section>
</Flex.Item>
);
};
const MiningVendorSearch = (props, context) => {
const [
_searchText,
setSearchText,
] = useLocalState(context, 'search', '');
const [
_sortOrder,
setSortOrder,
] = useLocalState(context, 'sort', '');
const [
descending,
setDescending,
] = useLocalState(context, 'descending', false);
return (
<Box mb="0.5rem">
<Flex width="100%">
<Flex.Item grow="1" mr="0.5rem">
<Input
placeholder="Search by item name.."
width="100%"
onInput={(_e, value) => setSearchText(value)}
/>
</Flex.Item>
<Flex.Item basis="30%">
<Dropdown
selected="Alphabetical"
options={Object.keys(sortTypes)}
width="100%"
lineHeight="19px"
onSelected={v => setSortOrder(v)} />
</Flex.Item>
<Flex.Item>
<Button
icon={descending ? "arrow-down" : "arrow-up"}
height="19px"
tooltip={descending ? "Descending order" : "Ascending order"}
tooltipPosition="bottom-left"
ml="0.5rem"
onClick={() => setDescending(!descending)}
/>
</Flex.Item>
</Flex>
</Box>
);
};
const MiningVendorItemsCategory = (properties, context) => {
const { act, data } = useBackend(context);
const {
title,
items,
...rest
} = properties;
return (
<Collapsible open title={title} {...rest}>
{items.map(item => (
<Box key={item.name}>
<Box
display="inline-block"
verticalAlign="middle"
lineHeight="20px"
style={{
float: 'left',
}}>
{item.name}
</Box>
<Button
disabled={!data.has_id || data.id.points < item.price}
content={item.price.toLocaleString('en-US')}
width="15%"
textAlign="center"
style={{
float: 'right',
}}
onClick={() => act('purchase', {
cat: title,
name: item.name,
})}
/>
<Box
style={{
clear: "both",
}}
/>
</Box>
))}
</Collapsible>
);
};

View File

@@ -0,0 +1,139 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
export const MuleBot = (props, context) => {
const { act, data } = useBackend(context);
const {
suffix,
power,
load,
locked,
issilicon,
auto_return,
crates_only,
hatch,
safety,
} = data;
return (
<Window width={350} height={500}>
<Window.Content>
<Section title="Multiple Utility Load Effector Mk. III">
<LabeledList>
<LabeledList.Item label="ID">
{suffix}
</LabeledList.Item>
<LabeledList.Item label="Current Load" buttons={
<Button
icon="eject"
content="Unload Now"
disabled={!load}
onClick={() => act("unload")} />
}>
{load ? load : "None."}
</LabeledList.Item>
</LabeledList>
{hatch ? <MuleBotOpen /> : <MuleBotClosed />}
</Section>
</Window.Content>
</Window>
);
};
const MuleBotClosed = (props, context) => {
const { act, data } = useBackend(context);
const {
suffix,
power,
load,
locked,
issilicon,
auto_return,
crates_only,
open,
safety,
} = data;
return (
<Section level={2} title="Controls" buttons={
<Button
icon="power-off"
content={power ? "On" : "Off"}
selected={power}
disabled={locked && !issilicon}
onClick={() => act("power")} />
}>
{(locked && !issilicon) ? (
<Box color="bad">This interface is currently locked.</Box>
) : (
<Fragment>
<Button
fluid
icon="stop"
content="Stop"
onClick={() => act("stop")} />
<Button
fluid
icon="truck-monster"
content="Proceed"
onClick={() => act("go")} />
<Button
fluid
icon="home"
content="Return Home"
onClick={() => act("home")} />
<Button
fluid
icon="map-marker-alt"
content="Set Destination"
onClick={() => act("destination")} />
<Button
fluid
icon="cog"
content="Set Home"
onClick={() => act("sethome")} />
<Button
fluid
icon="home"
selected={auto_return}
content={"Auto Return Home: " + (auto_return ? "Enabled" : "Disabled")}
onClick={() => act("autoret")} />
<Button
fluid
icon="biking"
selected={!crates_only}
content={"Non-standard Cargo: " + (crates_only ? "Disabled" : "Enabled")}
onClick={() => act("cargotypes")} />
</Fragment>
)}
</Section>
);
};
const MuleBotOpen = (props, context) => {
const { act, data } = useBackend(context);
const {
suffix,
power,
load,
locked,
issilicon,
auto_return,
crates_only,
open,
safety,
} = data;
return (
<Section level={2} title="Maintenance Panel">
<Button
fluid
icon="skull-crossbones"
color={safety ? "green" : "red"}
content={"Safety: " + (safety ? "Engaged" : "Disengaged (DANGER)")}
onClick={() => act("safety")} />
</Section>
);
};

View File

@@ -0,0 +1,53 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
export const NoticeBoard = (props, context) => {
const { act, data } = useBackend(context);
const {
notices,
} = data;
return (
<Window width={330} height={300}>
<Window.Content>
<Section>
{notices.length ? (
<LabeledList>
{notices.map((notice, i) => (
<LabeledList.Item key={i} label={notice.name}>
{notice.isphoto && (
<Button
icon="image"
content="Look"
onClick={() => act("look", { ref: notice.ref })} />
) || notice.ispaper && (
<Fragment>
<Button
icon="sticky-note"
content="Read"
onClick={() => act("read", { ref: notice.ref })} />
<Button
icon="pen"
content="Write"
onClick={() => act("write", { ref: notice.ref })} />
</Fragment>
) || "Unknown Entity"}
<Button
icon="minus-circle"
content="Remove"
onClick={() => act("remove", { ref: notice.ref })} />
</LabeledList.Item>
))}
</LabeledList>
) : (
<Box color="average">No notices posted here.</Box>
)}
</Section>
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,332 @@
import { decodeHtmlEntities } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Tabs } from "../components";
import { Window } from "../layouts";
const RCS_MAINMENU = 0; // Settings menu
const RCS_RQASSIST = 1; // Request supplies
const RCS_RQSUPPLY = 2; // Request assistance
const RCS_SENDINFO = 3; // Relay information
const RCS_SENTPASS = 4; // Message sent successfully
const RCS_SENTFAIL = 5; // Message sent unsuccessfully
const RCS_VIEWMSGS = 6; // View messages
const RCS_MESSAUTH = 7; // Authentication before sending
const RCS_ANNOUNCE = 8; // Send announcement
const RequestConsoleSettings = (props, context) => {
const { act, data } = useBackend(context);
const {
silent,
} = data;
return (
<Section title="Settings">
<Button
selected={!silent}
icon={silent ? "volume-mute" : "volume-up"}
onClick={() => act("toggleSilent")}>
Speaker {silent ? "OFF" : "ON"}
</Button>
</Section>
);
};
const RequestConsoleSupplies = (props, context) => {
const { act, data } = useBackend(context);
const {
department,
supply_dept,
} = data;
return (
<Section title="Supplies">
<RequestConsoleSendMenu dept_list={supply_dept} department={department} />
</Section>
);
};
const RequestConsoleAssistance = (props, context) => {
const { act, data } = useBackend(context);
const {
department,
assist_dept,
} = data;
return (
<Section title="Request assistance from another department">
<RequestConsoleSendMenu dept_list={assist_dept} department={department} />
</Section>
);
};
const RequestConsoleRelay = (props, context) => {
const { act, data } = useBackend(context);
const {
department,
info_dept,
} = data;
return (
<Section title="Report Anonymous Information">
<RequestConsoleSendMenu dept_list={info_dept} department={department} />
</Section>
);
};
const RequestConsoleSendMenu = (props, context) => {
const { act } = useBackend(context);
const {
dept_list,
department,
} = props;
return (
<LabeledList>
{dept_list.sort().map(dept => dept !== department && (
<LabeledList.Item label={dept} buttons={
<Fragment>
<Button
icon="envelope-open-text"
onClick={() => act("write", { write: dept, priority: 1 })}>
Message
</Button>
<Button
icon="exclamation-triangle"
onClick={() => act("write", { write: dept, priority: 2 })}>
High Priority
</Button>
</Fragment>
} />
) || null)}
</LabeledList>
);
};
const RequestConsoleSendPass = (props, context) => {
const { act, data } = useBackend(context);
return (
<Section>
<Box fontSize={2} color="good">
Message Sent Successfully
</Box>
<Box>
<Button
icon="arrow-right"
onClick={() => act("setScreen", { setScreen: RCS_MAINMENU })}>
Continue
</Button>
</Box>
</Section>
);
};
const RequestConsoleSendFail = (props, context) => {
const { act, data } = useBackend(context);
return (
<Section>
<Box fontSize={1.5} bold color="bad">
An error occured. Message Not Sent.
</Box>
<Box>
<Button
icon="arrow-right"
onClick={() => act("setScreen", { setScreen: RCS_MAINMENU })}>
Continue
</Button>
</Box>
</Section>
);
};
const RequestConsoleViewMessages = (props, context) => {
const { act, data } = useBackend(context);
const {
message_log,
} = data;
return (
<Section title="Messages">
{(message_log.length && message_log.map((msg, i) => (
<LabeledList.Item label={decodeHtmlEntities(msg[0])} key={i}
buttons={
<Button
icon="print"
onClick={() => act("print", { print: i + 1 })}>
Print
</Button>
}>
{decodeHtmlEntities(msg[1])}
</LabeledList.Item>
))) || (
<Box>
No messages.
</Box>
)}
</Section>
);
};
const RequestConsoleMessageAuth = (props, context) => {
const { act, data } = useBackend(context);
const {
message,
recipient,
priority,
msgStamped,
msgVerified,
} = data;
return (
<Section title="Message Authentication">
<LabeledList>
<LabeledList.Item label={"Message for " + recipient}>
{message}
</LabeledList.Item>
<LabeledList.Item label="Priority">
{priority === 2 ? "High Priority" : (priority === 1 ? "Normal Priority" : "Unknown")}
</LabeledList.Item>
<LabeledList.Item label="Validated By" color={msgVerified ? "good" : "bad"}>
{decodeHtmlEntities(msgVerified) || "No Validation"}
</LabeledList.Item>
<LabeledList.Item label="Stamped By" color={msgStamped ? "good" : "bad"}>
{decodeHtmlEntities(msgStamped) || "No Stamp"}
</LabeledList.Item>
</LabeledList>
<Button
mt={1}
icon="share"
onClick={() => act("department", { department: recipient })}>
Send Message
</Button>
<Button
icon="undo"
onClick={() => act("setScreen", { setScreen: RCS_MAINMENU })}>
Back
</Button>
</Section>
);
};
const RequestConsoleAnnounce = (props, context) => {
const { act, data } = useBackend(context);
const {
department,
screen,
message_log,
newmessagepriority,
silent,
announcementConsole,
assist_dept,
supply_dept,
info_dept,
message,
recipient,
priority,
msgStamped,
msgVerified,
announceAuth,
} = data;
return (
<Section title="Send Station-Wide Announcement">
{announceAuth && (
<Fragment>
<Box bold color="good" mb={1}>
ID Verified. Authentication Accepted.
</Box>
<Section title="Message" mt={1} maxHeight="200px" scrollable buttons={
<Button
ml={1}
icon="pen"
onClick={() => act("writeAnnouncement")}>
Edit
</Button>
}>
{message || "No Message"}
</Section>
</Fragment>
) || (
<Box bold color="bad" mb={1}>
Swipe your ID card to authenticate yourself.
</Box>
)}
<Button
disabled={!message || !announceAuth}
icon="share"
onClick={() => act("sendAnnouncement")}>
Announce
</Button>
<Button
icon="undo"
onClick={() => act("setScreen", { setScreen: RCS_MAINMENU })}>
Back
</Button>
</Section>
);
};
let screenToTemplate = {};
screenToTemplate[RCS_MAINMENU] = RequestConsoleSettings;
screenToTemplate[RCS_RQASSIST] = RequestConsoleAssistance;
screenToTemplate[RCS_RQSUPPLY] = RequestConsoleSupplies;
screenToTemplate[RCS_SENDINFO] = RequestConsoleRelay;
screenToTemplate[RCS_SENTPASS] = RequestConsoleSendPass;
screenToTemplate[RCS_SENTFAIL] = RequestConsoleSendFail;
screenToTemplate[RCS_VIEWMSGS] = RequestConsoleViewMessages;
screenToTemplate[RCS_MESSAUTH] = RequestConsoleMessageAuth;
screenToTemplate[RCS_ANNOUNCE] = RequestConsoleAnnounce;
export const RequestConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
screen,
newmessagepriority,
announcementConsole,
} = data;
let BodyElement = screenToTemplate[screen];
return (
<Window width={520} height={410} resizable>
<Window.Content scrollable>
<Tabs>
<Tabs.Tab
selected={screen === RCS_VIEWMSGS}
onClick={() => act("setScreen", { setScreen: RCS_VIEWMSGS })}
icon="envelope-open-text">
Messages
</Tabs.Tab>
<Tabs.Tab
selected={screen === RCS_RQASSIST}
onClick={() => act("setScreen", { setScreen: RCS_RQASSIST })}
icon="share-square">
Assistance
</Tabs.Tab>
<Tabs.Tab
selected={screen === RCS_RQSUPPLY}
onClick={() => act("setScreen", { setScreen: RCS_RQSUPPLY })}
icon="share-square">
Supplies
</Tabs.Tab>
<Tabs.Tab
selected={screen === RCS_SENDINFO}
onClick={() => act("setScreen", { setScreen: RCS_SENDINFO })}
icon="share-square-o">
Report
</Tabs.Tab>
{announcementConsole && (
<Tabs.Tab
selected={screen === RCS_ANNOUNCE}
onClick={() => act("setScreen", { setScreen: RCS_ANNOUNCE })}
icon="volume-up">
Announce
</Tabs.Tab>
) || null}
<Tabs.Tab
selected={screen === RCS_MAINMENU}
onClick={() => act("setScreen", { setScreen: RCS_MAINMENU })}
icon="cog" />
</Tabs>
{newmessagepriority && (
<Section
title={newmessagepriority > 1 ? "NEW PRIORITY MESSAGES" : "There are new messages!"}
color={newmessagepriority > 1 ? "bad" : "average"} bold={newmessagepriority > 1} />
) || null}
<BodyElement />
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,98 @@
import { useBackend } from "../backend";
import { Box, Button, LabeledList, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
export const RogueZones = (props, context) => {
const { act, data } = useBackend(context);
const {
timeout_percent,
diffstep,
difficulty,
occupied,
scanning,
updated,
debug,
shuttle_location,
shuttle_at_station,
scan_ready,
can_recall_shuttle,
} = data;
return (
<Window width={360} height={250} resizable>
<Window.Content>
<Section title="Current Area">
<LabeledList>
<LabeledList.Item label="Mineral Content">
{difficulty}
</LabeledList.Item>
<LabeledList.Item label="Shuttle Location" buttons={
can_recall_shuttle && (
<Button
color="bad"
icon="rocket"
onClick={() => act("recall_shuttle")}>
Recall Shuttle
</Button>
) || null
}>
{shuttle_location}
</LabeledList.Item>
{occupied && (
<LabeledList.Item color="bad" labelColor="bad" label="Personnel">
WARNING: Area occupied by {occupied} personnel!
</LabeledList.Item>
) || (
<LabeledList.Item label="Personnel" color="good">
No personnel detected.
</LabeledList.Item>
)}
</LabeledList>
</Section>
<Section title="Scanner" buttons={
<Button
disabled={!scan_ready}
fluid
icon="search"
onClick={() => act("scan_for_new")}>
Scan For Asteroids
</Button>
}>
<LabeledList>
<LabeledList.Item label="Scn Ramestat Core">
<ProgressBar
value={timeout_percent}
maxValue={100}
ranges={{
good: [100, Infinity],
average: [75, 100],
bad: [-Infinity, 75],
}} />
</LabeledList.Item>
{scanning && (
<LabeledList.Item label="Scanning">
In progress.
</LabeledList.Item>
) || null}
{(updated && !scanning) && (
<LabeledList.Item label="Info">
Updated shuttle destination!
</LabeledList.Item>
) || null}
{debug && (
<LabeledList.Item label="Debug" labelColor="bad">
<Box>Timeout Percent: {timeout_percent}</Box>
<Box>Diffstep: {diffstep}</Box>
<Box>Difficulty: {difficulty}</Box>
<Box>Occupied: {occupied}</Box>
<Box>Debug: {debug}</Box>
<Box>Shuttle Location: {shuttle_location}</Box>
<Box>Shuttle at station: {shuttle_at_station}</Box>
<Box>Scan Ready: {scan_ready}</Box>
</LabeledList.Item>
) || null}
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,478 @@
import { toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, AnimatedNumber } from "../components";
import { Window } from "../layouts";
/* Helpers */
const getDockingStatus = (docking_status, docking_override) => {
let main = "ERROR";
let color = "bad";
let showsOverride = false;
if (docking_status === "docked") {
main = "DOCKED";
color = "good";
} else if (docking_status === "docking") {
main = "DOCKING";
color = "average";
showsOverride = true;
} else if (docking_status === "undocking") {
main = "UNDOCKING";
color = "average";
showsOverride = true;
} else if (docking_status === "undocked") {
main = "UNDOCKED";
color = "#676767";
}
if (showsOverride && docking_override) {
main = main + "-MANUAL";
}
return (
<Box color={color}>
{main}
</Box>
);
};
/* Templates */
const ShuttleControlSharedShuttleStatus = (props, context) => {
const { act, data } = useBackend(context);
const {
engineName = "Bluespace Drive",
} = props;
const {
shuttle_status,
shuttle_state,
has_docking,
docking_status,
docking_override,
docking_codes,
} = data;
return (
<Section title="Shuttle Status">
<Box color="label" mb={1}>{shuttle_status}</Box>
<LabeledList>
<LabeledList.Item label={engineName}>
{shuttle_state === "idle" && (
<Box color="#676767" bold>
IDLE
</Box>
) || shuttle_state === "warmup" && (
<Box color="#336699">
SPINNING UP
</Box>
) || shuttle_state === "in_transit" && (
<Box color="#336699">
ENGAGED
</Box>
) || (
<Box color="bad">
ERROR
</Box>
)}
</LabeledList.Item>
{has_docking && (
<Fragment>
<LabeledList.Item label="Docking Status">
{getDockingStatus(docking_status, docking_override)}
</LabeledList.Item>
<LabeledList.Item label="Docking Codes">
<Button
icon="pen"
onClick={() => act("set_codes")}>
{docking_codes || "Not Set"}
</Button>
</LabeledList.Item>
</Fragment>
) || null}
</LabeledList>
</Section>
);
};
const ShuttleControlSharedShuttleControls = (props, context) => {
const { act, data } = useBackend(context);
const {
can_launch,
can_cancel,
can_force,
} = data;
return (
<Section title="Controls">
<Flex spacing={1}>
<Flex.Item grow={1}>
<Button
onClick={() => act("move")}
disabled={!can_launch}
icon="rocket"
fluid>
Launch Shuttle
</Button>
</Flex.Item>
<Flex.Item grow={1}>
<Button
onClick={() => act("cancel")}
disabled={!can_cancel}
icon="ban"
fluid>
Cancel Launch
</Button>
</Flex.Item>
<Flex.Item grow={1}>
<Button
onClick={() => act("force")}
color="bad"
disabled={!can_force}
icon="exclamation-triangle"
fluid>
Force Launch
</Button>
</Flex.Item>
</Flex>
</Section>
);
};
const ShuttleControlConsoleDefault = (props, context) => {
const { act, data } = useBackend(context);
return (
<Fragment>
<ShuttleControlSharedShuttleStatus />
<ShuttleControlSharedShuttleControls />
</Fragment>
);
};
const ShuttleControlConsoleMulti = (props, context) => {
const { act, data } = useBackend(context);
const {
can_cloak,
can_pick,
legit,
cloaked,
destination_name,
} = data;
return (
<Fragment>
<ShuttleControlSharedShuttleStatus />
<Section title="Multishuttle Controls">
<LabeledList>
{can_cloak && (
<LabeledList.Item label={legit ? "ATC Inhibitor" : "Cloaking"}>
<Button
selected={cloaked}
icon={cloaked ? "eye" : "eye-o"}
onClick={() => act("toggle_cloaked")}>
{cloaked ? "Enabled" : "Disabled"}
</Button>
</LabeledList.Item>
) || null}
<LabeledList.Item label="Current Destination">
<Button
icon="taxi"
disabled={!can_pick}
onClick={() => act("pick")}>
{destination_name}
</Button>
</LabeledList.Item>
</LabeledList>
</Section>
<ShuttleControlSharedShuttleControls />
</Fragment>
);
};
const ShuttleControlConsoleExploration = (props, context) => {
const { act, data } = useBackend(context);
const {
can_pick,
destination_name,
fuel_usage,
fuel_span,
remaining_fuel,
} = data;
return (
<Fragment>
<ShuttleControlSharedShuttleStatus engineName="Engines" />
<Section title="Jump Controls">
<LabeledList>
<LabeledList.Item label="Current Destination">
<Button
icon="taxi"
disabled={!can_pick}
onClick={() => act("pick")}>
{destination_name}
</Button>
</LabeledList.Item>
{fuel_usage && (
<Fragment>
<LabeledList.Item label="Est. Delta-V Budget" color={fuel_span}>
{remaining_fuel} m/s
</LabeledList.Item>
<LabeledList.Item label="Avg. Delta-V Per Maneuver">
{fuel_usage} m/s
</LabeledList.Item>
</Fragment>
) || null}
</LabeledList>
</Section>
<ShuttleControlSharedShuttleControls />
</Fragment>
);
};
/* Ugh. Just ugh. */
const ShuttleControlConsoleWeb = (props, context) => {
const { act, data } = useBackend(context);
const {
autopilot,
can_rename,
shuttle_state,
is_moving,
skip_docking,
docking_status,
docking_override,
shuttle_location,
can_cloak,
cloaked,
can_autopilot,
routes,
is_in_transit,
travel_progress,
time_left,
doors,
sensors,
} = data;
return (
<Fragment>
{autopilot && (
<Section title="AI PILOT (CLASS D) ACTIVE">
<Box inline italic>
This vessel will start and stop automatically.
Ensure that all non-cycling capable hatches and doors are closed,
as the automated system may not be able to control them.
Docking and flight controls are locked. To unlock, disable the automated flight system.
</Box>
</Section>
) || null}
<Section title="Shuttle Status" buttons={
can_rename && (
<Button
icon="pen"
onClick={() => act("rename_command")}>
Rename
</Button>
) || null
}>
<LabeledList>
<LabeledList.Item label="Engines">
{shuttle_state === "idle" && (
<Box color="#676767" bold>
IDLE
</Box>
) || shuttle_state === "warmup" && (
<Box color="#336699">
SPINNING UP
</Box>
) || shuttle_state === "in_transit" && (
<Box color="#336699">
ENGAGED
</Box>
) || (
<Box color="bad">
ERROR
</Box>
)}
</LabeledList.Item>
{!is_moving && (
<Fragment>
<LabeledList.Item label="Current Location">
{toTitleCase(shuttle_location)}
</LabeledList.Item>
{!skip_docking && (
<LabeledList.Item label="Docking Status" buttons={
<Fragment>
<Button
selected={docking_status === "docked"}
disabled={docking_status !== "undocked" && docking_status !== "docked"}
onClick={() => act("dock_command")}>
Dock
</Button>
<Button
selected={docking_status === "undocked"}
disabled={docking_status !== "docked" && docking_status !== "undocked"}
onClick={() => act("undock_command")}>
Undock
</Button>
</Fragment>
}>
<Box bold inline>{getDockingStatus(docking_status, docking_override)}</Box>
</LabeledList.Item>
) || null}
{can_cloak && (
<LabeledList.Item label="Cloaking">
<Button
selected={cloaked}
icon={cloaked ? "eye" : "eye-o"}
onClick={() => act("toggle_cloaked")}>
{cloaked ? "Enabled" : "Disabled"}
</Button>
</LabeledList.Item>
) || null}
{can_autopilot && (
<LabeledList.Item label="Autopilot">
<Button
selected={autopilot}
icon={autopilot ? "eye" : "eye-o"}
onClick={() => act("toggle_autopilot")}>
{autopilot ? "Enabled" : "Disabled"}
</Button>
</LabeledList.Item>
) || null}
</Fragment>
) || null}
</LabeledList>
{!is_moving && (
<Section level={2} title="Available Destinations">
<LabeledList>
{routes.length && routes.map(route => (
<LabeledList.Item label={route.name} key={route.name}>
<Button
icon="rocket"
onClick={() => act("traverse", { traverse: route.index })}>
{route.travel_time}
</Button>
</LabeledList.Item>
)) || (
<LabeledList.Item label="Error" color="bad">
No routes found.
</LabeledList.Item>
)}
</LabeledList>
</Section>
) || null}
</Section>
{is_in_transit && (
<Section title="Transit ETA">
<LabeledList>
<LabeledList.Item label="Distance from target">
<ProgressBar
color="good"
minValue={0}
maxValue={100}
value={travel_progress}>
{time_left}s
</ProgressBar>
</LabeledList.Item>
</LabeledList>
</Section>
) || null}
{Object.keys(doors).length && (
<Section title="Hatch Status">
<LabeledList>
{Object.keys(doors).map(key => {
let door = doors[key];
return (
<LabeledList.Item label={key} key={key}>
{door.open && (
<Box inline color="bad">
Open
</Box>
) || (
<Box inline color="good">
Closed
</Box>
)}
&nbsp;-&nbsp;
{door.bolted && (
<Box inline color="good">
Bolted
</Box>
) || (
<Box inline color="bad">
Unbolted
</Box>
)}
</LabeledList.Item>
);
})}
</LabeledList>
</Section>
) || null}
{Object.keys(sensors).length && (
<Section title="Sensors">
<LabeledList>
{Object.keys(sensors).map(key => {
let sensor = sensors[key];
if (sensor.reading !== -1) {
return (
<LabeledList.Item label={key} color="bad">
Unable to get sensor air reading.
</LabeledList.Item>
);
}
return (
<LabeledList.Item label={key} key={key}>
<LabeledList>
<LabeledList.Item label="Pressure">
{sensor.pressure}kPa
</LabeledList.Item>
<LabeledList.Item label="Temperature">
{sensor.temp}&deg;C
</LabeledList.Item>
<LabeledList.Item label="Oxygen">
{sensor.oxygen}%
</LabeledList.Item>
<LabeledList.Item label="Nitrogen">
{sensor.nitrogen}%
</LabeledList.Item>
<LabeledList.Item label="Carbon Dioxide">
{sensor.carbon_dioxide}%
</LabeledList.Item>
<LabeledList.Item label="Phoron">
{sensor.phoron}%
</LabeledList.Item>
{sensor.other && (
<LabeledList.Item label="Other">
{sensor.other}%
</LabeledList.Item>
) || null}
</LabeledList>
</LabeledList.Item>
);
})}
</LabeledList>
</Section>
) || null}
</Fragment>
);
};
// This may look tempting to convert to require() or some kind of dynamic call
// Don't do it. XSS abound.
const SubtemplateList = {
"ShuttleControlConsoleDefault": <ShuttleControlConsoleDefault />,
"ShuttleControlConsoleMulti": <ShuttleControlConsoleMulti />,
"ShuttleControlConsoleExploration": <ShuttleControlConsoleExploration />,
"ShuttleControlConsoleWeb": <ShuttleControlConsoleWeb />,
};
export const ShuttleControl = (props, context) => {
const { act, data } = useBackend(context);
const {
subtemplate,
} = data;
return (
<Window width={470} height={(subtemplate === "ShuttleControlConsoleWeb") ? 560 : 370} resizable>
<Window.Content>
{SubtemplateList[subtemplate]}
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,439 @@
import { filter, sortBy } from 'common/collections';
import { round } from "common/math";
import { Fragment } from "inferno";
import { formatTime } from "../format";
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Tabs, Collapsible, AnimatedNumber } from "../components";
import { ComplexModal, modalRegisterBodyOverride } from '../interfaces/common/ComplexModal';
import { Window } from "../layouts";
import { flow } from 'common/fp';
const viewCrateContents = (modal, context) => {
const { act, data } = useBackend(context);
const {
supply_points,
} = data;
const {
name,
cost,
manifest,
ref,
random,
} = modal.args;
return (
<Section
width="400px"
level={2}
m="-1rem"
pb="1rem"
title={name}
buttons={
<Button
icon="shopping-cart"
content={"Buy - " + cost + " points"}
disabled={cost > supply_points}
onClick={() => act("request_crate", { ref: ref })} />
}>
<Section title={"Contains" + (random ? (" any " + random + " of:") : "")} scrollable height="200px">
{manifest.map(m => (
<Box key={m}>
{m}
</Box>
))}
</Section>
</Section>
);
};
export const SupplyConsole = (props, context) => {
const { act, data } = useBackend(context);
modalRegisterBodyOverride("view_crate", viewCrateContents);
return (
<Window width={700} height={620}>
<Window.Content>
<ComplexModal maxWidth="100%" />
<Section title="Supply Records">
<SupplyConsoleShuttleStatus />
<SupplyConsoleMenu />
</Section>
</Window.Content>
</Window>
);
};
const SupplyConsoleShuttleStatus = (props, context) => {
const { act, data } = useBackend(context);
const {
supply_points,
shuttle,
shuttle_auth,
} = data;
let shuttle_buttons = null;
let showShuttleForce = false;
if (shuttle_auth) {
if (shuttle.launch === 1 && shuttle.mode === 0) {
shuttle_buttons = (
<Button
icon="rocket"
content="Send Away"
onClick={() => act("send_shuttle", { mode: "send_away" })} />
);
} else if (shuttle.launch === 2 && (shuttle.mode === 3 || shuttle.mode === 1)) {
shuttle_buttons = (
<Button
icon="ban"
content="Cancel Launch"
onClick={() => act("send_shuttle", { mode: "cancel_shuttle" })} />
);
} else if (shuttle.launch === 1 && shuttle.mode === 5) {
shuttle_buttons = (
<Button
icon="rocket"
content="Send Shuttle"
onClick={() => act("send_shuttle", { mode: "send_to_station" })} />
);
}
if (shuttle.force) {
showShuttleForce = true;
}
}
return (
<Section>
<LabeledList>
<LabeledList.Item label="Supply Points">
<AnimatedNumber value={supply_points} />
</LabeledList.Item>
</LabeledList>
<Section level={2} title="Supply Shuttle" mt={2}>
<LabeledList>
<LabeledList.Item label="Location" buttons={(
<Fragment>
{shuttle_buttons}
{showShuttleForce ? (
<Button
icon="exclamation-triangle"
content="Force Launch"
onClick={() => act("send_shuttle", { mode: "force_shuttle" })} />
) : null}
</Fragment>
)}>
{shuttle.location}
</LabeledList.Item>
<LabeledList.Item label="Engine">
{shuttle.engine}
</LabeledList.Item>
{shuttle.mode === 4 ? (
<LabeledList.Item label="ETA">
{(shuttle.time > 1) ? formatTime(shuttle.time) : "LATE"}
</LabeledList.Item>
) : null}
</LabeledList>
</Section>
</Section>
);
};
const SupplyConsoleMenu = (props, context) => {
const { act, data } = useBackend(context);
const {
order_auth,
} = data;
const [tabIndex, setTabIndex] = useLocalState(context, "tabIndex", 0);
return (
<Section title="Menu">
<Tabs>
<Tabs.Tab
icon="box"
selected={tabIndex === 0}
onClick={() => setTabIndex(0)}>
Request
</Tabs.Tab>
<Tabs.Tab
icon="check-circle-o"
selected={tabIndex === 1}
onClick={() => setTabIndex(1)}>
Accepted
</Tabs.Tab>
<Tabs.Tab
icon="circle-o"
selected={tabIndex === 2}
onClick={() => setTabIndex(2)}>
Requests
</Tabs.Tab>
<Tabs.Tab
icon="book"
selected={tabIndex === 3}
onClick={() => setTabIndex(3)}>
Order history
</Tabs.Tab>
<Tabs.Tab
icon="book"
selected={tabIndex === 4}
onClick={() => setTabIndex(4)}>
Export history
</Tabs.Tab>
</Tabs>
{tabIndex === 0 ? <SupplyConsoleMenuOrder /> : null}
{tabIndex === 1 ? <SupplyConsoleMenuOrderList mode="Approved" /> : null}
{tabIndex === 2 ? <SupplyConsoleMenuOrderList mode="Requested" /> : null}
{tabIndex === 3 ? <SupplyConsoleMenuOrderList mode="All" /> : null}
{tabIndex === 4 ? <SupplyConsoleMenuHistoryExport /> : null}
</Section>
);
};
const SupplyConsoleMenuOrder = (props, context) => {
const { act, data } = useBackend(context);
const {
categories,
supply_packs,
contraband,
supply_points,
} = data;
const [activeCategory, setActiveCategory] = useLocalState(context, "activeCategory", null);
const viewingPacks = flow([
filter(val => val.group === activeCategory),
filter(val => !val.contraband || contraband),
sortBy(val => val.name),
sortBy(val => (val.cost > supply_points)),
])(supply_packs);
// const viewingPacks = sortBy(val => val.name)(supply_packs).filter(val => val.group === activeCategory);
return (
<Section level={2}>
<Flex spacing={1}>
<Flex.Item basis="25%">
<Section title="Categories" scrollable fill height="290px">
{categories.map(category => (
<Button
key={category}
fluid
content={category}
selected={category === activeCategory}
onClick={() => setActiveCategory(category)} />
))}
</Section>
</Flex.Item>
<Flex.Item grow={1}>
<Section title="Contents" scrollable fill height="290px">
{viewingPacks.map(pack => (
<Box key={pack.name}>
<Flex align="center" justify="flex-start" spacing={1}>
<Flex.Item basis="70%">
<Button
fluid
icon="shopping-cart"
ellipsis
content={pack.name}
color={(pack.cost > supply_points) ? "red" : null}
onClick={() => act("request_crate", { ref: pack.ref })} />
</Flex.Item>
<Flex.Item>
<Button
content="#"
color={(pack.cost > supply_points) ? "red" : null}
onClick={() => act("request_crate_multi", { ref: pack.ref })} />
</Flex.Item>
<Flex.Item>
<Button
content="C"
color={(pack.cost > supply_points) ? "red" : null}
onClick={() => act("view_crate", { crate: pack.ref })} />
</Flex.Item>
<Flex.Item grow={1}>
{pack.cost} points
</Flex.Item>
</Flex>
</Box>
))}
{/* Alternative collapsible style folders */}
{/* {viewingPacks.map(pack => (
<Collapsible title={pack.name} mb={-0.7}>
<center>
{pack.manifest.map(item => (
<Box mb={0.5}>
{item}
</Box>
))}
<Button
fluid
color="green"
content={"Buy - " + pack.cost + " points"} />
</center>
</Collapsible>
))} */}
</Section>
</Flex.Item>
</Flex>
</Section>
);
};
const SupplyConsoleMenuOrderList = (props, context) => {
const { act, data } = useBackend(context);
const {
mode,
} = props;
const {
orders,
order_auth,
supply_points,
} = data;
const displayedOrders = orders.filter(val => (val.status === mode || mode === "All"));
if (!displayedOrders.length) {
return (
<Section level={2}>
No orders found.
</Section>
);
}
return (
<Section level={2}>
{(mode === "Requested" && order_auth) ? (
<Button
mt={-1}
mb={1}
fluid
color="red"
icon="trash"
content="Clear all requests"
onClick={() => act("clear_all_requests")} />
) : null}
{displayedOrders.map((order, i) => (
<Section title={"Order " + (i + 1)} key={i} buttons={(mode === "All" && order_auth) ? (
<Button
color="red"
icon="trash"
content="Delete Record"
onClick={() => act("delete_order", { ref: order.ref })} />
) : null}>
<LabeledList>
{order.entries.map(field => field.entry ? (
<LabeledList.Item label={field.field} buttons={order_auth ? (
<Button
icon="pen"
content="Edit"
onClick={() => {
act("edit_order_value", { ref: order.ref, edit: field.field, default: field.entry });
}} />
) : null}>
{field.entry}
</LabeledList.Item>
) : null)}
{mode === "All" ? (
<LabeledList.Item label="Status">
{order.status}
</LabeledList.Item>
) : null}
</LabeledList>
{order_auth && mode === "Requested" ? (
<Fragment>
<Button
icon="check"
content="Approve"
disabled={order.cost > supply_points}
onClick={() => act("approve_order", { ref: order.ref })} />
<Button
icon="times"
content="Deny"
onClick={() => act("deny_order", { ref: order.ref })} />
</Fragment>
) : null}
</Section>
))}
</Section>
);
};
const SupplyConsoleMenuHistoryExport = (props, context) => {
const { act, data } = useBackend(context);
const {
receipts,
order_auth,
} = data;
if (!receipts.length) {
return (
<Section level={2}>
No receipts found.
</Section>
);
}
return (
<Section level={2}>
{receipts.map((r, ri) => (
<Section key={ri}>
<LabeledList>
{r.title.map(title => (
<LabeledList.Item label={title.field} key={title.field} buttons={order_auth ? (
<Button
icon="pen"
content="Edit"
onClick={() => act("export_edit", { ref: r.ref, edit: title.field, default: title.entry })} />
) : null}>
{title.entry}
</LabeledList.Item>
))}
{r.error ? (
<LabeledList.Item labelColor="red" label="Error">
{r.error}
</LabeledList.Item>
) : r.contents.map((item, i) => (
<LabeledList.Item label={item.object} key={i} buttons={order_auth ? (
<Fragment>
<Button
icon="pen"
content="Edit"
onClick={() => act("export_edit_field", {
ref: r.ref,
index: i + 1,
edit: "meow",
default: item.object,
})} />
<Button
icon="trash"
color="red"
content="Delete"
onClick={() => act("export_delete_field", {
ref: r.ref,
index: i + 1,
})} />
</Fragment>
) : null}>
{item.quantity}x -&gt; {item.value} points
</LabeledList.Item>
))}
</LabeledList>
{order_auth ? (
<Fragment>
<Button
mt={1}
icon="plus"
content="Add Item To Record"
onClick={() => act("export_add_field", { ref: r.ref })} />
<Button
icon="trash"
content="Delete Record"
onClick={() => act("export_delete", { ref: r.ref })} />
</Fragment>
) : null}
</Section>
))}
</Section>
);
};

View File

@@ -0,0 +1,44 @@
import { Fragment } from 'inferno';
import { useBackend } from "../../backend";
import { Box, Button, Input, NoticeBox } from '../../components';
export const MiningUser = (props, context) => {
const { act, data } = useBackend(context);
const {
insertIdText,
} = props;
const {
has_id,
id,
} = data;
return (
<NoticeBox success={has_id}>
{has_id ? (
<Fragment>
<Box
display="inline-block"
verticalAlign="middle"
style={{
float: 'left',
}}>
Logged in as {id.name}.<br />
You have {id.points.toLocaleString('en-US')} points.
</Box>
<Button
icon="eject"
content="Eject ID"
style={{
float: 'right',
}}
onClick={() => act('logoff')}
/>
<Box
style={{
clear: "both",
}}
/>
</Fragment>
) : insertIdText}
</NoticeBox>
);
};

File diff suppressed because one or more lines are too long

View File

@@ -36,4 +36,4 @@
.Table__cell--collapsing {
width: 1%;
white-space: nowrap;
}
}