mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-25 21:19:44 +01:00
TGUI Supply Computer
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -103,4 +103,13 @@ 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(":");
|
||||
};
|
||||
|
||||
@@ -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 -> {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>
|
||||
);
|
||||
};
|
||||
@@ -36,4 +36,4 @@
|
||||
.Table__cell--collapsing {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user