Merge pull request #9062 from ShadowLarkens/tgui_finale

NanoUI Goes To Brazil
This commit is contained in:
Novacat
2020-09-21 14:13:16 -04:00
committed by GitHub
240 changed files with 3952 additions and 21677 deletions
+26 -40
View File
@@ -433,45 +433,6 @@
// Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
// ..()
/datum/asset/nanoui
var/list/common = list()
var/list/common_dirs = list(
"nano/css/",
"nano/images/",
"nano/images/modular_computers/",
"nano/js/"
)
var/list/template_dirs = list(
"nano/templates/"
)
/datum/asset/nanoui/register()
// Crawl the directories to find files.
for(var/path in common_dirs)
var/list/filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) != "/") // Ignore directories.
if(fexists(path + filename))
common[filename] = fcopy_rsc(path + filename)
register_asset(filename, common[filename])
// Combine all templates into a single bundle.
var/list/template_data = list()
for(var/path in template_dirs)
var/list/filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename) - 4) == ".tmpl") // Ignore directories.
template_data[filename] = file2text(path + filename)
var/template_bundle = "function nanouiTemplateBundle(){return [json_encode(template_data)];}"
var/fname = "data/nano_templates_bundle.js"
fdel(fname)
text2file(template_bundle, fname)
register_asset("nano_templates_bundle.js", fcopy_rsc(fname))
fdel(fname)
/datum/asset/nanoui/send(client)
send_asset_list(client, common)
//Pill sprites for UIs
/datum/asset/chem_master
var/assets = list()
@@ -522,4 +483,29 @@
/datum/asset/spritesheet/sheetmaterials/register()
InsertAll("", 'icons/obj/stacks.dmi')
..()
..()
// Nanomaps
/datum/asset/simple/nanomaps
// It REALLY doesnt matter too much if these arent up to date
// They are relatively big
assets = list(
"southern_cross_nanomap_z1.png" = 'icons/_nanomaps/southern_cross_nanomap_z1.png',
"southern_cross_nanomap_z10.png" = 'icons/_nanomaps/southern_cross_nanomap_z10.png',
"southern_cross_nanomap_z2.png" = 'icons/_nanomaps/southern_cross_nanomap_z2.png',
"southern_cross_nanomap_z3.png" = 'icons/_nanomaps/southern_cross_nanomap_z3.png',
"southern_cross_nanomap_z5.png" = 'icons/_nanomaps/southern_cross_nanomap_z5.png',
"southern_cross_nanomap_z6.png" = 'icons/_nanomaps/southern_cross_nanomap_z6.png',
"tether_nanomap_z1.png" = 'icons/_nanomaps/tether_nanomap_z1.png',
"tether_nanomap_z10.png" = 'icons/_nanomaps/tether_nanomap_z10.png',
"tether_nanomap_z13.png" = 'icons/_nanomaps/tether_nanomap_z13.png',
"tether_nanomap_z14.png" = 'icons/_nanomaps/tether_nanomap_z14.png',
"tether_nanomap_z2.png" = 'icons/_nanomaps/tether_nanomap_z2.png',
"tether_nanomap_z3.png" = 'icons/_nanomaps/tether_nanomap_z3.png',
"tether_nanomap_z4.png" = 'icons/_nanomaps/tether_nanomap_z4.png',
"tether_nanomap_z5.png" = 'icons/_nanomaps/tether_nanomap_z5.png',
"tether_nanomap_z6.png" = 'icons/_nanomaps/tether_nanomap_z6.png',
"tether_nanomap_z7.png" = 'icons/_nanomaps/tether_nanomap_z7.png',
"tether_nanomap_z8.png" = 'icons/_nanomaps/tether_nanomap_z8.png',
"tether_nanomap_z9.png" = 'icons/_nanomaps/tether_nanomap_z9.png',
)
-12
View File
@@ -8,8 +8,6 @@
var/obj/item/clothing/glasses/hud/omni/hud = null
var/mode = "civ"
icon_state = "glasses"
var/datum/nano_module/arscreen
var/arscreen_path
var/datum/tgui_module/tgarscreen
var/tgarscreen_path
var/flash_prot = 0 //0 for none, 1 for flash weapon protection, 2 for welder protection
@@ -18,34 +16,24 @@
/obj/item/clothing/glasses/omnihud/New()
..()
if(arscreen_path)
arscreen = new arscreen_path(src)
if(tgarscreen_path)
tgarscreen = new tgarscreen_path(src)
/obj/item/clothing/glasses/omnihud/Destroy()
QDEL_NULL(arscreen)
QDEL_NULL(tgarscreen)
. = ..()
/obj/item/clothing/glasses/omnihud/dropped()
if(arscreen)
SSnanoui.close_uis(src)
if(tgarscreen)
SStgui.close_uis(src)
..()
/obj/item/clothing/glasses/omnihud/emp_act(var/severity)
if(arscreen)
SSnanoui.close_uis(src)
if(tgarscreen)
SStgui.close_uis(src)
var/disconnect_ar = arscreen
var/disconnect_tgar = tgarscreen
arscreen = null
tgarscreen = null
spawn(20 SECONDS)
arscreen = disconnect_ar
tgarscreen = disconnect_tgar
//extra fun for non-sci variants; a small chance flip the state to the dumb 3d glasses when EMP'd
@@ -23,7 +23,7 @@
to_chat(usr, "Your module is not installed in a hardsuit.")
return
module.holder.ui_interact(usr, nano_state = contained_state)
module.holder.tgui_interact(usr, custom_state = GLOB.tgui_contained_state)
/obj/item/rig_module/ai_container
@@ -134,7 +134,7 @@
if(!target)
if(ai_card)
if(istype(ai_card,/obj/item/device/aicard))
ai_card.tgui_interact(H, custom_state = deep_inventory_state)
ai_card.tgui_interact(H, custom_state = GLOB.tgui_deep_inventory_state)
else
eject_ai(H)
update_verb_holder()
+157 -155
View File
@@ -15,7 +15,7 @@
var/const/fund_cap = 1000000
/obj/machinery/account_database/proc/get_access_level()
if (!held_card)
if(!held_card)
return 0
if(access_cent_captain in held_card.access)
return 2
@@ -53,19 +53,24 @@
O.loc = src
held_card = O
SSnanoui.update_uis(src)
SStgui.update_uis(src)
attack_hand(user)
/obj/machinery/account_database/attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN)) return
ui_interact(user)
tgui_interact(user)
/obj/machinery/account_database/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
/obj/machinery/account_database/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AccountsTerminal", name)
ui.open()
/obj/machinery/account_database/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/data[0]
data["src"] = "\ref[src]"
data["id_inserted"] = !!held_card
data["id_card"] = held_card ? text("[held_card.registered_name], [held_card.assignment]") : "-----"
data["access_level"] = get_access_level()
@@ -73,10 +78,14 @@
data["creating_new_account"] = creating_new_account
data["detailed_account_view"] = !!detailed_account_view
data["station_account_number"] = station_account.account_number
data["transactions"] = null
data["accounts"] = null
if (detailed_account_view)
data["account_number"] = null
data["owner_name"] = null
data["money"] = null
data["suspended"] = null
data["transactions"] = list()
if(detailed_account_view)
data["account_number"] = detailed_account_view.account_number
data["owner_name"] = detailed_account_view.owner_name
data["money"] = detailed_account_view.money
@@ -92,11 +101,10 @@
"amount" = T.amount, \
"source_terminal" = T.source_terminal)))
if (trx.len > 0)
data["transactions"] = trx
data["transactions"] = trx
var/list/accounts[0]
for(var/i=1, i<=all_money_accounts.len, i++)
var/list/accounts = list()
for(var/i in 1 to LAZYLEN(all_money_accounts))
var/datum/money_account/D = all_money_accounts[i]
if(D.offmap)
continue
@@ -106,174 +114,168 @@
"suspended"=D.suspended ? "SUSPENDED" : "",\
"account_index"=i)))
if (accounts.len > 0)
data["accounts"] = accounts
data["accounts"] = accounts
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "accounts_terminal.tmpl", src.name, 400, 640)
ui.set_initial_data(data)
ui.open()
return data
/obj/machinery/account_database/Topic(href, href_list)
/obj/machinery/account_database/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
var/datum/nanoui/ui = SSnanoui.get_open_ui(usr, src, "main")
switch(action)
if("create_account")
creating_new_account = 1
if(href_list["choice"])
switch(href_list["choice"])
if("create_account")
creating_new_account = 1
if("add_funds")
var/amount = input("Enter the amount you wish to add", "Silently add funds") as num
if(detailed_account_view)
detailed_account_view.money = min(detailed_account_view.money + amount, fund_cap)
if("add_funds")
var/amount = input("Enter the amount you wish to add", "Silently add funds") as num
if(detailed_account_view)
detailed_account_view.money = min(detailed_account_view.money + amount, fund_cap)
if("remove_funds")
var/amount = input("Enter the amount you wish to remove", "Silently remove funds") as num
if(detailed_account_view)
detailed_account_view.money = max(detailed_account_view.money - amount, -fund_cap)
if("remove_funds")
var/amount = input("Enter the amount you wish to remove", "Silently remove funds") as num
if(detailed_account_view)
detailed_account_view.money = max(detailed_account_view.money - amount, -fund_cap)
if("toggle_suspension")
if(detailed_account_view)
detailed_account_view.suspended = !detailed_account_view.suspended
callHook("change_account_status", list(detailed_account_view))
if("toggle_suspension")
if(detailed_account_view)
detailed_account_view.suspended = !detailed_account_view.suspended
callHook("change_account_status", list(detailed_account_view))
if("finalise_create_account")
var/account_name = params["holder_name"]
var/starting_funds = max(text2num(params["starting_funds"]), 0)
if("finalise_create_account")
var/account_name = href_list["holder_name"]
var/starting_funds = max(text2num(href_list["starting_funds"]), 0)
starting_funds = CLAMP(starting_funds, 0, station_account.money) // Not authorized to put the station in debt.
starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap.
starting_funds = CLAMP(starting_funds, 0, station_account.money) // Not authorized to put the station in debt.
starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap.
create_account(account_name, starting_funds, src)
if(starting_funds > 0)
//subtract the money
station_account.money -= starting_funds
create_account(account_name, starting_funds, src)
if(starting_funds > 0)
//subtract the money
station_account.money -= starting_funds
//create a transaction log entry
var/trx = create_transation(account_name, "New account activation", "([starting_funds])")
station_account.transaction_log.Add(trx)
creating_new_account = 0
ui.close()
//create a transaction log entry
var/trx = create_transation(account_name, "New account activation", "([starting_funds])")
station_account.transaction_log.Add(trx)
creating_new_account = 0
if("insert_card")
if(held_card)
held_card.loc = src.loc
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(held_card)
held_card = null
creating_new_account = 0
if("insert_card")
if(held_card)
held_card.loc = src.loc
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = I
usr.drop_item()
C.loc = src
held_card = C
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(held_card)
held_card = null
if("view_account_detail")
var/index = text2num(href_list["account_index"])
if(index && index <= all_money_accounts.len)
detailed_account_view = all_money_accounts[index]
else
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = I
usr.drop_item()
C.loc = src
held_card = C
if("view_accounts_list")
detailed_account_view = null
creating_new_account = 0
if("view_account_detail")
var/index = text2num(params["account_index"])
if(index && index <= all_money_accounts.len)
detailed_account_view = all_money_accounts[index]
if("revoke_payroll")
var/funds = detailed_account_view.money
var/account_trx = create_transation(station_account.owner_name, "Revoke payroll", "([funds])")
var/station_trx = create_transation(detailed_account_view.owner_name, "Revoke payroll", funds)
if("view_accounts_list")
detailed_account_view = null
creating_new_account = 0
station_account.money += funds
detailed_account_view.money = 0
if("revoke_payroll")
var/funds = detailed_account_view.money
var/account_trx = create_transation(station_account.owner_name, "Revoke payroll", "([funds])")
var/station_trx = create_transation(detailed_account_view.owner_name, "Revoke payroll", funds)
detailed_account_view.transaction_log.Add(account_trx)
station_account.transaction_log.Add(station_trx)
station_account.money += funds
detailed_account_view.money = 0
callHook("revoke_payroll", list(detailed_account_view))
detailed_account_view.transaction_log.Add(account_trx)
station_account.transaction_log.Add(station_trx)
if("print")
var/text
var/obj/item/weapon/paper/P = new(loc)
if (detailed_account_view)
P.name = "account #[detailed_account_view.account_number] details"
var/title = "Account #[detailed_account_view.account_number] Details"
text = {"
[accounting_letterhead(title)]
<u>Holder:</u> [detailed_account_view.owner_name]<br>
<u>Balance:</u> $[detailed_account_view.money]<br>
<u>Status:</u> [detailed_account_view.suspended ? "Suspended" : "Active"]<br>
<u>Transactions:</u> ([detailed_account_view.transaction_log.len])<br>
<table>
<thead>
<tr>
<td>Timestamp</td>
<td>Target</td>
<td>Reason</td>
<td>Value</td>
<td>Terminal</td>
</tr>
</thead>
<tbody>
"}
callHook("revoke_payroll", list(detailed_account_view))
for (var/datum/transaction/T in detailed_account_view.transaction_log)
text += {"
<tr>
<td>[T.date] [T.time]</td>
<td>[T.target_name]</td>
<td>[T.purpose]</td>
<td>[T.amount]</td>
<td>[T.source_terminal]</td>
</tr>
"}
if("print")
print()
text += {"
</tbody>
</table>
"}
return TRUE
else
P.name = "financial account list"
text = {"
[accounting_letterhead("Financial Account List")]
/obj/machinery/account_database/proc/print()
var/text
var/obj/item/weapon/paper/P = new(loc)
if(detailed_account_view)
P.name = "account #[detailed_account_view.account_number] details"
var/title = "Account #[detailed_account_view.account_number] Details"
text = {"
[accounting_letterhead(title)]
<u>Holder:</u> [detailed_account_view.owner_name]<br>
<u>Balance:</u> $[detailed_account_view.money]<br>
<u>Status:</u> [detailed_account_view.suspended ? "Suspended" : "Active"]<br>
<u>Transactions:</u> ([detailed_account_view.transaction_log.len])<br>
<table>
<thead>
<tr>
<td>Timestamp</td>
<td>Target</td>
<td>Reason</td>
<td>Value</td>
<td>Terminal</td>
</tr>
</thead>
<tbody>
"}
<table>
<thead>
<tr>
<td>Account Number</td>
<td>Holder</td>
<td>Balance</td>
<td>Status</td>
</tr>
</thead>
<tbody>
"}
for (var/datum/transaction/T in detailed_account_view.transaction_log)
text += {"
<tr>
<td>[T.date] [T.time]</td>
<td>[T.target_name]</td>
<td>[T.purpose]</td>
<td>[T.amount]</td>
<td>[T.source_terminal]</td>
</tr>
"}
for(var/i=1, i<=all_money_accounts.len, i++)
var/datum/money_account/D = all_money_accounts[i]
text += {"
<tr>
<td>#[D.account_number]</td>
<td>[D.owner_name]</td>
<td>$[D.money]</td>
<td>[D.suspended ? "Suspended" : "Active"]</td>
</tr>
"}
text += {"
</tbody>
</table>
"}
text += {"
</tbody>
</table>
"}
else
P.name = "financial account list"
text = {"
[accounting_letterhead("Financial Account List")]
P.info = text
state("The terminal prints out a report.")
<table>
<thead>
<tr>
<td>Account Number</td>
<td>Holder</td>
<td>Balance</td>
<td>Status</td>
</tr>
</thead>
<tbody>
"}
return 1
for(var/i=1, i<=all_money_accounts.len, i++)
var/datum/money_account/D = all_money_accounts[i]
text += {"
<tr>
<td>#[D.account_number]</td>
<td>[D.owner_name]</td>
<td>$[D.money]</td>
<td>[D.suspended ? "Suspended" : "Active"]</td>
</tr>
"}
text += {"
</tbody>
</table>
"}
P.info = text
state("The terminal prints out a report.")
@@ -78,7 +78,7 @@
output.assembly = src
/obj/item/device/electronic_assembly/device/check_interactivity(mob/user)
if(!CanInteract(user, state = deep_inventory_state))
if(!CanInteract(user, state = GLOB.tgui_deep_inventory_state))
return 0
return 1
@@ -40,8 +40,8 @@ D [1]/ ||
holder = null
. = ..()
/datum/integrated_io/nano_host()
return holder.nano_host()
/datum/integrated_io/tgui_host()
return holder.tgui_host()
/datum/integrated_io/proc/data_as_type(var/as_type)
@@ -117,7 +117,7 @@
/datum/integrated_io/list/display_pin_type()
return IC_FORMAT_LIST
/datum/integrated_io/list/Topic(href, href_list, state = interactive_state)
/datum/integrated_io/list/Topic(href, href_list, state = GLOB.tgui_always_state)
if(!holder.check_interactivity(usr))
return
if(..())
@@ -115,7 +115,7 @@
/obj/item/device/integrated_electronics/debugger/attack_self(mob/user)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
if(!CanInteract(user, physical_state))
if(!CanInteract(user, GLOB.tgui_physical_state))
return
var/new_data = null
@@ -124,13 +124,13 @@
accepting_refs = 0
new_data = input("Now type in a string.","[src] string writing") as null|text
new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0)
if(istext(new_data) && CanInteract(user, physical_state))
if(istext(new_data) && CanInteract(user, GLOB.tgui_physical_state))
data_to_write = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to \"[new_data]\".</span>")
if("number")
accepting_refs = 0
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && CanInteract(user, physical_state))
if(isnum(new_data) && CanInteract(user, GLOB.tgui_physical_state))
data_to_write = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [new_data].</span>")
if("ref")
@@ -54,7 +54,7 @@
/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter a number, please.","Number pad", get_pin_data(IC_OUTPUT, 1)) as null|num
if(isnum(new_input) && CanInteract(user, physical_state))
if(isnum(new_input) && CanInteract(user, GLOB.tgui_physical_state))
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
@@ -73,7 +73,7 @@
/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter some words, please.","Number pad", get_pin_data(IC_OUTPUT, 1)) as null|text
if(istext(new_input) && CanInteract(user, physical_state))
if(istext(new_input) && CanInteract(user, GLOB.tgui_physical_state))
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
@@ -92,7 +92,7 @@
/obj/item/integrated_circuit/input/colorpad/ask_for_input(mob/user)
var/new_color = input(user, "Enter a color, please.", "Color pad", get_pin_data(IC_OUTPUT, 1)) as color|null
if(new_color && CanInteract(user, physical_state))
if(new_color && CanInteract(user, GLOB.tgui_physical_state))
set_pin_data(IC_OUTPUT, 1, new_color)
push_data()
activate_pin(1)
@@ -89,7 +89,7 @@
/obj/item/integrated_circuit/memory/constant/attack_self(mob/user)
var/datum/integrated_io/O = outputs[1]
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
if(!CanInteract(user, physical_state))
if(!CanInteract(user, GLOB.tgui_physical_state))
return
var/new_data = null
@@ -97,13 +97,13 @@
if("string")
accepting_refs = 0
new_data = input("Now type in a string.","[src] string writing") as null|text
if(istext(new_data) && CanInteract(user, physical_state))
if(istext(new_data) && CanInteract(user, GLOB.tgui_physical_state))
O.data = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [O.display_data(O.data)].</span>")
if("number")
accepting_refs = 0
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && CanInteract(user, physical_state))
if(isnum(new_data) && CanInteract(user, GLOB.tgui_physical_state))
O.data = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [O.display_data(O.data)].</span>")
if("ref")
-7
View File
@@ -20,7 +20,6 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/ai_call_shuttle,
/mob/living/silicon/ai/proc/ai_camera_track,
/mob/living/silicon/ai/proc/ai_camera_list,
/mob/living/silicon/ai/proc/ai_roster,
/mob/living/silicon/ai/proc/ai_checklaws,
/mob/living/silicon/ai/proc/toggle_camera_light,
/mob/living/silicon/ai/proc/take_image,
@@ -355,12 +354,6 @@ var/list/ai_verbs_default = list(
if(new_sprite) selected_sprite = new_sprite
updateicon()
// this verb lets the ai see the stations manifest
/mob/living/silicon/ai/proc/ai_roster()
set category = "AI Commands"
set name = "Show Crew Manifest"
show_station_manifest()
/mob/living/silicon/ai/var/message_cooldown = 0
/mob/living/silicon/ai/proc/ai_announcement()
set category = "AI Commands"
+1 -1
View File
@@ -213,7 +213,7 @@
medicalActive1 = null
medicalActive2 = null
medical_cannotfind = 0
SSnanoui.update_uis(src)
SStgui.update_uis(src)
to_chat(usr, "<span class='notice'>You reset your record-viewing software.</span>")
/mob/living/silicon/pai/cancel_camera()
+43 -57
View File
@@ -41,27 +41,24 @@ var/global/list/default_pai_software = list()
set category = "pAI Commands"
set name = "Software Interface"
ui_interact(src)
tgui_interact(src)
/mob/living/silicon/pai/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
if(user != src)
if(ui) ui.set_status(STATUS_CLOSE, 0)
return
/mob/living/silicon/pai/tgui_state(mob/user)
return GLOB.tgui_self_state
if(ui_key != "main")
var/datum/pai_software/S = software[ui_key]
if(S && !S.toggle)
S.on_ui_interact(src, ui, force_open)
else
if(ui) ui.set_status(STATUS_CLOSE, 0)
return
var/data[0]
/mob/living/silicon/pai/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIInterface", "pAI Software Interface")
ui.open()
/mob/living/silicon/pai/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
// Software we have bought
var/bought_software[0]
var/list/bought_software = list()
// Software we have not bought
var/not_bought_software[0]
var/list/not_bought_software = list()
for(var/key in pai_software_by_key)
var/datum/pai_software/S = pai_software_by_key[key]
@@ -70,63 +67,52 @@ var/global/list/default_pai_software = list()
software_data["id"] = S.id
if(key in software)
software_data["on"] = S.is_active(src)
bought_software[++bought_software.len] = software_data
bought_software.Add(list(software_data))
else
software_data["ram"] = S.ram_cost
not_bought_software[++not_bought_software.len] = software_data
not_bought_software.Add(list(software_data))
data["bought"] = bought_software
data["not_bought"] = not_bought_software
data["available_ram"] = ram
// Emotions
var/emotions[0]
var/list/emotions = list()
for(var/name in pai_emotions)
var/emote[0]
var/list/emote = list()
emote["name"] = name
emote["id"] = pai_emotions[name]
emotions[++emotions.len] = emote
emotions.Add(list(emote))
data["emotions"] = emotions
data["current_emotion"] = card.current_emotion
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "pai_interface.tmpl", "pAI Software Interface", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/mob/living/silicon/pai/Topic(href, href_list)
. = ..()
if(.) return
/mob/living/silicon/pai/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(href_list["software"])
var/soft = href_list["software"]
var/datum/pai_software/S = software[soft]
if(S.toggle)
S.toggle(src)
else
ui_interact(src, ui_key = soft)
S.tgui_interact(src)
return 1
switch(action)
if("software")
var/soft = params["software"]
var/datum/pai_software/S = software[soft]
if(S.toggle)
S.toggle(src)
else
S.tgui_interact(src, parent_ui = ui)
return TRUE
else if(href_list["stopic"])
var/soft = href_list["stopic"]
var/datum/pai_software/S = software[soft]
if(S)
return S.Topic(href, href_list)
if("purchase")
var/soft = params["purchase"]
var/datum/pai_software/S = pai_software_by_key[soft]
if(S && (ram >= S.ram_cost))
ram -= S.ram_cost
software[S.id] = S
return TRUE
else if(href_list["purchase"])
var/soft = href_list["purchase"]
var/datum/pai_software/S = pai_software_by_key[soft]
if(S && (ram >= S.ram_cost))
ram -= S.ram_cost
software[S.id] = S
return 1
else if(href_list["image"])
var/img = text2num(href_list["image"])
if(1 <= img && img <= (pai_emotions.len))
card.setEmotion(img)
return 1
if("image")
var/img = text2num(params["image"])
if(1 <= img && img <= (pai_emotions.len))
card.setEmotion(img)
return TRUE
@@ -12,14 +12,11 @@
// Whether pAIs should automatically receive this module at no cost
var/default = 0
proc/on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
return
/datum/pai_software/proc/toggle(mob/living/silicon/pai/user)
return
proc/toggle(mob/living/silicon/pai/user)
return
proc/is_active(mob/living/silicon/pai/user)
return 0
/datum/pai_software/proc/is_active(mob/living/silicon/pai/user)
return 0
/datum/pai_software/tgui_state(mob/user)
return GLOB.tgui_always_state
@@ -36,55 +33,58 @@
toggle = 0
default = 1
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/pai_software/directives/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIDirectives", name, parent_ui)
ui.open()
data["master"] = user.master
data["dna"] = user.master_dna
data["prime"] = user.pai_law0
data["supplemental"] = user.pai_laws
/datum/pai_software/directives/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = list()
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_directives.tmpl", "pAI Directives", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["master"] = user.master
data["dna"] = user.master_dna
data["prime"] = user.pai_law0
data["supplemental"] = user.pai_laws
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
return data
if(href_list["getdna"])
var/mob/living/M = P.loc
var/count = 0
/datum/pai_software/directives/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
var/mob/living/silicon/pai/P = usr
if(!istype(P))
return TRUE
if(..())
return TRUE
// Find the carrier
while(!istype(M, /mob/living))
if(!M || !M.loc || count > 6)
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
to_chat(src, "You are not being carried by anyone!")
return 0
M = M.loc
count++
if(action == "getdna")
var/mob/living/M = P.loc
// Check the carrier
var/datum/gender/TM = gender_datums[M.get_visible_gender()]
var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
if(answer == "Yes")
var/turf/T = get_turf_or_move(P.loc)
for (var/mob/v in viewers(T))
v.show_message("<span class='notice'>[M] presses [TM.his] thumb against [P].</span>", 3, "<span class='notice'>[P] makes a sharp clicking sound as it extracts DNA material from [M].</span>", 2)
var/datum/dna/dna = M.dna
to_chat(P, "<font color = red><h3>[M]'s UE string : [dna.unique_enzymes]</h3></font>")
if(dna.unique_enzymes == P.master_dna)
to_chat(P, "<b>DNA is a match to stored Master DNA.</b>")
else
to_chat(P, "<b>DNA does not match stored Master DNA.</b>")
var/count = 0
// Find the carrier
while(!istype(M, /mob/living))
if(!M || !M.loc || count > 6)
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
to_chat(src, "You are not being carried by anyone!")
return 0
M = M.loc
count++
// Check the carrier
var/datum/gender/TM = gender_datums[M.get_visible_gender()]
var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
if(answer == "Yes")
var/turf/T = get_turf(P.loc)
for (var/mob/v in viewers(T))
v.show_message("<span class='notice'>[M] presses [TM.his] thumb against [P].</span>", 3, "<span class='notice'>[P] makes a sharp clicking sound as it extracts DNA material from [M].</span>", 2)
var/datum/dna/dna = M.dna
to_chat(P, "<font color = red><h3>[M]'s UE string : [dna.unique_enzymes]</h3></font>")
if(dna.unique_enzymes == P.master_dna)
to_chat(P, "<b>DNA is a match to stored Master DNA.</b>")
else
to_chat(P, "[M] does not seem like [TM.he] is going to provide a DNA sample willingly.")
return 1
to_chat(P, "<b>DNA does not match stored Master DNA.</b>")
else
to_chat(P, "[M] does not seem like [TM.he] is going to provide a DNA sample willingly.")
return TRUE
/datum/pai_software/radio_config
name = "Radio Configuration"
@@ -93,35 +93,8 @@
toggle = 0
default = 1
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui = null, force_open = 1)
var/data[0]
data["listening"] = user.radio.broadcasting
data["frequency"] = format_frequency(user.radio.frequency)
var/channels[0]
for(var/ch_name in user.radio.channels)
var/ch_stat = user.radio.channels[ch_name]
var/ch_dat[0]
ch_dat["name"] = ch_name
// FREQ_LISTENING is const in /obj/item/device/radio
ch_dat["listening"] = !!(ch_stat & user.radio.FREQ_LISTENING)
channels[++channels.len] = ch_dat
data["channels"] = channels
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
ui = new(user, user, id, "pai_radio.tmpl", "Radio Configuration", 300, 150)
ui.set_initial_data(data)
ui.open()
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
P.radio.Topic(href, href_list)
return 1
/datum/pai_software/radio_config/tgui_interact(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui/parent_ui)
return user.radio.tgui_interact(user, parent_ui = parent_ui)
/datum/pai_software/crew_manifest
name = "Crew Manifest"
@@ -129,20 +102,18 @@
id = "manifest"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
/datum/pai_software/crew_manifest/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "CrewManifest", name, parent_ui)
ui.open()
/datum/pai_software/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
if(data_core)
data_core.get_manifest_list()
var/data[0]
// This is dumb, but NanoUI breaks if it has no data to send
data["manifest"] = PDA_Manifest
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "crew_manifest.tmpl", "Crew Manifest", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["manifest"] = PDA_Manifest
return data
/datum/pai_software/messenger
name = "Digital Messenger"
@@ -151,7 +122,7 @@
toggle = 0
/datum/pai_software/messenger/tgui_interact(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui/parent_ui)
return user.pda.tgui_interact(user)
return user.pda.tgui_interact(user, parent_ui = parent_ui)
/datum/pai_software/med_records
name = "Medical Records"
@@ -159,53 +130,55 @@
id = "med_records"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/pai_software/med_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIMedrecords", name, parent_ui)
ui.open()
var/records[0]
for(var/datum/data/record/general in sortRecord(data_core.general))
var/record[0]
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records[++records.len] = record
/datum/pai_software/med_records/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/list/records = list()
for(var/datum/data/record/general in sortRecord(data_core.general))
var/list/record = list()
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records.Add(list(record))
data["records"] = records
data["records"] = records
var/datum/data/record/G = user.medicalActive1
var/datum/data/record/M = user.medicalActive2
data["general"] = G ? G.fields : null
data["medical"] = M ? M.fields : null
data["could_not_find"] = user.medical_cannotfind
var/datum/data/record/G = user.medicalActive1
var/datum/data/record/M = user.medicalActive2
data["general"] = G ? G.fields : null
data["medical"] = M ? M.fields : null
data["could_not_find"] = user.medical_cannotfind
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_medrecords.tmpl", "Medical Records", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
/datum/pai_software/med_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
. = ..()
var/mob/living/silicon/pai/P = usr
if(!istype(P))
return
if(href_list["select"])
var/datum/data/record/record = locate(href_list["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/M = null
if (!( data_core.general.Find(R) ))
P.medical_cannotfind = 1
else
P.medical_cannotfind = 0
for(var/datum/data/record/E in data_core.medical)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
P.medicalActive1 = R
P.medicalActive2 = M
else
if(action == "select")
var/datum/data/record/record = locate(params["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/M = null
if (!( data_core.general.Find(R) ))
P.medical_cannotfind = 1
return 1
else
P.medical_cannotfind = 0
for(var/datum/data/record/E in data_core.medical)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
P.medicalActive1 = R
P.medicalActive2 = M
else
P.medical_cannotfind = 1
return 1
/datum/pai_software/sec_records
name = "Security Records"
@@ -213,57 +186,59 @@
id = "sec_records"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/pai_software/sec_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAISecrecords", name, parent_ui)
ui.open()
var/records[0]
for(var/datum/data/record/general in sortRecord(data_core.general))
var/record[0]
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records[++records.len] = record
/datum/pai_software/sec_records/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/list/records = list()
for(var/datum/data/record/general in sortRecord(data_core.general))
var/list/record = list()
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records.Add(list(record))
data["records"] = records
data["records"] = records
var/datum/data/record/G = user.securityActive1
var/datum/data/record/S = user.securityActive2
data["general"] = G ? G.fields : null
data["security"] = S ? S.fields : null
data["could_not_find"] = user.security_cannotfind
var/datum/data/record/G = user.securityActive1
var/datum/data/record/S = user.securityActive2
data["general"] = G ? G.fields : null
data["security"] = S ? S.fields : null
data["could_not_find"] = user.security_cannotfind
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_secrecords.tmpl", "Security Records", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
/datum/pai_software/sec_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
. = ..()
var/mob/living/silicon/pai/P = usr
if(!istype(P))
return
if(href_list["select"])
var/datum/data/record/record = locate(href_list["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/S = null
if (!( data_core.general.Find(R) ))
P.securityActive1 = null
P.securityActive2 = null
P.security_cannotfind = 1
else
P.security_cannotfind = 0
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
S = E
P.securityActive1 = R
P.securityActive2 = S
else
if(action == "select")
var/datum/data/record/record = locate(params["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/S = null
if (!( data_core.general.Find(R) ))
P.securityActive1 = null
P.securityActive2 = null
P.security_cannotfind = 1
return 1
else
P.security_cannotfind = 0
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
S = E
P.securityActive1 = R
P.securityActive2 = S
else
P.securityActive1 = null
P.securityActive2 = null
P.security_cannotfind = 1
return TRUE
/datum/pai_software/door_jack
name = "Door Jack"
@@ -271,47 +246,49 @@
id = "door_jack"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/pai_software/door_jack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIDoorjack", "Door Jack", parent_ui)
ui.open()
data["cable"] = user.cable != null
data["machine"] = user.cable && (user.cable.machine != null)
data["inprogress"] = user.hackdoor != null
data["progress_a"] = round(user.hackprogress / 10)
data["progress_b"] = user.hackprogress % 10
data["aborted"] = user.hack_aborted
/datum/pai_software/door_jack/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_doorjack.tmpl", "Door Jack", 300, 150)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["cable"] = user.cable != null
data["machine"] = user.cable && (user.cable.machine != null)
data["inprogress"] = user.hackdoor != null
data["progress_a"] = round(user.hackprogress / 10)
data["progress_b"] = user.hackprogress % 10
data["aborted"] = user.hack_aborted
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
return data
if(href_list["jack"])
/datum/pai_software/door_jack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
var/mob/living/silicon/pai/P = usr
if(!istype(P) || ..())
return TRUE
switch(action)
if("jack")
if(P.cable && P.cable.machine)
P.hackdoor = P.cable.machine
P.hackloop()
return 1
else if(href_list["cancel"])
if("cancel")
P.hackdoor = null
return 1
else if(href_list["cable"])
var/turf/T = get_turf_or_move(P.loc)
if("cable")
var/turf/T = get_turf(P)
P.hack_aborted = 0
P.cable = new /obj/item/weapon/pai_cable(T)
for(var/mob/M in viewers(T))
M.show_message("<span class='warning'>A port on [P] opens to reveal [P.cable], which promptly falls to the floor.</span>", 3,
"<span class='warning'>You hear the soft click of something light and hard falling to the ground.</span>", 2)
"<span class='warning'>You hear the soft click of something light and hard falling to the ground.</span>", 2)
return 1
/mob/living/silicon/pai/proc/hackloop()
var/turf/T = get_turf_or_move(src.loc)
var/turf/T = get_turf(src)
for(var/mob/living/silicon/ai/AI in player_list)
if(T.loc)
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>")
@@ -345,134 +322,155 @@
id = "atmos_sense"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/pai_software/atmosphere_sensor/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIAtmos", name, parent_ui)
ui.open()
var/turf/T = get_turf_or_move(user.loc)
if(!T)
data["reading"] = 0
data["pressure"] = 0
data["temperature"] = 0
data["temperatureC"] = 0
data["gas"] = list()
else
var/datum/gas_mixture/env = T.return_air()
data["reading"] = 1
var/pres = env.return_pressure() * 10
data["pressure"] = "[round(pres/10)].[pres%10]"
data["temperature"] = round(env.temperature)
data["temperatureC"] = round(env.temperature-T0C)
/datum/pai_software/atmosphere_sensor/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/t_moles = env.total_moles
var/gases[0]
for(var/g in env.gas)
var/gas[0]
gas["name"] = gas_data.name[g]
gas["percent"] = round((env.gas[g] / t_moles) * 100)
gases[++gases.len] = gas
data["gas"] = gases
var/list/results = list()
var/turf/T = get_turf(user)
if(!isnull(T))
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles
if (total_moles)
var/o2_level = environment.gas["oxygen"]/total_moles
var/n2_level = environment.gas["nitrogen"]/total_moles
var/co2_level = environment.gas["carbon_dioxide"]/total_moles
var/phoron_level = environment.gas["phoron"]/total_moles
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_atmosphere.tmpl", "Atmosphere Sensor", 350, 300)
ui.set_initial_data(data)
ui.open()
// entry is what the element is describing
// Type identifies which unit or other special characters to use
// Val is the information reported
// Bad_high/_low are the values outside of which the entry reports as dangerous
// Poor_high/_low are the values outside of which the entry reports as unideal
// Values were extracted from the template itself
results = list(
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
list("entry" = "Temperature", "units" = "&deg;C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0),
list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0)
)
if(isnull(results))
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
data["aircontents"] = results
return data
/datum/pai_software/sec_hud
name = "Security HUD"
ram_cost = 20
id = "sec_hud"
toggle(mob/living/silicon/pai/user)
user.secHUD = !user.secHUD
user.plane_holder.set_vis(VIS_CH_ID, user.secHUD)
user.plane_holder.set_vis(VIS_CH_WANTED, user.secHUD)
user.plane_holder.set_vis(VIS_CH_IMPTRACK, user.secHUD)
user.plane_holder.set_vis(VIS_CH_IMPLOYAL, user.secHUD)
user.plane_holder.set_vis(VIS_CH_IMPCHEM, user.secHUD)
/datum/pai_software/sec_hud/toggle(mob/living/silicon/pai/user)
user.secHUD = !user.secHUD
user.plane_holder.set_vis(VIS_CH_ID, user.secHUD)
user.plane_holder.set_vis(VIS_CH_WANTED, user.secHUD)
user.plane_holder.set_vis(VIS_CH_IMPTRACK, user.secHUD)
user.plane_holder.set_vis(VIS_CH_IMPLOYAL, user.secHUD)
user.plane_holder.set_vis(VIS_CH_IMPCHEM, user.secHUD)
is_active(mob/living/silicon/pai/user)
return user.secHUD
/datum/pai_software/sec_hud/is_active(mob/living/silicon/pai/user)
return user.secHUD
/datum/pai_software/med_hud
name = "Medical HUD"
ram_cost = 20
id = "med_hud"
toggle(mob/living/silicon/pai/user)
user.medHUD = !user.medHUD
user.plane_holder.set_vis(VIS_CH_STATUS, user.medHUD)
user.plane_holder.set_vis(VIS_CH_HEALTH, user.medHUD)
/datum/pai_software/med_hud/toggle(mob/living/silicon/pai/user)
user.medHUD = !user.medHUD
user.plane_holder.set_vis(VIS_CH_STATUS, user.medHUD)
user.plane_holder.set_vis(VIS_CH_HEALTH, user.medHUD)
is_active(mob/living/silicon/pai/user)
return user.medHUD
/datum/pai_software/med_hud/is_active(mob/living/silicon/pai/user)
return user.medHUD
/datum/pai_software/translator
name = "Universal Translator"
ram_cost = 35
id = "translator"
toggle(mob/living/silicon/pai/user)
// Sol Common, Tradeband, Terminus and Gutter are added with New() and are therefore the current default, always active languages
user.translator_on = !user.translator_on
if(user.translator_on)
user.add_language(LANGUAGE_UNATHI)
user.add_language(LANGUAGE_SIIK)
user.add_language(LANGUAGE_AKHANI)
user.add_language(LANGUAGE_SKRELLIAN)
user.add_language(LANGUAGE_ZADDAT)
user.add_language(LANGUAGE_SCHECHI)
else
user.remove_language(LANGUAGE_UNATHI)
user.remove_language(LANGUAGE_SIIK)
user.remove_language(LANGUAGE_AKHANI)
user.remove_language(LANGUAGE_SKRELLIAN)
user.remove_language(LANGUAGE_ZADDAT)
user.remove_language(LANGUAGE_SCHECHI)
/datum/pai_software/translator/toggle(mob/living/silicon/pai/user)
// Sol Common, Tradeband, Terminus and Gutter are added with New() and are therefore the current default, always active languages
user.translator_on = !user.translator_on
if(user.translator_on)
user.add_language(LANGUAGE_UNATHI)
user.add_language(LANGUAGE_SIIK)
user.add_language(LANGUAGE_AKHANI)
user.add_language(LANGUAGE_SKRELLIAN)
user.add_language(LANGUAGE_ZADDAT)
user.add_language(LANGUAGE_SCHECHI)
else
user.remove_language(LANGUAGE_UNATHI)
user.remove_language(LANGUAGE_SIIK)
user.remove_language(LANGUAGE_AKHANI)
user.remove_language(LANGUAGE_SKRELLIAN)
user.remove_language(LANGUAGE_ZADDAT)
user.remove_language(LANGUAGE_SCHECHI)
is_active(mob/living/silicon/pai/user)
return user.translator_on
/datum/pai_software/translator/is_active(mob/living/silicon/pai/user)
return user.translator_on
/datum/pai_software/signaller
name = "Remote Signaller"
name = "Remote Signaler"
ram_cost = 5
id = "signaller"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/pai_software/signaller/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Signaler", "Signaler", parent_ui)
ui.open()
data["frequency"] = format_frequency(user.sradio.frequency)
data["code"] = user.sradio.code
/datum/pai_software/signaller/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/obj/item/radio/integrated/signal/R = user.sradio
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_signaller.tmpl", "Signaller", 320, 150)
ui.set_initial_data(data)
ui.open()
data["frequency"] = R.frequency
data["minFrequency"] = RADIO_LOW_FREQ
data["maxFrequency"] = RADIO_HIGH_FREQ
data["code"] = R.code
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
return data
if(href_list["send"])
P.sradio.send_signal("ACTIVATE")
for(var/mob/O in hearers(1, P.loc))
O.show_message("[bicon(P)] *beep* *beep*", 3, "*beep* *beep*", 2)
return 1
/datum/pai_software/signaller/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
else if(href_list["freq"])
var/new_frequency = (P.sradio.frequency + text2num(href_list["freq"]))
if(new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)
new_frequency = sanitize_frequency(new_frequency)
P.sradio.set_frequency(new_frequency)
return 1
var/mob/living/silicon/pai/user = usr
if(istype(user))
var/obj/item/radio/integrated/signal/R = user.sradio
else if(href_list["code"])
P.sradio.code += text2num(href_list["code"])
P.sradio.code = round(P.sradio.code)
P.sradio.code = min(100, P.sradio.code)
P.sradio.code = max(1, P.sradio.code)
return 1
switch(action)
if("signal")
spawn(0)
R.send_signal("ACTIVATE")
for(var/mob/O in hearers(1, R.loc))
O.show_message("[bicon(R)] *beep* *beep*", 3, "*beep* *beep*", 2)
if("freq")
var/frequency = unformat_frequency(params["freq"])
frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
R.set_frequency(frequency)
. = TRUE
if("code")
R.code = clamp(round(text2num(params["code"])), 1, 100)
. = TRUE
if("reset")
if(params["reset"] == "freq")
R.set_frequency(initial(R.frequency))
else
R.code = initial(R.code)
. = TRUE
@@ -349,12 +349,6 @@
updatename()
updateicon()
// this verb lets cyborgs see the stations manifest
/mob/living/silicon/robot/verb/cmd_station_manifest()
set category = "Robot Commands"
set name = "Show Crew Manifest"
show_station_manifest()
/mob/living/silicon/robot/proc/self_diagnosis()
if(!is_component_functioning("diagnosis unit"))
return null
@@ -153,18 +153,6 @@
show_malf_ai()
..()
// this function displays the stations manifest in a separate window
/mob/living/silicon/proc/show_station_manifest()
var/dat = "<div align='center'>"
if(!data_core)
to_chat(src, "<span class='notice'>There is no data to form a manifest with. Contact your Nanotrasen administrator.</span>")
return
dat += data_core.get_manifest(1) //The 1 makes it monochrome.
var/datum/browser/popup = new(src, "Crew Manifest", "Crew Manifest", 370, 420, src)
popup.set_content(dat)
popup.open()
//can't inject synths
/mob/living/silicon/can_inject(var/mob/user, var/error_msg)
if(error_msg)
@@ -2,6 +2,7 @@
var/register_alarms = 1
var/datum/tgui_module/alarm_monitor/all/robot/alarm_monitor
var/datum/tgui_module/atmos_control/robot/atmos_control
var/datum/tgui_module/crew_manifest/robot/crew_manifest
var/datum/tgui_module/crew_monitor/robot/crew_monitor
var/datum/tgui_module/law_manager/robot/law_manager
var/datum/tgui_module/power_monitor/robot/power_monitor
@@ -10,6 +11,7 @@
/mob/living/silicon
var/list/silicon_subsystems = list(
/mob/living/silicon/proc/subsystem_alarm_monitor,
/mob/living/silicon/proc/subsystem_crew_manifest,
/mob/living/silicon/proc/subsystem_law_manager
)
@@ -17,6 +19,7 @@
silicon_subsystems = list(
/mob/living/silicon/proc/subsystem_alarm_monitor,
/mob/living/silicon/proc/subsystem_atmos_control,
/mob/living/silicon/proc/subsystem_crew_manifest,
/mob/living/silicon/proc/subsystem_crew_monitor,
/mob/living/silicon/proc/subsystem_law_manager,
/mob/living/silicon/proc/subsystem_power_monitor,
@@ -30,6 +33,7 @@
/mob/living/silicon/proc/init_subsystems()
alarm_monitor = new(src)
atmos_control = new(src)
crew_manifest = new(src)
crew_monitor = new(src)
law_manager = new(src)
power_monitor = new(src)
@@ -60,6 +64,15 @@
atmos_control.tgui_interact(usr)
/********************
* Crew Manifest *
********************/
/mob/living/silicon/proc/subsystem_crew_manifest()
set category = "Subystems"
set name = "Crew Manifest"
crew_manifest.tgui_interact(usr)
/********************
* Crew Monitor *
********************/
-1
View File
@@ -1,5 +1,4 @@
/mob/Logout()
SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
SStgui.on_logout(src) // Cleanup any TGUIs the user has open
player_list -= src
disconnect_time = world.realtime //VOREStation Addition: logging when we disappear.
@@ -220,12 +220,6 @@
else
return -1
/obj/item/modular_computer/initial_data()
return get_header_data()
/obj/item/modular_computer/update_layout()
return TRUE
/datum/computer_file/program/apply_visual(mob/M)
if(TM)
return TM.apply_visual(M)
-7
View File
@@ -1,7 +0,0 @@
/*
This state checks that the user is an admin, end of story
*/
/var/global/datum/topic_state/admin_state/admin_state = new()
/datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user)
return check_rights(R_ADMIN|R_EVENT, 0, user) ? STATUS_INTERACTIVE : STATUS_CLOSE
-37
View File
@@ -1,37 +0,0 @@
/datum/proc/nano_host()
return src
/datum/proc/nano_container()
return src
/datum/proc/CanUseTopic(var/mob/user, var/datum/topic_state/state)
var/src_object = nano_host()
return state.can_use_topic(src_object, user)
/datum/topic_state/proc/href_list(var/mob/user)
return list()
/datum/topic_state/proc/can_use_topic(var/src_object, var/mob/user)
return STATUS_CLOSE
/mob/proc/shared_nano_interaction()
if (src.stat || !client)
return STATUS_CLOSE // no updates, close the interface
else if (incapacitated())
return STATUS_UPDATE // update only (orange visibility)
return STATUS_INTERACTIVE
/mob/living/silicon/ai/shared_nano_interaction()
if(lacks_power())
return STATUS_CLOSE
if (check_unable(1, 0))
return STATUS_CLOSE
return ..()
/mob/living/silicon/robot/shared_nano_interaction()
. = STATUS_INTERACTIVE
if(!has_power)
return STATUS_CLOSE
if(lockdown)
. = STATUS_DISABLED
return min(., ..())
@@ -1,7 +0,0 @@
/*
This state only checks if user is conscious.
*/
/var/global/datum/topic_state/conscious_state/conscious_state = new()
/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE
@@ -1,18 +0,0 @@
/*
This state checks if user is somewhere within src_object, as well as the default NanoUI interaction.
*/
/var/global/datum/topic_state/contained_state/contained_state = new()
/datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user)
if(!src_object.contains(user))
return STATUS_CLOSE
return user.shared_nano_interaction()
/atom/proc/contains(var/atom/location)
if(!location)
return 0
if(location == src)
return 1
return contains(location.loc)
-91
View File
@@ -1,91 +0,0 @@
/var/global/datum/topic_state/default/default_state = new()
/datum/topic_state/default/href_list(var/mob/user)
return list()
/datum/topic_state/default/can_use_topic(var/src_object, var/mob/user)
return user.default_can_use_topic(src_object)
/mob/proc/default_can_use_topic(var/src_object)
return STATUS_CLOSE // By default no mob can do anything with NanoUI
/mob/observer/dead/default_can_use_topic(var/src_object)
if(can_admin_interact())
return STATUS_INTERACTIVE // Admins are more equal
if(!client || get_dist(src_object, src) > client.view) // Preventing ghosts from having a million windows open by limiting to objects in range
return STATUS_CLOSE
return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/pai/default_can_use_topic(var/src_object)
if((src_object == src || src_object == radio || src_object == communicator) && !stat)
return STATUS_INTERACTIVE
else
return ..()
/mob/living/silicon/robot/default_can_use_topic(var/src_object)
. = shared_nano_interaction()
if(. <= STATUS_DISABLED)
return
// robots can interact with things they can see within their view range
if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view)
return STATUS_INTERACTIVE // interactive (green visibility)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
/mob/living/silicon/ai/default_can_use_topic(var/src_object)
. = shared_nano_interaction()
if(. != STATUS_INTERACTIVE)
return
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
if(!T || !(z == T.z || (T.z in using_map.player_levels)))
return STATUS_CLOSE
// If an object is in view then we can interact with it
if(src_object in view(client.view, src))
return STATUS_INTERACTIVE
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
if(is_in_chassis())
//stop AIs from leaving windows open and using then after they lose vision
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
return STATUS_CLOSE
return STATUS_INTERACTIVE
else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard
return STATUS_INTERACTIVE
return STATUS_CLOSE
//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI.
/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user)
return user.shared_living_nano_distance(src_object)
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
return STATUS_CLOSE
var/dist = get_dist(src_object, src)
if (dist <= 1)
return STATUS_INTERACTIVE // interactive (green visibility)
else if (dist <= 2)
return STATUS_UPDATE // update only (orange visibility)
else if (dist <= 4)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
return STATUS_CLOSE
/mob/living/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. != STATUS_CLOSE)
if(loc)
. = min(., loc.contents_nano_distance(src_object, src))
if(STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/human/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. != STATUS_CLOSE)
. = min(., shared_living_nano_distance(src_object))
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
return STATUS_INTERACTIVE
@@ -1,6 +0,0 @@
/mob/living/simple_mob/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. != STATUS_CLOSE)
. = min(., shared_living_nano_distance(src_object))
//Allows simple mobs to interact with nanoui as long as they have "has_hands = TRUE"
@@ -1,7 +0,0 @@
/*
This state always returns STATUS_INTERACTIVE
*/
/var/global/datum/topic_state/interactive/interactive_state = new()
/datum/topic_state/interactive/can_use_topic(var/src_object, var/mob/user)
return STATUS_INTERACTIVE
@@ -1,11 +0,0 @@
/*
This state checks that the src_object is somewhere in the user's first-level inventory (in hands, on ear, etc.), but not further down (such as in bags).
*/
/var/global/datum/topic_state/inventory_state/inventory_state = new()
/datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user)
if(!(src_object in user))
return STATUS_CLOSE
return user.shared_nano_interaction()
@@ -1,10 +0,0 @@
/*
This state checks if src_object is contained anywhere in the user's inventory, including bags, etc.
*/
/var/global/datum/topic_state/deep_inventory_state/deep_inventory_state = new()
/datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user)
if(!user.contains(src_object))
return STATUS_CLOSE
return user.shared_nano_interaction()
@@ -1,32 +0,0 @@
/*
This state checks that the src_object is on the user's glasses slot.
*/
/var/global/datum/topic_state/glasses_state/glasses_state = new()
/datum/topic_state/glasses_state/can_use_topic(var/src_object, var/mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.glasses == src_object)
return user.shared_nano_interaction()
return STATUS_CLOSE
/var/global/datum/topic_state/nif_state/nif_state = new()
/datum/topic_state/nif_state/can_use_topic(var/src_object, var/mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif)
return user.shared_nano_interaction()
return STATUS_CLOSE
/var/global/datum/topic_state/commlink_state/commlink_state = new()
/datum/topic_state/commlink_state/can_use_topic(var/src_object, var/mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object)
return user.shared_nano_interaction()
return STATUS_CLOSE
-6
View File
@@ -1,6 +0,0 @@
/var/global/datum/topic_state/default/outside/outside_state = new()
/datum/topic_state/default/outside/can_use_topic(var/src_object, var/mob/user)
if(user in src_object)
return STATUS_CLOSE
return ..()
-18
View File
@@ -1,18 +0,0 @@
/var/global/datum/topic_state/physical/physical_state = new()
/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user)
. = user.shared_nano_interaction(src_object)
if(. > STATUS_CLOSE)
return min(., user.check_physical_distance(src_object))
/mob/proc/check_physical_distance(var/src_object)
return STATUS_CLOSE
/mob/observer/dead/check_physical_distance(var/src_object)
return default_can_use_topic(src_object)
/mob/living/check_physical_distance(var/src_object)
return shared_living_nano_distance(src_object)
/mob/living/silicon/check_physical_distance(var/src_object)
return max(STATUS_UPDATE, shared_living_nano_distance(src_object))
-39
View File
@@ -1,39 +0,0 @@
/*
This state checks that user is capable, within range of the remoter, etc. and that src_object meets the basic requirements for interaction (being powered, non-broken, etc.
Whoever initializes this state is also responsible for deleting it properly.
*/
/datum/topic_state/remote
var/datum/remoter
var/datum/remote_target
var/datum/topic_state/remoter_state
/datum/topic_state/remote/New(var/remoter, var/remote_target, var/datum/topic_state/remoter_state = default_state)
src.remoter = remoter
src.remote_target = remote_target
src.remoter_state = remoter_state
..()
/datum/topic_state/remote/Destroy()
src.remoter = null
src.remoter_state = null
// Force an UI update before we go, ensuring that any windows we may have opened for the remote target closes.
SSnanoui.update_uis(remote_target.nano_container())
remote_target = null
return ..()
/datum/topic_state/remote/can_use_topic(var/datum/src_object, var/mob/user)
if(!(remoter && remoter_state)) // The remoter is gone, let us leave
return STATUS_CLOSE
if(src_object != remote_target)
error("remote - Unexpected src_object: Expected '[remote_target]'/[remote_target.type], was '[src_object]'/[src_object.type]")
// This checks if src_object is powered, etc.
// The interactive state is otherwise simplistic and only returns STATUS_INTERACTIVE and never checks distances, etc.
. = src_object.CanUseTopic(user, interactive_state)
if(. == STATUS_CLOSE)
return
// This is the (generally) heavy checking, making sure the user is capable, within range of the remoter source, etc.
return min(., remoter.CanUseTopic(user, remoter_state))
-9
View File
@@ -1,9 +0,0 @@
/*
This state checks that the src_object is the same the as user
*/
/var/global/datum/topic_state/self_state/self_state = new()
/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user)
if(src_object != user)
return STATUS_CLOSE
return user.shared_nano_interaction()
-13
View File
@@ -1,13 +0,0 @@
/*
This state checks that the user is on the same Z-level as src_object
*/
/var/global/datum/topic_state/z_state/z_state = new()
/datum/topic_state/z_state/can_use_topic(var/src_object, var/mob/user)
var/turf/turf_obj = get_turf(src_object)
var/turf/turf_usr = get_turf(user)
if(!turf_obj || !turf_usr)
return STATUS_CLOSE
return turf_obj.z == turf_usr.z ? STATUS_INTERACTIVE : STATUS_CLOSE
-60
View File
@@ -1,60 +0,0 @@
/datum/nano_module
var/name
var/datum/host
var/list/using_access
/datum/nano_module/New(var/datum/host)
..()
src.host = host.nano_host()
/datum/nano_module/nano_host()
return host ? host : src
/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = default_state)
return CanUseTopic(usr, state) == STATUS_INTERACTIVE
/datum/nano_module/proc/check_eye(var/mob/user)
return -1
/datum/nano_module/proc/check_access(var/mob/user, var/access)
if(!access)
return 1
if(using_access)
if(access in using_access)
return 1
else
return 0
if(!istype(user))
return 0
var/obj/item/weapon/card/id/I = user.GetIdCard()
if(!I)
return 0
if(access in I.access)
return 1
return 0
/datum/nano_module/proc/print_text(var/text, var/mob/user)
var/obj/item/modular_computer/MC = nano_host()
if(istype(MC))
if(!MC.nano_printer)
to_chat(user, "Error: No printer detected. Unable to print document.")
return
if(!MC.nano_printer.print_text(text))
to_chat(user, "Error: Printer was unable to print the document. It may be out of paper.")
else
to_chat(user, "Error: Unable to detect compatible printer interface. Are you running NTOSv2 compatible system?")
/datum/proc/initial_data()
return list()
/datum/proc/update_layout()
return FALSE
/datum/nano_module/proc/relaymove(var/mob/user, direction)
return FALSE
-44
View File
@@ -1,44 +0,0 @@
// This file contains all Nano procs/definitions for external classes/objects
/**
* Called when a Nano UI window is closed
* This is how Nano handles closed windows
* It must be a verb so that it can be called using winset
*
* @return nothing
*/
/client/verb/nanoclose(var/uiref as text)
set hidden = 1 // hide this verb from the user's panel
set name = "nanoclose"
var/datum/nanoui/ui = locate(uiref)
if (istype(ui))
ui.close()
if(ui.ref)
var/href = "close=1"
src.Topic(href, params2list(href), ui.ref) // this will direct to the atom's Topic() proc via client.Topic()
else if (ui.on_close_logic)
// no atomref specified (or not found)
// so just reset the user mob's machine var
if(src && src.mob)
src.mob.unset_machine()
/**
* The ui_interact proc is used to open and update Nano UIs
* If ui_interact is not used then the UI will not update correctly
* ui_interact is currently defined for /atom/movable
*
* @param user /mob The mob who is interacting with this ui
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
* @param force_open boolean Force the UI to (re)open, even if it's already open
*
* @return nothing
*/
/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/state = default_state)
return
// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob
/mob/var/list/open_uis = list()
-224
View File
@@ -1,224 +0,0 @@
/**
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
*
* @param user /mob The mob who opened/owns the ui
* @param src_object /obj|/mob The obj or mob which the ui belongs to
* @param ui_key string A string key used for the ui
* @param ui /datum/nanoui An existing instance of the ui (can be null)
* @param data list The data to be passed to the ui, if it exists
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
*
* @return /nanoui Returns the found ui, for null if none exists
*/
/datum/controller/subsystem/nanoui/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0)
if (isnull(ui)) // no ui has been passed, so we'll search for one
{
ui = get_open_ui(user, src_object, ui_key)
}
if (!isnull(ui))
// The UI is already open
if (!force_open)
ui.push_data(data)
return ui
else
ui.reinitialise(new_initial_data=data)
return ui
return null
/**
* Get an open /nanoui ui for the current user, src_object and ui_key
*
* @param user /mob The mob who opened/owns the ui
* @param src_object /obj|/mob The obj or mob which the ui belongs to
* @param ui_key string A string key used for the ui
*
* @return /nanoui Returns the found ui, or null if none exists
*/
/datum/controller/subsystem/nanoui/proc/get_open_ui(var/mob/user, src_object, ui_key)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
return null
else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
return null
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if (ui.user == user)
return ui
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
return null
/**
* Update all /nanoui uis attached to src_object
*
* @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis updated
*/
/datum/controller/subsystem/nanoui/proc/update_uis(src_object)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0
var/update_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.process(1)
update_count++
return update_count
/**
* Close all /nanoui uis attached to src_object
*
* @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis close
*/
/datum/controller/subsystem/nanoui/proc/close_uis(src_object)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0
var/close_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.close()
close_count++
return close_count
/**
* Update /nanoui uis belonging to user
*
* @param user /mob The mob who owns the uis
* @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional)
* @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional)
*
* @return int The number of uis updated
*/
/datum/controller/subsystem/nanoui/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // has no open uis
var/update_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.process(1)
update_count++
return update_count
/**
* Close /nanoui uis belonging to user
*
* @param user /mob The mob who owns the uis
* @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional)
* @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional)
*
* @return int The number of uis closed
*/
/datum/controller/subsystem/nanoui/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/close_user_uis mob [user.name] has no open uis")
return 0 // has no open uis
var/close_count = 0
for (var/datum/nanoui/ui in user.open_uis)
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.close()
close_count++
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
return close_count
/**
* Add a /nanoui ui to the list of open uis
* This is called by the /nanoui open() proc
*
* @param ui /nanoui The ui to add
*
* @return nothing
*/
/datum/controller/subsystem/nanoui/proc/ui_opened(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
open_uis[src_object_key] = list(ui.ui_key = list())
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
open_uis[src_object_key][ui.ui_key] = list();
ui.user.open_uis |= ui
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis |= ui
processing_uis |= ui
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
/**
* Remove a /nanoui ui from the list of open uis
* This is called by the /nanoui close() proc
*
* @param ui /nanoui The ui to remove
*
* @return int 0 if no ui was removed, 1 if removed successfully
*/
/datum/controller/subsystem/nanoui/proc/ui_closed(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // wasn't open
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
return 0 // wasn't open
processing_uis.Remove(ui)
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
ui.user.open_uis.Remove(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Remove(ui)
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
return 1
/**
* This is called on user logout
* Closes/clears all uis attached to the user's /mob
*
* @param user /mob The user's mob
*
* @return nothing
*/
//
/datum/controller/subsystem/nanoui/proc/user_logout(var/mob/user)
//testing("nanomanager/user_logout user [user.name]")
return close_user_uis(user)
/**
* This is called when a player transfers from one mob to another
* Transfers all open UIs to the new mob
*
* @param oldMob /mob The user's old mob
* @param newMob /mob The user's new mob
*
* @return nothing
*/
/datum/controller/subsystem/nanoui/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
return 0 // has no open uis
if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
newMob.open_uis = list()
for (var/datum/nanoui/ui in oldMob.open_uis)
ui.user = newMob
newMob.open_uis.Add(ui)
oldMob.open_uis.Cut()
return 1 // success
-529
View File
@@ -1,529 +0,0 @@
/**********************************************************
NANO UI FRAMEWORK
nanoui class (or whatever Byond calls classes)
nanoui is used to open and update nano browser uis
**********************************************************/
/datum/nanoui
// the user who opened this ui
var/mob/user
// the object this ui "belongs" to
var/datum/src_object
// the title of this ui
var/title
// the key of this ui, this is to allow multiple (different) uis for each src_object
var/ui_key
// window_id is used as the window name/identifier for browse and onclose
var/window_id
// the browser window width
var/width = 0
// the browser window height
var/height = 0
// whether to use extra logic when window closes
var/on_close_logic = 1
// an extra ref to use when the window is closed, usually null
var/atom/ref = null
// options for modifying window behaviour
var/window_options = "focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id
// the list of stylesheets to apply to this ui
var/list/stylesheets = list()
// the list of javascript scripts to use for this ui
var/list/scripts = list()
// a list of templates which can be used with this ui
var/templates[0]
// the layout key for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing)
var/layout_key = "default"
// this sets whether to re-render the ui layout with each update (default 0, turning on will break the map ui if it's in use)
var/auto_update_layout = 0
// this sets whether to re-render the ui content with each update (default 1)
var/auto_update_content = 1
// the default state to use for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing)
var/state_key = "default"
// show the map ui, this is used by the default layout
var/show_map = 0
// the map z level to display
var/map_z_level = 1
// initial data, containing the full data structure, must be sent to the ui (the data structure cannot be extended later on)
var/list/initial_data[0]
// set to 1 to update the ui automatically every master_controller tick
var/is_auto_updating = 0
// the current status/visibility of the ui
var/status = STATUS_INTERACTIVE
// Relationship between a master interface and its children. Used in update_status
var/datum/nanoui/master_ui
var/list/datum/nanoui/children = list()
var/datum/topic_state/state = null
/**
* Create a new nanoui instance.
*
* @param nuser /mob The mob who has opened/owns this ui
* @param nsrc_object /obj|/mob The obj or mob which this ui belongs to
* @param nui_key string A string key to use for this ui. Allows for multiple unique uis on one src_oject
* @param ntemplate string The filename of the template file from /nano/templates (e.g. "my_template.tmpl")
* @param ntitle string The title of this ui
* @param nwidth int the width of the ui window
* @param nheight int the height of the ui window
* @param nref /atom A custom ref to use if "on_close_logic" is set to 1
*
* @return /nanoui new nanoui object
*/
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state)
user = nuser
src_object = nsrc_object
ui_key = nui_key
window_id = "[ui_key]\ref[src_object]"
src.master_ui = master_ui
if(master_ui)
master_ui.children += src
src.state = state
// add the passed template filename as the "main" template, this is required
add_template("main", ntemplate_filename)
if (ntitle)
title = sanitize(ntitle)
if (nwidth)
width = nwidth
if (nheight)
height = nheight
if (nref)
ref = nref
add_common_assets()
/**
* Use this proc to add assets which are common to (and required by) all nano uis
*
* @return nothing
*/
/datum/nanoui/proc/add_common_assets()
add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together)
add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions.
add_script("nano_templates_bundle.js") // Contains all templates, generated by asset cache system at server start.
add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates.
add_script("nano_state_manager.js") // The NanoStateManager JS, it handles updates from the server and passes data to the current state
add_script("nano_state.js") // The NanoState JS, this is the base state which all states must inherit from
add_script("nano_state_default.js") // The NanoStateDefault JS, this is the "default" state (used by all UIs by default), which inherits from NanoState
add_script("nano_state_pda.js") // The NanoStatePDA JS, this is the state used for PDAs.
add_script("nano_base_callbacks.js") // The NanoBaseCallbacks JS, this is used to set up (before and after update) callbacks which are common to all UIs
add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all UIs
add_stylesheet("shared.css") // this CSS sheet is common to all UIs
add_stylesheet("shared_vr.css") // VOREStation Add
add_stylesheet("icons.css") // this CSS sheet is common to all UIs
/**
* Set the current status (also known as visibility) of this ui.
*
* @param state int The status to set, see the defines at the top of this file
* @param push_update int (bool) Push an update to the ui to update it's status (an update is always sent if the status has changed to red (0))
*
* @return nothing
*/
/datum/nanoui/proc/set_status(state, push_update)
if (state != status) // Only update if it is different
if (status == STATUS_DISABLED)
status = state
if (push_update)
update()
else
status = state
if (push_update || status == 0)
push_data(null, 1) // Update the UI, force the update in case the status is 0, data is null so that previous data is used
/**
* Update the status (visibility) of this ui based on the user's status
*
* @param push_update int (bool) Push an update to the ui to update it's status. This is set to 0/false if an update is going to be pushed anyway (to avoid unnessary updates)
*
* @return nothing
*/
/datum/nanoui/proc/update_status(var/push_update = 0)
var/obj/host = src_object.nano_host()
var/new_status = host.CanUseTopic(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
set_status(new_status, push_update)
if(new_status == STATUS_CLOSE)
close()
/**
* Set the ui to auto update (every master_controller tick)
*
* @param state int (bool) Set auto update to 1 or 0 (true/false)
*
* @return nothing
*/
/datum/nanoui/proc/set_auto_update(nstate = 1)
is_auto_updating = nstate
/**
* Set the initial data for the ui. This is vital as the data structure set here cannot be changed when pushing new updates.
*
* @param data /list The list of data for this ui
*
* @return nothing
*/
/datum/nanoui/proc/set_initial_data(list/data)
initial_data = data
/**
* Get config data to sent to the ui.
*
* @return /list config data
*/
/datum/nanoui/proc/get_config_data()
var/name = "[src_object]"
name = sanitize(name)
var/list/config_data = list(
"title" = title,
"srcObject" = list("name" = name),
"stateKey" = state_key,
"status" = status,
"autoUpdateLayout" = auto_update_layout,
"autoUpdateContent" = auto_update_content,
"showMap" = show_map,
"mapZLevel" = map_z_level,
"user" = list("name" = user.name)
)
return config_data
/**
* Get data to sent to the ui.
*
* @param data /list The list of general data for this ui (can be null to use previous data sent)
*
* @return /list data to send to the ui
*/
/datum/nanoui/proc/get_send_data(var/list/data)
var/list/config_data = get_config_data()
var/list/send_data = list("config" = config_data)
if (!isnull(data))
send_data["data"] = data
return send_data
/**
* Set the browser window options for this ui
*
* @param nwindow_options string The new window options
*
* @return nothing
*/
/datum/nanoui/proc/set_window_options(nwindow_options)
window_options = nwindow_options
/**
* Add a CSS stylesheet to this UI
* These must be added before the UI has been opened, adding after that will have no effect
*
* @param file string The name of the CSS file from /nano/css (e.g. "my_style.css")
*
* @return nothing
*/
/datum/nanoui/proc/add_stylesheet(file)
stylesheets.Add(file)
/**
* Add a JavsScript script to this UI
* These must be added before the UI has been opened, adding after that will have no effect
*
* @param file string The name of the JavaScript file from /nano/js (e.g. "my_script.js")
*
* @return nothing
*/
/datum/nanoui/proc/add_script(file)
scripts.Add(file)
/**
* Add a template for this UI
* Templates are combined with the data sent to the UI to create the rendered view
* These must be added before the UI has been opened, adding after that will have no effect
*
* @param key string The key which is used to reference this template in the frontend
* @param filename string The name of the template file from /nano/templates (e.g. "my_template.tmpl")
*
* @return nothing
*/
/datum/nanoui/proc/add_template(key, filename)
templates[key] = filename
/**
* Set the layout key for use in the frontend Javascript
* The layout key is the basic layout key for the page
* Two files are loaded on the client based on the layout key varable:
* -> a template in /nano/templates with the filename "layout_<layout_key>.tmpl
* -> a CSS stylesheet in /nano/css with the filename "layout_<layout_key>.css
*
* @param nlayout string The layout key to use
*
* @return nothing
*/
/datum/nanoui/proc/set_layout_key(nlayout_key)
layout_key = lowertext(nlayout_key)
/**
* Set the ui to update the layout (re-render it) on each update, turning this on will break the map ui (if it's being used)
*
* @param state int (bool) Set update to 1 or 0 (true/false) (default 0)
*
* @return nothing
*/
/datum/nanoui/proc/set_auto_update_layout(nstate)
auto_update_layout = nstate
/**
* Set the ui to update the main content (re-render it) on each update
*
* @param state int (bool) Set update to 1 or 0 (true/false) (default 1)
*
* @return nothing
*/
/datum/nanoui/proc/set_auto_update_content(nstate)
auto_update_content = nstate
/**
* Set the state key for use in the frontend Javascript
*
* @param nstate_key string The key of the state to use
*
* @return nothing
*/
/datum/nanoui/proc/set_state_key(nstate_key)
state_key = nstate_key
/**
* Toggle showing the map ui
*
* @param nstate_key boolean 1 to show map, 0 to hide (default is 0)
*
* @return nothing
*/
/datum/nanoui/proc/set_show_map(nstate)
show_map = nstate
/**
* Toggle showing the map ui
*
* @param nstate_key boolean 1 to show map, 0 to hide (default is 0)
*
* @return nothing
*/
/datum/nanoui/proc/set_map_z_level(nz)
map_z_level = nz
/**
* Set whether or not to use the "old" on close logic (mainly unset_machine())
*
* @param state int (bool) Set on_close_logic to 1 or 0 (true/false)
*
* @return nothing
*/
/datum/nanoui/proc/use_on_close_logic(state)
on_close_logic = state
/**
* Return the HTML for this UI
*
* @return string HTML for the UI
*/
/datum/nanoui/proc/get_html()
// before the UI opens, add the layout files based on the layout key
add_stylesheet("layout_[layout_key].css")
add_template("layout", "layout_[layout_key].tmpl")
var/head_content = ""
for (var/filename in scripts)
head_content += "<script type='text/javascript' src='[filename]'></script> "
for (var/filename in stylesheets)
head_content += "<link rel='stylesheet' type='text/css' href='[filename]'> "
var/template_data_json = "{}" // An empty JSON object
if (templates.len > 0)
template_data_json = strip_improper(json_encode(templates))
var/list/send_data = get_send_data(initial_data)
var/initial_data_json = replacetext(replacetext(json_encode(send_data), "&#34;", "&amp;#34;"), "'", "&#39;")
initial_data_json = strip_improper(initial_data_json);
var/url_parameters_json = json_encode(list("src" = "\ref[src]"))
return {"
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type='text/javascript'>
function receiveUpdateData(jsonString)
{
// We need both jQuery and NanoStateManager to be able to recieve data
// At the moment any data received before those libraries are loaded will be lost
if (typeof NanoStateManager != 'undefined' && typeof jQuery != 'undefined')
{
NanoStateManager.receiveUpdateData(jsonString);
}
//else
//{
// alert('browser.recieveUpdateData failed due to jQuery or NanoStateManager being unavailiable.');
//}
}
</script>
[head_content]
</head>
<body scroll=auto data-template-data='[template_data_json]' data-url-parameters='[url_parameters_json]' data-initial-data='[initial_data_json]'>
<div id='uiLayout'>
</div>
<noscript>
<div id='uiNoScript'>
<h2>JAVASCRIPT REQUIRED</h2>
<p>Your Internet Explorer's Javascript is disabled (or broken).<br/>
Enable Javascript and then open this UI again.</p>
</div>
</noscript>
</body>
</html>
"}
/**
* Open this UI
*
* @return nothing
*/
/datum/nanoui/proc/open()
if(!user.client)
return
// An attempted fix to UIs sometimes locking up spamming runtime errors due to src_object being null for whatever reason.
// This hard-deletes the UI, preventing the device that uses the UI from being locked up permanently.
if(!src_object)
del(src)
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
update_status(0)
if(status == STATUS_CLOSE)
return
user << browse(get_html(), "window=[window_id];[window_size][window_options]")
winset(user, "mapwindow.map", "focus=true") // return keyboard focus to map
on_close_winset()
//onclose(user, window_id)
SSnanoui.ui_opened(src)
/**
* Reinitialise this UI, potentially with a different template and/or initial data
*
* @return nothing
*/
/datum/nanoui/proc/reinitialise(template, new_initial_data)
if(template)
add_template("main", template)
if(new_initial_data)
set_initial_data(new_initial_data)
open()
/**
* Close this UI
*
* @return nothing
*/
/datum/nanoui/proc/close()
is_auto_updating = 0
SSnanoui.ui_closed(src)
user << browse(null, "window=[window_id]")
for(var/datum/nanoui/child in children)
child.close()
children.Cut()
state = null
master_ui = null
/**
* Set the UI window to call the nanoclose verb when the window is closed
* This allows Nano to handle closed windows
*
* @return nothing
*/
/datum/nanoui/proc/on_close_winset()
if(!user.client)
return
var/params = "\ref[src]"
winset(user, window_id, "on-close=\"nanoclose [params]\"")
/**
* Push data to an already open UI window
*
* @return nothing
*/
/datum/nanoui/proc/push_data(data, force_push = 0)
update_status(0)
if (status == STATUS_DISABLED && !force_push)
return // Cannot update UI, no visibility
var/list/send_data = get_send_data(data)
//to_chat(user,list2json_usecache(send_data)) // used for debugging //NANO DEBUG HOOK
user << output(list2params(list(strip_improper(json_encode(send_data)))),"[window_id].browser:receiveUpdateData")
/**
* This Topic() proc is called whenever a user clicks on a link within a Nano UI
* If the UI status is currently STATUS_INTERACTIVE then call the src_object Topic()
* If the src_object Topic() returns 1 (true) then update all UIs attached to src_object
*
* @return nothing
*/
/datum/nanoui/Topic(href, href_list)
update_status(0) // update the status
if (status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user
return
// This is used to toggle the nano map ui
var/map_update = 0
if(href_list["showMap"])
set_show_map(text2num(href_list["showMap"]))
map_update = 1
if(href_list["mapZLevel"])
set_map_z_level(text2num(href_list["mapZLevel"]))
map_update = 1
if ((src_object && src_object.Topic(href, href_list, state)) || map_update)
SSnanoui.update_uis(src_object) // update all UIs attached to src_object
/**
* Process this UI, updating the entire UI or just the status (aka visibility)
* This process proc is called by the master_controller
*
* @param update string For this UI to update
*
* @return nothing
*/
/datum/nanoui/process(update = 0)
if (!src_object || !user)
close()
return
if (status && (update || is_auto_updating))
update() // Update the UI (update_status() is called whenever a UI is updated)
else
update_status(1) // Not updating UI, so lets check here if status has changed
/**
* Update the UI
*
* @return nothing
*/
/datum/nanoui/proc/update(var/force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
@@ -47,6 +47,6 @@
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))
if(CanInteract(usr, GLOB.tgui_default_state) && (D in possible_d))
shuttle.set_destination(possible_d[D])
return TRUE
+82 -70
View File
@@ -17,8 +17,10 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins
active_power_usage = 200
circuit = /obj/item/weapon/circuitboard/fax
var/obj/item/weapon/card/id/scan = null // identification
var/authenticated = 0
var/obj/item/weapon/card/id/scan = null
var/authenticated = null
var/rank = null
var/sendcooldown = 0 // to avoid spamming fax messages
var/department = "Unknown" // our department
var/destination = null // the department we're sending to
@@ -33,91 +35,101 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins
/obj/machinery/photocopier/faxmachine/attack_hand(mob/user as mob)
user.set_machine(src)
ui_interact(user)
tgui_interact(user)
/**
* Display the NanoUI window for the fax machine.
*
* See NanoUI documentation for details.
*/
/obj/machinery/photocopier/faxmachine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
/obj/machinery/photocopier/faxmachine/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Fax", name)
ui.open()
var/list/data = list()
if(scan)
data["scanName"] = scan.name
else
data["scanName"] = null
data["bossName"] = using_map.boss_name
/obj/machinery/photocopier/faxmachine/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["scan"] = scan ? scan.name : null
data["authenticated"] = authenticated
data["rank"] = rank
data["isAI"] = isAI(user)
data["isRobot"] = isrobot(user)
data["bossName"] = using_map.boss_name
data["copyItem"] = copyitem
if(copyitem)
data["copyItemName"] = copyitem.name
else
data["copyItemName"] = null
data["cooldown"] = sendcooldown
data["destination"] = destination
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "fax.tmpl", src.name, 500, 500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(10) //this machine is so unimportant let's not have it update that often.
return data
/obj/machinery/photocopier/faxmachine/Topic(href, href_list)
if(href_list["send"])
if(copyitem)
if (destination in admin_departments)
send_admin_fax(usr, destination)
else
sendfax(destination)
/obj/machinery/photocopier/faxmachine/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if (sendcooldown)
spawn(sendcooldown) // cooldown time
sendcooldown = 0
else if(href_list["remove"])
if(copyitem)
if(get_dist(usr, src) >= 2)
to_chat(usr, "\The [copyitem] is too far away for you to remove it.")
return
copyitem.loc = usr.loc
usr.put_in_hands(copyitem)
to_chat(usr, "<span class='notice'>You take \the [copyitem] out of \the [src].</span>")
copyitem = null
if(href_list["scan"])
if (scan)
if(ishuman(usr))
scan.loc = usr.loc
if(!usr.get_active_hand())
switch(action)
if("scan")
if(scan)
scan.forceMove(loc)
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(scan)
scan = null
else
scan.loc = src.loc
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/weapon/card/id))
usr.drop_item()
I.forceMove(src)
scan = I
return TRUE
if("login")
var/login_type = text2num(params["login_type"])
if(login_type == LOGIN_TYPE_NORMAL && istype(scan))
if(check_access(scan))
authenticated = scan.registered_name
rank = scan.assignment
else if(login_type == LOGIN_TYPE_AI && isAI(usr))
authenticated = usr.name
rank = "AI"
else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr))
authenticated = usr.name
var/mob/living/silicon/robot/R = usr
rank = "[R.modtype] [R.braintype]"
return TRUE
if("logout")
if(scan)
scan.forceMove(loc)
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(scan)
scan = null
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.loc = src
scan = I
authenticated = 0
authenticated = null
return TRUE
if("remove")
if(copyitem)
if(get_dist(usr, src) >= 2)
to_chat(usr, "\The [copyitem] is too far away for you to remove it.")
return
copyitem.forceMove(loc)
usr.put_in_hands(copyitem)
to_chat(usr, "<span class='notice'>You take \the [copyitem] out of \the [src].</span>")
copyitem = null
if(href_list["dept"])
var/lastdestination = destination
destination = input(usr, "Which department?", "Choose a department", "") as null|anything in (alldepartments + admin_departments)
if(!destination) destination = lastdestination
if(!authenticated)
return
switch(action)
if("send")
if(copyitem)
if (destination in admin_departments)
send_admin_fax(usr, destination)
else
sendfax(destination)
if(href_list["auth"])
if ( (!( authenticated ) && (scan)) )
if (check_access(scan))
authenticated = 1
if (sendcooldown)
spawn(sendcooldown) // cooldown time
sendcooldown = 0
if(href_list["logout"])
authenticated = 0
if("dept")
var/lastdestination = destination
destination = input(usr, "Which department?", "Choose a department", "") as null|anything in (alldepartments + admin_departments)
if(!destination)
destination = lastdestination
SSnanoui.update_uis(src)
return TRUE
/obj/machinery/photocopier/faxmachine/attackby(obj/item/O as obj, mob/user as mob)
if(O.is_multitool() && panel_open)
+63 -70
View File
@@ -33,33 +33,71 @@
/obj/machinery/photocopier/attack_hand(mob/user as mob)
user.set_machine(src)
ui_interact(user)
tgui_interact(user)
/**
* Display the NanoUI window for the photocopier.
*
* See NanoUI documentation for details.
*/
/obj/machinery/photocopier/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
var/list/data = list()
data["copyItem"] = copyitem
data["assPresent"] = has_buckled_mobs()
data["toner"] = toner
data["copies"] = copies
data["maxCopies"] = maxcopies
if(istype(user,/mob/living/silicon))
data["isSilicon"] = 1
else
data["isSilicon"] = null
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "photocopier.tmpl", src.name, 300, 250)
ui.set_initial_data(data)
/obj/machinery/photocopier/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Photocopier", name)
ui.open()
ui.set_auto_update(10)
/obj/machinery/photocopier/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["has_item"] = copyitem || has_buckled_mobs() // VOREStation Edit: Ass copying
data["isAI"] = issilicon(user)
data["can_AI_print"] = (toner >= 5)
data["has_toner"] = !!toner
data["current_toner"] = toner
data["max_toner"] = 40
data["num_copies"] = copies
data["max_copies"] = maxcopies
return data
/obj/machinery/photocopier/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("make_copy")
addtimer(CALLBACK(src, .proc/copy_operation, usr), 0)
. = TRUE
if("remove")
if(copyitem)
copyitem.loc = usr.loc
usr.put_in_hands(copyitem)
to_chat(usr, "<span class='notice'>You take \the [copyitem] out of \the [src].</span>")
copyitem = null
else if(has_buckled_mobs())
to_chat(buckled_mobs[1], "<span class='notice'>You feel a slight pressure on your ass.</span>") // It can't eject your asscheeks, but it'll try.
. = TRUE
if("set_copies")
copies = clamp(text2num(params["num_copies"]), 1, maxcopies)
. = TRUE
if("ai_photo")
if(!issilicon(usr))
return
if(stat & (BROKEN|NOPOWER))
return
if(toner >= 5)
var/mob/living/silicon/tempAI = usr
var/obj/item/device/camera/siliconcam/camera = tempAI.aiCamera
if(!camera)
return
var/obj/item/weapon/photo/selection = camera.selectpicture()
if (!selection)
return
var/obj/item/weapon/photo/p = photocopy(selection)
if (p.desc == "")
p.desc += "Copied by [tempAI.name]"
else
p.desc += " - Copied by [tempAI.name]"
toner -= 5
. = TRUE
/obj/machinery/photocopier/proc/copy_operation(var/mob/user)
if(copying)
@@ -104,51 +142,6 @@
use_power(active_power_usage)
copying = FALSE
/obj/machinery/photocopier/Topic(href, href_list)
if(href_list["copy"])
if(stat & (BROKEN|NOPOWER))
return
addtimer(CALLBACK(src, .proc/copy_operation, usr), 0)
else if(href_list["remove"])
if(copyitem)
copyitem.loc = usr.loc
usr.put_in_hands(copyitem)
to_chat(usr, "<span class='notice'>You take \the [copyitem] out of \the [src].</span>")
copyitem = null
else if(has_buckled_mobs())
to_chat(buckled_mobs[1], "<span class='notice'>You feel a slight pressure on your ass.</span>") // It can't eject your asscheeks, but it'll try.
return TOPIC_REFRESH
else if(href_list["min"])
if(copies > 1)
copies--
else if(href_list["add"])
if(copies < maxcopies)
copies++
else if(href_list["aipic"])
if(!istype(usr,/mob/living/silicon)) return
if(stat & (BROKEN|NOPOWER)) return
if(toner >= 5)
var/mob/living/silicon/tempAI = usr
var/obj/item/device/camera/siliconcam/camera = tempAI.aiCamera
if(!camera)
return
var/obj/item/weapon/photo/selection = camera.selectpicture()
if (!selection)
return
var/obj/item/weapon/photo/p = photocopy(selection)
if (p.desc == "")
p.desc += "Copied by [tempAI.name]"
else
p.desc += " - Copied by [tempAI.name]"
toner -= 5
sleep(15)
SSnanoui.update_uis(src)
/obj/machinery/photocopier/attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/paper) || istype(O, /obj/item/weapon/photo) || istype(O, /obj/item/weapon/paper_bundle))
if(!copyitem)
+9 -61
View File
@@ -4,7 +4,12 @@
icon_state = "NONE"
ttone = "data"
detonate = 0
touch_silent = TRUE
programs = list(
new/datum/data/pda/app/main_menu,
new/datum/data/pda/app/notekeeper,
new/datum/data/pda/app/news,
new/datum/data/pda/app/messenger)
/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text)
owner = newname
@@ -16,70 +21,18 @@
name = newname + " (" + ownjob + ")"
//AI verb and proc for sending PDA messages.
/obj/item/device/pda/ai/verb/cmd_send_pdamesg()
/obj/item/device/pda/ai/verb/cmd_pda_open_ui()
set category = "AI IM"
set name = "Send PDA Message"
set name = "Use PDA"
set src in usr
if(!can_use())
return
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
if(!M)
to_chat(usr, "<span class='warning'>Cannot use messenger!</span>")
var/list/plist = M.available_pdas()
if(plist)
var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist)
if(!c) // if the user hasn't selected a PDA file we can't send a message
return
var/selected = plist[c]
M.create_message(usr, selected)
/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver()
set category = "AI IM"
set name = "Toggle Sender/Receiver"
set src in usr
if(!can_use())
return
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
M.toff = !M.toff
to_chat(usr, "<span class='notice'>PDA sender/receiver toggled [(M.toff ? "Off" : "On")]!</span>")
/obj/item/device/pda/ai/verb/cmd_toggle_pda_silent()
set category = "AI IM"
set name = "Toggle Ringer"
set src in usr
if(!can_use())
return
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
M.notify_silent = !M.notify_silent
to_chat(usr, "<span class='notice'>PDA ringer toggled [(M.notify_silent ? "Off" : "On")]!</span>")
/obj/item/device/pda/ai/verb/cmd_show_message_log()
set category = "AI IM"
set name = "Show Message Log"
set src in usr
if(!can_use())
return
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
if(!M)
to_chat(usr, "<span class='warning'>Cannot use messenger!</span>")
var/HTML = "<html><head><title>AI PDA Message Log</title></head><body>"
for(var/index in M.tnote)
if(index["sent"])
HTML += addtext("<i><b>&rarr; To <a href='byond://?src=[REF(src)];choice=Message;target=",index["src"],"'>", index["owner"],"</a>:</b></i><br>", index["message"], "<br>")
else
HTML += addtext("<i><b>&larr; From <a href='byond://?src=[REF(src)];choice=Message;target=",index["target"],"'>", index["owner"],"</a>:</b></i><br>", index["message"], "<br>")
HTML +="</body></html>"
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
tgui_interact(usr)
/obj/item/device/pda/ai/can_use()
return 1
/obj/item/device/pda/ai/attack_self(mob/user as mob)
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
@@ -90,11 +43,6 @@
/obj/item/device/pda/ai/pai
ttone = "assist"
var/our_owner = null // Ref to a pAI
touch_silent = TRUE
programs = list(
new/datum/data/pda/app/main_menu,
new/datum/data/pda/app/notekeeper,
new/datum/data/pda/app/messenger)
/obj/item/device/pda/ai/pai/New(mob/living/silicon/pai/P)
if(istype(P))
+2 -2
View File
@@ -7,10 +7,10 @@
if(!can_use())
. = min(., STATUS_UPDATE)
/obj/item/device/pda/tgui_interact(mob/user, datum/tgui/ui)
/obj/item/device/pda/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Pda", "Personal Data Assistant")
ui = new(user, src, "Pda", "Personal Data Assistant", parent_ui)
ui.open()
/obj/item/device/pda/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
+73 -66
View File
@@ -25,6 +25,7 @@
var/equalise = 0 // If true try to equalise charge between cells
var/icon_update = 0 // Timer in ticks for icon update.
var/ui_tick = 0
should_be_mapped = TRUE
/obj/machinery/power/smes/batteryrack/New()
@@ -113,6 +114,8 @@
if(equalise)
// Now try to get least charged cell and use the power from it.
var/obj/item/weapon/cell/CL = get_least_charged_cell()
if(!CL)
return
amount -= CL.give(amount)
if(!amount)
return
@@ -209,8 +212,43 @@
celldiff = min(min(celldiff, most.charge), least.maxcharge - least.charge)
least.give(most.use(celldiff))
/obj/machinery/power/smes/batteryrack/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/power/smes/batteryrack/dismantle()
for(var/obj/item/weapon/cell/C in internal_cells)
C.forceMove(get_turf(src))
internal_cells -= C
return ..()
/obj/machinery/power/smes/batteryrack/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if(istype(W, /obj/item/weapon/cell)) // ID Card, try to insert it.
if(insert_cell(W, user))
to_chat(user, "<span class='filter_notice'>You insert \the [W] into \the [src].</span>")
else
to_chat(user, "<span class='filter_notice'>\The [src] has no empty slot for \the [W]</span>")
if(!..())
return 0
if(default_deconstruction_crowbar(user, W))
return
if(default_part_replacement(user, W))
return
/obj/machinery/power/smes/batteryrack/inputting()
return
/obj/machinery/power/smes/batteryrack/outputting()
return
/obj/machinery/power/smes/batteryrack/attack_hand(var/mob/user)
tgui_interact(user)
/obj/machinery/power/smes/batteryrack/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Batteryrack", name)
ui.open()
/obj/machinery/power/smes/batteryrack/tgui_data(mob/user)
// DO NOT CALL PARENT.
var/list/data = list()
data["mode"] = mode
data["transfer_max"] = max_transfer_rate
@@ -238,75 +276,44 @@
cells += list(cell)
data["cells_list"] = cells
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "psu.tmpl", "Cell Rack PSU", 500, 430)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/power/smes/batteryrack/dismantle()
for(var/obj/item/weapon/cell/C in internal_cells)
C.forceMove(get_turf(src))
internal_cells -= C
return ..()
/obj/machinery/power/smes/batteryrack/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if(!..())
return 0
if(default_deconstruction_crowbar(user, W))
return
if(default_part_replacement(user, W))
return
if(istype(W, /obj/item/weapon/cell)) // ID Card, try to insert it.
if(insert_cell(W, user))
to_chat(user, "<span class='filter_notice'>You insert \the [W] into \the [src].</span>")
else
to_chat(user, "<span class='filter_notice'>\The [src] has no empty slot for \the [W]</span>")
/obj/machinery/power/smes/batteryrack/attack_hand(var/mob/user)
ui_interact(user)
/obj/machinery/power/smes/batteryrack/inputting()
return
/obj/machinery/power/smes/batteryrack/outputting()
return
/obj/machinery/power/smes/batteryrack/Topic(href, href_list)
/obj/machinery/power/smes/batteryrack/tgui_act(action, list/params)
// ..() would respond to those topic calls, but we don't want to use them at all.
// Calls to these shouldn't occur anyway, due to usage of different nanoUI, but
// it's here in case someone decides to try hrefhacking/modified templates.
if(href_list["input"] || href_list["output"])
return 1
if(!(action in list("disable", "enable", "equaliseon", "equaliseoff", "ejectcell")))
return TRUE
if(..())
return 1
if( href_list["disable"] )
update_io(0)
return 1
else if( href_list["enable"] )
update_io(between(1, text2num(href_list["enable"]), 3))
return 1
else if( href_list["equaliseon"] )
equalise = 1
return 1
else if( href_list["equaliseoff"] )
equalise = 0
return 1
else if( href_list["ejectcell"] )
var/obj/item/weapon/cell/C
for(var/obj/item/weapon/cell/CL in internal_cells)
if(CL.c_uid == text2num(href_list["ejectcell"]))
C = CL
break
return TRUE
if(!istype(C))
return 1
switch(action)
if("disable")
update_io(0)
return TRUE
if("enable")
update_io(between(1, text2num(params["enable"]), 3))
return TRUE
if("equaliseon")
equalise = 1
return TRUE
if("equaliseoff")
equalise = 0
return TRUE
if("ejectcell")
var/obj/item/weapon/cell/C
for(var/obj/item/weapon/cell/CL in internal_cells)
if(CL.c_uid == text2num(params["ejectcell"]))
C = CL
break
C.forceMove(get_turf(src))
internal_cells -= C
update_icon()
RefreshParts()
update_maxcharge()
return 1
if(!istype(C))
return TRUE
C.forceMove(get_turf(src))
internal_cells -= C
update_icon()
RefreshParts()
update_maxcharge()
return TRUE
+1 -1
View File
@@ -59,7 +59,7 @@
if(opened)
wires.Interact(user)
return ui_interact(user)
return tgui_interact(user)
/obj/machinery/power/grid_checker/proc/power_failure(var/announce = TRUE)
if(announce)
+36 -36
View File
@@ -345,59 +345,59 @@
/obj/machinery/computer/turbine_computer/attack_hand(var/mob/user as mob)
if((. = ..()))
return
src.interact(user)
tgui_interact(user)
/obj/machinery/computer/turbine_computer/interact(mob/user)
return ui_interact(user)
/obj/machinery/computer/turbine_computer/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TurbineControl", name)
ui.open()
/obj/machinery/computer/turbine_computer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/computer/turbine_computer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = list()
data["connected"] = (compressor && compressor.turbine) ? TRUE : FALSE
data["compressor_broke"] = (!compressor || (compressor.stat & BROKEN)) ? TRUE : FALSE
data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.stat & BROKEN)) ? TRUE : FALSE
data["broken"] = (data["compressor_broke"] || data["turbine_broke"])
data["door_status"] = door_status ? TRUE : FALSE
data["online"] = FALSE
data["power"] = 0
data["rpm"] = 0
data["temp"] = 0
if(compressor && compressor.turbine)
data["online"] = compressor.starter
data["power"] = DisplayPower(compressor.turbine.lastgen)
data["power"] = compressor.turbine.lastgen // DisplayPower
data["rpm"] = compressor.rpm
data["temp"] = compressor.gas_contained.temperature
// 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, "turbine_computer.tmpl", name, 520, 440)
// 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 Master Controller tick
ui.set_auto_update(TRUE)
return data
/obj/machinery/computer/turbine_computer/Topic(href, href_list)
/obj/machinery/computer/turbine_computer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
if(href_list["power-on"])
if(compressor && compressor.turbine)
compressor.starter = TRUE
return TRUE
switch(action)
if("power-on")
if(compressor && compressor.turbine)
compressor.starter = TRUE
. = TRUE
if("power-off")
if(compressor && compressor.turbine)
compressor.starter = FALSE
. = TRUE
if("reconnect")
locate_machinery()
. = TRUE
else if(href_list["power-off"])
if(compressor && compressor.turbine)
compressor.starter = FALSE
if("doors")
door_status = !door_status
for(var/obj/machinery/door/blast/D in src.doors)
if (door_status)
spawn(0) D.close()
else
spawn(0)D.open()
. = TRUE
else if(href_list["reconnect"])
locate_machinery()
. = TRUE
else if(href_list["doors"])
door_status = !door_status
for(var/obj/machinery/door/blast/D in src.doors)
if (door_status)
spawn(0) D.close()
else
spawn(0)D.open()
. = TRUE
#undef COMPFRICTION
#undef COMPSTARTERLOAD
@@ -25,7 +25,7 @@
C.reagents.add_reagent(id, to_restore)
. = 1
if(.)
SSnanoui.update_uis(src)
SStgui.update_uis(src)
/obj/machinery/chemical_dispenser
dispense_reagents = list(
+47 -60
View File
@@ -147,9 +147,9 @@ var/list/infomorph_emotions = list(
return 0
..()
/mob/living/silicon/infomorph/default_can_use_topic(var/src_object)
/mob/living/silicon/infomorph/default_can_use_tgui_topic(var/src_object)
if(src_object in src)
return shared_nano_interaction()
return shared_tgui_interaction()
/////////// DAMAGES
/mob/living/silicon/infomorph/emp_act(severity)
@@ -190,7 +190,7 @@ var/list/infomorph_emotions = list(
medicalActive1 = null
medicalActive2 = null
medical_cannotfind = 0
SSnanoui.update_uis(src)
SStgui.update_uis(src)
to_chat(usr, "<span class='notice'>You reset your record-viewing software.</span>")
/*
@@ -463,94 +463,81 @@ var/global/list/default_infomorph_software = list()
set category = "Card Commands"
set name = "Software Interface"
ui_interact(src)
tgui_interact(src)
/mob/living/silicon/infomorph/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, key_state = self_state)
if(user != src)
if(ui) ui.set_status(STATUS_CLOSE, 0)
return
/mob/living/silicon/infomorph/tgui_state(mob/user)
return GLOB.tgui_self_state
if(ui_key != "main")
var/datum/infomorph_software/S = software[ui_key]
if(S && !S.toggle)
S.on_ui_interact(src, ui, force_open)
else
if(ui) ui.set_status(STATUS_CLOSE, 0)
return
var/data[0]
/mob/living/silicon/infomorph/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIInterface", "Card Software Interface")
ui.open()
/mob/living/silicon/infomorph/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
// Software we have bought
var/bought_software[0]
var/list/bought_software = list()
// Software we have not bought
var/not_bought_software[0]
var/list/not_bought_software = list()
for(var/key in infomorph_software_by_key)
var/datum/infomorph_software/S = infomorph_software_by_key[key]
var/software_data[0]
var/list/software_data = list()
software_data["name"] = S.name
software_data["id"] = S.id
if(key in software)
software_data["on"] = S.is_active(src)
bought_software[++bought_software.len] = software_data
bought_software.Add(list(software_data))
else
software_data["ram"] = S.ram_cost
not_bought_software[++not_bought_software.len] = software_data
not_bought_software.Add(list(software_data))
data["bought"] = bought_software
data["not_bought"] = not_bought_software
data["available_ram"] = ram
// Emotions
var/emotions[0]
var/list/emotions = list()
for(var/name in infomorph_emotions)
var/emote[0]
var/list/emote = list()
emote["name"] = name
emote["id"] = infomorph_emotions[name]
emotions[++emotions.len] = emote
emotions.Add(list(emote))
data["emotions"] = emotions
data["current_emotion"] = card.current_emotion
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open, key_state)
if (!ui)
ui = new(user, src, ui_key, "pai_interface.tmpl", "Card Software Interface", 450, 600, state = key_state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/mob/living/silicon/infomorph/Topic(href, href_list)
. = ..()
if(.) return
/mob/living/silicon/infomorph/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(href_list["software"])
var/soft = href_list["software"]
var/datum/infomorph_software/S = software[soft]
if(S.toggle)
S.toggle(src)
else
ui_interact(src, ui_key = soft)
return 1
switch(action)
if("software")
var/soft = params["software"]
var/datum/infomorph_software/S = software[soft]
if(S.toggle)
S.toggle(src)
else
S.tgui_interact(src, parent_ui = ui)
return TRUE
else if(href_list["stopic"])
var/soft = href_list["stopic"]
var/datum/infomorph_software/S = software[soft]
if(S)
return S.Topic(href, href_list)
if("purchase")
var/soft = params["purchase"]
var/datum/infomorph_software/S = infomorph_software_by_key[soft]
if(S && (ram >= S.ram_cost))
ram -= S.ram_cost
software[S.id] = S
return TRUE
else if(href_list["purchase"])
var/soft = href_list["purchase"]
var/datum/infomorph_software/S = infomorph_software_by_key[soft]
if(S && (ram >= S.ram_cost))
ram -= S.ram_cost
software[S.id] = S
return 1
else if(href_list["image"])
var/img = href_list["image"]
if(img)
card.setEmotion(img)
return 1
if("image")
var/img = text2num(params["image"])
if(img)
card.setEmotion(img)
return TRUE
/mob/living/silicon/infomorph/examine(mob/user)
. = ..(user, infix = ", personal AI")
+220 -190
View File
@@ -12,35 +12,38 @@
// Whether pAIs should automatically receive this module at no cost
var/default = 0
proc/on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
return
/datum/infomorph_software/tgui_state(mob/user)
return GLOB.tgui_always_state
proc/toggle(mob/living/silicon/infomorph/user)
return
/datum/infomorph_software/tgui_status(mob/user)
if(!istype(user, /mob/living/silicon/infomorph))
return STATUS_CLOSE
return ..()
proc/is_active(mob/living/silicon/infomorph/user)
return 0
/datum/infomorph_software/proc/toggle(mob/living/silicon/infomorph/user)
return
/datum/infomorph_software/proc/is_active(mob/living/silicon/infomorph/user)
return 0
/datum/infomorph_software/crew_manifest
name = "Crew Manifest"
ram_cost = 15
ram_cost = 5
id = "manifest"
toggle = 0
on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
/datum/infomorph_software/crew_manifest/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "CrewManifest", name, parent_ui)
ui.open()
/datum/infomorph_software/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
if(data_core)
data_core.get_manifest_list()
var/data[0]
// This is dumb, but NanoUI breaks if it has no data to send
data["manifest"] = PDA_Manifest
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_manifest.tmpl", "Crew Manifest", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["manifest"] = PDA_Manifest
return data
/datum/infomorph_software/med_records
name = "Medical Records"
@@ -48,53 +51,55 @@
id = "med_records"
toggle = 0
on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/infomorph_software/med_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIMedrecords", name, parent_ui)
ui.open()
var/records[0]
for(var/datum/data/record/general in sortRecord(data_core.general))
var/record[0]
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records[++records.len] = record
/datum/infomorph_software/med_records/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/list/records = list()
for(var/datum/data/record/general in sortRecord(data_core.general))
var/list/record = list()
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records.Add(list(record))
data["records"] = records
data["records"] = records
var/datum/data/record/G = user.medicalActive1
var/datum/data/record/M = user.medicalActive2
data["general"] = G ? G.fields : null
data["medical"] = M ? M.fields : null
data["could_not_find"] = user.medical_cannotfind
var/datum/data/record/G = user.medicalActive1
var/datum/data/record/M = user.medicalActive2
data["general"] = G ? G.fields : null
data["medical"] = M ? M.fields : null
data["could_not_find"] = user.medical_cannotfind
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_medrecords.tmpl", "Medical Records", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
Topic(href, href_list)
var/mob/living/silicon/infomorph/P = usr
if(!istype(P)) return
/datum/infomorph_software/med_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
. = ..()
var/mob/living/silicon/infomorph/P = usr
if(!istype(P))
return
if(href_list["select"])
var/datum/data/record/record = locate(href_list["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/M = null
if (!( data_core.general.Find(R) ))
P.medical_cannotfind = 1
else
P.medical_cannotfind = 0
for(var/datum/data/record/E in data_core.medical)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
P.medicalActive1 = R
P.medicalActive2 = M
else
if(action == "select")
var/datum/data/record/record = locate(params["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/M = null
if (!( data_core.general.Find(R) ))
P.medical_cannotfind = 1
return 1
else
P.medical_cannotfind = 0
for(var/datum/data/record/E in data_core.medical)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
P.medicalActive1 = R
P.medicalActive2 = M
else
P.medical_cannotfind = 1
return 1
/datum/infomorph_software/sec_records
name = "Security Records"
@@ -102,57 +107,59 @@
id = "sec_records"
toggle = 0
on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/infomorph_software/sec_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAISecrecords", name, parent_ui)
ui.open()
var/records[0]
for(var/datum/data/record/general in sortRecord(data_core.general))
var/record[0]
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records[++records.len] = record
/datum/infomorph_software/sec_records/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/list/records = list()
for(var/datum/data/record/general in sortRecord(data_core.general))
var/list/record = list()
record["name"] = general.fields["name"]
record["ref"] = "\ref[general]"
records.Add(list(record))
data["records"] = records
data["records"] = records
var/datum/data/record/G = user.securityActive1
var/datum/data/record/S = user.securityActive2
data["general"] = G ? G.fields : null
data["security"] = S ? S.fields : null
data["could_not_find"] = user.security_cannotfind
var/datum/data/record/G = user.securityActive1
var/datum/data/record/S = user.securityActive2
data["general"] = G ? G.fields : null
data["security"] = S ? S.fields : null
data["could_not_find"] = user.security_cannotfind
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_secrecords.tmpl", "Security Records", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
Topic(href, href_list)
var/mob/living/silicon/infomorph/P = usr
if(!istype(P)) return
/datum/infomorph_software/sec_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
. = ..()
var/mob/living/silicon/infomorph/P = usr
if(!istype(P))
return
if(href_list["select"])
var/datum/data/record/record = locate(href_list["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/S = null
if (!( data_core.general.Find(R) ))
P.securityActive1 = null
P.securityActive2 = null
P.security_cannotfind = 1
else
P.security_cannotfind = 0
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
S = E
P.securityActive1 = R
P.securityActive2 = S
else
if(action == "select")
var/datum/data/record/record = locate(params["select"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/S = null
if (!( data_core.general.Find(R) ))
P.securityActive1 = null
P.securityActive2 = null
P.security_cannotfind = 1
return 1
else
P.security_cannotfind = 0
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
S = E
P.securityActive1 = R
P.securityActive2 = S
else
P.securityActive1 = null
P.securityActive2 = null
P.security_cannotfind = 1
return TRUE
/datum/infomorph_software/door_jack
name = "Door Jack"
@@ -160,44 +167,45 @@
id = "door_jack"
toggle = 0
on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/infomorph_software/door_jack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIDoorjack", "Door Jack", parent_ui)
ui.open()
data["cable"] = user.cable != null
data["machine"] = user.cable && (user.cable.machine != null)
data["inprogress"] = user.hackdoor != null
data["progress_a"] = round(user.hackprogress)
data["progress_b"] = user.hackprogress % 10
data["aborted"] = user.hack_aborted
/datum/infomorph_software/door_jack/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_doorjack.tmpl", "Door Jack", 300, 150)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["cable"] = user.cable != null
data["machine"] = user.cable && (user.cable.machine != null)
data["inprogress"] = user.hackdoor != null
data["progress_a"] = round(user.hackprogress / 10)
data["progress_b"] = user.hackprogress % 10
data["aborted"] = user.hack_aborted
Topic(href, href_list)
var/mob/living/silicon/infomorph/P = usr
if(!istype(P)) return
return data
if(href_list["jack"])
/datum/infomorph_software/door_jack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
var/mob/living/silicon/infomorph/P = usr
if(!istype(P) || ..())
return TRUE
switch(action)
if("jack")
if(P.cable && P.cable.machine)
P.hackdoor = P.cable.machine
P.hackloop()
return 1
else if(href_list["cancel"])
if("cancel")
P.hackdoor = null
return 1
else if(href_list["cable"])
if("cable")
var/turf/T = get_turf(P)
P.hack_aborted = 0
P.cable = new /obj/item/weapon/pai_cable(T)
if(ishuman(P.card.loc))
var/mob/living/carbon/human/H = P.card.loc
H.put_in_any_hand_if_possible(P.cable)
T.visible_message("<span class='warning'>A port on \the [P] opens to reveal \the [P.cable].</span>")
for(var/mob/M in viewers(T))
M.show_message("<span class='warning'>A port on [P] opens to reveal [P.cable], which promptly falls to the floor.</span>", 3,
"<span class='warning'>You hear the soft click of something light and hard falling to the ground.</span>", 2)
return 1
/mob/living/silicon/infomorph/proc/hackloop()
@@ -239,43 +247,54 @@
/datum/infomorph_software/atmosphere_sensor
name = "Atmosphere Sensor"
ram_cost = 15
ram_cost = 5
id = "atmos_sense"
toggle = 0
on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/infomorph_software/atmosphere_sensor/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "pAIAtmos", name, parent_ui)
ui.open()
var/turf/T = get_turf_or_move(user.loc)
if(!T)
data["reading"] = 0
data["pressure"] = 0
data["temperature"] = 0
data["temperatureC"] = 0
data["gas"] = list()
else
var/datum/gas_mixture/env = T.return_air()
data["reading"] = 1
var/pres = env.return_pressure() * 10
data["pressure"] = "[round(pres/10)].[pres%10]"
data["temperature"] = round(env.temperature)
data["temperatureC"] = round(env.temperature-T0C)
/datum/infomorph_software/atmosphere_sensor/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/t_moles = env.total_moles
var/gases[0]
for(var/g in env.gas)
var/gas[0]
gas["name"] = gas_data.name[g]
gas["percent"] = round((env.gas[g] / t_moles) * 100)
gases[++gases.len] = gas
data["gas"] = gases
var/list/results = list()
var/turf/T = get_turf(user)
if(!isnull(T))
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles
if (total_moles)
var/o2_level = environment.gas["oxygen"]/total_moles
var/n2_level = environment.gas["nitrogen"]/total_moles
var/co2_level = environment.gas["carbon_dioxide"]/total_moles
var/phoron_level = environment.gas["phoron"]/total_moles
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_atmosphere.tmpl", "Atmosphere Sensor", 350, 300)
ui.set_initial_data(data)
ui.open()
// entry is what the element is describing
// Type identifies which unit or other special characters to use
// Val is the information reported
// Bad_high/_low are the values outside of which the entry reports as dangerous
// Poor_high/_low are the values outside of which the entry reports as unideal
// Values were extracted from the template itself
results = list(
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
list("entry" = "Temperature", "units" = "&deg;C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0),
list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0)
)
if(isnull(results))
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
data["aircontents"] = results
return data
/datum/infomorph_software/ar_hud
name = "AR HUD"
@@ -302,45 +321,56 @@
is_active(mob/living/silicon/infomorph/user)
return user.translator.listening
/datum/infomorph_software/signaller
name = "Remote Signaller"
ram_cost = 15
name = "Remote Signaler"
ram_cost = 5
id = "signaller"
toggle = 0
on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
/datum/infomorph_software/signaller/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Signaler", "Signaler", parent_ui)
ui.open()
data["frequency"] = format_frequency(user.sradio.frequency)
data["code"] = user.sradio.code
/datum/infomorph_software/signaller/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/obj/item/radio/integrated/signal/R = user.sradio
ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_signaller.tmpl", "Signaller", 320, 150)
ui.set_initial_data(data)
ui.open()
data["frequency"] = R.frequency
data["minFrequency"] = RADIO_LOW_FREQ
data["maxFrequency"] = RADIO_HIGH_FREQ
data["code"] = R.code
Topic(href, href_list)
var/mob/living/silicon/infomorph/P = usr
if(!istype(P)) return
return data
if(href_list["send"])
P.sradio.send_signal("ACTIVATE")
for(var/mob/O in hearers(1, P.loc))
O.show_message("[bicon(P)] *beep* *beep*", 3, "*beep* *beep*", 2)
return 1
/datum/infomorph_software/signaller/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
else if(href_list["freq"])
var/new_frequency = (P.sradio.frequency + text2num(href_list["freq"]))
if(new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)
new_frequency = sanitize_frequency(new_frequency)
P.sradio.set_frequency(new_frequency)
return 1
var/mob/living/silicon/infomorph/user = usr
if(istype(user))
var/obj/item/radio/integrated/signal/R = user.sradio
else if(href_list["code"])
P.sradio.code += text2num(href_list["code"])
P.sradio.code = round(P.sradio.code)
P.sradio.code = min(100, P.sradio.code)
P.sradio.code = max(1, P.sradio.code)
return 1
switch(action)
if("signal")
spawn(0)
R.send_signal("ACTIVATE")
for(var/mob/O in hearers(1, R.loc))
O.show_message("[bicon(R)] *beep* *beep*", 3, "*beep* *beep*", 2)
if("freq")
var/frequency = unformat_frequency(params["freq"])
frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
R.set_frequency(frequency)
. = TRUE
if("code")
R.code = clamp(round(text2num(params["code"])), 1, 100)
. = TRUE
if("reset")
if(params["reset"] == "freq")
R.set_frequency(initial(R.frequency))
else
R.code = initial(R.code)
. = TRUE
+3
View File
@@ -1,6 +1,9 @@
/obj/item/device/radio/sleevecard
canhear_range = 0
/obj/item/device/radio/sleevecard/tgui_state(mob/user)
return GLOB.tgui_always_state
/obj/item/device/sleevecard
name = "sleevecard"
desc = "This KHI-upgraded pAI module has enough capacity to run a whole mind of human-level intelligence."
@@ -26,7 +26,7 @@
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))
if(dest_key && CanInteract(usr, GLOB.tgui_default_state))
shuttle.set_destination(dest_key, usr)
return TRUE
@@ -175,84 +175,3 @@
/obj/machinery/computer/shuttle_control/emergency/attackby(obj/item/weapon/W as obj, mob/user as mob)
read_authorization(W)
..()
/obj/machinery/computer/shuttle_control/emergency/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/shuttle/autodock/ferry/emergency/shuttle = SSshuttles.shuttles[shuttle_tag]
if (!istype(shuttle))
return
var/shuttle_state
switch(shuttle.moving_status)
if(SHUTTLE_IDLE) shuttle_state = "idle"
if(SHUTTLE_WARMUP) shuttle_state = "warmup"
if(SHUTTLE_INTRANSIT) shuttle_state = "in_transit"
var/shuttle_status
switch (shuttle.process_state)
if(IDLE_STATE)
if (shuttle.in_use)
shuttle_status = "Busy."
else if (!shuttle.location)
shuttle_status = "Standing by at [station_name()]."
else
shuttle_status = "Standing by at [using_map.dock_name]."
if(WAIT_LAUNCH, FORCE_LAUNCH)
shuttle_status = "Shuttle has received command and will depart shortly."
if(WAIT_ARRIVE)
shuttle_status = "Proceeding to destination."
if(WAIT_FINISH)
shuttle_status = "Arriving at destination now."
//build a list of authorizations
var/list/auth_list[req_authorizations]
if (!emagged)
var/i = 1
for (var/dna_hash in authorized)
auth_list[i++] = list("auth_name"=authorized[dna_hash], "auth_hash"=dna_hash)
while (i <= req_authorizations) //fill up the rest of the list with blank entries
auth_list[i++] = list("auth_name"="", "auth_hash"=null)
else
for (var/i = 1; i <= req_authorizations; i++)
auth_list[i] = list("auth_name"="<font color=\"red\">ERROR</font>", "auth_hash"=null)
var/has_auth = has_authorization()
data = list(
"shuttle_status" = shuttle_status,
"shuttle_state" = shuttle_state,
"has_docking" = shuttle.active_docking_controller? 1 : 0,
"docking_status" = shuttle.active_docking_controller? shuttle.active_docking_controller.get_docking_status() : null,
"docking_override" = shuttle.active_docking_controller? shuttle.active_docking_controller.override_enabled : null,
"can_launch" = shuttle.can_launch(src),
"can_cancel" = shuttle.can_cancel(src),
"can_force" = shuttle.can_force(src),
"auth_list" = auth_list,
"has_auth" = has_auth,
"user" = debug? user : null,
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "escape_shuttle_control_console.tmpl", "Shuttle Control", 470, 420)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/shuttle_control/emergency/Topic(href, href_list)
if(..())
return 1
if(href_list["removeid"])
var/dna_hash = href_list["removeid"]
authorized -= dna_hash
if(!emagged && href_list["scanid"])
//They selected an empty entry. Try to scan their id.
if (ishuman(usr))
var/mob/living/carbon/human/H = usr
if (!read_authorization(H.get_active_hand())) //try to read what's in their hand first
read_authorization(H.wear_id)
+73 -76
View File
@@ -6,7 +6,7 @@
circuit = /obj/item/weapon/circuitboard/telesci_console
var/sending = 1
var/obj/machinery/telepad/telepad = null
var/temp_msg = "Telescience control console initialized.<BR>Welcome."
var/temp_msg = "Telescience control console initialized. Welcome."
// VARIABLES //
var/teles_left // How many teleports left until it becomes uncalibrated
@@ -83,16 +83,21 @@
/obj/machinery/computer/telescience/attack_hand(mob/user)
if(..())
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/computer/telescience/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
/obj/machinery/computer/telescience/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TelesciConsole", name)
ui.open()
var/data[0]
/obj/machinery/computer/telescience/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = list()
if(!telepad)
in_use = 0 //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console
data["noTelepad"] = 1
else
data["noTelepad"] = 0
data["insertedGps"] = inserted_gps
data["rotation"] = rotation
data["currentZ"] = z_co
@@ -110,6 +115,7 @@
//We'll base our options on connected z's or overmap
data["sectorOptions"] = using_map.get_map_levels(z, TRUE, overmap_range)
data["lastTeleData"] = null
if(last_tele_data)
data["lastTeleData"] = list()
data["lastTeleData"]["src_x"] = last_tele_data.src_x
@@ -117,12 +123,61 @@
data["lastTeleData"]["distance"] = last_tele_data.distance
data["lastTeleData"]["time"] = last_tele_data.time
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "telescience_console.tmpl", src.name, 400, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(5)
return data
/obj/machinery/computer/telescience/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(!telepad || telepad.panel_open)
return TRUE
switch(action)
if("setrotation")
rotation = CLAMP(text2num(params["val"]), -900, 900)
rotation = round(rotation, 0.01)
if("setdistance")
distance = CLAMP(text2num(params["val"]), 1, get_max_allowed_distance())
distance = FLOOR(distance, 1)
if("setz")
var/new_z = text2num(params["setz"])
if(new_z in using_map.player_levels)
z_co = new_z
if("ejectGPS")
if(inserted_gps)
inserted_gps.forceMove(loc)
inserted_gps = null
if("setMemory")
if(last_target && inserted_gps)
// TODO - What was this even supposed to do??
//inserted_gps.locked_location = last_target
temp_msg = "Location saved."
else
temp_msg = "ERROR! No data was stored."
if("send")
sending = 1
teleport(usr)
if("receive")
sending = 0
teleport(usr)
if("recal")
recalibrate()
sparks()
temp_msg = "NOTICE: Calibration successful."
if("eject")
eject()
temp_msg = "NOTICE: Bluespace crystals ejected."
else
return FALSE
return TRUE
/obj/machinery/computer/telescience/proc/sparks()
if(telepad)
@@ -198,7 +253,7 @@
playsound(telepad, 'sound/weapons/flash.ogg', 50, 1)
// Wait depending on the time the projectile took to get there
teleporting = 1
temp_msg = "Powering up bluespace crystals.<BR>Please wait."
temp_msg = "Powering up bluespace crystals. Please wait."
spawn(spawn_time) // in deciseconds
if(!telepad)
@@ -218,12 +273,12 @@
if(!A || (A.flags & BLUE_SHIELDED))
telefail()
temp_msg = "ERROR!<BR>Target is shielded from bluespace intersection!"
temp_msg = "ERROR! Target is shielded from bluespace intersection!"
return
temp_msg = "Teleport successful.<BR>"
temp_msg = "Teleport successful. "
if(teles_left < 10)
temp_msg += "Calibration required soon.<BR>"
temp_msg += "Calibration required soon. "
temp_msg += "Data printed below."
var/sparks = get_turf(target)
@@ -286,11 +341,11 @@
/obj/machinery/computer/telescience/proc/teleport(mob/user)
distance = CLAMP(distance, 0, get_max_allowed_distance())
if(rotation == null || distance == null || z_co == null)
temp_msg = "ERROR!<BR>Set a distance, rotation and sector."
temp_msg = "ERROR! Set a distance, rotation and sector."
return
if(distance <= 0)
telefail()
temp_msg = "ERROR!<BR>No distance selected!"
temp_msg = "ERROR! No distance selected!"
return
if(!(z_co in using_map.player_levels))
telefail()
@@ -300,7 +355,7 @@
doteleport(user)
else
telefail()
temp_msg = "ERROR!<BR>Calibration required."
temp_msg = "ERROR! Calibration required."
return
return
@@ -310,64 +365,6 @@
crystals -= I
distance = 0
/obj/machinery/computer/telescience/Topic(href, href_list)
if(..())
return
if(!telepad || telepad.panel_open)
updateDialog()
return
if(href_list["setrotation"])
var/new_rot = input("Please input desired bearing in degrees.", name, rotation) as num
if(..()) // Check after we input a value, as they could've moved after they entered something
return
rotation = CLAMP(new_rot, -900, 900)
rotation = round(rotation, 0.01)
if(href_list["setdistance"])
var/new_pow = input("Please input desired distance in meters.", name, rotation) as num
if(..()) // Check after we input a value, as they could've moved after they entered something
return
distance = CLAMP(new_pow, 1, get_max_allowed_distance())
distance = FLOOR(distance, 1)
if(href_list["setz"])
var/new_z = text2num(href_list["setz"])
if(new_z in using_map.player_levels)
z_co = new_z
if(href_list["ejectGPS"])
if(inserted_gps)
inserted_gps.forceMove(loc)
inserted_gps = null
if(href_list["setMemory"])
if(last_target && inserted_gps)
// TODO - What was this even supposed to do??
//inserted_gps.locked_location = last_target
temp_msg = "Location saved."
else
temp_msg = "ERROR!<BR>No data was stored."
if(href_list["send"])
sending = 1
teleport(usr)
if(href_list["receive"])
sending = 0
teleport(usr)
if(href_list["recal"])
recalibrate()
sparks()
temp_msg = "NOTICE:<BR>Calibration successful."
if(href_list["eject"])
eject()
temp_msg = "NOTICE:<BR>Bluespace crystals ejected."
updateDialog()
/obj/machinery/computer/telescience/proc/recalibrate()
teles_left = rand(40, 50)
distance_off = rand(-4, 4)
+135
View File
@@ -0,0 +1,135 @@
/datum/tgui_module/agentcard
name = "Agent Card"
tgui_id = "AgentCard"
/datum/tgui_module/agentcard/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/obj/item/weapon/card/id/syndicate/S = tgui_host()
if(!istype(S))
return list()
var/list/entries = list()
entries += list(list("name" = "Age", "value" = S.age))
entries += list(list("name" = "Appearance", "value" = "Set"))
entries += list(list("name" = "Assignment", "value" = S.assignment))
entries += list(list("name" = "Blood Type", "value" = S.blood_type))
entries += list(list("name" = "DNA Hash", "value" = S.dna_hash))
entries += list(list("name" = "Fingerprint Hash", "value" = S.fingerprint_hash))
entries += list(list("name" = "Name", "value" = S.registered_name))
entries += list(list("name" = "Photo", "value" = "Update"))
entries += list(list("name" = "Sex", "value" = S.sex))
entries += list(list("name" = "Factory Reset", "value" = "Use With Care"))
data["entries"] = entries
data["electronic_warfare"] = S.electronic_warfare
return data
/datum/tgui_module/agentcard/tgui_status(mob/user, datum/tgui_state/state)
var/obj/item/weapon/card/id/syndicate/S = tgui_host()
if(!istype(S))
return STATUS_CLOSE
if(user != S.registered_user)
return STATUS_CLOSE
return ..()
/datum/tgui_module/agentcard/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
var/obj/item/weapon/card/id/syndicate/S = tgui_host()
switch(action)
if("electronic_warfare")
S.electronic_warfare = !S.electronic_warfare
to_chat(usr, "<span class='notice'>Electronic warfare [S.electronic_warfare ? "enabled" : "disabled"].</span>")
. = TRUE
if("age")
var/new_age = input(usr,"What age would you like to put on this card?","Agent Card Age", S.age) as null|num
if(!isnull(new_age) && tgui_status(usr, state) == STATUS_INTERACTIVE)
if(new_age < 0)
S.age = initial(S.age)
else
S.age = new_age
to_chat(usr, "<span class='notice'>Age has been set to '[S.age]'.</span>")
. = TRUE
if("appearance")
var/datum/card_state/choice = input(usr, "Select the appearance for this card.", "Agent Card Appearance") as null|anything in id_card_states()
if(choice && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.icon_state = choice.icon_state
S.item_state = choice.item_state
to_chat(usr, "<span class='notice'>Appearance changed to [choice].</span>")
. = TRUE
if("assignment")
var/new_job = sanitize(input(usr,"What assignment would you like to put on this card?\nChanging assignment will not grant or remove any access levels.","Agent Card Assignment", S.assignment) as null|text)
if(!isnull(new_job) && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.assignment = new_job
to_chat(usr, "<span class='notice'>Occupation changed to '[new_job]'.</span>")
S.update_name()
. = TRUE
if("bloodtype")
var/default = S.blood_type
if(default == initial(S.blood_type) && ishuman(usr))
var/mob/living/carbon/human/H = usr
if(H.dna)
default = H.dna.b_type
var/new_blood_type = sanitize(input(usr,"What blood type would you like to be written on this card?","Agent Card Blood Type",default) as null|text)
if(!isnull(new_blood_type) && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.blood_type = new_blood_type
to_chat(usr, "<span class='notice'>Blood type changed to '[new_blood_type]'.</span>")
. = TRUE
if("dnahash")
var/default = S.dna_hash
if(default == initial(S.dna_hash) && ishuman(usr))
var/mob/living/carbon/human/H = usr
if(H.dna)
default = H.dna.unique_enzymes
var/new_dna_hash = sanitize(input(usr,"What DNA hash would you like to be written on this card?","Agent Card DNA Hash",default) as null|text)
if(!isnull(new_dna_hash) && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.dna_hash = new_dna_hash
to_chat(usr, "<span class='notice'>DNA hash changed to '[new_dna_hash]'.</span>")
. = TRUE
if("fingerprinthash")
var/default = S.fingerprint_hash
if(default == initial(S.fingerprint_hash) && ishuman(usr))
var/mob/living/carbon/human/H = usr
if(H.dna)
default = md5(H.dna.uni_identity)
var/new_fingerprint_hash = sanitize(input(usr,"What fingerprint hash would you like to be written on this card?","Agent Card Fingerprint Hash",default) as null|text)
if(!isnull(new_fingerprint_hash) && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.fingerprint_hash = new_fingerprint_hash
to_chat(usr, "<span class='notice'>Fingerprint hash changed to '[new_fingerprint_hash]'.</span>")
. = TRUE
if("name")
var/new_name = sanitizeName(input(usr,"What name would you like to put on this card?","Agent Card Name", S.registered_name) as null|text)
if(!isnull(new_name) && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.registered_name = new_name
S.update_name()
to_chat(usr, "<span class='notice'>Name changed to '[new_name]'.</span>")
. = TRUE
if("photo")
S.set_id_photo(usr)
to_chat(usr, "<span class='notice'>Photo changed.</span>")
. = TRUE
if("sex")
var/new_sex = sanitize(input(usr,"What sex would you like to put on this card?","Agent Card Sex", S.sex) as null|text)
if(!isnull(new_sex) && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.sex = new_sex
to_chat(usr, "<span class='notice'>Sex changed to '[new_sex]'.</span>")
. = TRUE
if("factoryreset")
if(alert("This will factory reset the card, including access and owner. Continue?", "Factory Reset", "No", "Yes") == "Yes" && tgui_status(usr, state) == STATUS_INTERACTIVE)
S.age = initial(S.age)
S.access = syndicate_access.Copy()
S.assignment = initial(S.assignment)
S.blood_type = initial(S.blood_type)
S.dna_hash = initial(S.dna_hash)
S.electronic_warfare = initial(S.electronic_warfare)
S.fingerprint_hash = initial(S.fingerprint_hash)
S.icon_state = initial(S.icon_state)
S.name = initial(S.name)
S.registered_name = initial(S.registered_name)
S.unset_registered_user()
S.sex = initial(S.sex)
to_chat(usr, "<span class='notice'>All information has been deleted from \the [src].</span>")
. = TRUE
@@ -34,6 +34,11 @@
ui.set_map_z_level(params["mapZLevel"])
return TRUE
/datum/tgui_module/atmos_control/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/simple/nanomaps),
)
/datum/tgui_module/atmos_control/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -0,0 +1,14 @@
/datum/tgui_module/crew_manifest
name = "Crew Manifest"
tgui_id = "CrewManifest"
/datum/tgui_module/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
if(data_core)
data_core.get_manifest_list()
data["manifest"] = PDA_Manifest
return data
/datum/tgui_module/crew_manifest/robot
/datum/tgui_module/crew_manifest/robot/tgui_state(mob/user)
return GLOB.tgui_self_state
@@ -2,6 +2,11 @@
name = "Crew monitor"
tgui_id = "CrewMonitor"
/datum/tgui_module/crew_monitor/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/simple/nanomaps),
)
/datum/tgui_module/crew_monitor/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
+85
View File
@@ -0,0 +1,85 @@
/datum/tgui_module/teleport_control
name = "Teleporter Control"
tgui_id = "Teleporter"
var/locked_name = "Not Locked"
var/obj/item/locked = null
var/obj/machinery/teleport/station/station = null
var/obj/machinery/teleport/hub/hub = null
/datum/tgui_module/teleport_control/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["locked_name"] = locked_name || "No Target"
data["station_connected"] = !!station
data["hub_connected"] = !!hub
data["calibrated"] = hub?.accurate
data["teleporter_on"] = station?.engaged
return data
/datum/tgui_module/teleport_control/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("select_target")
var/list/L = list()
var/list/areaindex = list()
for(var/obj/item/device/radio/beacon/R in all_beacons)
var/turf/T = get_turf(R)
if(!T)
continue
if(!(T.z in using_map.player_levels))
continue
var/tmpname = T.loc.name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
else
areaindex[tmpname] = 1
L[tmpname] = R
for(var/obj/item/weapon/implant/tracking/I in all_tracking_implants)
if(!I.implanted || !ismob(I.loc))
continue
else
var/mob/M = I.loc
if(M.stat == 2)
if(M.timeofdeath + 6000 < world.time)
continue
var/turf/T = get_turf(M)
if(T)
continue
if(!(T in using_map.station_levels))
continue
var/tmpname = M.real_name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
else
areaindex[tmpname] = 1
L[tmpname] = I
var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null
if(!desc)
return FALSE
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
locked = L[desc]
locked_name = desc
return TRUE
if("test_fire")
station?.testfire()
return TRUE
if("toggle_on")
if(!station)
return FALSE
if(station.engaged)
station.disengage()
else
station.engage()
return TRUE
@@ -48,7 +48,7 @@
sleep(3)
return NANOMAP_TERMINALERR
var/icon/Tile = icon(file("nano/mapbase1200.png"))
var/icon/Tile = icon('icons/_nanomaps/mapbase1200.png')
if (Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION)
to_world_log("NanoMapGen: <B>ERROR: BASE IMAGE DIMENSIONS ARE NOT [NANOMAP_MAX_ICON_DIMENSION]x[NANOMAP_MAX_ICON_DIMENSION]</B>")
sleep(3)
+4
View File
@@ -123,3 +123,7 @@
if((TK in mutations) && (get_dist(src, src_object) <= 2))
return STATUS_INTERACTIVE
return ..()
// Topic Extensions for old UIs
/datum/proc/CanUseTopic(var/mob/user, var/datum/tgui_state/state)
return tgui_status(user, state)
@@ -10,3 +10,11 @@ GLOBAL_DATUM_INIT(tgui_deep_inventory_state, /datum/tgui_state/deep_inventory_st
if(!user.contains(src_object))
return STATUS_CLOSE
return user.shared_tgui_interaction(src_object)
/atom/proc/contains(var/atom/location)
if(!location)
return 0
if(location == src)
return 1
return contains(location.loc)
+2 -2
View File
@@ -68,12 +68,12 @@ GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new)
/mob/living/silicon/pai/default_can_use_tgui_topic(src_object)
// pAIs can only use themselves and the owner's radio.
if((src_object == src || src_object == radio) && !stat)
if((src_object == src || src_object == radio || src_object == communicator) && !stat)
return STATUS_INTERACTIVE
else
return ..()
/mob/observer/dead/default_can_use_tgui_topic()
if(check_rights(R_ADMIN, 0, src))
if(can_admin_interact())
return STATUS_INTERACTIVE // Admins are more equal
return STATUS_UPDATE // Ghosts can view updates
+2 -1
View File
@@ -114,7 +114,6 @@
closing = TRUE
for(var/datum/tgui/child in children)
child.close(can_be_suspended, logout)
children.Cut()
// If we don't have window_id, open proc did not have the opportunity
// to finish, therefore it's safe to skip this whole block.
if(window)
@@ -126,6 +125,8 @@
src_object.tgui_close(user)
SStgui.on_close(src)
state = null
if(parent_ui)
parent_ui.children -= src
parent_ui = null
qdel(src)